Skip to content

Commit ee02b9a

Browse files
committed
auto merge of #624 : alexcrichton/cargo/issue-484, r=wycats
This commit adds a flag, --precise, to cargo update. This flag is used to update a dependency to precisely an exact revision (or branch) as part of an update step. For git repositories the argument is some form of reference, while registry packages this will be a version number. The flag --precise forces a non-aggressive update and will fail if the --aggresive flag is specified. Closes #484 r? @wycats
2 parents e74ed43 + c098a9a commit ee02b9a

File tree

5 files changed

+60
-15
lines changed

5 files changed

+60
-15
lines changed

src/bin/update.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Usage:
1515
Options:
1616
-h, --help Print this message
1717
--aggressive Force updating all dependencies of <name> as well
18+
--precise PRECISE Update a single dependency to exactly PRECISE
1819
--manifest-path PATH Path to the manifest to compile
1920
-v, --verbose Use verbose output
2021
@@ -27,18 +28,32 @@ updated. Its transitive dependencies will be updated only if <spec> cannot be
2728
updated without updating dependencies. All other dependencies will remain
2829
locked at their currently recorded versions.
2930
31+
If PRECISE is specified, then --aggressive must not also be specified. The
32+
argument PRECISE is a string representing a precise revision that the package
33+
being updated should be updated to. For example, if the package comes from a git
34+
repository, then PRECISE would be the exact revision that the repository should
35+
be updated to.
36+
3037
If <spec> is not given, then all dependencies will be re-resolved and
3138
updated.
3239
3340
For more information about package ids, see `cargo help pkgid`.
34-
", flag_manifest_path: Option<String>, arg_spec: Option<String>)
41+
", flag_manifest_path: Option<String>, arg_spec: Option<String>,
42+
flag_precise: Option<String>)
3543

3644
pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
3745
debug!("executing; cmd=cargo-update; args={}", os::args());
3846
shell.set_verbose(options.flag_verbose);
3947
let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
4048

41-
ops::update_lockfile(&root, shell, options.arg_spec, options.flag_aggressive)
49+
let mut update_opts = ops::UpdateOptions {
50+
aggressive: options.flag_aggressive,
51+
precise: options.flag_precise.as_ref().map(|s| s.as_slice()),
52+
to_update: options.arg_spec.as_ref().map(|s| s.as_slice()),
53+
shell: shell,
54+
};
55+
56+
ops::update_lockfile(&root, &mut update_opts)
4257
.map(|_| None).map_err(|err| CliError::from_boxed(err, 101))
4358
}
4459

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ use util::config::{Config};
1212
use util::{CargoResult, human};
1313
use util::toml as cargo_toml;
1414

