Skip to content

Commit 414ec70

Browse files
committed
Auto merge of #7631 - jsgf:explicit-version, r=alexcrichton
vendor: implement --versioned-dirs Implement `--explicit-version` from standalone cargo-vendor. This helps with vendoring performance as it avoids redundantly deleting and re-copying already vendored packages. For example, re-vendoring cargo's dependencies it makes a big difference in wallclock time. For initial vendoring it makes no difference, but re-vendoring (ie, when most or all dependencies haven't changed) without explicit versions is actually slightly slower (5.8s -> 6s), but with explicit versions it goes from 5.8s -> 1.6s. Timings: Without explicit versions, initial vendor real 0m5.810s user 0m0.924s sys 0m2.491s Re-vendor: real 0m6.083s user 0m0.937s sys 0m2.654s With explicit versions, initial vendor: real 0m5.810s user 0m0.937s sys 0m2.461s Re-vendor: real 0m1.567s user 0m0.578s sys 0m0.967s Its interesting to look at the syscall summary: Without explicit versions: ``` % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 25.17 1.104699 18 59432 1065 openat 19.86 0.871574 21 41156 13825 unlink 13.64 0.598739 2 210510 lstat 9.02 0.395948 29 13208 copy_file_range 8.00 0.351242 11 30245 read 6.36 0.279005 3 72487 4476 statx 5.35 0.235027 6 37219 write 4.02 0.176267 3 58368 close ``` with explicit versions: ``` 29.38 0.419068 15 27798 13825 unlink 25.52 0.364021 1 209586 lstat 20.67 0.294788 16 17967 1032 openat 10.42 0.148586 4 35646 write 3.53 0.050350 3 13825 chmod 3.14 0.044786 2 16701 1622 statx 2.19 0.031171 1 16936 close 1.86 0.026538 24 1078 rmdir ``` Specifically, there are a lot fewer opens, copy_file_ranges, and unlinks.
2 parents 19a0de2 + 2214cf1 commit 414ec70

File tree

6 files changed

+79
-11
lines changed

6 files changed

+79
-11
lines changed

