Skip to content

Commit cf38b96

Browse files
committed
Auto merge of #14231 - epage:git-clean, r=Muscraft
refactor(source): More RecursivePathSource clean up ### What does this PR try to resolve? This is a follow up to #13993 and #14169 and is part of my work towards #10752. ### How should we test and review this PR? ### Additional information
2 parents 8519ad2 + 848dd7f commit cf38b96

File tree

3 files changed

+264
-279
lines changed

3 files changed

+264
-279
lines changed

src/cargo/ops/cargo_read_manifest.rs

Lines changed: 3 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
use std::collections::{HashMap, HashSet};
2-
use std::fs;
3-
use std::io;
4-
use std::path::{Path, PathBuf};
1+
use std::path::Path;
52

6-
use crate::core::{EitherManifest, Manifest, Package, PackageId, SourceId};
3+
use crate::core::{EitherManifest, Package, SourceId};
74
use crate::util::errors::CargoResult;
8-
use crate::util::important_paths::find_project_manifest_exact;
95
use crate::util::toml::read_manifest;
106
use crate::util::GlobalContext;
11-
use cargo_util::paths;
12-
use tracing::{info, trace};
7+
use tracing::trace;
138

149
pub fn read_package(
1510
path: &Path,
@@ -33,242 +28,3 @@ pub fn read_package(
3328

3429
Ok(Package::new(manifest, path))
3530
}
36-
37-
#[tracing::instrument(skip(source_id, gctx))]
38-
pub fn read_packages(
39-
path: &Path,
40-
source_id: SourceId,
41-
gctx: &GlobalContext,
42-
) -> CargoResult<Vec<Package>> {
43-
let mut all_packages = HashMap::new();
44-
let mut visited = HashSet::<PathBuf>::new();
45-
let mut errors = Vec::<anyhow::Error>::new();
46-
47-
trace!(
48-
"looking for root package: {}, source_id={}",
49-
path.display(),
50-
source_id
51-
);
52-
53-
walk(path, &mut |dir| {
54-
trace!("looking for child package: {}", dir.display());
55-
56-
// Don't recurse into hidden/dot directories unless we're at the toplevel
57-
if dir != path {
58-
let name = dir.file_name().and_then(|s| s.to_str());
59-
if name.map(|s| s.starts_with('.')) == Some(true) {
60-
return Ok(false);
61-
}
62-
63-
// Don't automatically discover packages across git submodules
64-
if dir.join(".git").exists() {
65-
return Ok(false);
66-
}
67-
}
68-
69-
// Don't ever look at target directories
70-
if dir.file_name().and_then(|s| s.to_str()) == Some("target")
71-
&& has_manifest(dir.parent().unwrap())
72-
{
73-
return Ok(false);
74-
}
75-
76-
if has_manifest(dir) {
77-
read_nested_packages(
78-
dir,
79-
&mut all_packages,
80-
source_id,
81-
gctx,
82-
&mut visited,
83-
&mut errors,
84-
)?;
85-
}
86-
Ok(true)
87-
})?;
88-
89-
if all_packages.is_empty() {
90-
match errors.pop() {
91-
Some(err) => Err(err),
92-
None => {
93-
if find_project_manifest_exact(path, "cargo.toml").is_ok() {
94-
Err(anyhow::format_err!(
95-
"Could not find Cargo.toml in `{}`, but found cargo.toml please try to rename it to Cargo.toml",
96-
path.display()
97-
))
98-
} else {
99-
Err(anyhow::format_err!(
100-
"Could not find Cargo.toml in `{}`",
101-
path.display()
102-
))
103-
}
104-
}
105-
}
106-
} else {
107-
Ok(all_packages.into_iter().map(|(_, v)| v).collect())
108-
}
109-
}
110-
111-
fn nested_paths(manifest: &Manifest) -> Vec<PathBuf> {
112-
let mut nested_paths = Vec::new();
113-
let resolved = manifest.resolved_toml();
114-
let dependencies = resolved
115-
.dependencies
116-
.iter()
117-
.chain(resolved.build_dependencies())
118-
.chain(resolved.dev_dependencies())
119-
.chain(
120-
resolved
121-
.target
122-
.as_ref()
123-
.into_iter()
124-
.flat_map(|t| t.values())
125-
.flat_map(|t| {
126-
t.dependencies
127-
.iter()
128-
.chain(t.build_dependencies())
129-
.chain(t.dev_dependencies())
130-
}),
131-
);
132-
for dep_table in dependencies {
133-
for dep in dep_table.values() {
134-
let cargo_util_schemas::manifest::InheritableDependency::Value(dep) = dep else {
135-
continue;
136-
};
137-
let cargo_util_schemas::manifest::TomlDependency::Detailed(dep) = dep else {
138-
continue;
139-
};
140-
let Some(path) = dep.path.as_ref() else {
141-
continue;
142-
};
143-
nested_paths.push(PathBuf::from(path.as_str()));
144-
}
145-
}
146-
nested_paths
147-
}
148-
149-
fn walk(path: &Path, callback: &mut dyn FnMut(&Path) -> CargoResult<bool>) -> CargoResult<()> {
150-
if !callback(path)? {
151-
trace!("not processing {}", path.display());
152-
return Ok(());
153-
}
154-
155-
// Ignore any permission denied errors because temporary directories
156-
// can often have some weird permissions on them.
157-
let dirs = match fs::read_dir(path) {
158-
Ok(dirs) => dirs,
159-
Err(ref e) if e.kind() == io::ErrorKind::PermissionDenied => return Ok(()),
160-
Err(e) => {
161-
let cx = format!("failed to read directory `{}`", path.display());
162-
let e = anyhow::Error::from(e);
163-
return Err(e.context(cx));
164-
}
165-
};
166-
for dir in dirs {
167-
let dir = dir?;
168-
if dir.file_type()?.is_dir() {
169-
walk(&dir.path(), callback)?;
170-
}
171-
}
172-
Ok(())
173-
}
174-
175-
fn has_manifest(path: &Path) -> bool {
176-
find_project_manifest_exact(path, "Cargo.toml").is_ok()
177-
}
178-
179-
fn read_nested_packages(
180-
path: &Path,
181-
all_packages: &mut HashMap<PackageId, Package>,
182-
source_id: SourceId,
183-
gctx: &GlobalContext,
184-
visited: &mut HashSet<PathBuf>,
185-
errors: &mut Vec<anyhow::Error>,
186-
) -> CargoResult<()> {
187-
if !visited.insert(path.to_path_buf()) {
188-
return Ok(());
189-
}
190-
191-
let manifest_path = find_project_manifest_exact(path, "Cargo.toml")?;
192-
193-
let manifest = match read_manifest(&manifest_path, source_id, gctx) {
194-
Err(err) => {
195-
// Ignore malformed manifests found on git repositories
196-
//
197-
// git source try to find and read all manifests from the repository
198-
// but since it's not possible to exclude folders from this search
199-
// it's safer to ignore malformed manifests to avoid
200-
//
201-
// TODO: Add a way to exclude folders?
202-
info!(
203-
"skipping malformed package found at `{}`",
204-
path.to_string_lossy()
205-
);
206-
errors.push(err.into());
207-
return Ok(());
208-
}
209-
Ok(tuple) => tuple,
210-
};
211-
212-
let manifest = match manifest {
213-
EitherManifest::Real(manifest) => manifest,
214-
EitherManifest::Virtual(..) => return Ok(()),
215-
};
216-
let nested = nested_paths(&manifest);
217-
let pkg = Package::new(manifest, &manifest_path);
218-
219-
let pkg_id = pkg.package_id();
220-
use std::collections::hash_map::Entry;
221-
match all_packages.entry(pkg_id) {
222-
Entry::Vacant(v) => {
223-
v.insert(pkg);
224-
}
225-
Entry::Occupied(_) => {
226-
// We can assume a package with publish = false isn't intended to be seen
227-
// by users so we can hide the warning about those since the user is unlikely
228-
// to care about those cases.
229-
if pkg.publish().is_none() {
230-
let _ = gctx.shell().warn(format!(
231-
"skipping duplicate package `{}` found at `{}`",
232-
pkg.name(),
233-
path.display()
234-
));
235-
}
236-
}
237-
}
238-
239-
// Registry sources are not allowed to have `path=` dependencies because
240-
// they're all translated to actual registry dependencies.
241-
//
242-
// We normalize the path here ensure that we don't infinitely walk around
243-
// looking for crates. By normalizing we ensure that we visit this crate at
244-
// most once.
245-
//
246-
// TODO: filesystem/symlink implications?
247-
if !source_id.is_registry() {
248-
for p in nested.iter() {
249-
let path = paths::normalize_path(&path.join(p));
250-
let result =
251-
read_nested_packages(&path, all_packages, source_id, gctx, visited, errors);
252-
// Ignore broken manifests found on git repositories.
253-
//
254-
// A well formed manifest might still fail to load due to reasons
255-
// like referring to a "path" that requires an extra build step.
256-
//
257-
// See https://github.com/rust-lang/cargo/issues/6822.
258-
if let Err(err) = result {
259-
if source_id.is_git() {
260-
info!(
261-
"skipping nested package found at `{}`: {:?}",
262-
path.display(),
263-
&err,
264-
);
265-
errors.push(err);
266-
} else {
267-
return Err(err);
268-
}
269-
}
270-
}
271-
}
272-
273-
Ok(())
274-
}

src/cargo/ops/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub use self::cargo_new::{init, new, NewOptions, NewProjectKind, VersionControl}
1212
pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions};
1313
pub use self::cargo_package::{check_yanked, package, package_one, PackageOpts};
1414
pub use self::cargo_pkgid::pkgid;
15-
pub use self::cargo_read_manifest::{read_package, read_packages};
15+
pub use self::cargo_read_manifest::read_package;
1616
pub use self::cargo_run::run;
1717
pub use self::cargo_test::{run_benches, run_tests, TestOptions};
1818
pub use self::cargo_uninstall::uninstall;

0 commit comments

Comments
 (0)