Skip to content

Commit 6bd76c7

Browse files
committed
cargo miri: factor package manifest logic into separate function
1 parent 14d58ca commit 6bd76c7

File tree

2 files changed

+75
-51
lines changed

2 files changed

+75
-51
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ log = "0.4"
4242
vergen = "3"
4343

4444
[features]
45+
default = ["cargo_miri"]
4546
cargo_miri = ["cargo_metadata"]
4647
rustc_tests = []
4748

src/bin/cargo-miri.rs

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![feature(inner_deref)]
2+
13
extern crate cargo_metadata;
24

35
use std::path::{PathBuf, Path};
@@ -25,6 +27,13 @@ it to configure the resource limits
2527
available resource limits are `memory_size`, `step_limit`, `stack_limit`
2628
"#;
2729

30+
#[derive(Copy, Clone, Debug)]
31+
enum MiriCommand {
32+
Run,
33+
Test,
34+
Setup,
35+
}
36+
2837
fn show_help() {
2938
println!("{}", CARGO_MIRI_HELP);
3039
}
@@ -34,6 +43,54 @@ fn show_version() {
3443
env!("CARGO_PKG_VERSION"), env!("VERGEN_SHA_SHORT"), env!("VERGEN_COMMIT_DATE"));
3544
}
3645

46+
fn list_targets(mut args: impl Iterator<Item=String>) -> impl Iterator<Item=cargo_metadata::Target> {
47+
// We need to get the manifest, and then the metadata, to enumerate targets.
48+
let manifest_path_arg = args.find(|val| {
49+
val.starts_with("--manifest-path=")
50+
});
51+
52+
let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(
53+
manifest_path_arg.as_ref().map(AsRef::as_ref),
54+
)
55+
{
56+
metadata
57+
} else {
58+
let _ = std::io::stderr().write_fmt(format_args!(
59+
"error: Could not obtain cargo metadata."
60+
));
61+
std::process::exit(101);
62+
};
63+
64+
let manifest_path = manifest_path_arg.map(|arg| {
65+
PathBuf::from(Path::new(&arg["--manifest-path=".len()..]))
66+
});
67+
68+
let current_dir = std::env::current_dir();
69+
70+
let package_index = metadata
71+
.packages
72+
.iter()
73+
.position(|package| {
74+
let package_manifest_path = Path::new(&package.manifest_path);
75+
if let Some(ref manifest_path) = manifest_path {
76+
package_manifest_path == manifest_path
77+
} else {
78+
let current_dir = current_dir.as_ref().expect(
79+
"could not read current directory",
80+
);
81+
let package_manifest_directory = package_manifest_path.parent().expect(
82+
"could not find parent directory of package manifest",
83+
);
84+
package_manifest_directory == current_dir
85+
}
86+
})
87+
.expect("could not find matching package");
88+
let package = metadata.packages.remove(package_index);
89+
90+
// Finally we got the list of targets to build
91+
package.targets.into_iter()
92+
}
93+
3794
fn main() {
3895
// Check for version and help flags even when invoked as 'cargo-miri'
3996
if std::env::args().any(|a| a == "--help" || a == "-h") {
@@ -51,61 +108,27 @@ fn main() {
51108
// binary so that we come back in the other branch, and dispatch
52109
// the invocations to rustc and miri, respectively.
53110

54-
let test = std::env::args().nth(2).map_or(false, |text| text == "test");
55-
let skip = if test { 3 } else { 2 };
56-
57-
// We need to get the manifest, and then the metadata, to enumerate targets.
58-
let manifest_path_arg = std::env::args().skip(skip).find(|val| {
59-
val.starts_with("--manifest-path=")
60-
});
61-
62-
let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(
63-
manifest_path_arg.as_ref().map(AsRef::as_ref),
64-
)
65-
{
66-
metadata
67-
} else {
68-
let _ = std::io::stderr().write_fmt(format_args!(
69-
"error: Could not obtain cargo metadata."
70-
));
71-
std::process::exit(101);
111+
let (subcommand, skip) = match std::env::args().nth(2).deref() {
112+
Some("test") => (MiriCommand::Test, 3),
113+
Some("run") => (MiriCommand::Run, 3),
114+
Some("setup") => (MiriCommand::Setup, 3),
115+
// Default command, if there is an option or nothing
116+
Some(s) if s.starts_with("-") => (MiriCommand::Run, 2),
117+
None => (MiriCommand::Run, 2),
118+
// Unvalid command
119+
Some(s) => {
120+
eprintln!("Unknown command `{}`", s);
121+
std::process::exit(1)
122+
}
72123
};
73124

74-
let manifest_path = manifest_path_arg.map(|arg| {
75-
PathBuf::from(Path::new(&arg["--manifest-path=".len()..]))
76-
});
77-
78-
let current_dir = std::env::current_dir();
79-
80-
let package_index = metadata
81-
.packages
82-
.iter()
83-
.position(|package| {
84-
let package_manifest_path = Path::new(&package.manifest_path);
85-
if let Some(ref manifest_path) = manifest_path {
86-
package_manifest_path == manifest_path
87-
} else {
88-
let current_dir = current_dir.as_ref().expect(
89-
"could not read current directory",
90-
);
91-
let package_manifest_directory = package_manifest_path.parent().expect(
92-
"could not find parent directory of package manifest",
93-
);
94-
package_manifest_directory == current_dir
95-
}
96-
})
97-
.expect("could not find matching package");
98-
let package = metadata.packages.remove(package_index);
99-
100-
// Finally we got the metadata, iterate all targets and see for which ones
101-
// we do anything.
102-
for target in package.targets {
125+
for target in list_targets(std::env::args().skip(skip)) {
103126
let args = std::env::args().skip(skip);
104127
let kind = target.kind.get(0).expect(
105128
"badly formatted cargo metadata: target::kind is an empty array",
106129
);
107-
match (test, &kind[..]) {
108-
(true, "test") => {
130+
match (subcommand, &kind[..]) {
131+
(MiriCommand::Test, "test") => {
109132
// For test binaries we call `cargo rustc --test target -- <rustc args>`
110133
if let Err(code) = process(
111134
vec!["--test".to_string(), target.name].into_iter().chain(
@@ -116,7 +139,7 @@ fn main() {
116139
std::process::exit(code);
117140
}
118141
}
119-
(true, "lib") => {
142+
(MiriCommand::Test, "lib") => {
120143
// For libraries we call `cargo rustc -- --test <rustc args>`
121144
// Notice now that `--test` is a rustc arg rather than a cargo arg. This tells
122145
// rustc to build a test harness which calls all #[test] functions. We don't
@@ -131,7 +154,7 @@ fn main() {
131154
std::process::exit(code);
132155
}
133156
}
134-
(false, "bin") => {
157+
(MiriCommand::Run, "bin") => {
135158
// For ordinary binaries we call `cargo rustc --bin target -- <rustc args>`
136159
if let Err(code) = process(
137160
vec!["--bin".to_string(), target.name].into_iter().chain(

0 commit comments

Comments
 (0)