Skip to content

Commit 89f7f73

Browse files
committed
Revert "old"
This reverts commit f5351f147a242fa466acbd951574888a91b2550b.
1 parent b3eb71f commit 89f7f73

File tree

1 file changed

+129
-86
lines changed
  • library/compiler-builtins/crates/josh-sync/src

1 file changed

+129
-86
lines changed

library/compiler-builtins/crates/josh-sync/src/sync.rs

Lines changed: 129 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,173 @@
1-
use std::io::Write;
1+
use std::io::{Write, stdout};
22
use std::ops::Not;
33
use std::path::PathBuf;
4+
use std::process::{Command, Stdio};
45
use std::time::Duration;
5-
use std::{env, net, process};
6+
use std::{env, fs, net, process};
67

78
use anyhow::{Context, anyhow, bail};
89
use xshell::{Shell, cmd};
910

10-
/// Used for rustc syncs.
11-
const JOSH_FILTER: &str = ":/src/doc/rustc-dev-guide";
12-
const JOSH_PORT: u16 = 42042;
13-
const UPSTREAM_REPO: &str = "rust-lang/rust";
14-
15-
pub enum RustcPullError {
16-
/// No changes are available to be pulled.
17-
NothingToPull,
18-
/// A rustc-pull has failed, probably a git operation error has occurred.
19-
PullFailed(anyhow::Error),
20-
}
21-
22-
impl<E> From<E> for RustcPullError
23-
where
24-
E: Into<anyhow::Error>,
25-
{
26-
fn from(error: E) -> Self {
27-
Self::PullFailed(error.into())
28-
}
29-
}
11+
const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rustc";
12+
const MERGE_COMMIT_MESSAGE: &str = "Merge from rustc";
3013

3114
pub struct GitSync {
3215
dir: PathBuf,
16+
upstream_repo: String,
17+
upstream_ref: String,
18+
upstream_url: String,
19+
josh_filter: String,
20+
josh_port: u16,
21+
josh_url_base: String,
3322
}
3423

