mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
feat: glob support for target selection
This commit is contained in:
parent
be31989a43
commit
42696ae234
@ -41,8 +41,11 @@ use crate::core::{PackageId, PackageIdSpec, TargetKind, Workspace};
|
|||||||
use crate::ops;
|
use crate::ops;
|
||||||
use crate::ops::resolve::WorkspaceResolve;
|
use crate::ops::resolve::WorkspaceResolve;
|
||||||
use crate::util::config::Config;
|
use crate::util::config::Config;
|
||||||
|
use crate::util::restricted_names::is_glob_pattern;
|
||||||
use crate::util::{closest_msg, profile, CargoResult, StableHasher};
|
use crate::util::{closest_msg, profile, CargoResult, StableHasher};
|
||||||
|
|
||||||
|
use anyhow::Context as _;
|
||||||
|
|
||||||
/// Contains information about how a package should be compiled.
|
/// Contains information about how a package should be compiled.
|
||||||
///
|
///
|
||||||
/// Note on distinction between `CompileOptions` and `BuildConfig`:
|
/// Note on distinction between `CompileOptions` and `BuildConfig`:
|
||||||
@ -577,6 +580,13 @@ impl FilterRule {
|
|||||||
FilterRule::Just(ref targets) => Some(targets.clone()),
|
FilterRule::Just(ref targets) => Some(targets.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn contains_glob_patterns(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
FilterRule::All => false,
|
||||||
|
FilterRule::Just(targets) => targets.iter().any(is_glob_pattern),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileFilter {
|
impl CompileFilter {
|
||||||
@ -706,6 +716,24 @@ impl CompileFilter {
|
|||||||
CompileFilter::Only { .. } => true,
|
CompileFilter::Only { .. } => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn contains_glob_patterns(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CompileFilter::Default { .. } => false,
|
||||||
|
CompileFilter::Only {
|
||||||
|
bins,
|
||||||
|
examples,
|
||||||
|
tests,
|
||||||
|
benches,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
bins.contains_glob_patterns()
|
||||||
|
|| examples.contains_glob_patterns()
|
||||||
|
|| tests.contains_glob_patterns()
|
||||||
|
|| benches.contains_glob_patterns()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A proposed target.
|
/// A proposed target.
|
||||||
@ -1163,8 +1191,16 @@ fn find_named_targets<'a>(
|
|||||||
is_expected_kind: fn(&Target) -> bool,
|
is_expected_kind: fn(&Target) -> bool,
|
||||||
mode: CompileMode,
|
mode: CompileMode,
|
||||||
) -> CargoResult<Vec<Proposal<'a>>> {
|
) -> CargoResult<Vec<Proposal<'a>>> {
|
||||||
let filter = |t: &Target| t.name() == target_name && is_expected_kind(t);
|
let is_glob = is_glob_pattern(target_name);
|
||||||
let proposals = filter_targets(packages, filter, true, mode);
|
let proposals = if is_glob {
|
||||||
|
let pattern = build_glob(target_name)?;
|
||||||
|
let filter = |t: &Target| is_expected_kind(t) && pattern.matches(t.name());
|
||||||
|
filter_targets(packages, filter, true, mode)
|
||||||
|
} else {
|
||||||
|
let filter = |t: &Target| t.name() == target_name && is_expected_kind(t);
|
||||||
|
filter_targets(packages, filter, true, mode)
|
||||||
|
};
|
||||||
|
|
||||||
if proposals.is_empty() {
|
if proposals.is_empty() {
|
||||||
let targets = packages.iter().flat_map(|pkg| {
|
let targets = packages.iter().flat_map(|pkg| {
|
||||||
pkg.targets()
|
pkg.targets()
|
||||||
@ -1173,8 +1209,9 @@ fn find_named_targets<'a>(
|
|||||||
});
|
});
|
||||||
let suggestion = closest_msg(target_name, targets, |t| t.name());
|
let suggestion = closest_msg(target_name, targets, |t| t.name());
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"no {} target named `{}`{}",
|
"no {} target {} `{}`{}",
|
||||||
target_desc,
|
target_desc,
|
||||||
|
if is_glob { "matches pattern" } else { "named" },
|
||||||
target_name,
|
target_name,
|
||||||
suggestion
|
suggestion
|
||||||
);
|
);
|
||||||
@ -1291,3 +1328,8 @@ fn traverse_and_share(
|
|||||||
new_graph.entry(new_unit.clone()).or_insert(new_deps);
|
new_graph.entry(new_unit.clone()).or_insert(new_deps);
|
||||||
new_unit
|
new_unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: @weihanglo
|
||||||
|
fn build_glob(pat: &str) -> CargoResult<glob::Pattern> {
|
||||||
|
glob::Pattern::new(pat).with_context(|| format!("Cannot build glob pattern from `{}`", pat))
|
||||||
|
}
|
||||||
|
@ -13,6 +13,10 @@ pub fn run(
|
|||||||
) -> CargoResult<()> {
|
) -> CargoResult<()> {
|
||||||
let config = ws.config();
|
let config = ws.config();
|
||||||
|
|
||||||
|
if options.filter.contains_glob_patterns() {
|
||||||
|
anyhow::bail!("`cargo run` does not support glob patterns on target selection")
|
||||||
|
}
|
||||||
|
|
||||||
// We compute the `bins` here *just for diagnosis*. The actual set of
|
// We compute the `bins` here *just for diagnosis*. The actual set of
|
||||||
// packages to be run is determined by the `ops::compile` call below.
|
// packages to be run is determined by the `ops::compile` call below.
|
||||||
let packages = options.spec.get_packages(ws)?;
|
let packages = options.spec.get_packages(ws)?;
|
||||||
|
@ -83,7 +83,7 @@ pub fn validate_package_name(name: &str, what: &str, help: &str) -> CargoResult<
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the entire path for names reserved in Windows.
|
/// Check the entire path for names reserved in Windows.
|
||||||
pub fn is_windows_reserved_path(path: &Path) -> bool {
|
pub fn is_windows_reserved_path(path: &Path) -> bool {
|
||||||
path.iter()
|
path.iter()
|
||||||
.filter_map(|component| component.to_str())
|
.filter_map(|component| component.to_str())
|
||||||
@ -92,3 +92,8 @@ pub fn is_windows_reserved_path(path: &Path) -> bool {
|
|||||||
is_windows_reserved(stem)
|
is_windows_reserved(stem)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the name contains any glob pattern wildcards.
|
||||||
|
pub fn is_glob_pattern<T: AsRef<str>>(name: T) -> bool {
|
||||||
|
name.as_ref().contains(&['*', '?', '[', ']'][..])
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user