Skip to content

Commit e3450ad

Browse files
committed
Fix bootstrap issue with git on MSYS
src/bootstrap runs git to find the root of the repository, but this can go awry when building in MSYS for the mingw target. This is because MSYS git returns a unix-y path, but bootstrap requires a Windows-y path.
1 parent 8ace7ea commit e3450ad

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

src/bootstrap/src/core/config/config.rs

+20-11
Original file line numberDiff line numberDiff line change
@@ -1227,37 +1227,46 @@ impl Config {
12271227
// Infer the rest of the configuration.
12281228

12291229
// Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,
1230-
// running on a completely machine from where it was compiled.
1230+
// running on a completely different machine from where it was compiled.
12311231
let mut cmd = Command::new("git");
1232-
// NOTE: we cannot support running from outside the repository because the only path we have available
1233-
// is set at compile time, which can be wrong if bootstrap was downloaded from source.
1232+
// NOTE: we cannot support running from outside the repository because the only other path we have available
1233+
// is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally.
12341234
// We still support running outside the repository if we find we aren't in a git directory.
1235-
cmd.arg("rev-parse").arg("--show-toplevel");
1235+
1236+
// NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path,
1237+
// and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap
1238+
// has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path.
1239+
cmd.arg("rev-parse").arg("--show-cdup");
12361240
// Discard stderr because we expect this to fail when building from a tarball.
12371241
let output = cmd
12381242
.stderr(std::process::Stdio::null())
12391243
.output()
12401244
.ok()
12411245
.and_then(|output| if output.status.success() { Some(output) } else { None });
12421246
if let Some(output) = output {
1243-
let git_root = String::from_utf8(output.stdout).unwrap();
1244-
// We need to canonicalize this path to make sure it uses backslashes instead of forward slashes.
1245-
let git_root = PathBuf::from(git_root.trim()).canonicalize().unwrap();
1247+
let git_root_relative = String::from_utf8(output.stdout).unwrap();
1248+
// We need to canonicalize this path to make sure it uses backslashes instead of forward slashes,
1249+
// and to resolve any relative components.
1250+
let git_root = env::current_dir()
1251+
.unwrap()
1252+
.join(PathBuf::from(git_root_relative.trim()))
1253+
.canonicalize()
1254+
.unwrap();
12461255
let s = git_root.to_str().unwrap();
12471256

12481257
// Bootstrap is quite bad at handling /? in front of paths
1249-
let src = match s.strip_prefix("\\\\?\\") {
1258+
let git_root = match s.strip_prefix("\\\\?\\") {
12501259
Some(p) => PathBuf::from(p),
1251-
None => PathBuf::from(git_root),
1260+
None => git_root,
12521261
};
12531262
// If this doesn't have at least `stage0.json`, we guessed wrong. This can happen when,
12541263
// for example, the build directory is inside of another unrelated git directory.
12551264
// In that case keep the original `CARGO_MANIFEST_DIR` handling.
12561265
//
12571266
// NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
12581267
// the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
1259-
if src.join("src").join("stage0.json").exists() {
1260-
config.src = src;
1268+
if git_root.join("src").join("stage0.json").exists() {
1269+
config.src = git_root;
12611270
}
12621271
} else {
12631272
// We're building from a tarball, not git sources.

0 commit comments

Comments
 (0)