Skip to content

Commit

Permalink
Add --update-only flag to cargo-add
Browse files Browse the repository at this point in the history
This adds the specified dependency/ies only if they are already present. Thus, it acts like a 'cargo upgrade' (see killercup#74)
  • Loading branch information
bjgill committed Jun 18, 2017
1 parent c914202 commit 39bf731
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/bin/add/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub struct Args {
pub flag_version: bool,
/// `---upgrade`
pub flag_upgrade: Option<String>,
/// `--update-only`
pub flag_update_only: bool,
/// '--fetch-prereleases'
pub flag_allow_prerelease: bool,
}
Expand Down Expand Up @@ -144,6 +146,7 @@ impl Default for Args {
flag_manifest_path: None,
flag_version: false,
flag_upgrade: None,
flag_update_only: false,
flag_allow_prerelease: false,
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/bin/add/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Options:
--upgrade=<method> Choose method of semantic version upgrade. Must be one of
"none" (exact version), "patch" (`~` modifier), "minor"
(`^` modifier, default), or "all" (`>=`).
--update-only Only add the updated dependency if it already exists.
--manifest-path=<path> Path to the manifest to add a dependency to.
--allow-prerelease Include prerelease versions when fetching from crates.io (e.g.
'0.6.0-alpha'). Defaults to false.
Expand All @@ -72,12 +73,17 @@ fn handle_add(args: &Args) -> Result<(), Box<Error>> {
let mut manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
let deps = try!(args.parse_dependencies());

for dep in deps {
if let Err(err) = manifest.insert_into_table(&args.get_section(), &dep) {
deps
.iter()
.map(|dep| if args.flag_update_only {
manifest.update_table_entry(&args.get_section(), &dep)
} else {
manifest.insert_into_table(&args.get_section(), &dep)})
.collect::<Result<Vec<_>,_>>()
.map_err(|err| {
println!("Could not edit `Cargo.toml`.\n\nERROR: {}", err);
return Err(From::from(err));
}
}
err
})?;

let mut file = try!(Manifest::find_file(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
manifest.write_to_file(&mut file)
Expand Down
50 changes: 48 additions & 2 deletions src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,8 @@ impl Manifest {
dep: &Dependency)
-> Result<(), ManifestError> {
let (ref name, ref data) = dep.to_toml();
let manifest = &mut self.data;

let mut entry = manifest;
let mut entry = &mut self.data;
for part in table {
let tmp_entry = entry; // Make the borrow checker happy
let value = tmp_entry.entry(part.clone())
Expand All @@ -181,6 +180,30 @@ impl Manifest {
Ok(())
}

/// Update an entry in Cargo.toml.
#[cfg_attr(feature = "dev", allow(toplevel_ref_arg))]
pub fn update_table_entry(&mut self,
table: &[String],
dep: &Dependency)
-> Result<(), ManifestError> {
let (ref name, ref data) = dep.to_toml();

let mut entry = &mut self.data;
for part in table {
let tmp_entry = entry; // Make the borrow checker happy
let value = tmp_entry.entry(part.clone())
.or_insert_with(|| toml::Value::Table(BTreeMap::new()));
match *value {
toml::Value::Table(ref mut table) => entry = table,
_ => return Err(ManifestError::NonExistentTable(part.clone())),
}
}
if entry.contains_key(name) {
entry.insert(name.clone(), data.clone());
}
Ok(())
}

/// Remove entry from a Cargo.toml.
///
/// # Examples
Expand Down Expand Up @@ -277,6 +300,29 @@ mod tests {
assert_eq!(manifest, clone);
}

#[test]
fn update_dependency() {
let mut manifest = Manifest { data: toml::Table::new() };
let dep = Dependency::new("cargo-edit").set_version("0.1.0");
manifest.insert_into_table(&["dependencies".to_owned()], &dep).unwrap();

let new_dep = Dependency::new("cargo-edit").set_version("0.2.0");
manifest.update_table_entry(&["dependencies".to_owned()], &new_dep).unwrap();
}

#[test]
fn update_wrong_dependency() {
let mut manifest = Manifest { data: toml::Table::new() };
let dep = Dependency::new("cargo-edit").set_version("0.1.0");
manifest.insert_into_table(&["dependencies".to_owned()], &dep).unwrap();
let original = manifest.clone();

let new_dep = Dependency::new("wrong-dep").set_version("0.2.0");
manifest.update_table_entry(&["dependencies".to_owned()], &new_dep).unwrap();

assert_eq!(manifest, original);
}

#[test]
fn remove_dependency_no_section() {
let mut manifest = Manifest { data: toml::Table::new() };
Expand Down

0 comments on commit 39bf731

Please sign in to comment.