Skip to content

Commit 5bb478a

Browse files
committed
Auto merge of #4743 - SimonSapin:default-members, r=matklad
Add a workspace.default-members config that overrides implied --all Fixes #4507.
2 parents 6529d41 + 82d563b commit 5bb478a

File tree

10 files changed

+193
-43
lines changed

10 files changed

+193
-43
lines changed

Diff for: src/bin/bench.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
109109
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
110110
let ws = Workspace::new(&root, config)?;
111111

112-
let spec = Packages::from_flags(ws.is_virtual(),
113-
options.flag_all,
112+
let spec = Packages::from_flags(options.flag_all,
114113
&options.flag_exclude,
115114
&options.flag_package)?;
116115

Diff for: src/bin/build.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
100100
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
101101
let ws = Workspace::new(&root, config)?;
102102

103-
let spec = Packages::from_flags(ws.is_virtual(),
104-
options.flag_all,
103+
let spec = Packages::from_flags(options.flag_all,
105104
&options.flag_exclude,
106105
&options.flag_package)?;
107106

Diff for: src/bin/check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
106106
let root = find_root_manifest_for_wd(options.flag_manifest_path, config.cwd())?;
107107
let ws = Workspace::new(&root, config)?;
108108

109-
let spec = Packages::from_flags(ws.is_virtual(),
110-
options.flag_all,
109+
let spec = Packages::from_flags(options.flag_all,
111110
&options.flag_exclude,
112111
&options.flag_package)?;
113112

Diff for: src/bin/test.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ pub fn execute(options: Options, config: &mut Config) -> CliResult {
147147
options.flag_all_targets);
148148
}
149149

150-
let spec = Packages::from_flags(ws.is_virtual(),
151-
options.flag_all,
150+
let spec = Packages::from_flags(options.flag_all,
152151
&options.flag_exclude,
153152
&options.flag_package)?;
154153

Diff for: src/cargo/core/workspace.rs

+69-17
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ pub struct Workspace<'cfg> {
4646
// set above.
4747
members: Vec<PathBuf>,
4848

49+
// The subset of `members` that are used by the
50+
// `build`, `check`, `test`, and `bench` subcommands
51+
// when no package is selected with `--package` / `-p` and `--all`
52+
// is not used.
53+
//
54+
// This is set by the `default-members` config
55+
// in the `[workspace]` section.
56+
// When unset, this is the same as `members` for virtual workspaces
57+
// (`--all` is implied)
58+
// or only the root package for non-virtual workspaces.
59+
default_members: Vec<PathBuf>,
60+
4961
// True, if this is a temporary workspace created for the purposes of
5062
// cargo install or cargo package.
5163
is_ephemeral: bool,
@@ -90,6 +102,7 @@ pub enum WorkspaceConfig {
90102
pub struct WorkspaceRootConfig {
91103
root_dir: PathBuf,
92104
members: Option<Vec<String>>,
105+
default_members: Option<Vec<String>>,
93106
exclude: Vec<String>,
94107
}
95108

@@ -121,6 +134,7 @@ impl<'cfg> Workspace<'cfg> {
121134
root_manifest: None,
122135
target_dir: target_dir,
123136
members: Vec::new(),
137+
default_members: Vec::new(),
124138
is_ephemeral: false,
125139
require_optional_deps: true,
126140
};
@@ -157,6 +171,7 @@ impl<'cfg> Workspace<'cfg> {
157171
root_manifest: None,
158172
target_dir: None,
159173
members: Vec::new(),
174+
default_members: Vec::new(),
160175
is_ephemeral: true,
161176
require_optional_deps: require_optional_deps,
162177
};
@@ -170,6 +185,7 @@ impl<'cfg> Workspace<'cfg> {
170185
ws.config.target_dir()?
171186
};
172187
ws.members.push(ws.current_manifest.clone());
188+
ws.default_members.push(ws.current_manifest.clone());
173189
}
174190
Ok(ws)
175191
}
@@ -267,6 +283,14 @@ impl<'cfg> Workspace<'cfg> {
267283
}
268284
}
269285

286+
/// Returns an iterator over default packages in this workspace
287+
pub fn default_members<'a>(&'a self) -> Members<'a, 'cfg> {
288+
Members {
289+
ws: self,
290+
iter: self.default_members.iter(),
291+
}
292+
}
293+
270294
pub fn is_ephemeral(&self) -> bool {
271295
self.is_ephemeral
272296
}
@@ -345,23 +369,51 @@ impl<'cfg> Workspace<'cfg> {
345369
None => {
346370
debug!("find_members - only me as a member");
347371
self.members.push(self.current_manifest.clone());
372+
self.default_members.push(self.current_manifest.clone());
348373
return Ok(())
349374
}
350375
};
351376

