diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index b12a72db579..b54a16d2c9b 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -796,7 +796,7 @@ fn check_repo_state( .and_then(|p| p.to_str()) .unwrap_or("") .replace("\\", "/"); - let Some(git) = git(src_files, &repo, &opts)? else { + let Some(git) = git(gctx, src_files, &repo, &opts)? else { // If the git repo lacks essensial field like `sha1`, and since this field exists from the beginning, // then don't generate the corresponding file in order to maintain consistency with past behavior. return Ok(None); @@ -805,6 +805,7 @@ fn check_repo_state( return Ok(Some(VcsInfo { git, path_in_vcs })); fn git( + gctx: &GlobalContext, src_files: &[PathBuf], repo: &git2::Repository, opts: &PackageOpts<'_>, @@ -823,12 +824,13 @@ fn check_repo_state( // Find the intersection of dirty in git, and the src_files that would // be packaged. This is a lazy n^2 check, but seems fine with // thousands of files. - let workdir = repo.workdir().unwrap(); + let cwd = gctx.cwd(); let mut dirty_src_files: Vec<_> = src_files .iter() .filter(|src_file| dirty_files.iter().any(|path| src_file.starts_with(path))) .map(|path| { - path.strip_prefix(workdir) + pathdiff::diff_paths(path, cwd) + .as_ref() .unwrap_or(path) .display() .to_string() diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 75d21ffb2ce..1740de4ac77 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -1099,6 +1099,20 @@ Cargo.toml to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag +"#]]) + .run(); + + // cd to `src` and cargo report relative paths. + p.cargo("package") + .cwd(p.root().join("src")) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +../Cargo.toml + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + "#]]) .run(); }