Skip to content

Commit 43d4259

Browse files
authored
Auto merge of #2912 - matklad:move-target-dir, r=alexcrichton
Move `target_dir` to Workspace and fix #2848 Target dir is now an API of Workspace. It is still initialized eagerly, just later. I also had to errors in the config file when retrieving `verbose` and `color` config. Seems fishy, but is probably OK.
2 parents dc12479 + 886c878 commit 43d4259

File tree

9 files changed

+86
-56
lines changed

9 files changed

+86
-56
lines changed

src/cargo/core/workspace.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::slice;
66
use core::{Package, VirtualManifest, EitherManifest, SourceId};
77
use core::{PackageIdSpec, Dependency};
88
use ops;
9-
use util::{Config, CargoResult};
9+
use util::{Config, CargoResult, Filesystem};
1010
use util::paths;
1111

1212
/// The core abstraction in Cargo for working with a workspace of crates.
@@ -32,6 +32,10 @@ pub struct Workspace<'cfg> {
3232
// `current_manifest` was found on the filesystem with `[workspace]`.
3333
root_manifest: Option<PathBuf>,
3434

35+
// Shared target directory for all the packages of this workspace.
36+
// `None` if the default path of `root/target` should be used.
37+
target_dir: Option<Filesystem>,
38+
3539
// List of members in this workspace with a listing of all their manifest
3640
// paths. The packages themselves can be looked up through the `packages`
3741
// set above.
@@ -78,6 +82,8 @@ impl<'cfg> Workspace<'cfg> {
7882
/// before returning it, so `Ok` is only returned for valid workspaces.
7983
pub fn new(manifest_path: &Path, config: &'cfg Config)
8084
-> CargoResult<Workspace<'cfg>> {
85+
let target_dir = try!(config.target_dir());
86+
8187
let mut ws = Workspace {
8288
config: config,
8389
current_manifest: manifest_path.to_path_buf(),
@@ -86,6 +92,7 @@ impl<'cfg> Workspace<'cfg> {
8692
packages: HashMap::new(),
8793
},
8894
root_manifest: None,
95+
target_dir: target_dir,
8996
members: Vec::new(),
9097
};
9198
ws.root_manifest = try!(ws.find_root(manifest_path));
@@ -103,7 +110,8 @@ impl<'cfg> Workspace<'cfg> {
103110
///
104111
/// This is currently only used in niche situations like `cargo install` or
105112
/// `cargo package`.
106-
pub fn one(package: Package, config: &'cfg Config) -> Workspace<'cfg> {
113+
pub fn one(package: Package, config: &'cfg Config, target_dir: Option<Filesystem>)
114+
-> CargoResult<Workspace<'cfg>> {
107115
let mut ws = Workspace {
108116
config: config,
109117
current_manifest: package.manifest_path().to_path_buf(),
@@ -112,15 +120,21 @@ impl<'cfg> Workspace<'cfg> {
112120
packages: HashMap::new(),
113121
},
114122
root_manifest: None,
123+
target_dir: None,
115124
members: Vec::new(),
116125
};
117126
{
118127
let key = ws.current_manifest.parent().unwrap();
119128
let package = MaybePackage::Package(package);
120129
ws.packages.packages.insert(key.to_path_buf(), package);
130+
ws.target_dir = if let Some(dir) = target_dir {
131+
Some(dir)
132+
} else {
133+
try!(ws.config.target_dir())
134+
};
121135
ws.members.push(ws.current_manifest.clone());
122136
}
123-
return ws
137+
return Ok(ws)
124138
}
125139

126140
/// Returns the current package of this workspace.
@@ -155,6 +169,12 @@ impl<'cfg> Workspace<'cfg> {
155169
}.parent().unwrap()
156170
}
157171

172+
pub fn target_dir(&self) -> Filesystem {
173+
self.target_dir.clone().unwrap_or_else(|| {
174+
Filesystem::new(self.root().join("target"))
175+
})
176+
}
177+
158178
/// Returns the root [replace] section of this workspace.
159179
///
160180
/// This may be from a virtual crate or an actual crate.

src/cargo/ops/cargo_clean.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct CleanOptions<'a> {
1616

1717
/// Cleans the project from build artifacts.
1818
pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
19-
let target_dir = opts.config.target_dir(&ws);
19+
let target_dir = ws.target_dir();
2020

2121
// If we have a spec, then we need to delete some packages, otherwise, just
2222
// remove the whole target directory and be done with it!

src/cargo/ops/cargo_doc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub fn doc(ws: &Workspace,
5353
// Don't bother locking here as if this is getting deleted there's
5454
// nothing we can do about it and otherwise if it's getting overwritten
5555
// then that's also ok!
56-
let target_dir = options.compile_opts.config.target_dir(ws);
56+
let target_dir = ws.target_dir();
5757
let path = target_dir.join("doc").join(&name).join("index.html");
5858
let path = path.into_path_unlocked();
5959
if fs::metadata(&path).is_ok() {

src/cargo/ops/cargo_install.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,20 @@ pub fn install(root: Option<&str>,
7676
crates.io, or use --path or --git to \
7777
specify alternate source"))))
7878
};
79-
let ws = Workspace::one(pkg, config);
79+
80+
81+
let mut td_opt = None;
82+
let overidden_target_dir = if source_id.is_path() {
83+
None
84+
} else if let Ok(td) = TempDir::new("cargo-install") {
85+
let p = td.path().to_owned();
86+
td_opt = Some(td);
87+
Some(Filesystem::new(p))
88+
} else {
89+
Some(Filesystem::new(config.cwd().join("target-install")))
90+
};
91+
92+
let ws = try!(Workspace::one(pkg, config, overidden_target_dir));
8093
let pkg = try!(ws.current());
8194

8295
// Preflight checks to check up front whether we'll overwrite something.
@@ -89,27 +102,14 @@ pub fn install(root: Option<&str>,
89102
try!(check_overwrites(&dst, pkg, &opts.filter, &list, force));
90103
}
91104

92-
let mut td_opt = None;
93-
let target_dir = if source_id.is_path() {
94-
config.target_dir(&ws)
95-
} else {
96-
if let Ok(td) = TempDir::new("cargo-install") {
97-
let p = td.path().to_owned();
98-
td_opt = Some(td);
99-
Filesystem::new(p)
100-
} else {
101-
Filesystem::new(config.cwd().join("target-install"))
102-
}
103-
};
104-
config.set_target_dir(target_dir.clone());
105105
let compile = try!(ops::compile_ws(&ws, Some(source), opts).chain_error(|| {
106106
if let Some(td) = td_opt.take() {
107107
// preserve the temporary directory, so the user can inspect it
108108
td.into_path();
109109
}
110110

111111
human(format!("failed to compile `{}`, intermediate artifacts can be \
112-
found at `{}`", pkg, target_dir.display()))
112+
found at `{}`", pkg, ws.target_dir().display()))
113113
}));
114114
let binaries: Vec<(&str, &Path)> = try!(compile.binaries.iter().map(|bin| {
115115
let name = bin.file_name().unwrap();
@@ -224,7 +224,7 @@ pub fn install(root: Option<&str>,
224224
if !source_id.is_path() {
225225
// Don't bother grabbing a lock as we're going to blow it all away
226226
// anyway.
227-
let target_dir = target_dir.into_path_unlocked();
227+
let target_dir = ws.target_dir().into_path_unlocked();
228228
try!(fs::remove_dir_all(&target_dir));
229229
}
230230

src/cargo/ops/cargo_package.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub fn package(ws: &Workspace,
5252
}
5353

5454
let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
55-
let dir = config.target_dir(ws).join("package");
55+
let dir = ws.target_dir().join("package");
5656
let mut dst = {
5757
let tmp = format!(".{}", filename);
5858
try!(dir.open_rw(&tmp, config, "package scratch space"))
@@ -266,7 +266,7 @@ fn run_verify(ws: &Workspace, tar: &File, opts: &PackageOpts) -> CargoResult<()>
266266
let new_pkg = Package::new(new_manifest, &manifest_path);
267267

268268
// Now that we've rewritten all our path dependencies, compile it!
269-
let ws = Workspace::one(new_pkg, config);
269+
let ws = try!(Workspace::one(new_pkg, config, None));
270270
try!(ops::compile_ws(&ws, None, &ops::CompileOptions {
271271
config: config,
272272
jobs: opts.jobs,

src/cargo/ops/cargo_rustc/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl Layout {
7272
pub fn new(ws: &Workspace,
7373
triple: Option<&str>,
7474
dest: &str) -> CargoResult<Layout> {
75-
let mut path = ws.config().target_dir(ws);
75+
let mut path = ws.target_dir();
7676
// Flexible target specifications often point at filenames, so interpret
7777
// the target triple as a Path and then just use the file stem as the
7878
// component for the directory name.

src/cargo/util/config.rs

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::str::FromStr;
1313
use rustc_serialize::{Encodable,Encoder};
1414
use toml;
1515
use core::shell::{Verbosity, ColorConfig};
16-
use core::{MultiShell, Workspace};
16+
use core::MultiShell;
1717
use util::{CargoResult, CargoError, ChainError, Rustc, internal, human};
1818
use util::{Filesystem, LazyCell};
1919

@@ -28,7 +28,6 @@ pub struct Config {
2828
values: LazyCell<HashMap<String, ConfigValue>>,
2929
cwd: PathBuf,
3030
rustdoc: LazyCell<PathBuf>,
31-
target_dir: RefCell<Option<Filesystem>>,
3231
extra_verbose: Cell<bool>,
3332
frozen: Cell<bool>,
3433
locked: Cell<bool>,
@@ -37,23 +36,18 @@ pub struct Config {
3736
impl Config {
3837
pub fn new(shell: MultiShell,
3938
cwd: PathBuf,
40-
homedir: PathBuf) -> CargoResult<Config> {
41-
let mut cfg = Config {
39+
homedir: PathBuf) -> Config {
40+
Config {
4241
home_path: Filesystem::new(homedir),
4342
shell: RefCell::new(shell),
4443
rustc: LazyCell::new(),
4544
cwd: cwd,
4645
values: LazyCell::new(),
4746
rustdoc: LazyCell::new(),
48-
target_dir: RefCell::new(None),
4947
extra_verbose: Cell::new(false),
5048
frozen: Cell::new(false),
5149
locked: Cell::new(false),
52-
};
53-
54-
try!(cfg.scrape_target_dir_config());
55-
56-
Ok(cfg)
50+
}
5751
}
5852

5953
pub fn default() -> CargoResult<Config> {
@@ -65,7 +59,7 @@ impl Config {
6559
human("Cargo couldn't find your home directory. \
6660
This probably means that $HOME was not set.")
6761
}));
68-
Config::new(shell, cwd, homedir)
62+
Ok(Config::new(shell, cwd, homedir))
6963
}
7064

7165
pub fn home(&self) -> &Filesystem { &self.home_path }
@@ -108,14 +102,15 @@ impl Config {
108102

109103
pub fn cwd(&self) -> &Path { &self.cwd }
110104

111-
pub fn target_dir(&self, ws: &Workspace) -> Filesystem {
112-
self.target_dir.borrow().clone().unwrap_or_else(|| {
113-
Filesystem::new(ws.root().join("target"))
114-
})
115-
}
116-
117-
pub fn set_target_dir(&self, path: Filesystem) {
118-
*self.target_dir.borrow_mut() = Some(path);
105+
pub fn target_dir(&self) -> CargoResult<Option<Filesystem>> {
106+
if let Some(dir) = env::var_os("CARGO_TARGET_DIR") {
107+
Ok(Some(Filesystem::new(self.cwd.join(dir))))
108+
} else if let Some(val) = try!(self.get_path("build.target-dir")) {
109+
let val = self.cwd.join(val.val);
110+
Ok(Some(Filesystem::new(val)))
111+
} else {
112+
Ok(None)
113+
}
119114
}
120115

121116
fn get(&self, key: &str) -> CargoResult<Option<ConfigValue>> {
@@ -292,8 +287,11 @@ impl Config {
292287
locked: bool) -> CargoResult<()> {
293288
let extra_verbose = verbose >= 2;
294289
let verbose = if verbose == 0 {None} else {Some(true)};
295-
let cfg_verbose = try!(self.get_bool("term.verbose")).map(|v| v.val);
296-
let cfg_color = try!(self.get_string("term.color")).map(|v| v.val);
290+
291+
// Ignore errors in the configuration files.
292+
let cfg_verbose = self.get_bool("term.verbose").unwrap_or(None).map(|v| v.val);
293+
let cfg_color = self.get_string("term.color").unwrap_or(None).map(|v| v.val);
294+
297295
let color = color.as_ref().or(cfg_color.as_ref());
298296

299297
let verbosity = match (verbose, cfg_verbose, quiet) {
@@ -369,16 +367,6 @@ impl Config {
369367
}
370368
}
371369

372-
fn scrape_target_dir_config(&mut self) -> CargoResult<()> {
373-
if let Some(dir) = env::var_os("CARGO_TARGET_DIR") {
374-
*self.target_dir.borrow_mut() = Some(Filesystem::new(self.cwd.join(dir)));
375-
} else if let Some(val) = try!(self.get_path("build.target-dir")) {
376-
let val = self.cwd.join(val.val);
377-
*self.target_dir.borrow_mut() = Some(Filesystem::new(val));
378-
}
379-
Ok(())
380-
}
381-
382370
fn get_tool(&self, tool: &str) -> CargoResult<PathBuf> {
383371
let var = tool.chars().flat_map(|c| c.to_uppercase()).collect::<String>();
384372
if let Some(tool_path) = env::var_os(&var) {

tests/bad-config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ fn bad5() {
112112
assert_that(foo.cargo("new")
113113
.arg("-v").arg("foo").cwd(&foo.root().join("foo")),
114114
execs().with_status(101).with_stderr("\
115-
[ERROR] Couldn't load Cargo configuration
115+
[ERROR] Failed to create project `foo` at `[..]`
116+
117+
Caused by:
118+
Couldn't load Cargo configuration
116119
117120
Caused by:
118121
failed to merge key `foo` between files:

tests/version.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,22 @@ fn version_works_without_rustc() {
5656
assert_that(p.cargo_process("version").env("PATH", ""),
5757
execs().with_status(0));
5858
}
59+
60+
#[test]
61+
fn version_works_with_bad_config() {
62+
let p = project("foo")
63+
.file(".cargo/config", "this is not toml");
64+
assert_that(p.cargo_process("version"),
65+
execs().with_status(0));
66+
}
67+
68+
#[test]
69+
fn version_works_with_bad_target_dir() {
70+
let p = project("foo")
71+
.file(".cargo/config", r#"
72+
[build]
73+
target-dir = 4
74+
"#);
75+
assert_that(p.cargo_process("version"),
76+
execs().with_status(0));
77+
}

0 commit comments

Comments
 (0)