352-
let members_paths = {
377+
let members_paths;
378+
let default_members_paths;
379+
{
353380
let root_package = self.packages.load(&root_manifest_path)?;
354381
match *root_package.workspace_config() {
355-
WorkspaceConfig::Root(ref root_config) => root_config.members_paths()?,
382+
WorkspaceConfig::Root(ref root_config) => {
383+
members_paths = root_config.members_paths(
384+
root_config.members.as_ref().unwrap_or(&vec![])
385+
)?;
386+
default_members_paths = if let Some(ref default) = root_config.default_members {
387+
Some(root_config.members_paths(default)?)
388+
} else {
389+
None
390+
}
391+
}
356392
_ => bail!("root of a workspace inferred but wasn't a root: {}",
357393
root_manifest_path.display()),
358394
}
359-
};
395+
}
360396

361397
for path in members_paths {
362398
self.find_path_deps(&path.join("Cargo.toml"), &root_manifest_path, false)?;
363399
}
364400

401+
if let Some(default) = default_members_paths {
402+
for path in default {
403+
let manifest_path = paths::normalize_path(&path.join("Cargo.toml"));
404+
if !self.members.contains(&manifest_path) {
405+
bail!("package `{}` is listed in workspace’s default-members \
406+
but is not a member.",
407+
path.display())
408+
}
409+
self.default_members.push(manifest_path)
410+
}
411+
} else if self.is_virtual() {
412+
self.default_members = self.members.clone()
413+
} else {
414+
self.default_members.push(self.current_manifest.clone())
415+
}
416+
365417
self.find_path_deps(&root_manifest_path, &root_manifest_path, false)
366418
}
367419

