From 41f9ba9ff04e095b6efdea197352971ffa6195b3 Mon Sep 17 00:00:00 2001 From: Alex Huszagh Date: Mon, 11 Jul 2022 11:38:18 -0500 Subject: [PATCH] Allow users to ignore config files in the package. Adds the `CROSS_IGNORE_CARGO_CONFIG` environment variable, which if set will mount an anoymous data volume for each `.cargo` subdirectory for the current directory and any parent directories up to the workspace root. If the build is called outside the workspace root or at the workspace root, only mount at the `$PWD/.cargo`. --- .changes/936.json | 5 +++++ src/config.rs | 10 +++++++++ src/docker/local.rs | 3 ++- src/docker/remote.rs | 3 ++- src/docker/shared.rs | 51 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 .changes/936.json diff --git a/.changes/936.json b/.changes/936.json new file mode 100644 index 000000000..27fc3d223 --- /dev/null +++ b/.changes/936.json @@ -0,0 +1,5 @@ +{ + "type": "added", + "description": "allow users to ignore config files in the package.", + "issues": [621] +} diff --git a/src/config.rs b/src/config.rs index a5d583016..5448cb78b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -115,6 +115,12 @@ impl Environment { .ok() } + fn ignore_cargo_config(&self) -> Option { + env::var("CROSS_IGNORE_CARGO_CONFIG") + .map(|s| bool_from_envvar(&s)) + .ok() + } + fn custom_toolchain(&self) -> bool { std::env::var("CROSS_CUSTOM_TOOLCHAIN").is_ok() } @@ -291,6 +297,10 @@ impl Config { self.env.custom_toolchain() } + pub fn ignore_cargo_config(&self) -> Option { + self.env.ignore_cargo_config() + } + pub fn env_passthrough(&self, target: &Target) -> Result>> { self.vec_from_config( target, diff --git a/src/docker/local.rs b/src/docker/local.rs index 2d86d3d07..284ded28a 100644 --- a/src/docker/local.rs +++ b/src/docker/local.rs @@ -54,7 +54,8 @@ pub(crate) fn run( docker .args(&["-v", &format!("{}:/rust:Z,ro", dirs.sysroot.to_utf8()?)]) .args(&["-v", &format!("{}:/target:Z", dirs.target.to_utf8()?)]); - docker_cwd(&mut docker, &paths, mount_volumes)?; + let ignore_cargo_config = options.config.ignore_cargo_config().unwrap_or_default(); + docker_cwd(&mut docker, &paths, mount_volumes, ignore_cargo_config)?; // When running inside NixOS or using Nix packaging we need to add the Nix // Store to the running container so it can load the needed binaries. diff --git a/src/docker/remote.rs b/src/docker/remote.rs index c42dd3a72..d548e9c74 100644 --- a/src/docker/remote.rs +++ b/src/docker/remote.rs @@ -1175,7 +1175,8 @@ symlink_recurse \"${{prefix}}\" let mut docker = subcommand(engine, "exec"); docker_user_id(&mut docker, engine.kind); docker_envvars(&mut docker, &options.config, target, msg_info)?; - docker_cwd(&mut docker, &paths, mount_volumes)?; + let ignore_cargo_config = options.config.ignore_cargo_config().unwrap_or_default(); + docker_cwd(&mut docker, &paths, mount_volumes, ignore_cargo_config)?; docker.arg(&container); docker.args(&["sh", "-c", &format!("PATH=$PATH:/rust/bin {:?}", cmd)]); bail_container_exited!(); diff --git a/src/docker/shared.rs b/src/docker/shared.rs index 586a0bc59..a1374ca41 100644 --- a/src/docker/shared.rs +++ b/src/docker/shared.rs @@ -217,10 +217,18 @@ impl DockerPaths { self.workspace_from_cwd().is_ok() } + pub fn cargo_home(&self) -> &Path { + &self.directories.cargo + } + pub fn mount_cwd(&self) -> &str { &self.directories.mount_cwd } + pub fn mount_root(&self) -> &str { + &self.directories.mount_root + } + pub fn host_root(&self) -> &Path { &self.directories.host_root } @@ -496,19 +504,60 @@ pub(crate) fn docker_envvars( Ok(()) } +fn mount_to_ignore_cargo_config( + docker: &mut Command, + paths: &DockerPaths, + root: &str, + cwd: &str, + ignore_cargo_config: bool, +) -> Result<()> { + let is_cargo_home_parent = paths + .cargo_home() + .parent() + .map(|x| x == paths.host_root()) + .unwrap_or_default(); + if ignore_cargo_config && !is_cargo_home_parent { + let root_path = Path::new(root); + let cwd_path = Path::new(cwd); + docker.args(&["-v", &cwd_path.join(".cargo").as_posix()?]); + let mut relpath = Path::new(cwd).strip_prefix(root_path).wrap_err_with(|| { + eyre::eyre!("cwd \"{cwd}\" must be a subdirectory of root \"{root}\"") + })?; + + while let Some(parent) = relpath.parent() { + let path = root_path.join(parent); + docker.args(&["-v", &path.join(".cargo").as_posix()?]); + relpath = parent; + } + } + + Ok(()) +} + pub(crate) fn docker_cwd( docker: &mut Command, paths: &DockerPaths, mount_volumes: bool, + ignore_cargo_config: bool, ) -> Result<()> { if mount_volumes { docker.args(&["-w", paths.mount_cwd()]); + mount_to_ignore_cargo_config( + docker, + paths, + paths.mount_root(), + paths.mount_cwd(), + ignore_cargo_config, + )?; } else if paths.mount_cwd() == paths.workspace_root().to_utf8()? { docker.args(&["-w", "/project"]); + mount_to_ignore_cargo_config(docker, paths, "/project", "/project", ignore_cargo_config)?; } else { // We do this to avoid clashes with path separators. Windows uses `\` as a path separator on Path::join let working_dir = Path::new("/project").join(paths.workspace_from_cwd()?); - docker.args(&["-w", &working_dir.as_posix()?]); + let cwd = working_dir.as_posix()?; + docker.args(&["-w", &cwd]); + mount_to_ignore_cargo_config(docker, paths, "/project", &cwd, ignore_cargo_config)?; } Ok(())