Skip to content

Commit 74c3ba6

Browse files
Merge #904
904: Various bug fixes for cross. r=Emilgardis a=Alexhuszagh Fixed `cargo metadata` failing with unstable arguments in rustflags if the default toolchain was not nightly. We also log any warnings that occurred if we cannot get metadata. Also fixed a lack of formatting in messages with remote docker support. The mount paths are also correctly processed if using docker-in-docker for mounted volumes. Closes #901. Closes #903. Required for #873. Co-authored-by: Alex Huszagh <[email protected]>
2 parents 00c1de2 + 2c13e20 commit 74c3ba6

File tree

7 files changed

+81
-34
lines changed

7 files changed

+81
-34
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2020

2121
### Fixed
2222

23+
- #904 - ensure `cargo metadata` works by using the same channel.
24+
- #904 - fixed the path for workspace volumes and passthrough volumes with docker-in-docker.
2325
- #898 - fix the path to the mount root with docker-in-docker if mounting volumes.
2426
- #897 - ensure `target.$(...)` config options override `build` ones when parsing strings and vecs.
2527
- #895 - convert filenames in docker tags to ASCII lowercase and ignore invalid characters

src/cargo.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::process::{Command, ExitStatus};
55
use crate::cli::Args;
66
use crate::errors::*;
77
use crate::extensions::CommandExt;
8-
use crate::shell::MessageInfo;
8+
use crate::shell::{self, MessageInfo};
99

