mirror of
https://github.com/rust-lang/cargo
synced 2024-10-06 15:59:39 +00:00
Allow updating to a precise revision
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
This commit is contained in:
parent
3b814b64c2
commit
c098a9a7a9
|
@ -15,6 +15,7 @@ Usage:
|
|||
Options:
|
||||
-h, --help Print this message
|
||||
--aggressive Force updating all dependencies of <name> as well
|
||||
--precise PRECISE Update a single dependency to exactly PRECISE
|
||||
--manifest-path PATH Path to the manifest to compile
|
||||
-v, --verbose Use verbose output
|
||||
|
||||
|
@ -27,18 +28,32 @@ updated. Its transitive dependencies will be updated only if <spec> cannot be
|
|||
updated without updating dependencies. All other dependencies will remain
|
||||
locked at their currently recorded versions.
|
||||
|
||||
If PRECISE is specified, then --aggressive must not also be specified. The
|
||||
argument PRECISE is a string representing a precise revision that the package
|
||||
being updated should be updated to. For example, if the package comes from a git
|
||||
repository, then PRECISE would be the exact revision that the repository should
|
||||
be updated to.
|
||||
|
||||
If <spec> is not given, then all dependencies will be re-resolved and
|
||||
updated.
|
||||
|
||||
For more information about package ids, see `cargo help pkgid`.
|
||||
", flag_manifest_path: Option<String>, arg_spec: Option<String>)
|
||||
", flag_manifest_path: Option<String>, arg_spec: Option<String>,
|
||||
flag_precise: Option<String>)
|
||||
|
||||
pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
|
||||
debug!("executing; cmd=cargo-update; args={}", os::args());
|
||||
shell.set_verbose(options.flag_verbose);
|
||||
let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
|
||||
|
||||
ops::update_lockfile(&root, shell, options.arg_spec, options.flag_aggressive)
|
||||
let mut update_opts = ops::UpdateOptions {
|
||||
aggressive: options.flag_aggressive,
|
||||
precise: options.flag_precise.as_ref().map(|s| s.as_slice()),
|
||||
to_update: options.arg_spec.as_ref().map(|s| s.as_slice()),
|
||||
shell: shell,
|
||||
};
|
||||
|
||||
ops::update_lockfile(&root, &mut update_opts)
|
||||
.map(|_| None).map_err(|err| CliError::from_boxed(err, 101))
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,13 @@ use util::config::{Config};
|
|||
use util::{CargoResult, human};
|
||||
use util::toml as cargo_toml;
|
||||
|
||||
pub struct UpdateOptions<'a> {
|
||||
pub shell: &'a mut MultiShell<'a>,
|
||||
pub to_update: Option<&'a str>,
|
||||
pub precise: Option<&'a str>,
|
||||
pub aggressive: bool,
|
||||
}
|
||||
|
||||
pub fn generate_lockfile(manifest_path: &Path,
|
||||
shell: &mut MultiShell)
|
||||
-> CargoResult<()> {
|
||||
|
@ -33,9 +40,7 @@ pub fn generate_lockfile(manifest_path: &Path,
|
|||
}
|
||||
|
||||
pub fn update_lockfile(manifest_path: &Path,
|
||||
shell: &mut MultiShell,
|
||||
to_update: Option<String>,
|
||||
aggressive: bool) -> CargoResult<()> {
|
||||
opts: &mut UpdateOptions) -> CargoResult<()> {
|
||||
let mut source = try!(PathSource::for_path(&manifest_path.dir_path()));
|
||||
try!(source.update());
|
||||
let package = try!(source.get_root_package());
|
||||
|
@ -47,23 +52,37 @@ pub fn update_lockfile(manifest_path: &Path,
|
|||
None => return Err(human("A Cargo.lock must exist before it is updated"))
|
||||
};
|
||||
|
||||
let mut config = try!(Config::new(shell, None, None));
|
||||
if opts.aggressive && opts.precise.is_some() {
|
||||
return Err(human("cannot specify both aggressive and precise \
|
||||
simultaneously"))
|
||||
}
|
||||
|
||||
let mut config = try!(Config::new(opts.shell, None, None));
|
||||
let mut registry = PackageRegistry::new(&mut config);
|
||||
|
||||
let sources = match to_update {
|
||||
let mut sources = Vec::new();
|
||||
match opts.to_update {
|
||||
Some(name) => {
|
||||
let mut to_avoid = HashSet::new();
|
||||
let dep = try!(resolve.query(name.as_slice()));
|
||||
if aggressive {
|
||||
let dep = try!(resolve.query(name));
|
||||
if opts.aggressive {
|
||||
fill_with_deps(&resolve, dep, &mut to_avoid);
|
||||
} else {
|
||||
to_avoid.insert(dep);
|
||||
match opts.precise {
|
||||
Some(precise) => {
|
||||
sources.push(dep.get_source_id().clone()
|
||||
.with_precise(precise.to_string()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
resolve.iter().filter(|pkgid| !to_avoid.contains(pkgid))
|
||||
.map(|pkgid| pkgid.get_source_id().clone()).collect()
|
||||
sources.extend(resolve.iter()
|
||||
.filter(|p| !to_avoid.contains(p))
|
||||
.map(|p| p.get_source_id().clone()));
|
||||
}
|
||||
None => package.get_source_ids(),
|
||||
};
|
||||
None => sources.extend(package.get_source_ids().into_iter()),
|
||||
}
|
||||
try!(registry.add_sources(sources));
|
||||
|
||||
let resolve = try!(resolver::resolve(package.get_summary(),
|
||||
|
|
|
@ -7,6 +7,7 @@ pub use self::cargo_new::{new, NewOptions};
|
|||
pub use self::cargo_doc::{doc, DocOptions};
|
||||
pub use self::cargo_generate_lockfile::{generate_lockfile, write_resolve};
|
||||
pub use self::cargo_generate_lockfile::{update_lockfile, load_lockfile};
|
||||
pub use self::cargo_generate_lockfile::UpdateOptions;
|
||||
pub use self::cargo_test::{run_tests, run_benches, TestOptions};
|
||||
pub use self::cargo_package::package;
|
||||
pub use self::cargo_upload::{upload, upload_configuration, UploadConfig};
|
||||
|
|
|
@ -144,13 +144,13 @@ impl ConfigValue {
|
|||
toml::String(val) => Ok((val, path.clone())),
|
||||
_ => Err(internal("")),
|
||||
}
|
||||
}).collect::<Result<_, _>>())))
|
||||
}).collect::<CargoResult<_>>())))
|
||||
}
|
||||
toml::Table(val) => {
|
||||
Ok(Table(try!(val.into_iter().map(|(key, value)| {
|
||||
let value = raw_try!(ConfigValue::from_toml(path, value));
|
||||
Ok((key, value))
|
||||
}).collect::<Result<_, _>>())))
|
||||
}).collect::<CargoResult<_>>())))
|
||||
}
|
||||
_ => return Err(internal(""))
|
||||
}
|
||||
|
|
|
@ -681,13 +681,23 @@ test!(update_with_shared_deps {
|
|||
pub fn bar() { println!("hello!"); }
|
||||
"#).assert();
|
||||
let repo = git2::Repository::open(&git_project.root()).unwrap();
|
||||
let old_head = repo.head().unwrap().target().unwrap();
|
||||
add(&repo);
|
||||
commit(&repo);
|
||||
|
||||
timer::sleep(Duration::milliseconds(1000));
|
||||
|
||||
// By default, not transitive updates
|
||||
assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("dep1"),
|
||||
execs().with_stdout(""));
|
||||
|
||||
// Specifying a precise rev to the old rev shouldn't actually update
|
||||
// anything because we already have the rev in the db.
|
||||
assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("bar")
|
||||
.arg("--precise").arg(old_head.to_string()),
|
||||
execs().with_stdout(""));
|
||||
|
||||
// Updating aggressively should, however, update the repo.
|
||||
assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("dep1")
|
||||
.arg("--aggressive"),
|
||||
execs().with_stdout(format!("{} git repository `{}`",
|
||||
|
|
Loading…
Reference in a new issue