|
1 | 1 | //! Helpers to gather the VCS information for `cargo package`.
|
2 | 2 |
|
3 | 3 | use std::collections::HashSet;
|
| 4 | +use std::path::Path; |
4 | 5 | use std::path::PathBuf;
|
5 | 6 |
|
6 | 7 | use anyhow::Context as _;
|
@@ -173,7 +174,9 @@ fn git(
|
173 | 174 | // - ignored (in case the user has an `include` directive that
|
174 | 175 | // conflicts with .gitignore).
|
175 | 176 | let mut dirty_files = Vec::new();
|
176 |
| - collect_statuses(repo, &mut dirty_files)?; |
| 177 | + let pathspec = relative_pathspec(repo, pkg.root()); |
| 178 | + collect_statuses(repo, &[pathspec.as_str()], &mut dirty_files)?; |
| 179 | + |
177 | 180 | // Include each submodule so that the error message can provide
|
178 | 181 | // specifically *which* files in a submodule are modified.
|
179 | 182 | status_submodules(repo, &mut dirty_files)?;
|
@@ -263,12 +266,18 @@ fn dirty_files_outside_pkg_root(
|
263 | 266 | }
|
264 | 267 |
|
265 | 268 | /// Helper to collect dirty statuses for a single repo.
|
266 |
| -fn collect_statuses(repo: &git2::Repository, dirty_files: &mut Vec<PathBuf>) -> CargoResult<()> { |
| 269 | +fn collect_statuses( |
| 270 | + repo: &git2::Repository, |
| 271 | + pathspecs: &[&str], |
| 272 | + dirty_files: &mut Vec<PathBuf>, |
| 273 | +) -> CargoResult<()> { |
267 | 274 | let mut status_opts = git2::StatusOptions::new();
|
268 | 275 | // Exclude submodules, as they are being handled manually by recursing
|
269 | 276 | // into each one so that details about specific files can be
|
270 | 277 | // retrieved.
|
271 |
| - status_opts |
| 278 | + pathspecs |
| 279 | + .iter() |
| 280 | + .fold(&mut status_opts, git2::StatusOptions::pathspec) |
272 | 281 | .exclude_submodules(true)
|
273 | 282 | .include_ignored(true)
|
274 | 283 | .include_untracked(true);
|
@@ -300,8 +309,16 @@ fn status_submodules(repo: &git2::Repository, dirty_files: &mut Vec<PathBuf>) ->
|
300 | 309 | // If its files are required, then the verification step should fail.
|
301 | 310 | if let Ok(sub_repo) = submodule.open() {
|
302 | 311 | status_submodules(&sub_repo, dirty_files)?;
|
303 |
| - collect_statuses(&sub_repo, dirty_files)?; |
| 312 | + collect_statuses(&sub_repo, &[], dirty_files)?; |
304 | 313 | }
|
305 | 314 | }
|
306 | 315 | Ok(())
|
307 | 316 | }
|
| 317 | + |
| 318 | +/// Use pathspec so git only matches a certain path prefix |
| 319 | +fn relative_pathspec(repo: &git2::Repository, pkg_root: &Path) -> String { |
| 320 | + let workdir = repo.workdir().unwrap(); |
| 321 | + let relpath = pkg_root.strip_prefix(workdir).unwrap_or(Path::new("")); |
| 322 | + // to unix separators |
| 323 | + relpath.to_str().unwrap().replace('\\', "/") |
| 324 | +} |
0 commit comments