src/bin/cargo/commands/vendor.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ pub fn cli() -> App {
2727
.help("Respect `[source]` config in `.cargo/config`")
2828
.multiple(true),
2929
)
30+
.arg(
31+
Arg::with_name("versioned-dirs")
32+
.long("versioned-dirs")
33+
.help("Always include version in subdir name"),
34+
)
3035
.arg(
3136
Arg::with_name("no-merge-sources")
3237
.long("no-merge-sources")
@@ -42,12 +47,6 @@ pub fn cli() -> App {
4247
.long("only-git-deps")
4348
.hidden(true),
4449
)
45-
.arg(
46-
Arg::with_name("explicit-version")
47-
.short("-x")
48-
.long("explicit-version")
49-
.hidden(true),
50-
)
5150
.arg(
5251
Arg::with_name("disallow-duplicates")
5352
.long("disallow-duplicates")
@@ -85,8 +84,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
8584
Some("--relative-path")
8685
} else if args.is_present("only-git-deps") {
8786
Some("--only-git-deps")
88-
} else if args.is_present("explicit-version") {
89-
Some("--explicit-version")
9087
} else if args.is_present("disallow-duplicates") {
9188
Some("--disallow-duplicates")
9289
} else {
@@ -116,6 +113,7 @@ https://github.com/rust-lang/cargo/issues/new
116113
&ops::VendorOptions {
117114
no_delete: args.is_present("no-delete"),
118115
destination: &path,
116+
versioned_dirs: args.is_present("versioned-dirs"),
119117
extra: args
120118
.values_of_os("tomls")
121119
.unwrap_or_default()

src/cargo/ops/vendor.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::path::{Path, PathBuf};
1414

1515
pub struct VendorOptions<'a> {
1616
pub no_delete: bool,
17+
pub versioned_dirs: bool,
1718
pub destination: &'a Path,
1819
pub extra: Vec<PathBuf>,
1920
}
@@ -186,7 +187,7 @@ fn sync(
186187
.parent()
187188
.expect("manifest_path should point to a file");
188189
let max_version = *versions[&id.name()].iter().rev().next().unwrap().0;
189-
let dir_has_version_suffix = id.version() != max_version;
190+
let dir_has_version_suffix = opts.versioned_dirs || id.version() != max_version;
190191
let dst_name = if dir_has_version_suffix {
191192
// Eg vendor/futures-0.1.13
192193
format!("{}-{}", id.name(), id.version())

src/doc/man/cargo-vendor.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ to use the vendored sources, which you will need to add to `.cargo/config`.
3838
Instead of ignoring `[source]` configuration by default in `.cargo/config`
3939
read it and use it when downloading crates from crates.io, for example
4040

41+
*--versioned-dirs*::
42+
Normally versions are only added to disambiguate multiple versions of the
43+
same package. This option causes all directories in the "vendor" directory
44+
to be versioned, which makes it easier to track the history of vendored
45+
packages over time, and can help with the performance of re-vendoring when
46+
only a subset of the packages have changed.
47+
4148
=== Manifest Options
4249

4350
include::options-manifest-path.adoc[]

src/doc/man/generated/cargo-vendor.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ <h3 id="cargo_vendor_owner_options">Owner Options</h3>
4949
<p>Instead of ignoring <code>[source]</code> configuration by default in <code>.cargo/config</code>
5050
read it and use it when downloading crates from crates.io, for example</p>
5151
</dd>
52+
<dt class="hdlist1"><strong>--versioned-dirs</strong></dt>
53+
<dd>
54+
<p>Normally versions are only added to disambiguate multiple versions of the
55+
same package. This option causes all directories in the "vendor" directory
56+
to be versioned, which makes it easier to track the history of vendored
57+
packages over time, and can help with the performance of re-vendoring when
58+
only a subset of the packages have changed.</p>
59+
</dd>
5260
</dl>
5361
</div>
5462
</div>

src/etc/man/cargo-vendor.1

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
.\" Title: cargo-vendor
33
.\" Author: [see the "AUTHOR(S)" section]
44
.\" Generator: Asciidoctor 2.0.10
5-
.\" Date: 2019-09-08
5+
.\" Date: 2019-12-09
66
.\" Manual: \ \&
77
.\" Source: \ \&
88
.\" Language: English
99
.\"
10-
.TH "CARGO\-VENDOR" "1" "2019-09-08" "\ \&" "\ \&"
10+
.TH "CARGO\-VENDOR" "1" "2019-12-09" "\ \&" "\ \&"
1111
.ie \n(.g .ds Aq \(aq
1212
.el .ds Aq '
1313
.ss \n[.ss] 0
@@ -62,6 +62,15 @@ existing contents of the vendor directory
6262
Instead of ignoring \fB[source]\fP configuration by default in \fB.cargo/config\fP
6363
read it and use it when downloading crates from crates.io, for example
6464
.RE
65+
.sp
66+
\fB\-\-versioned\-dirs\fP
67+
.RS 4
68+
Normally versions are only added to disambiguate multiple versions of the
69+
same package. This option causes all directories in the "vendor" directory
70+
to be versioned, which makes it easier to track the history of vendored
71+
packages over time, and can help with the performance of re\-vendoring when
72+
only a subset of the packages have changed.
73+
.RE
6574
.SS "Manifest Options"
6675
.sp
6776
\fB\-\-manifest\-path\fP \fIPATH\fP

tests/testsuite/vendor.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,51 @@ fn two_versions() {
8888
p.cargo("build").run();
8989
}
9090

91+
#[cargo_test]
92+
fn two_explicit_versions() {
93+
let p = project()
94+
.file(
95+
"Cargo.toml",
96+
r#"
97+
[package]
98+
name = "foo"
99+
version = "0.1.0"
100+
101+
[dependencies]
102+
bitflags = "0.8.0"
103+
bar = { path = "bar" }
104+
"#,
105+
)
106+
.file("src/lib.rs", "")
107+
.file(
108+
"bar/Cargo.toml",
109+
r#"
110+
[package]
111+
name = "bar"
112+
version = "0.1.0"
113+
114+
[dependencies]
115+
bitflags = "0.7.0"
116+
"#,
117+
)
118+
.file("bar/src/lib.rs", "")
119+
.build();
120+
121+
Package::new("bitflags", "0.7.0").publish();
122+
Package::new("bitflags", "0.8.0").publish();
123+
124+
p.cargo("vendor --respect-source-config --versioned-dirs")
125+
.run();
126+
127+
let lock = p.read_file("vendor/bitflags-0.8.0/Cargo.toml");
128+
assert!(lock.contains("version = \"0.8.0\""));
129+
let lock = p.read_file("vendor/bitflags-0.7.0/Cargo.toml");
130+
assert!(lock.contains("version = \"0.7.0\""));
131+
132+
add_vendor_config(&p);
133+
p.cargo("build").run();
134+
}
135+
91136
#[cargo_test]
92137
fn help() {
93138
let p = project().build();

0 commit comments

Comments
 (0)