Skip to content

Commit 92f1232

Browse files
committed
fix(vendor): Make vendor use Manifest's "original" Cargo.toml
1 parent 23424fd commit 92f1232

2 files changed

Lines changed: 172 additions & 17 deletions

File tree

src/cargo/ops/vendor.rs

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::core::shell::Verbosity;
2-
use crate::core::{GitReference, Workspace};
2+
use crate::core::{GitReference, Package, Workspace};
33
use crate::ops;
44
use crate::sources::path::PathSource;
55
use crate::sources::CRATES_IO_REGISTRY;
@@ -9,6 +9,7 @@ use cargo_util::{paths, Sha256};
99
use serde::Serialize;
1010
use std::collections::HashSet;
1111
use std::collections::{BTreeMap, BTreeSet, HashMap};
12+
use std::ffi::OsStr;
1213
use std::fs::{self, File, OpenOptions};
1314
use std::io::{Read, Write};
1415
use std::path::{Path, PathBuf};
@@ -225,7 +226,7 @@ fn sync(
225226
let pathsource = PathSource::new(src, id.source_id(), config);
226227
let paths = pathsource.list_files(pkg)?;
227228
let mut map = BTreeMap::new();
228-
cp_sources(src, &paths, &dst, &mut map, &mut tmp_buf)
229+
cp_sources(pkg, src, &paths, &dst, &mut map, &mut tmp_buf)
229230
.with_context(|| format!("failed to copy over vendored sources for: {}", id))?;
230231

231232
// Finally, emit the metadata about this package
@@ -315,6 +316,7 @@ fn sync(
315316
}
316317

317318
fn cp_sources(
319+
pkg: &Package,
318320
src: &Path,
319321
paths: &[PathBuf],
320322
dst: &Path,
@@ -354,35 +356,54 @@ fn cp_sources(
354356
.fold(dst.to_owned(), |acc, component| acc.join(&component));
355357

356358
paths::create_dir_all(dst.parent().unwrap())?;
359+
let mut dst_opts = OpenOptions::new();
360+
dst_opts.write(true).create(true).truncate(true);
361+
let cksum = if dst.file_name() == Some(OsStr::new("Cargo.toml"))
362+
&& pkg.package_id().source_id().is_git()
363+
{
364+
let contents = toml::to_string_pretty(pkg.manifest().original())?;
365+
copy_and_checksum(
366+
&dst,
367+
&mut dst_opts,
368+
&mut contents.as_bytes(),
369+
"Generated Cargo.toml",
370+
tmp_buf,
371+
)?
372+
} else {
373+
let mut src = File::open(&p).with_context(|| format!("failed to open {:?}", &p))?;
374+
#[cfg(unix)]
375+
{
376+
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
377+
let src_metadata = src
378+
.metadata()
379+
.with_context(|| format!("failed to stat {:?}", p))?;
380+
dst_opts.mode(src_metadata.mode());
381+
}
382+
copy_and_checksum(&dst, &mut dst_opts, &mut src, p.to_str().unwrap(), tmp_buf)?
383+
};
357384

358-
let cksum = copy_and_checksum(p, &dst, tmp_buf)?;
359385
cksums.insert(relative.to_str().unwrap().replace("\\", "/"), cksum);
360386
}
361387
Ok(())
362388
}
363389

364-
fn copy_and_checksum(src_path: &Path, dst_path: &Path, buf: &mut [u8]) -> CargoResult<String> {
365-
let mut src = File::open(src_path).with_context(|| format!("failed to open {:?}", src_path))?;
366-
let mut dst_opts = OpenOptions::new();
367-
dst_opts.write(true).create(true).truncate(true);
368-
#[cfg(unix)]
369-
{
370-
use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
371-
let src_metadata = src
372-
.metadata()
373-
.with_context(|| format!("failed to stat {:?}", src_path))?;
374-
dst_opts.mode(src_metadata.mode());
375-
}
390+
fn copy_and_checksum<T: Read>(
391+
dst_path: &Path,
392+
dst_opts: &mut OpenOptions,
393+
contents: &mut T,
394+
contents_path: &str,
395+
buf: &mut [u8],
396+
) -> CargoResult<String> {
376397
let mut dst = dst_opts
377398
.open(dst_path)
378399
.with_context(|| format!("failed to create {:?}", dst_path))?;
379400
// Not going to bother setting mode on pre-existing files, since there
380401
// shouldn't be any under normal conditions.
381402
let mut cksum = Sha256::new();
382403
loop {
383-
let n = src
404+
let n = contents
384405
.read(buf)
385-
.with_context(|| format!("failed to read from {:?}", src_path))?;
406+
.with_context(|| format!("failed to read from {:?}", contents_path))?;
386407
if n == 0 {
387408
break Ok(cksum.finish_hex());
388409
}

tests/testsuite/vendor.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,79 @@ Caused by:
789789
.run();
790790
}
791791

792+
#[cargo_test]
793+
fn git_complex() {
794+
let git_b = git::new("git_b", |p| {
795+
p.file(
796+
"Cargo.toml",
797+
r#"
798+
[package]
799+
name = "b"
800+
version = "0.1.0"
801+
802+
[dependencies]
803+
dep_b = { path = 'dep_b' }
804+
"#,
805+
)
806+
.file("src/lib.rs", "")
807+
.file("dep_b/Cargo.toml", &basic_lib_manifest("dep_b"))
808+
.file("dep_b/src/lib.rs", "")
809+
});
810+
811+
let git_a = git::new("git_a", |p| {
812+
p.file(
813+
"Cargo.toml",
814+
&format!(
815+
r#"
816+
[package]
817+
name = "a"
818+
version = "0.1.0"
819+
820+
[dependencies]
821+
b = {{ git = '{}' }}
822+
dep_a = {{ path = 'dep_a' }}
823+
"#,
824+
git_b.url()
825+
),
826+
)
827+
.file("src/lib.rs", "")
828+
.file("dep_a/Cargo.toml", &basic_lib_manifest("dep_a"))
829+
.file("dep_a/src/lib.rs", "")
830+
});
831+
832+
let p = project()
833+
.file(
834+
"Cargo.toml",
835+
&format!(
836+
r#"
837+
[package]
838+
name = "foo"
839+
version = "0.1.0"
840+
841+
[dependencies]
842+
a = {{ git = '{}' }}
843+
"#,
844+
git_a.url()
845+
),
846+
)
847+
.file("src/lib.rs", "")
848+
.build();
849+
850+
let output = p
851+
.cargo("vendor --respect-source-config")
852+
.exec_with_output()
853+
.unwrap();
854+
let output = String::from_utf8(output.stdout).unwrap();
855+
p.change_file(".cargo/config", &output);
856+
857+
p.cargo("check -v")
858+
.with_stderr_contains("[..]foo/vendor/a/src/lib.rs[..]")
859+
.with_stderr_contains("[..]foo/vendor/dep_a/src/lib.rs[..]")
860+
.with_stderr_contains("[..]foo/vendor/b/src/lib.rs[..]")
861+
.with_stderr_contains("[..]foo/vendor/dep_b/src/lib.rs[..]")
862+
.run();
863+
}
864+
792865
#[cargo_test]
793866
fn depend_on_vendor_dir_not_deleted() {
794867
let p = project()
@@ -1015,3 +1088,64 @@ fn no_remote_dependency_no_vendor() {
10151088
.run();
10161089
assert!(!p.root().join("vendor").exists());
10171090
}
1091+
1092+
#[cargo_test]
1093+
fn vendor_crate_with_ws_inherit() {
1094+
let git = git::new("ws", |p| {
1095+
p.file(
1096+
"Cargo.toml",
1097+
r#"
1098+
[workspace]
1099+
members = ["bar"]
1100+
[workspace.package]
1101+
version = "0.1.0"
1102+
"#,
1103+
)
1104+
.file(
1105+
"bar/Cargo.toml",
1106+
r#"
1107+
[package]
1108+
name = "bar"
1109+
version.workspace = true
1110+
"#,
1111+
)
1112+
.file("bar/src/lib.rs", "")
1113+
});
1114+
1115+
let p = project()
1116+
.file(
1117+
"Cargo.toml",
1118+
&format!(
1119+
r#"
1120+
[package]
1121+
name = "foo"
1122+
version = "0.1.0"
1123+
1124+
[dependencies]
1125+
bar = {{ git = '{}' }}
1126+
"#,
1127+
git.url()
1128+
),
1129+
)
1130+
.file("src/lib.rs", "")
1131+
.build();
1132+
1133+
p.cargo("vendor --respect-source-config").run();
1134+
p.change_file(
1135+
".cargo/config",
1136+
&format!(
1137+
r#"
1138+
[source."{}"]
1139+
git = "{}"
1140+
replace-with = "vendor"
1141+
1142+
[source.vendor]
1143+
directory = "vendor"
1144+
"#,
1145+
git.url(),
1146+
git.url()
1147+
),
1148+
);
1149+
1150+
p.cargo("check").run()
1151+
}

0 commit comments

Comments
 (0)