Skip to content

Commit 1df629b

Browse files
committed
refactor(source): wrap PathBuf with PathEntry
This gives us more room to store file metadata. For example, * knowing a source file is a symlink and resolving it when packaging, * providing a rich JSON output for `cargo package --list` * enriching the `.cargo-vcs-info.json` with copied/symlinked file info
1 parent 0499e31 commit 1df629b

File tree

5 files changed

+52
-16
lines changed

5 files changed

+52
-16
lines changed

src/cargo/ops/cargo_package/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::core::Workspace;
1616
use crate::core::{Package, PackageId, PackageSet, Resolve, SourceId};
1717
use crate::ops::lockfile::LOCKFILE_NAME;
1818
use crate::ops::registry::{infer_registry, RegistryOrIndex};
19+
use crate::sources::path::PathEntry;
1920
use crate::sources::registry::index::{IndexPackage, RegistryDependency};
2021
use crate::sources::{PathSource, CRATES_IO_REGISTRY};
2122
use crate::util::cache_lock::CacheLockMode;
@@ -396,7 +397,7 @@ fn prepare_archive(
396397
fn build_ar_list(
397398
ws: &Workspace<'_>,
398399
pkg: &Package,
399-
src_files: Vec<PathBuf>,
400+
src_files: Vec<PathEntry>,
400401
vcs_info: Option<vcs::VcsInfo>,
401402
) -> CargoResult<Vec<ArchiveFile>> {
402403
let mut result = HashMap::new();
@@ -420,7 +421,7 @@ fn build_ar_list(
420421
.push(ArchiveFile {
421422
rel_path: rel_path.to_owned(),
422423
rel_str: rel_str.to_owned(),
423-
contents: FileContents::OnDisk(src_file.clone()),
424+
contents: FileContents::OnDisk(src_file.to_path_buf()),
424425
});
425426
}
426427
}

src/cargo/ops/cargo_package/vcs.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use serde::Serialize;
99
use tracing::debug;
1010

1111
use crate::core::Package;
12+
use crate::sources::PathEntry;
1213
use crate::CargoResult;
1314
use crate::GlobalContext;
1415

@@ -41,7 +42,7 @@ pub struct GitVcsInfo {
4142
#[tracing::instrument(skip_all)]
4243
pub fn check_repo_state(
4344
p: &Package,
44-
src_files: &[PathBuf],
45+
src_files: &[PathEntry],
4546
gctx: &GlobalContext,
4647
opts: &PackageOpts<'_>,
4748
) -> CargoResult<Option<VcsInfo>> {
@@ -114,7 +115,7 @@ pub fn check_repo_state(
114115
fn git(
115116
pkg: &Package,
116117
gctx: &GlobalContext,
117-
src_files: &[PathBuf],
118+
src_files: &[PathEntry],
118119
repo: &git2::Repository,
119120
opts: &PackageOpts<'_>,
120121
) -> CargoResult<Option<GitVcsInfo>> {
@@ -136,6 +137,7 @@ fn git(
136137
let mut dirty_src_files: Vec<_> = src_files
137138
.iter()
138139
.filter(|src_file| dirty_files.iter().any(|path| src_file.starts_with(path)))
140+
.map(|p| p.as_ref())
139141
.chain(dirty_metadata_paths(pkg, repo)?.iter())
140142
.map(|path| {
141143
pathdiff::diff_paths(path, cwd)

src/cargo/ops/vendor.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::core::shell::Verbosity;
22
use crate::core::{GitReference, Package, Workspace};
33
use crate::ops;
44
use crate::sources::path::PathSource;
5+
use crate::sources::PathEntry;
56
use crate::sources::CRATES_IO_REGISTRY;
67
use crate::util::cache_lock::CacheLockMode;
78
use crate::util::{try_canonicalize, CargoResult, GlobalContext};
@@ -315,13 +316,14 @@ fn sync(
315316
fn cp_sources(
316317
pkg: &Package,
317318
src: &Path,
318-
paths: &[PathBuf],
319+
paths: &[PathEntry],
319320
dst: &Path,
320321
cksums: &mut BTreeMap<String, String>,
321322
tmp_buf: &mut [u8],
322323
gctx: &GlobalContext,
323324
) -> CargoResult<()> {
324325
for p in paths {
326+
let p = p.as_ref();
325327
let relative = p.strip_prefix(&src).unwrap();
326328

327329
match relative.to_str() {

src/cargo/sources/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
pub use self::config::SourceConfigMap;
3030
pub use self::directory::DirectorySource;
3131
pub use self::git::GitSource;
32+
pub use self::path::PathEntry;
3233
pub use self::path::PathSource;
3334
pub use self::path::RecursivePathSource;
3435
pub use self::registry::{

src/cargo/sources/path.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl<'gctx> PathSource<'gctx> {
9494
/// use other methods like `.gitignore`, `package.include`, or
9595
/// `package.exclude` to filter the list of files.
9696
#[tracing::instrument(skip_all)]
97-
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathBuf>> {
97+
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathEntry>> {
9898
list_files(pkg, self.gctx)
9999
}
100100

@@ -278,7 +278,7 @@ impl<'gctx> RecursivePathSource<'gctx> {
278278
/// are relevant for building this package, but it also contains logic to
279279
/// use other methods like `.gitignore`, `package.include`, or
280280
/// `package.exclude` to filter the list of files.
281-
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathBuf>> {
281+
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathEntry>> {
282282
list_files(pkg, self.gctx)
283283
}
284284

@@ -404,6 +404,32 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
404404
}
405405
}
406406

407+
/// [`PathBuf`] with extra metadata.
408+
#[derive(Clone, Debug)]
409+
pub struct PathEntry {
410+
path: PathBuf,
411+
}
412+
413+
impl PathEntry {
414+
pub fn into_path_buf(self) -> PathBuf {
415+
self.path
416+
}
417+
}
418+
419+
impl std::ops::Deref for PathEntry {
420+
type Target = Path;
421+
422+
fn deref(&self) -> &Self::Target {
423+
self.path.as_path()
424+
}
425+
}
426+
427+
impl AsRef<PathBuf> for PathEntry {
428+
fn as_ref(&self) -> &PathBuf {
429+
&self.path
430+
}
431+
}
432+
407433
fn first_package<'p>(
408434
pkg_id: PackageId,
409435
pkgs: &'p Vec<Package>,
@@ -446,7 +472,7 @@ fn first_package<'p>(
446472
/// are relevant for building this package, but it also contains logic to
447473
/// use other methods like `.gitignore`, `package.include`, or
448474
/// `package.exclude` to filter the list of files.
449-
pub fn list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathBuf>> {
475+
pub fn list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathEntry>> {
450476
_list_files(pkg, gctx).with_context(|| {
451477
format!(
452478
"failed to determine list of files in {}",
@@ -456,7 +482,7 @@ pub fn list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathBu
456482
}
457483

458484
/// See [`PathSource::list_files`].
459-
fn _list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathBuf>> {
485+
fn _list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathEntry>> {
460486
let root = pkg.root();
461487
let no_include_option = pkg.manifest().include().is_empty();
462488
let git_repo = if no_include_option {
@@ -580,7 +606,7 @@ fn list_files_gix(
580606
repo: &gix::Repository,
581607
filter: &dyn Fn(&Path, bool) -> bool,
582608
gctx: &GlobalContext,
583-
) -> CargoResult<Vec<PathBuf>> {
609+
) -> CargoResult<Vec<PathEntry>> {
584610
debug!("list_files_gix {}", pkg.package_id());
585611
let options = repo
586612
.dirwalk_options()?
@@ -619,7 +645,7 @@ fn list_files_gix(
619645
vec![include, exclude]
620646
};
621647

622-
let mut files = Vec::<PathBuf>::new();
648+
let mut files = Vec::<PathEntry>::new();
623649
let mut subpackages_found = Vec::new();
624650
for item in repo
625651
.dirwalk_iter(index.clone(), pathspec, Default::default(), options)?
@@ -701,7 +727,7 @@ fn list_files_gix(
701727
} else if (filter)(&file_path, is_dir) {
702728
assert!(!is_dir);
703729
trace!(" found {}", file_path.display());
704-
files.push(file_path);
730+
files.push(PathEntry { path: file_path });
705731
}
706732
}
707733

@@ -715,7 +741,7 @@ fn list_files_gix(
715741
/// is not tracked under a Git repository.
716742
fn list_files_walk(
717743
path: &Path,
718-
ret: &mut Vec<PathBuf>,
744+
ret: &mut Vec<PathEntry>,
719745
is_root: bool,
720746
filter: &dyn Fn(&Path, bool) -> bool,
721747
gctx: &GlobalContext,
@@ -756,7 +782,9 @@ fn list_files_walk(
756782
Ok(entry) => {
757783
let file_type = entry.file_type();
758784
if file_type.is_file() || file_type.is_symlink() {
759-
ret.push(entry.into_path());
785+
ret.push(PathEntry {
786+
path: entry.into_path(),
787+
});
760788
}
761789
}
762790
Err(err) if err.loop_ancestor().is_some() => {
@@ -770,7 +798,9 @@ fn list_files_walk(
770798
// Otherwise, simply recover from it.
771799
// Don't worry about error skipping here, the callers would
772800
// still hit the IO error if they do access it thereafter.
773-
Some(path) => ret.push(path.to_path_buf()),
801+
Some(path) => ret.push(PathEntry {
802+
path: path.to_path_buf(),
803+
}),
774804
None => return Err(err.into()),
775805
},
776806
}
@@ -801,7 +831,7 @@ fn last_modified_file(
801831
let mtime = paths::mtime(&file).unwrap_or_else(|_| FileTime::zero());
802832
if mtime > max {
803833
max = mtime;
804-
max_path = file;
834+
max_path = file.into_path_buf();
805835
}
806836
}
807837
trace!("last modified file {}: {}", path.display(), max);

0 commit comments

Comments
 (0)