Skip to content

Commit 956a98c

Browse files
author
Vurich
committed
Allow cargo-clippy to work in subdirectories
1 parent 6a2525c commit 956a98c

File tree

1 file changed

+41
-15
lines changed

1 file changed

+41
-15
lines changed

src/main.rs

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ fn show_version() {
158158
println!("{}", env!("CARGO_PKG_VERSION"));
159159
}
160160

161+
fn has_prefix<'a, T: PartialEq, I: Iterator<Item = &'a T>>(v: &'a [T], itr: I) -> bool {
162+
v.iter().zip(itr).all(|(a, b)| a == b)
163+
}
164+
161165
pub fn main() {
162166
use std::env;
163167

@@ -192,26 +196,48 @@ pub fn main() {
192196

193197
let manifest_path = manifest_path_arg.map(|arg| PathBuf::from(Path::new(&arg["--manifest-path=".len()..])));
194198

195-
let current_dir = std::env::current_dir();
199+
let package_index = {
200+
let mut iterator = metadata.packages.iter();
196201

197-
let package_index = metadata
198-
.packages
199-
.iter()
200-
.position(|package| {
201-
let package_manifest_path = Path::new(&package.manifest_path);
202202
if let Some(ref manifest_path) = manifest_path {
203-
package_manifest_path == manifest_path
203+
iterator.position(|package| {
204+
let package_manifest_path = Path::new(&package.manifest_path);
205+
package_manifest_path == manifest_path
206+
})
204207
} else {
205-
let current_dir = current_dir
206-
.as_ref()
207-
.expect("could not read current directory");
208-
let package_manifest_directory = package_manifest_path
209-
.parent()
210-
.expect("could not find parent directory of package manifest");
211-
package_manifest_directory == current_dir
208+
let current_dir = std::env::current_dir()
209+
.expect("could not read current directory")
210+
.canonicalize()
211+
.expect("current directory cannot be canonicalized");
212+
let current_dir_components = current_dir.components().collect::<Vec<_>>();
213+
214+
// This gets the most-recent parent (the one that takes the fewest `cd ..`s to
215+
// reach).
216+
iterator
217+
.enumerate()
218+
.filter_map(|(i, package)| {
219+
let package_manifest_path = Path::new(&package.manifest_path);
220+
let canonical_path = package_manifest_path
221+
.parent()
222+
.expect("could not find parent directory of package manifest")
223+
.canonicalize()
224+
.expect("package directory cannot be canonicalized");
225+
226+
// TODO: We can do this in `O(1)` by combining the `len` and the
227+
// iteration.
228+
let components = canonical_path.components().collect::<Vec<_>>();
229+
if has_prefix(&current_dir_components, components.iter()) {
230+
Some((i, components.len()))
231+
} else {
232+
None
233+
}
234+
})
235+
.max_by_key(|&(_, length)| length)
236+
.map(|(i, _)| i)
212237
}
213-
})
238+
}
214239
.expect("could not find matching package");
240+
215241
let package = metadata.packages.remove(package_index);
216242
for target in package.targets {
217243
let args = std::env::args().skip(2);

0 commit comments

Comments
 (0)