1010
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1111
pub enum Subcommand {
@@ -123,6 +123,9 @@ pub fn cargo_metadata_with_args(
123123
msg_info: MessageInfo,
124124
) -> Result<Option<CargoMetadata>> {
125125
let mut command = cargo_command();
126+
if let Some(channel) = args.and_then(|x| x.channel.as_deref()) {
127+
command.arg(format!("+{channel}"));
128+
}
126129
command.arg("metadata").args(&["--format-version", "1"]);
127130
if let Some(cd) = cd {
128131
command.current_dir(cd);
@@ -142,7 +145,9 @@ pub fn cargo_metadata_with_args(
142145
}
143146
let output = command.run_and_get_output(msg_info)?;
144147
if !output.status.success() {
145-
// TODO: logging
148+
shell::warn("unable to get metadata for package", msg_info)?;
149+
let indented = shell::indent(&String::from_utf8(output.stderr)?, shell::default_ident());
150+
shell::debug(indented, msg_info)?;
146151
return Ok(None);
147152
}
148153
let manifest: Option<CargoMetadata> = serde_json::from_slice(&output.stdout)?;

src/docker/local.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ pub(crate) fn run(
2525
docker_in_docker: bool,
2626
cwd: &Path,
2727
) -> Result<ExitStatus> {
28-
let dirs = Directories::create(engine, metadata, cwd, sysroot, docker_in_docker)?;
28+
let mount_finder = MountFinder::create(engine, docker_in_docker)?;
29+
let dirs = Directories::create(&mount_finder, metadata, cwd, sysroot)?;
2930

3031
let mut cmd = cargo_safe_command(uses_xargo);
3132
cmd.args(args);
@@ -37,6 +38,7 @@ pub(crate) fn run(
3738
let mount_volumes = docker_mount(
3839
&mut docker,
3940
metadata,
41+
&mount_finder,
4042
config,
4143
target,
4244
cwd,

src/docker/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::process::ExitStatus;
1212

1313
use crate::cargo::CargoMetadata;
1414
use crate::errors::*;
15-
use crate::shell::MessageInfo;
15+
use crate::shell::{self, MessageInfo};
1616
use crate::{Config, Target};
1717

1818
#[allow(clippy::too_many_arguments)] // TODO: refactor
@@ -28,6 +28,13 @@ pub fn run(
2828
docker_in_docker: bool,
2929
cwd: &Path,
3030
) -> Result<ExitStatus> {
31+
if cfg!(target_os = "windows") && docker_in_docker {
32+
shell::fatal(
33+
"running cross insider a container running windows is currently unsupported",
34+
msg_info,
35+
1,
36+
);
37+
}
3138
if engine.is_remote {
3239
remote::run(
3340
engine,

src/docker/remote.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,8 @@ pub(crate) fn run(
764764
docker_in_docker: bool,
765765
cwd: &Path,
766766
) -> Result<ExitStatus> {
767-
let dirs = Directories::create(engine, metadata, cwd, sysroot, docker_in_docker)?;
767+
let mount_finder = MountFinder::create(engine, docker_in_docker)?;
768+
let dirs = Directories::create(&mount_finder, metadata, cwd, sysroot)?;
768769

769770
let mount_prefix = MOUNT_PREFIX;
770771

@@ -793,16 +794,16 @@ pub(crate) fn run(
793794
let volume = VolumeId::create(engine, &toolchain_id, &container, msg_info)?;
794795
let state = container_state(engine, &container, msg_info)?;
795796
if !state.is_stopped() {
796-
shell::warn("container {container} was running.", msg_info)?;
797+
shell::warn(format_args!("container {container} was running."), msg_info)?;
797798
container_stop(engine, &container, msg_info)?;
798799
}
799800
if state.exists() {
800-
shell::warn("container {container} was exited.", msg_info)?;
801+
shell::warn(format_args!("container {container} was exited."), msg_info)?;
801802
container_rm(engine, &container, msg_info)?;
802803
}
803804
if let VolumeId::Discard(ref id) = volume {
804805
if volume_exists(engine, id, msg_info)? {
805-
shell::warn("temporary volume {container} existed.", msg_info)?;
806+
shell::warn(format_args!("temporary volume {id} existed."), msg_info)?;
806807
volume_rm(engine, id, msg_info)?;
807808
}
808809
}
@@ -824,6 +825,7 @@ pub(crate) fn run(
824825
let mount_volumes = docker_mount(
825826
&mut docker,
826827
metadata,
828+
&mount_finder,
827829
config,
828830
target,
829831
cwd,

src/docker/shared.rs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,11 @@ pub struct Directories {
4343

4444
impl Directories {
4545
pub fn create(
46-
engine: &Engine,
46+
mount_finder: &MountFinder,
4747
metadata: &CargoMetadata,
4848
cwd: &Path,
4949
sysroot: &Path,
50-
docker_in_docker: bool,
5150
) -> Result<Self> {
52-
let mount_finder = if docker_in_docker {
53-
MountFinder::new(docker_read_mount_paths(engine)?)
54-
} else {
55-
MountFinder::default()
56-
};
5751
let home_dir =
5852
home::home_dir().ok_or_else(|| eyre::eyre!("could not find home directory"))?;
5953
let cargo = home::cargo_home()?;
@@ -89,18 +83,10 @@ impl Directories {
8983
}
9084
#[cfg(not(target_os = "windows"))]
9185
{
86+
// NOTE: host root has already found the mount path
9287
mount_root = host_root.to_utf8()?.to_string();
9388
}
94-
let mount_cwd: String;
95-
#[cfg(target_os = "windows")]
96-
{
97-
// On Windows, we can not mount the directory name directly. Instead, we use wslpath to convert the path to a linux compatible path.
98-
mount_cwd = cwd.as_wslpath()?;
99-
}
100-
#[cfg(not(target_os = "windows"))]
101-
{
102-
mount_cwd = mount_finder.find_mount_path(cwd).to_utf8()?.to_string();
103-
}
89+
let mount_cwd = mount_finder.find_path(cwd, false)?;
10490
let sysroot = mount_finder.find_mount_path(sysroot);
10591

10692
Ok(Directories {
@@ -163,8 +149,10 @@ pub fn get_package_info(
163149
let cwd = std::env::current_dir()?;
164150
let host_meta = rustc::version_meta()?;
165151
let host = host_meta.host();
152+
166153
let sysroot = rustc::get_sysroot(&host, &target, channel, msg_info)?.1;
167-
let dirs = Directories::create(engine, &metadata, &cwd, &sysroot, docker_in_docker)?;
154+
let mount_finder = MountFinder::create(engine, docker_in_docker)?;
155+
let dirs = Directories::create(&mount_finder, &metadata, &cwd, &sysroot)?;
168156

169157
Ok((target, metadata, dirs))
170158
}
@@ -251,9 +239,9 @@ fn add_cargo_configuration_envvars(docker: &mut Command) {
251239
}
252240
}
253241

254-
pub(crate) fn mount(docker: &mut Command, val: &Path, prefix: &str) -> Result<String> {
255-
let host_path = file::canonicalize(val)?;
256-
let mount_path = canonicalize_mount_path(&host_path)?;
242+
// NOTE: host path must be canonical
243+
pub(crate) fn mount(docker: &mut Command, host_path: &Path, prefix: &str) -> Result<String> {
244+
let mount_path = canonicalize_mount_path(host_path)?;
257245
docker.args(&[
258246
"-v",
259247
&format!("{}:{prefix}{}", host_path.to_utf8()?, mount_path),
@@ -338,6 +326,7 @@ pub(crate) fn docker_cwd(
338326
pub(crate) fn docker_mount(
339327
docker: &mut Command,
340328
metadata: &CargoMetadata,
329+
mount_finder: &MountFinder,
341330
config: &Config,
342331
target: &Target,
343332
cwd: &Path,
@@ -359,15 +348,19 @@ pub(crate) fn docker_mount(
359348
};
360349

361350
if let Ok(val) = value {
362-
let mount_path = mount_cb(docker, val.as_ref())?;
363-
docker.args(&["-e", &format!("{}={}", var, mount_path)]);
351+
let canonical_val = file::canonicalize(&val)?;
352+
let host_path = mount_finder.find_path(&canonical_val, true)?;
353+
let mount_path = mount_cb(docker, host_path.as_ref())?;
354+
docker.args(&["-e", &format!("{}={}", host_path, mount_path)]);
364355
store_cb((val, mount_path));
365356
mount_volumes = true;
366357
}
367358
}
368359

369360
for path in metadata.path_dependencies() {
370-
let mount_path = mount_cb(docker, path)?;
361+
let canonical_path = file::canonicalize(path)?;
362+
let host_path = mount_finder.find_path(&canonical_path, true)?;
363+
let mount_path = mount_cb(docker, host_path.as_ref())?;
371364
store_cb((path.to_utf8()?.to_string(), mount_path));
372365
mount_volumes = true;
373366
}
@@ -614,7 +607,7 @@ fn dockerinfo_parse_user_mounts(info: &serde_json::Value) -> Vec<MountDetail> {
614607
}
615608

616609
#[derive(Debug, Default)]
617-
struct MountFinder {
610+
pub struct MountFinder {
618611
mounts: Vec<MountDetail>,
619612
}
620613

@@ -636,7 +629,15 @@ impl MountFinder {
636629
MountFinder { mounts }
637630
}
638631

639-
fn find_mount_path(&self, path: impl AsRef<Path>) -> PathBuf {
632+
pub fn create(engine: &Engine, docker_in_docker: bool) -> Result<MountFinder> {
633+
Ok(if docker_in_docker {
634+
MountFinder::new(docker_read_mount_paths(engine)?)
635+
} else {
636+
MountFinder::default()
637+
})
638+
}
639+
640+
pub fn find_mount_path(&self, path: impl AsRef<Path>) -> PathBuf {
640641
let path = path.as_ref();
641642

642643
for info in &self.mounts {
@@ -647,6 +648,23 @@ impl MountFinder {
647648

648649
path.to_path_buf()
649650
}
651+
652+
#[allow(unused_variables, clippy::needless_return)]
653+
fn find_path(&self, path: &Path, host: bool) -> Result<String> {
654+
#[cfg(target_os = "windows")]
655+
{
656+
// On Windows, we can not mount the directory name directly. Instead, we use wslpath to convert the path to a linux compatible path.
657+
if host {
658+
return Ok(path.to_utf8()?.to_string());
659+
} else {
660+
return path.as_wslpath();
661+
}
662+
}
663+
#[cfg(not(target_os = "windows"))]
664+
{
665+
return Ok(self.find_mount_path(path).to_utf8()?.to_string());
666+
}
667+
}
650668
}
651669

652670
fn path_digest(path: &Path) -> Result<const_sha1::Digest> {

src/shell.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,14 @@ impl Stream for io::Stderr {
308308
const TTY: atty::Stream = atty::Stream::Stderr;
309309
const OWO: owo_colors::Stream = owo_colors::Stream::Stderr;
310310
}
311+
312+
pub fn default_ident() -> usize {
313+
cross_prefix!("").len()
314+
}
315+
316+
pub fn indent(message: &str, spaces: usize) -> String {
317+
message
318+
.lines()
319+
.map(|s| format!("{:spaces$}{s}", ""))
320+
.collect()
321+
}

0 commit comments

Comments
 (0)