Skip to content

Commit f768fc8

Browse files
committed
fix checking git submodules during a commit hook
1 parent d402830 commit f768fc8

File tree

2 files changed

+42
-45
lines changed

2 files changed

+42
-45
lines changed

src/bootstrap/src/lib.rs

+29-32
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,12 @@ impl Build {
509509
if !self.config.submodules(self.rust_info()) {
510510
return;
511511
}
512+
if env::var_os("GIT_DIR").is_some() {
513+
// GIT_DIR is set when we are running inside a git invocation, e.g. in a commit hook.
514+
// Skip submodule processing as messing with the git state here can have "fun" results.
515+
// Also see the discussion in <https://github.com/rust-lang/rust/pull/126255>.
516+
return;
517+
}
512518

513519
let absolute_path = self.config.src.join(relative_path);
514520

@@ -520,34 +526,29 @@ impl Build {
520526
return;
521527
}
522528

523-
// check_submodule
524-
let checked_out_hash =
525-
output(Command::new("git").args(["rev-parse", "HEAD"]).current_dir(&absolute_path));
526-
// update_submodules
527-
let recorded = output(
528-
Command::new("git")
529-
.args(["ls-tree", "HEAD"])
530-
.arg(relative_path)
531-
.current_dir(&self.config.src),
532-
);
529+
let submodule_git = || {
530+
let mut cmd = Command::new("git");
531+
cmd.current_dir(&absolute_path);
532+
cmd
533+
};
534+
535+
// Determine commit checked out in submodule.
536+
let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"]));
537+
let checked_out_hash = checked_out_hash.trim_end();
538+
// Determine commit that the submodule *should* have.
539+
let recorded = output(self.config.git().args(["ls-tree", "HEAD"]).arg(relative_path));
533540
let actual_hash = recorded
534541
.split_whitespace()
535542
.nth(2)
536543
.unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
537544

538-
// update_submodule
539-
if actual_hash == checked_out_hash.trim_end() {
545+
if actual_hash == checked_out_hash {
540546
// already checked out
541547
return;
542548
}
543549

544550
println!("Updating submodule {}", relative_path.display());
545-
self.run(
546-
Command::new("git")
547-
.args(["submodule", "-q", "sync"])
548-
.arg(relative_path)
549-
.current_dir(&self.config.src),
550-
);
551+
self.run(self.config.git().args(["submodule", "-q", "sync"]).arg(relative_path));
551552

552553
// Try passing `--progress` to start, then run git again without if that fails.
553554
let update = |progress: bool| {
@@ -590,26 +591,22 @@ impl Build {
590591
// Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
591592
// diff-index reports the modifications through the exit status
592593
let has_local_modifications = !self.run_cmd(
593-
BootstrapCommand::from(
594-
Command::new("git")
595-
.args(["diff-index", "--quiet", "HEAD"])
596-
.current_dir(&absolute_path),
597-
)
598-
.allow_failure()
599-
.output_mode(match self.is_verbose() {
600-
true => OutputMode::PrintAll,
601-
false => OutputMode::PrintOutput,
602-
}),
594+
BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"]))
595+
.allow_failure()
596+
.output_mode(match self.is_verbose() {
597+
true => OutputMode::PrintAll,
598+
false => OutputMode::PrintOutput,
599+
}),
603600
);
604601
if has_local_modifications {
605-
self.run(Command::new("git").args(["stash", "push"]).current_dir(&absolute_path));
602+
self.run(submodule_git().args(["stash", "push"]));
606603
}
607604

608-
self.run(Command::new("git").args(["reset", "-q", "--hard"]).current_dir(&absolute_path));
609-
self.run(Command::new("git").args(["clean", "-qdfx"]).current_dir(&absolute_path));
605+
self.run(submodule_git().args(["reset", "-q", "--hard"]));
606+
self.run(submodule_git().args(["clean", "-qdfx"]));
610607

611608
if has_local_modifications {
612-
self.run(Command::new("git").args(["stash", "pop"]).current_dir(absolute_path));
609+
self.run(submodule_git().args(["stash", "pop"]));
613610
}
614611
}
615612

src/bootstrap/src/utils/channel.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,17 @@ impl GitInfo {
4242
None => return GitInfo::Absent,
4343
}
4444
}
45+
let git = || {
46+
let mut cmd = Command::new("git");
47+
cmd.current_dir(dir);
48+
// If we are running inside git (e.g. via a hook), `GIT_DIR` is set and takes precedence
49+
// over the current dir. Un-set it to make the current dir matter.
50+
cmd.env_remove("GIT_DIR");
51+
cmd
52+
};
4553

4654
// Make sure git commands work
47-
match Command::new("git").arg("rev-parse").current_dir(dir).output() {
55+
match git().arg("rev-parse").output() {
4856
Ok(ref out) if out.status.success() => {}
4957
_ => return GitInfo::Absent,
5058
}
@@ -56,18 +64,10 @@ impl GitInfo {
5664
}
5765

5866
// Ok, let's scrape some info
59-
let ver_date = output(
60-
Command::new("git")
61-
.current_dir(dir)
62-
.arg("log")
63-
.arg("-1")
64-
.arg("--date=short")
65-
.arg("--pretty=format:%cd"),
66-
);
67-
let ver_hash = output(Command::new("git").current_dir(dir).arg("rev-parse").arg("HEAD"));
68-
let short_ver_hash = output(
69-
Command::new("git").current_dir(dir).arg("rev-parse").arg("--short=9").arg("HEAD"),
70-
);
67+
let ver_date =
68+
output(git().arg("log").arg("-1").arg("--date=short").arg("--pretty=format:%cd"));
69+
let ver_hash = output(git().arg("rev-parse").arg("HEAD"));
70+
let short_ver_hash = output(git().arg("rev-parse").arg("--short=9").arg("HEAD"));
7171
GitInfo::Present(Some(Info {
7272
commit_date: ver_date.trim().to_string(),
7373
sha: ver_hash.trim().to_string(),

0 commit comments

Comments
 (0)