Merge pull request #2194 from topecongiro/use-cargo_metadata
Use cargo_metadata
This commit is contained in:
commit
3c4d260bfc
4 changed files with 249 additions and 205 deletions
92
Cargo.lock
generated
92
Cargo.lock
generated
|
|
@ -6,6 +6,60 @@ dependencies = [
|
|||
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.3.2"
|
||||
source = "git+https://github.com/topecongiro/cargo_metadata#1f5bbc43efdad3dfc1d622174b976982cf1f8bf8"
|
||||
dependencies = [
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-new"
|
||||
version = "0.5.0"
|
||||
|
|
@ -34,6 +88,14 @@ dependencies = [
|
|||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.15"
|
||||
|
|
@ -103,10 +165,16 @@ name = "regex-syntax"
|
|||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustfmt-nightly"
|
||||
version = "0.2.16"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.3.2 (git+https://github.com/topecongiro/cargo_metadata)",
|
||||
"derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -125,6 +193,20 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.21"
|
||||
|
|
@ -252,10 +334,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
|
||||
"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum cargo_metadata 0.3.2 (git+https://github.com/topecongiro/cargo_metadata)" = "<none>"
|
||||
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba"
|
||||
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9"
|
||||
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
|
|
@ -267,6 +356,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
|
||||
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
|
||||
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
|
||||
"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e"
|
||||
"checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788"
|
||||
"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ log = "0.3"
|
|||
env_logger = "0.4"
|
||||
getopts = "0.2"
|
||||
derive-new = "0.5"
|
||||
cargo_metadata = { git = "https://github.com/topecongiro/cargo_metadata" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2.11"
|
||||
|
|
|
|||
|
|
@ -13,19 +13,21 @@
|
|||
#![cfg(not(test))]
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate cargo_metadata;
|
||||
extern crate getopts;
|
||||
extern crate serde_json as json;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::io::{self, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, ExitStatus};
|
||||
use std::str;
|
||||
use std::collections::HashSet;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use getopts::{Matches, Options};
|
||||
use json::Value;
|
||||
|
||||
fn main() {
|
||||
let exit_status = execute();
|
||||
|
|
@ -50,13 +52,16 @@ fn execute() -> i32 {
|
|||
opts.optflag("", "all", "format all packages (only usable in workspaces)");
|
||||
|
||||
// If there is any invalid argument passed to `cargo fmt`, return without formatting.
|
||||
if let Some(arg) = env::args()
|
||||
.skip(2)
|
||||
.take_while(|a| a != "--")
|
||||
.find(|a| !a.starts_with('-'))
|
||||
{
|
||||
print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
|
||||
return failure;
|
||||
let mut is_package_arg = false;
|
||||
for arg in env::args().skip(2).take_while(|a| a != "--") {
|
||||
if arg.starts_with("-") {
|
||||
is_package_arg = arg.starts_with("--package");
|
||||
} else if !is_package_arg {
|
||||
print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
|
||||
return failure;
|
||||
} else {
|
||||
is_package_arg = false;
|
||||
}
|
||||
}
|
||||
|
||||
let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
|
||||
|
|
@ -82,9 +87,9 @@ fn execute() -> i32 {
|
|||
return success;
|
||||
}
|
||||
|
||||
let workspace_hitlist = WorkspaceHitlist::from_matches(&matches);
|
||||
let strategy = CargoFmtStrategy::from_matches(&matches);
|
||||
|
||||
match format_crate(verbosity, &workspace_hitlist) {
|
||||
match format_crate(verbosity, &strategy) {
|
||||
Err(e) => {
|
||||
print_usage_to_stderr(&opts, &e.to_string());
|
||||
failure
|
||||
|
|
@ -125,17 +130,16 @@ pub enum Verbosity {
|
|||
|
||||
fn format_crate(
|
||||
verbosity: Verbosity,
|
||||
workspace_hitlist: &WorkspaceHitlist,
|
||||
strategy: &CargoFmtStrategy,
|
||||
) -> Result<ExitStatus, io::Error> {
|
||||
let targets = get_targets(workspace_hitlist)?;
|
||||
let targets = get_targets(strategy)?;
|
||||
|
||||
// Currently only bin and lib files get formatted
|
||||
let files: Vec<_> = targets
|
||||
.into_iter()
|
||||
.filter(|t| t.kind.should_format())
|
||||
.inspect(|t| {
|
||||
if verbosity == Verbosity::Verbose {
|
||||
println!("[{:?}] {:?}", t.kind, t.path)
|
||||
println!("[{}] {:?}", t.kind, t.path)
|
||||
}
|
||||
})
|
||||
.map(|t| t.path)
|
||||
|
|
@ -149,223 +153,157 @@ fn get_fmt_args() -> Vec<String> {
|
|||
env::args().skip_while(|a| a != "--").skip(1).collect()
|
||||
}
|
||||
|
||||
/// Target uses a `path` field for equality and hashing.
|
||||
#[derive(Debug)]
|
||||
enum TargetKind {
|
||||
Lib, // dylib, staticlib, lib
|
||||
Bin, // bin
|
||||
Example, // example file
|
||||
Test, // test file
|
||||
Bench, // bench file
|
||||
CustomBuild, // build script
|
||||
ProcMacro, // a proc macro implementation
|
||||
Other, // plugin,...
|
||||
pub struct Target {
|
||||
/// A path to the main source file of the target.
|
||||
path: PathBuf,
|
||||
/// A kind of target (e.g. lib, bin, example, ...).
|
||||
kind: String,
|
||||
}
|
||||
|
||||
impl TargetKind {
|
||||
fn should_format(&self) -> bool {
|
||||
match *self {
|
||||
TargetKind::Lib
|
||||
| TargetKind::Bin
|
||||
| TargetKind::Example
|
||||
| TargetKind::Test
|
||||
| TargetKind::Bench
|
||||
| TargetKind::CustomBuild
|
||||
| TargetKind::ProcMacro => true,
|
||||
_ => false,
|
||||
impl Target {
|
||||
pub fn from_target(target: &cargo_metadata::Target) -> Self {
|
||||
let path = PathBuf::from(&target.src_path);
|
||||
let canonicalized = fs::canonicalize(&path).unwrap_or(path);
|
||||
|
||||
Target {
|
||||
path: canonicalized,
|
||||
kind: target.kind[0].clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Target {
|
||||
path: PathBuf,
|
||||
kind: TargetKind,
|
||||
impl PartialEq for Target {
|
||||
fn eq(&self, other: &Target) -> bool {
|
||||
self.path == other.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn from_json(json_val: &Value) -> Option<Self> {
|
||||
let jtarget = json_val.as_object()?;
|
||||
let path = PathBuf::from(jtarget.get("src_path")?.as_str()?);
|
||||
let kinds = jtarget.get("kind")?.as_array()?;
|
||||
let kind = match kinds[0].as_str()? {
|
||||
"bin" => TargetKind::Bin,
|
||||
"lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib,
|
||||
"test" => TargetKind::Test,
|
||||
"example" => TargetKind::Example,
|
||||
"bench" => TargetKind::Bench,
|
||||
"custom-build" => TargetKind::CustomBuild,
|
||||
"proc-macro" => TargetKind::ProcMacro,
|
||||
_ => TargetKind::Other,
|
||||
};
|
||||
impl Eq for Target {}
|
||||
|
||||
Some(Target {
|
||||
path: path,
|
||||
kind: kind,
|
||||
})
|
||||
impl Hash for Target {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.path.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum WorkspaceHitlist {
|
||||
pub enum CargoFmtStrategy {
|
||||
/// Format every packages and dependencies.
|
||||
All,
|
||||
/// Format pacakges that are specified by the command line argument.
|
||||
Some(Vec<String>),
|
||||
None,
|
||||
/// Format the root packages only.
|
||||
Root,
|
||||
}
|
||||
|
||||
impl WorkspaceHitlist {
|
||||
pub fn get_some(&self) -> Option<&[String]> {
|
||||
if let WorkspaceHitlist::Some(ref hitlist) = *self {
|
||||
Some(hitlist)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_matches(matches: &Matches) -> WorkspaceHitlist {
|
||||
impl CargoFmtStrategy {
|
||||
pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
|
||||
match (matches.opt_present("all"), matches.opt_present("p")) {
|
||||
(false, false) => WorkspaceHitlist::None,
|
||||
(true, _) => WorkspaceHitlist::All,
|
||||
(false, true) => WorkspaceHitlist::Some(matches.opt_strs("p")),
|
||||
(false, false) => CargoFmtStrategy::Root,
|
||||
(true, _) => CargoFmtStrategy::All,
|
||||
(false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cargo_metadata_from_utf8(v: &[u8]) -> Option<Value> {
|
||||
json::from_str(str::from_utf8(v).ok()?).ok()
|
||||
}
|
||||
/// Based on the specified CargoFmtStrategy, returns a set of main source files.
|
||||
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
|
||||
let mut targets = HashSet::new();
|
||||
|
||||
fn get_json_array_with<'a>(v: &'a Value, key: &str) -> Option<&'a Vec<Value>> {
|
||||
v.as_object()?.get(key)?.as_array()
|
||||
}
|
||||
|
||||
// `cargo metadata --no-deps | jq '.["packages"]'`
|
||||
fn get_packages(v: &[u8]) -> Result<Vec<Value>, io::Error> {
|
||||
let e = io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
String::from("`cargo metadata` returned json without a 'packages' key"),
|
||||
);
|
||||
match get_cargo_metadata_from_utf8(v) {
|
||||
Some(ref json_obj) => get_json_array_with(json_obj, "packages").cloned().ok_or(e),
|
||||
None => Err(e),
|
||||
match *strategy {
|
||||
CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
|
||||
CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
|
||||
CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_target_from_package(package: &Value) -> Option<Vec<Target>> {
|
||||
let jtargets = get_json_array_with(package, "targets")?;
|
||||
let mut targets: Vec<Target> = vec![];
|
||||
for jtarget in jtargets {
|
||||
targets.push(Target::from_json(jtarget)?);
|
||||
}
|
||||
Some(targets)
|
||||
}
|
||||
|
||||
fn filter_packages_with_hitlist(
|
||||
packages: Vec<Value>,
|
||||
workspace_hitlist: &WorkspaceHitlist,
|
||||
) -> Result<Vec<Value>, &String> {
|
||||
let some_hitlist: Option<HashSet<&String>> =
|
||||
workspace_hitlist.get_some().map(HashSet::from_iter);
|
||||
if some_hitlist.is_none() {
|
||||
return Ok(packages);
|
||||
}
|
||||
let mut hitlist = some_hitlist.unwrap();
|
||||
let members: Vec<Value> = packages
|
||||
.into_iter()
|
||||
.filter(|member| {
|
||||
member
|
||||
.as_object()
|
||||
.and_then(|member_obj| {
|
||||
member_obj
|
||||
.get("name")
|
||||
.and_then(Value::as_str)
|
||||
.map(|member_name| {
|
||||
hitlist.take(&member_name.to_string()).is_some()
|
||||
})
|
||||
})
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.collect();
|
||||
if hitlist.is_empty() {
|
||||
Ok(members)
|
||||
} else {
|
||||
Err(hitlist.into_iter().next().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dependencies_from_package(package: &Value) -> Option<Vec<PathBuf>> {
|
||||
let jdependencies = get_json_array_with(package, "dependencies")?;
|
||||
let root_path = env::current_dir().ok()?;
|
||||
let mut dependencies: Vec<PathBuf> = vec![];
|
||||
for jdep in jdependencies {
|
||||
let jdependency = jdep.as_object()?;
|
||||
if !jdependency.get("source")?.is_null() {
|
||||
continue;
|
||||
}
|
||||
let name = jdependency.get("name")?.as_str()?;
|
||||
let mut path = root_path.clone();
|
||||
path.push(&name);
|
||||
dependencies.push(path);
|
||||
}
|
||||
Some(dependencies)
|
||||
}
|
||||
|
||||
// Returns a vector of local dependencies under this crate
|
||||
fn get_path_to_local_dependencies(packages: &[Value]) -> Vec<PathBuf> {
|
||||
let mut local_dependencies: Vec<PathBuf> = vec![];
|
||||
for package in packages {
|
||||
if let Some(mut d) = get_dependencies_from_package(package) {
|
||||
local_dependencies.append(&mut d);
|
||||
}
|
||||
}
|
||||
local_dependencies
|
||||
}
|
||||
|
||||
// Returns a vector of all compile targets of a crate
|
||||
fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result<Vec<Target>, io::Error> {
|
||||
let output = Command::new("cargo")
|
||||
.args(&["metadata", "--no-deps", "--format-version=1"])
|
||||
.output()?;
|
||||
if output.status.success() {
|
||||
let cur_dir = env::current_dir()?;
|
||||
let mut targets: Vec<Target> = vec![];
|
||||
let packages = get_packages(&output.stdout)?;
|
||||
|
||||
// If we can find any local dependencies, we will try to get targets from those as well.
|
||||
if *workspace_hitlist == WorkspaceHitlist::All {
|
||||
for path in get_path_to_local_dependencies(&packages) {
|
||||
match env::set_current_dir(path) {
|
||||
Ok(..) => match get_targets(workspace_hitlist) {
|
||||
Ok(ref mut t) => targets.append(t),
|
||||
Err(..) => continue,
|
||||
},
|
||||
Err(..) => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env::set_current_dir(cur_dir)?;
|
||||
match filter_packages_with_hitlist(packages, workspace_hitlist) {
|
||||
Ok(packages) => {
|
||||
for package in packages {
|
||||
if let Some(mut target) = extract_target_from_package(&package) {
|
||||
targets.append(&mut target);
|
||||
}
|
||||
}
|
||||
Ok(targets)
|
||||
}
|
||||
Err(package) => {
|
||||
// Mimick cargo of only outputting one <package> spec.
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("package `{}` is not a member of the workspace", package),
|
||||
))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if targets.is_empty() {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
str::from_utf8(&output.stderr).unwrap(),
|
||||
io::ErrorKind::Other,
|
||||
format!("Failed to find targets"),
|
||||
))
|
||||
} else {
|
||||
Ok(targets)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
|
||||
let metadata = get_cargo_metadata(None)?;
|
||||
|
||||
for package in metadata.packages {
|
||||
for target in package.targets {
|
||||
if target.name == package.name {
|
||||
targets.insert(Target::from_target(&target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_targets_recursive(
|
||||
manifest_path: Option<&Path>,
|
||||
mut targets: &mut HashSet<Target>,
|
||||
visited: &mut HashSet<String>,
|
||||
) -> Result<(), io::Error> {
|
||||
let metadata = get_cargo_metadata(manifest_path)?;
|
||||
|
||||
for package in metadata.packages {
|
||||
add_targets(&package.targets, &mut targets);
|
||||
|
||||
// Look for local dependencies.
|
||||
for dependency in package.dependencies {
|
||||
if dependency.source.is_some() || visited.contains(&dependency.name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut manifest_path = PathBuf::from(&package.manifest_path);
|
||||
|
||||
manifest_path.pop();
|
||||
manifest_path.push(&dependency.name);
|
||||
manifest_path.push("Cargo.toml");
|
||||
|
||||
if manifest_path.exists() {
|
||||
visited.insert(dependency.name);
|
||||
get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_targets_with_hitlist(
|
||||
hitlist: &[String],
|
||||
targets: &mut HashSet<Target>,
|
||||
) -> Result<(), io::Error> {
|
||||
let metadata = get_cargo_metadata(None)?;
|
||||
|
||||
let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);
|
||||
|
||||
for package in metadata.packages {
|
||||
for target in package.targets {
|
||||
if workspace_hitlist.remove(&target.name) {
|
||||
targets.insert(Target::from_target(&target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if workspace_hitlist.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
let package = workspace_hitlist.iter().next().unwrap();
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("package `{}` is not a member of the workspace", package),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
|
||||
for target in target_paths {
|
||||
targets.insert(Target::from_target(&target));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -379,6 +317,7 @@ fn format_files(
|
|||
} else {
|
||||
std::process::Stdio::inherit()
|
||||
};
|
||||
|
||||
if verbosity == Verbosity::Verbose {
|
||||
print!("rustfmt");
|
||||
for a in fmt_args {
|
||||
|
|
@ -389,6 +328,7 @@ fn format_files(
|
|||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
let mut command = Command::new("rustfmt")
|
||||
.stdout(stdout)
|
||||
.args(files)
|
||||
|
|
@ -401,5 +341,16 @@ fn format_files(
|
|||
),
|
||||
_ => e,
|
||||
})?;
|
||||
|
||||
command.wait()
|
||||
}
|
||||
|
||||
fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
|
||||
match cargo_metadata::metadata(manifest_path) {
|
||||
Ok(metadata) => Ok(metadata),
|
||||
Err(..) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"`cargo manifest` failed.",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ macro_rules! create_config {
|
|||
self.$i.2 = val;
|
||||
} else {
|
||||
println!("Warning: can't set some features as unstable \
|
||||
features are only available in nightly channel.");
|
||||
features are only available in nightly channel.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue