Skip to content

Commit 8537ab9

Browse files
committed
Auto merge of #5927 - dwijnand:uninstall-cwd, r=ehuss
Make "cargo uninstall" uninstall the cwd bins Fixes #5916 Tested with a local build of cargo, using coreutils: 17:33:57 $ dcargo uninstall Removing /Users/dnw/.cargo/bin/uutils
2 parents 502f0ae + d87951a commit 8537ab9

File tree

3 files changed

+107
-19
lines changed

3 files changed

+107
-19
lines changed

src/cargo/ops/cargo_install.rs

+44-19
Original file line numberDiff line numberDiff line change
@@ -171,27 +171,16 @@ fn install_one(
171171
&mut |git| git.read_packages(),
172172
)?
173173
} else if source_id.is_path() {
174-
let path = source_id
175-
.url()
176-
.to_file_path()
177-
.map_err(|()| format_err!("path sources must have a valid path"))?;
178-
let mut src = PathSource::new(&path, source_id, config);
174+
let mut src = path_source(source_id, config)?;
179175
src.update().chain_err(|| {
180176
format_err!(
181177
"`{}` is not a crate root; specify a crate to \
182178
install from crates.io, or use --path or --git to \
183179
specify an alternate source",
184-
path.display()
180+
src.path().display()
185181
)
186182
})?;
187-
select_pkg(
188-
PathSource::new(&path, source_id, config),
189-
krate,
190-
vers,
191-
config,
192-
is_first_install,
193-
&mut |path| path.read_packages(),
194-
)?
183+
select_pkg(src, krate, vers, config, false, &mut |path| path.read_packages())?
195184
} else {
196185
select_pkg(
197186
map.load(source_id)?,
@@ -419,6 +408,14 @@ fn install_one(
419408
Ok(())
420409
}
421410

411+
fn path_source<'a>(source_id: &SourceId, config: &'a Config) -> CargoResult<PathSource<'a>> {
412+
let path = source_id
413+
.url()
414+
.to_file_path()
415+
.map_err(|()| format_err!("path sources must have a valid path"))?;
416+
Ok(PathSource::new(&path, source_id, config))
417+
}
418+
422419
fn select_pkg<'a, T>(
423420
mut source: T,
424421
name: Option<&str>,
@@ -720,6 +717,9 @@ pub fn uninstall(
720717
let scheduled_error = if specs.len() == 1 {
721718
uninstall_one(&root, specs[0], bins, config)?;
722719
false
720+
} else if specs.len() == 0 {
721+
uninstall_cwd(&root, bins, config)?;
722+
false
723723
} else {
724724
let mut succeeded = vec![];
725725
let mut failed = vec![];
@@ -769,13 +769,38 @@ pub fn uninstall_one(
769769
config: &Config,
770770
) -> CargoResult<()> {
771771
let crate_metadata = metadata(config, root)?;
772-
let mut metadata = read_crate_list(&crate_metadata)?;
772+
let metadata = read_crate_list(&crate_metadata)?;
773+
let pkgid = PackageIdSpec::query_str(spec, metadata.v1.keys())?.clone();
774+
uninstall_pkgid(crate_metadata, metadata, &pkgid, bins, config)
775+
}
776+
777+
fn uninstall_cwd(
778+
root: &Filesystem,
779+
bins: &[String],
780+
config: &Config,
781+
) -> CargoResult<()> {
782+
let crate_metadata = metadata(config, root)?;
783+
let metadata = read_crate_list(&crate_metadata)?;
784+
let source_id = SourceId::for_path(config.cwd())?;
785+
let src = path_source(&source_id, config)?;
786+
let (pkg, _source) =
787+
select_pkg(src, None, None, config, true, &mut |path| path.read_packages())?;
788+
let pkgid = pkg.package_id();
789+
uninstall_pkgid(crate_metadata, metadata, pkgid, bins, config)
790+
}
791+
792+
fn uninstall_pkgid(
793+
crate_metadata: FileLock,
794+
mut metadata: CrateListingV1,
795+
pkgid: &PackageId,
796+
bins: &[String],
797+
config: &Config,
798+
) -> CargoResult<()> {
773799
let mut to_remove = Vec::new();
774800
{
775-
let result = PackageIdSpec::query_str(spec, metadata.v1.keys())?.clone();
776-
let mut installed = match metadata.v1.entry(result.clone()) {
801+
let mut installed = match metadata.v1.entry(pkgid.clone()) {
777802
Entry::Occupied(e) => e,
778-
Entry::Vacant(..) => panic!("entry not found: {}", result),
803+
Entry::Vacant(..) => bail!("package `{}` is not installed", pkgid),
779804
};
780805
let dst = crate_metadata.parent().join("bin");
781806
for bin in installed.get() {
@@ -800,7 +825,7 @@ pub fn uninstall_one(
800825

801826
for bin in bins.iter() {
802827
if !installed.get().contains(bin) {
803-
bail!("binary `{}` not installed as part of `{}`", bin, result)
828+
bail!("binary `{}` not installed as part of `{}`", bin, pkgid)
804829
}
805830
}
806831

src/cargo/sources/path.rs

+4
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,10 @@ impl<'cfg> PathSource<'cfg> {
489489
trace!("last modified file {}: {}", self.path.display(), max);
490490
Ok((max, max_path))
491491
}
492+
493+
pub fn path(&self) -> &Path {
494+
&self.path
495+
}
492496
}
493497

494498
impl<'cfg> Debug for PathSource<'cfg> {

tests/testsuite/install.rs

+59
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,65 @@ fn installs_from_cwd_with_2018_warnings() {
829829
assert_that(cargo_home(), is_not(has_installed_exe("foo")));
830830
}
831831

832+
#[test]
833+
fn uninstall_cwd() {
834+
let p = project().file("src/main.rs", "fn main() {}").build();
835+
assert_that(
836+
p.cargo("install --path ."),
837+
execs().with_stderr(&format!("\
838+
[INSTALLING] foo v0.0.1 ({url})
839+
[COMPILING] foo v0.0.1 ({url})
840+
[FINISHED] release [optimized] target(s) in [..]
841+
[INSTALLING] {home}/bin/foo[EXE]
842+
warning: be sure to add `{home}/bin` to your PATH to be able to run the installed binaries",
843+
home = cargo_home().display(),
844+
url = p.url(),
845+
)),
846+
);
847+
assert_that(cargo_home(), has_installed_exe("foo"));
848+
849+
assert_that(
850+
p.cargo("uninstall"),
851+
execs().with_stdout("").with_stderr(&format!("\
852+
[REMOVING] {home}/bin/foo[EXE]",
853+
home = cargo_home().display()
854+
)),
855+
);
856+
assert_that(cargo_home(), is_not(has_installed_exe("foo")));
857+
}
858+
859+
#[test]
860+
fn uninstall_cwd_not_installed() {
861+
let p = project().file("src/main.rs", "fn main() {}").build();
862+
assert_that(
863+
p.cargo("uninstall"),
864+
execs().with_status(101).with_stdout("").with_stderr(format!("\
865+
error: package `foo v0.0.1 ({url})` is not installed",
866+
url = p.url(),
867+
)),
868+
);
869+
}
870+
871+
#[test]
872+
fn uninstall_cwd_no_project() {
873+
let err_msg = if cfg!(windows) {
874+
"The system cannot find the file specified."
875+
} else {
876+
"No such file or directory"
877+
};
878+
assert_that(
879+
cargo_process("uninstall"),
880+
execs().with_status(101).with_stdout("").with_stderr(format!("\
881+
[ERROR] failed to read `{root}/Cargo.toml`
882+
883+
Caused by:
884+
{err_msg} (os error 2)",
885+
root = paths::root().display(),
886+
err_msg = err_msg,
887+
)),
888+
);
889+
}
890+
832891
#[test]
833892
fn do_not_rebuilds_on_local_install() {
834893
let p = project()

0 commit comments

Comments
 (0)