Skip to content

Commit 4e8c599

Browse files
committed
fix(build.rs): ensure detected git repo root is ours
We don't want to find the dotfile repo in my home directory when doing 'cargo install gloam' for example. Signed-off-by: Steven Noonan <steven@uplinklabs.net>
1 parent 9d5de22 commit 4e8c599

1 file changed

Lines changed: 28 additions & 21 deletions

File tree

build.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,32 +45,39 @@ fn git_ok(repo_dir: &Path, args: &[&str]) -> Option<bool> {
4545
/// Find the git repo root for the crate being built.
4646
///
4747
/// Uses `git rev-parse --show-toplevel` from CARGO_MANIFEST_DIR, which
48-
/// lets git itself determine whether we're inside a repo. This avoids
49-
/// the problem of manually walking up the directory tree and accidentally
50-
/// finding an unrelated `.git` in a parent directory (e.g. when
51-
/// `cargo install` extracts into `~/.cargo/registry/src/` and some
52-
/// ancestor has a `.git`).
48+
/// lets git itself determine whether we're inside a repo.
5349
///
54-
/// Returns None if git isn't installed, we're not in a repo (crates.io
55-
/// tarball), or the detected repo root isn't an ancestor of our manifest
56-
/// directory (sanity check).
50+
/// Returns None if:
51+
/// - git isn't installed
52+
/// - we're not in a repo (crates.io tarball)
53+
/// - the detected repo root is an unrelated repo (e.g. the user's home
54+
/// directory under dotfiles management, which contains the cargo
55+
/// registry extraction path)
56+
///
57+
/// The "is this our repo?" check verifies that the repo root contains a
58+
/// Cargo.toml with our package name. This is more robust than a simple
59+
/// `starts_with` ancestor check, which passes when `cargo install` extracts
60+
/// into `~/.cargo/registry/src/` inside a home-directory git repo.
5761
fn find_repo_root(manifest_dir: &Path) -> Option<PathBuf> {
5862
let toplevel = git(manifest_dir, &["rev-parse", "--show-toplevel"])?;
5963
let root = PathBuf::from(&toplevel);
6064

61-
// Sanity check: the manifest dir must be inside the detected repo.
62-
// This guards against pathological setups where a completely unrelated
63-
// git repo contains our extraction directory.
64-
let canonical_root = root.canonicalize().unwrap_or_else(|_| root.clone());
65-
let canonical_manifest = manifest_dir
66-
.canonicalize()
67-
.unwrap_or_else(|_| manifest_dir.to_path_buf());
68-
if !canonical_manifest.starts_with(&canonical_root) {
69-
println!(
70-
"cargo:warning=build.rs: git toplevel {:?} is not an ancestor of manifest dir {:?}, ignoring",
71-
canonical_root, canonical_manifest
72-
);
73-
return None;
65+
// The repo root must contain a Cargo.toml that declares our package.
66+
// This rejects unrelated repos that happen to be ancestors of the
67+
// extraction directory (e.g. dotfiles repos tracking ~/).
68+
let cargo_toml = root.join("Cargo.toml");
69+
let pkg_name = env::var("CARGO_PKG_NAME").unwrap_or_default();
70+
match fs::read_to_string(&cargo_toml) {
71+
Ok(contents) => {
72+
// Look for `name = "gloam"` (or whatever CARGO_PKG_NAME is).
73+
// A simple string search is sufficient — we're not trying to
74+
// parse TOML, just confirm this is plausibly our repo.
75+
let needle = format!("name = \"{pkg_name}\"");
76+
if !contents.contains(&needle) {
77+
return None;
78+
}
79+
}
80+
Err(_) => return None,
7481
}
7582

7683
Some(root)

0 commit comments

Comments
 (0)