15+
pub struct UpdateOptions<'a> {
16+
pub shell: &'a mut MultiShell<'a>,
17+
pub to_update: Option<&'a str>,
18+
pub precise: Option<&'a str>,
19+
pub aggressive: bool,
20+
}
21+
1522
pub fn generate_lockfile(manifest_path: &Path,
1623
shell: &mut MultiShell)
1724
-> CargoResult<()> {
@@ -33,9 +40,7 @@ pub fn generate_lockfile(manifest_path: &Path,
3340
}
3441

3542
pub fn update_lockfile(manifest_path: &Path,
36-
shell: &mut MultiShell,
37-
to_update: Option<String>,
38-
aggressive: bool) -> CargoResult<()> {
43+
opts: &mut UpdateOptions) -> CargoResult<()> {
3944
let mut source = try!(PathSource::for_path(&manifest_path.dir_path()));
4045
try!(source.update());
4146
let package = try!(source.get_root_package());
@@ -47,23 +52,37 @@ pub fn update_lockfile(manifest_path: &Path,
4752
None => return Err(human("A Cargo.lock must exist before it is updated"))
4853
};
4954

50-
let mut config = try!(Config::new(shell, None, None));
55+
if opts.aggressive && opts.precise.is_some() {
56+
return Err(human("cannot specify both aggressive and precise \
57+
simultaneously"))
58+
}
59+
60+
let mut config = try!(Config::new(opts.shell, None, None));
5161
let mut registry = PackageRegistry::new(&mut config);
5262

53-
let sources = match to_update {
63+
let mut sources = Vec::new();
64+
match opts.to_update {
5465
Some(name) => {
5566
let mut to_avoid = HashSet::new();
56-
let dep = try!(resolve.query(name.as_slice()));
57-
if aggressive {
67+
let dep = try!(resolve.query(name));
68+
if opts.aggressive {
5869
fill_with_deps(&resolve, dep, &mut to_avoid);
5970
} else {
6071
to_avoid.insert(dep);
72+
match opts.precise {
73+
Some(precise) => {
74+
sources.push(dep.get_source_id().clone()
75+
.with_precise(precise.to_string()));
76+
}
77+
None => {}
78+
}
6179
}
62-
resolve.iter().filter(|pkgid| !to_avoid.contains(pkgid))
63-
.map(|pkgid| pkgid.get_source_id().clone()).collect()
80+
sources.extend(resolve.iter()
81+
.filter(|p| !to_avoid.contains(p))
82+
.map(|p| p.get_source_id().clone()));
6483
}
65-
None => package.get_source_ids(),
66-
};
84+
None => sources.extend(package.get_source_ids().into_iter()),
85+
}
6786
try!(registry.add_sources(sources));
6887

6988
let resolve = try!(resolver::resolve(package.get_summary(),

src/cargo/ops/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub use self::cargo_new::{new, NewOptions};
77
pub use self::cargo_doc::{doc, DocOptions};
88
pub use self::cargo_generate_lockfile::{generate_lockfile, write_resolve};
99
pub use self::cargo_generate_lockfile::{update_lockfile, load_lockfile};
10+
pub use self::cargo_generate_lockfile::UpdateOptions;
1011
pub use self::cargo_test::{run_tests, run_benches, TestOptions};
1112
pub use self::cargo_package::package;
1213
pub use self::cargo_upload::{upload, upload_configuration, UploadConfig};

src/cargo/util/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,13 @@ impl ConfigValue {
144144
toml::String(val) => Ok((val, path.clone())),
145145
_ => Err(internal("")),
146146
}
147-
}).collect::<Result<_, _>>())))
147+
}).collect::<CargoResult<_>>())))
148148
}
149149
toml::Table(val) => {
150150
Ok(Table(try!(val.into_iter().map(|(key, value)| {
151151
let value = raw_try!(ConfigValue::from_toml(path, value));
152152
Ok((key, value))
153-
}).collect::<Result<_, _>>())))
153+
}).collect::<CargoResult<_>>())))
154154
}
155155
_ => return Err(internal(""))
156156
}

tests/test_cargo_compile_git_deps.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,13 +681,23 @@ test!(update_with_shared_deps {
681681
pub fn bar() { println!("hello!"); }
682682
"#).assert();
683683
let repo = git2::Repository::open(&git_project.root()).unwrap();
684+
let old_head = repo.head().unwrap().target().unwrap();
684685
add(&repo);
685686
commit(&repo);
686687

687688
timer::sleep(Duration::milliseconds(1000));
688689

690+
// By default, not transitive updates
689691
assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("dep1"),
690692
execs().with_stdout(""));
693+
694+
// Specifying a precise rev to the old rev shouldn't actually update
695+
// anything because we already have the rev in the db.
696+
assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("bar")
697+
.arg("--precise").arg(old_head.to_string()),
698+
execs().with_stdout(""));
699+
700+
// Updating aggressively should, however, update the repo.
691701
assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("dep1")
692702
.arg("--aggressive"),
693703
execs().with_stdout(format!("{} git repository `{}`",

0 commit comments

Comments
 (0)