3524
/// This code was adapted from the miri repository
3625
/// (https://github.com/rust-lang/miri/blob/6a68a79f38064c3bc30617cca4bdbfb2c336b140/miri-script/src/commands.rs#L236).
3726
impl GitSync {
3827
pub fn from_current_dir() -> anyhow::Result<Self> {
28+
let upstream_repo =
29+
env::var("UPSTREAM_ORG").unwrap_or_else(|_| "rust-lang".to_owned()) + "/rust";
30+
let josh_port = 42042;
3931
Ok(Self {
4032
dir: std::env::current_dir()?,
33+
upstream_url: format!("https://github.com/{upstream_repo}/"),
34+
upstream_repo,
35+
upstream_ref: env::var("UPSTREAM_REF").unwrap_or_else(|_| "HEAD".to_owned()),
36+
josh_filter: ":/library/compiler-builtins".to_owned(),
37+
josh_port,
38+
josh_url_base: format!("http://localhost:{josh_port}"),
4139
})
4240
}
4341

4442
pub fn rustc_pull(&self, commit: Option<String>) -> Result<(), RustcPullError> {
43+
let Self {
44+
upstream_repo,
45+
upstream_ref,
46+
upstream_url,
47+
josh_filter,
48+
josh_url_base,
49+
..
50+
} = self;
51+
4552
let sh = Shell::new()?;
4653
sh.change_dir(&self.dir);
47-
let commit = commit.map(Ok).unwrap_or_else(|| {
48-
let rust_repo_head =
49-
cmd!(sh, "git ls-remote https://github.com/{UPSTREAM_REPO}/ HEAD").read()?;
50-
rust_repo_head
51-
.split_whitespace()
54+
55+
let upstream_head = commit.unwrap_or_else(|| {
56+
let out = cmd!(sh, "git ls-remote {upstream_url} {upstream_ref}")
57+
.read()
58+
.unwrap();
59+
out.split_whitespace()
5260
.next()
53-
.map(|front| front.trim().to_owned())
54-
.ok_or_else(|| anyhow!("Could not obtain Rust repo HEAD from remote."))
55-
})?;
56-
// Make sure the repo is clean.
57-
if cmd!(sh, "git status --untracked-files=no --porcelain")
58-
.read()?
59-
.is_empty()
60-
.not()
61-
{
62-
return Err(anyhow::anyhow!(
63-
"working directory must be clean before performing rustc pull"
64-
)
65-
.into());
66-
}
61+
.unwrap_or_else(|| panic!("could not split output: '{out}'"))
62+
.to_owned()
63+
});
64+
65+
ensure_clean(&sh)?;
66+
6767
// Make sure josh is running.
68-
let josh = Self::start_josh()?;
68+
let _josh = self.start_josh()?;
6969
let josh_url =
70-
format!("http://localhost:{JOSH_PORT}/{UPSTREAM_REPO}.git@{commit}{JOSH_FILTER}.git");
70+
format!("{josh_url_base}/{upstream_repo}.git@{upstream_head}{josh_filter}.git");
7171

72-
let previous_base_commit = sh.read_file("rust-version")?.trim().to_string();
73-
if previous_base_commit == commit {
74-
return Err(RustcPullError::NothingToPull);
75-
}
72+
let previous_base_commit = sh.read_file("rust-version").unwrap().trim().to_string();
73+
assert_ne!(previous_base_commit, upstream_head, "nothing to pull");
74+
75+
let orig_head = cmd!(sh, "git rev-parse HEAD").read().unwrap();
7676

7777
// Update rust-version file. As a separate commit, since making it part of
7878
// the merge has confused the heck out of josh in the past.
7979
// We pass `--no-verify` to avoid running git hooks.
8080
// We do this before the merge so that if there are merge conflicts, we have
8181
// the right rust-version file while resolving them.
82-
sh.write_file("rust-version", format!("{commit}\n"))?;
83-
const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rustc";
82+
sh.write_file("rust-version", format!("{upstream_head}\n"))?;
8483
cmd!(
8584
sh,
8685
"git commit rust-version --no-verify -m {PREPARING_COMMIT_MESSAGE}"
8786
)
88-
.run()
89-
.context("FAILED to commit rust-version file, something went wrong")?;
87+
.run()?;
9088

9189
// Fetch given rustc commit.
9290
cmd!(sh, "git fetch {josh_url}")
9391
.run()
94-
.inspect_err(|_| {
95-
// Try to un-do the previous `git commit`, to leave the repo in the state we found it.
96-
cmd!(sh, "git reset --hard HEAD^")
97-
.run()
98-
.expect("FAILED to clean up again after failed `git fetch`, sorry for that");
99-
})
100-
.context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?;
92+
.expect("FAILED to fetch new commits, something went wrong");
93+
94+
// // Fetch given rustc commit.
95+
// if let Err(e) = cmd!(sh, "git fetch {josh_url}").run() {
96+
// println!("FAILED to fetch new commits, something went wrong");
97+
98+
// // Try to un-do the previous `git commit`, to leave the repo in the state we found it.
99+
// cmd!(sh, "git reset --hard {orig_head}")
100+
// .run()
101+
// .expect("FAILED to clean up again after failed `git fetch`, sorry for that");
102+
103+
// println!("committing the rust-version file has been undone");
104+
// panic!("{e}");
105+
// }
101106

102107
// This should not add any new root commits. So count those before and after merging.
103-
let num_roots = || -> anyhow::Result<u32> {
104-
Ok(cmd!(sh, "git rev-list HEAD --max-parents=0 --count")
108+
let num_roots = || -> u32 {
109+
let out = cmd!(sh, "git rev-list HEAD --max-parents=0 --count")
105110
.read()
106-
.context("failed to determine the number of root commits")?
107-
.parse::<u32>()?)
111+
.expect("failed to determine the number of root commits");
112+
out.parse::<u32>()
113+
.unwrap_or_else(|e| panic!("failed to parse `out`: {e}"))
108114
};
109-
let num_roots_before = num_roots()?;
115+
let num_roots_before = num_roots();
110116

111117
let sha = cmd!(sh, "git rev-parse HEAD")
112118
.output()
113-
.context("FAILED to get current commit")?
119+
.expect("FAILED to get current commit")
114120
.stdout;
115121

116122
// Merge the fetched commit.
117-
const MERGE_COMMIT_MESSAGE: &str = "Merge from rustc";
118123
cmd!(
119124
sh,
120125
"git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}"
121126
)
122127
.run()
123-
.context("FAILED to merge new commits, something went wrong")?;
128+
.expect("FAILED to merge new commits, something went wrong");
124129

125130
let current_sha = cmd!(sh, "git rev-parse HEAD")
126131
.output()
127132
.context("FAILED to get current commit")?
128133
.stdout;
129134
if current_sha == sha {
130-
cmd!(sh, "git reset --hard HEAD^")
135+
cmd!(sh, "git reset --hard {orig_head}")
131136
.run()
132137
.expect("FAILED to clean up after creating the preparation commit");
133138
eprintln!(
134-
"No merge was performed, no changes to pull were found. Rolled back the preparation commit."
139+
"No merge was performed, no changes to pull were found. \
140+
Rolled back the preparation commit."
135141
);
136142
return Err(RustcPullError::NothingToPull);
137143
}
138144

139145
// Check that the number of roots did not increase.
140-
if num_roots()? != num_roots_before {
146+
if num_roots() != num_roots_before {
141147
return Err(anyhow::anyhow!(
142148
"Josh created a new root commit. This is probably not the history you want."
143149
)
144150
.into());
145151
}
146152

147-
drop(josh);
148153
Ok(())
149154
}
150155

151156
pub fn rustc_push(&self, github_user: &str, branch: &str) -> anyhow::Result<()> {
152157
let sh = Shell::new()?;
158+
let Self {
159+
upstream_repo,
160+
josh_filter,
161+
josh_url_base,
162+
..
163+
} = self;
153164
sh.change_dir(&self.dir);
154165
let base = sh.read_file("rust-version")?.trim().to_owned();
155-
// Make sure the repo is clean.
156-
if cmd!(sh, "git status --untracked-files=no --porcelain")
157-
.read()?
158-
.is_empty()
159-
.not()
160-
{
161-
bail!("working directory must be clean before running `rustc-push`");
162-
}
166+
ensure_clean(&sh)?;
167+
163168
// Make sure josh is running.
164-
let josh = Self::start_josh()?;
165-
let josh_url =
166-
format!("http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git");
169+
let josh = self.start_josh()?;
170+
let josh_url = format!("{josh_url_base}/{github_user}/rust.git{josh_filter}.git");
167171

168172
// Find a repo we can do our preparation in.
169173
if let Ok(rustc_git) = env::var("RUSTC_GIT") {
@@ -201,7 +205,7 @@ impl GitSync {
201205
);
202206
std::process::exit(1);
203207
}
204-
cmd!(sh, "git fetch https://github.com/{UPSTREAM_REPO} {base}").run()?;
208+
cmd!(sh, "git fetch https://github.com/{upstream_repo} {base}").run()?;
205209
cmd!(
206210
sh,
207211
"git push https://github.com/{github_user}/rust {base}:refs/heads/{branch}"
@@ -234,14 +238,14 @@ impl GitSync {
234238
);
235239
println!(
236240
// Open PR with `subtree update` title to silence the `no-merges` triagebot check
237-
" https://github.com/{UPSTREAM_REPO}/compare/{github_user}:{branch}?quick_pull=1&title=rustc-dev-guide+subtree+update&body=r?+@ghost"
241+
" https://github.com/{upstream_repo}/compare/{github_user}:{branch}?quick_pull=1&title=rustc-dev-guide+subtree+update&body=r?+@ghost"
238242
);
239243

240244
drop(josh);
241245
Ok(())
242246
}
243247

244-
fn start_josh() -> anyhow::Result<impl Drop> {
248+
fn start_josh(&self) -> anyhow::Result<impl Drop> {
245249
// Determine cache directory.
246250
let local_dir = {
247251
let user_dirs =
@@ -253,7 +257,7 @@ impl GitSync {
253257
let mut cmd = process::Command::new("josh-proxy");
254258
cmd.arg("--local").arg(local_dir);
255259
cmd.arg("--remote").arg("https://github.com");
256-
cmd.arg("--port").arg(JOSH_PORT.to_string());
260+
cmd.arg("--port").arg(self.josh_port.to_string());
257261
cmd.arg("--no-background");
258262
cmd.stdout(process::Stdio::null());
259263
cmd.stderr(process::Stdio::null());
@@ -296,7 +300,7 @@ impl GitSync {
296300
for _ in 0..100 {
297301
// This will generally fail immediately when the port is still closed.
298302
let josh_ready = net::TcpStream::connect_timeout(
299-
&net::SocketAddr::from(([127, 0, 0, 1], JOSH_PORT)),
303+
&net::SocketAddr::from(([127, 0, 0, 1], self.josh_port)),
300304
Duration::from_millis(1),
301305
);
302306
if josh_ready.is_ok() {
@@ -307,4 +311,43 @@ impl GitSync {
307311
}
308312
bail!("Even after waiting for 1s, josh-proxy is still not available.")
309313
}
314+
315+
fn run(&self, prog: &str, f: impl FnOnce(&mut Command) -> &mut Command) -> String {
316+
let mut cmd = Command::new(prog);
317+
cmd.current_dir(&self.dir).stderr(Stdio::inherit());
318+
f(&mut cmd);
319+
eprintln!("+ {cmd:?}");
320+
let out = cmd.output().expect("command failed");
321+
assert!(out.status.success());
322+
String::from_utf8(out.stdout).expect("non-UTF8 output")
323+
}
324+
}
325+
326+
fn ensure_clean(sh: &Shell) -> anyhow::Result<()> {
327+
// Make sure the repo is clean.
328+
if cmd!(sh, "git status --untracked-files=no --porcelain")
329+
.read()?
330+
.is_empty()
331+
.not()
332+
{
333+
bail!("working directory must be clean before performing rustc pull");
334+
}
335+
336+
Ok(())
337+
}
338+
339+
pub enum RustcPullError {
340+
/// No changes are available to be pulled.
341+
NothingToPull,
342+
/// A rustc-pull has failed, probably a git operation error has occurred.
343+
PullFailed(anyhow::Error),
344+
}
345+
346+
impl<E> From<E> for RustcPullError
347+
where
348+
E: Into<anyhow::Error>,
349+
{
350+
fn from(error: E) -> Self {
351+
Self::PullFailed(error.into())
352+
}
310353
}

0 commit comments

Comments
 (0)