Skip to content

Commit 8921abd

Browse files
committed
Make "cargo uninstall" uninstall the cwd bins
1 parent c0ec76f commit 8921abd

File tree

3 files changed

+101
-19
lines changed

3 files changed

+101
-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)?,
@@ -418,6 +407,14 @@ fn install_one(
418407
Ok(())
419408
}
420409

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

800825
for bin in bins.iter() {
801826
if !installed.get().contains(bin) {
802-
bail!("binary `{}` not installed as part of `{}`", bin, result)
827+
bail!("binary `{}` not installed as part of `{}`", bin, pkgid)
803828
}
804829
}
805830

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

+53
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,59 @@ 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+
assert_that(
874+
cargo_process("uninstall"),
875+
execs().with_status(101).with_stdout("").with_stderr(format!("\
876+
[ERROR] failed to read `{root}/Cargo.toml`
877+
878+
Caused by:
879+
No such file or directory (os error 2)",
880+
root = paths::root().display(),
881+
)),
882+
);
883+
}
884+
832885
#[test]
833886
fn do_not_rebuilds_on_local_install() {
834887
let p = project()

0 commit comments

Comments
 (0)