@@ -370,7 +422,7 @@ impl<'cfg> Workspace<'cfg> {
370422
root_manifest: &Path,
371423
is_path_dep: bool) -> CargoResult<()> {
372424
let manifest_path = paths::normalize_path(manifest_path);
373-
if self.members.iter().any(|p| p == &manifest_path) {
425+
if self.members.contains(&manifest_path) {
374426
return Ok(())
375427
}
376428
if is_path_dep
@@ -632,11 +684,13 @@ impl WorkspaceRootConfig {
632684
pub fn new(
633685
root_dir: &Path,
634686
members: &Option<Vec<String>>,
687+
default_members: &Option<Vec<String>>,
635688
exclude: &Option<Vec<String>>,
636689
) -> WorkspaceRootConfig {
637690
WorkspaceRootConfig {
638691
root_dir: root_dir.to_path_buf(),
639692
members: members.clone(),
693+
default_members: default_members.clone(),
640694
exclude: exclude.clone().unwrap_or_default(),
641695
}
642696
}
@@ -665,21 +719,19 @@ impl WorkspaceRootConfig {
665719
self.members.is_some()
666720
}
667721

668-
fn members_paths(&self) -> CargoResult<Vec<PathBuf>> {
722+
fn members_paths(&self, globs: &[String]) -> CargoResult<Vec<PathBuf>> {
669723
let mut expanded_list = Vec::new();
670724

671-
if let Some(globs) = self.members.clone() {
672-
for glob in globs {
673-
let pathbuf = self.root_dir.join(glob);
674-
let expanded_paths = Self::expand_member_path(&pathbuf)?;
675-
676-
// If glob does not find any valid paths, then put the original
677-
// path in the expanded list to maintain backwards compatibility.
678-
if expanded_paths.is_empty() {
679-
expanded_list.push(pathbuf);
680-
} else {
681-
expanded_list.extend(expanded_paths);
682-
}
725+
for glob in globs {
726+
let pathbuf = self.root_dir.join(glob);
727+
let expanded_paths = Self::expand_member_path(&pathbuf)?;
728+
729+
// If glob does not find any valid paths, then put the original
730+
// path in the expanded list to maintain backwards compatibility.
731+
if expanded_paths.is_empty() {
732+
expanded_list.push(pathbuf);
733+
} else {
734+
expanded_list.extend(expanded_paths);
683735
}
684736
}
685737

Diff for: src/cargo/ops/cargo_compile.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -106,26 +106,23 @@ pub enum MessageFormat {
106106

107107
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
108108
pub enum Packages<'a> {
109+
Default,
109110
All,
110111
OptOut(&'a [String]),
111112
Packages(&'a [String]),
112113
}
113114

114115
impl<'a> Packages<'a> {
115-
pub fn from_flags(virtual_ws: bool, all: bool, exclude: &'a [String], package: &'a [String])
116+
pub fn from_flags(all: bool, exclude: &'a [String], package: &'a [String])
116117
-> CargoResult<Self>
117118
{
118-
let all = all || (virtual_ws && package.is_empty());
119-
120-
let packages = match (all, &exclude) {
121-
(true, exclude) if exclude.is_empty() => Packages::All,
122-
(true, exclude) => Packages::OptOut(exclude),
123-
(false, exclude) if !exclude.is_empty() => bail!("--exclude can only be used together \
124-
with --all"),
125-
_ => Packages::Packages(package),
126-
};
127-
128-
Ok(packages)
119+
Ok(match (all, exclude.len(), package.len()) {
120+
(false, 0, 0) => Packages::Default,
121+
(false, 0, _) => Packages::Packages(package),
122+
(false, _, _) => bail!("--exclude can only be used together with --all"),
123+
(true, 0, _) => Packages::All,
124+
(true, _, _) => Packages::OptOut(exclude),
125+
})
129126
}
130127

131128
pub fn into_package_id_specs(self, ws: &Workspace) -> CargoResult<Vec<PackageIdSpec>> {
@@ -152,6 +149,12 @@ impl<'a> Packages<'a> {
152149
Packages::Packages(packages) => {
153150
packages.iter().map(|p| PackageIdSpec::parse(p)).collect::<CargoResult<Vec<_>>>()?
154151
}
152+
Packages::Default => {
153+
ws.default_members()
154+
.map(Package::package_id)
155+
.map(PackageIdSpec::from_package_id)
156+
.collect()
157+
}
155158
};
156159
Ok(specs)
157160
}

Diff for: src/cargo/ops/cargo_run.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ pub fn run(ws: &Workspace,
1111
let config = ws.config();
1212

1313
let pkg = match options.spec {
14-
Packages::All => unreachable!("cargo run supports single package only"),
14+
Packages::All |
15+
Packages::Default |
1516
Packages::OptOut(_) => unreachable!("cargo run supports single package only"),
1617
Packages::Packages(xs) => match xs.len() {
1718
0 => ws.current()?,

Diff for: src/cargo/util/toml/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,8 @@ pub struct TomlProject {
450450
#[derive(Debug, Deserialize, Serialize)]
451451
pub struct TomlWorkspace {
452452
members: Option<Vec<String>>,
453+
#[serde(rename = "default-members")]
454+
default_members: Option<Vec<String>>,
453455
exclude: Option<Vec<String>>,
454456
}
455457

@@ -681,7 +683,9 @@ impl TomlManifest {
681683
project.workspace.as_ref()) {
682684
(Some(config), None) => {
683685
WorkspaceConfig::Root(
684-
WorkspaceRootConfig::new(&package_root, &config.members, &config.exclude)
686+
WorkspaceRootConfig::new(
687+
&package_root, &config.members, &config.default_members, &config.exclude,
688+
)
685689
)
686690
}
687691
(None, root) => {
@@ -785,7 +789,9 @@ impl TomlManifest {
785789
let workspace_config = match me.workspace {
786790
Some(ref config) => {
787791
WorkspaceConfig::Root(
788-
WorkspaceRootConfig::new(&root, &config.members, &config.exclude)
792+
WorkspaceRootConfig::new(
793+
&root, &config.members, &config.default_members, &config.exclude,
794+
)
789795
)
790796
}
791797
None => {

Diff for: src/doc/manifest.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,19 @@ crate will be treated as a normal package, as well as a workspace. If the
520520
manifest*.
521521

522522
When working with *virtual manifests*, package-related cargo commands, like
523-
`cargo build`, won't be available anymore. But, most of such commands support
524-
the `--all` option, will execute the command for all the non-virtual manifest in
525-
the workspace.
523+
`cargo build`, default to the set of packages specified by the `default-members`
524+
configuration:
525+
526+
```toml
527+
[workspace]
528+
members = ["path/to/member1", "path/to/member2", "path/to/member3/*"]
529+
530+
# The members that commands like `cargo build` apply to by deault.
531+
# This must expand to a subset of `members`.
532+
# Optional key, defaults to the same as `members`
533+
# (as if `--all` were used on the command line).
534+
default-members = ["path/to/member2", "path/to/member3/*"]
535+
```
526536

527537
# The project layout
528538

0 commit comments

Comments
 (0)