1 use crate::core
::PackageId
;
2 use crate::core
::{PackageIdSpec, SourceId}
;
3 use crate::ops
::common_for_install_and_uninstall
::*;
4 use crate::sources
::PathSource
;
5 use crate::util
::errors
::CargoResult
;
6 use crate::util
::Config
;
7 use crate::util
::Filesystem
;
10 use std
::collections
::BTreeSet
;
18 ) -> CargoResult
<()> {
19 if specs
.len() > 1 && !bins
.is_empty() {
20 bail
!("A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant.");
23 let root
= resolve_root(root
, config
)?
;
24 let scheduled_error
= if specs
.len() == 1 {
25 uninstall_one(&root
, specs
[0], bins
, config
)?
;
27 } else if specs
.is_empty() {
28 uninstall_cwd(&root
, bins
, config
)?
;
31 let mut succeeded
= vec
![];
32 let mut failed
= vec
![];
34 let root
= root
.clone();
35 match uninstall_one(&root
, spec
, bins
, config
) {
36 Ok(()) => succeeded
.push(spec
),
38 crate::display_error(&e
, &mut config
.shell());
44 let mut summary
= vec
![];
45 if !succeeded
.is_empty() {
47 "Successfully uninstalled {}!",
51 if !failed
.is_empty() {
53 "Failed to uninstall {} (see error(s) above).",
58 if !succeeded
.is_empty() || !failed
.is_empty() {
59 config
.shell().status("Summary", summary
.join(" "))?
;
66 bail
!("some packages failed to uninstall");
77 ) -> CargoResult
<()> {
78 let tracker
= InstallTracker
::load(config
, root
)?
;
79 let all_pkgs
= tracker
.all_installed_bins().map(|(pkg_id
, _set
)| *pkg_id
);
80 let pkgid
= PackageIdSpec
::query_str(spec
, all_pkgs
)?
;
81 uninstall_pkgid(root
, tracker
, pkgid
, bins
, config
)
84 fn uninstall_cwd(root
: &Filesystem
, bins
: &[String
], config
: &Config
) -> CargoResult
<()> {
85 let tracker
= InstallTracker
::load(config
, root
)?
;
86 let source_id
= SourceId
::for_path(config
.cwd())?
;
87 let mut src
= path_source(source_id
, config
)?
;
91 |path
: &mut PathSource
<'_
>| path
.read_packages(),
94 let pkgid
= pkg
.package_id();
95 uninstall_pkgid(root
, tracker
, pkgid
, bins
, config
)
100 mut tracker
: InstallTracker
,
104 ) -> CargoResult
<()> {
105 let mut to_remove
= Vec
::new();
106 let installed
= match tracker
.installed_bins(pkgid
) {
107 Some(bins
) => bins
.clone(),
108 None
=> bail
!("package `{}` is not installed", pkgid
),
111 let dst
= root
.join("bin").into_path_unlocked();
112 for bin
in &installed
{
113 let bin
= dst
.join(bin
);
116 "corrupt metadata, `{}` does not exist when it should",
125 if s
.ends_with(env
::consts
::EXE_SUFFIX
) {
128 format
!("{}{}", s
, env
::consts
::EXE_SUFFIX
)
131 .collect
::<BTreeSet
<_
>>();
133 for bin
in bins
.iter() {
134 if !installed
.contains(bin
) {
135 bail
!("binary `{}` not installed as part of `{}`", bin
, pkgid
)
140 to_remove
.extend(installed
.iter().map(|b
| dst
.join(b
)));
141 tracker
.remove(pkgid
, &installed
);
143 for bin
in bins
.iter() {
144 to_remove
.push(dst
.join(bin
));
146 tracker
.remove(pkgid
, &bins
);
149 for bin
in to_remove
{
150 config
.shell().status("Removing", bin
.display())?
;
151 paths
::remove_file(bin
)?
;