1
1
//! Core of cargo-remove command
2
2
3
3
use crate :: core:: Package ;
4
+ use crate :: core:: Workspace ;
4
5
use crate :: util:: toml_mut:: manifest:: DepTable ;
5
6
use crate :: util:: toml_mut:: manifest:: LocalManifest ;
6
7
use crate :: CargoResult ;
@@ -11,6 +12,8 @@ use crate::Config;
11
12
pub struct RemoveOptions < ' a > {
12
13
/// Configuration information for Cargo operations
13
14
pub config : & ' a Config ,
15
+ /// Workspace in which the operation is occurring.
16
+ pub workspace : & ' a Workspace < ' a > ,
14
17
/// Package to remove dependencies from
15
18
pub spec : & ' a Package ,
16
19
/// Dependencies to remove
@@ -33,7 +36,18 @@ pub fn remove(options: &RemoveOptions<'_>) -> CargoResult<()> {
33
36
let manifest_path = options. spec . manifest_path ( ) . to_path_buf ( ) ;
34
37
let mut manifest = LocalManifest :: try_new ( & manifest_path) ?;
35
38
39
+ // virtual manifest, if exists
40
+ let mut virtual_manifest = if options. workspace . is_virtual ( ) {
41
+ let data = cargo_util:: paths:: read ( options. workspace . root_manifest ( ) ) ?;
42
+ let manifest: toml_edit:: Document = data. parse ( ) ?;
43
+ Some ( manifest)
44
+ } else {
45
+ None
46
+ } ;
47
+
36
48
for dep in & options. dependencies {
49
+ let is_workspace_dep = dependency_is_workspace ( dep, & dep_table, & manifest) ;
50
+
37
51
let section = if dep_table. len ( ) >= 3 {
38
52
format ! ( "{} for target `{}`" , & dep_table[ 2 ] , & dep_table[ 1 ] )
39
53
} else {
@@ -50,6 +64,23 @@ pub fn remove(options: &RemoveOptions<'_>) -> CargoResult<()> {
50
64
// crate, then we need to drop any explicitly activated features on
51
65
// that crate.
52
66
manifest. gc_dep ( dep) ;
67
+
68
+ // If this was the last instance of a workspace dependency, remove it
69
+ // from the workspace dependencies.
70
+ if is_workspace_dep {
71
+ let workspace_manifest = match & mut virtual_manifest {
72
+ Some ( virtual_manifest) => virtual_manifest,
73
+ None => & mut manifest. data ,
74
+ } ;
75
+ if !dependency_in_workspace ( dep, options. spec , options. workspace ) {
76
+ remove_dependency_from_workspace ( dep, workspace_manifest) ;
77
+
78
+ options
79
+ . config
80
+ . shell ( )
81
+ . status ( "Removing" , format ! ( "{dep} from workspace dependencies" ) ) ?;
82
+ }
83
+ }
53
84
}
54
85
55
86
if options. dry_run {
@@ -59,7 +90,46 @@ pub fn remove(options: &RemoveOptions<'_>) -> CargoResult<()> {
59
90
. warn ( "aborting remove due to dry run" ) ?;
60
91
} else {
61
92
manifest. write ( ) ?;
93
+
94
+ if let Some ( virtual_manifest) = virtual_manifest {
95
+ cargo_util:: paths:: write (
96
+ options. workspace . root_manifest ( ) ,
97
+ virtual_manifest. to_string ( ) . as_bytes ( ) ,
98
+ ) ?;
99
+ }
62
100
}
63
101
64
102
Ok ( ( ) )
65
103
}
104
+
105
+ /// Get whether or not a dependency is marked as `workspace`.
106
+ fn dependency_is_workspace ( dep : & str , dep_table : & [ String ] , manifest : & LocalManifest ) -> bool {
107
+ if let Ok ( toml_edit:: Item :: Table ( table) ) = manifest. get_table ( dep_table) {
108
+ let value = table. get ( dep) . and_then ( |i| i. get ( "workspace" ) ) ;
109
+ if let Some ( toml_edit:: Item :: Value ( value) ) = value {
110
+ return value. as_bool ( ) == Some ( true ) ;
111
+ }
112
+ }
113
+
114
+ false
115
+ }
116
+
117
+ /// Get whether or not a dependency is depended upon in a workspace.
118
+ fn dependency_in_workspace ( dep : & str , exclude : & Package , workspace : & Workspace < ' _ > ) -> bool {
119
+ workspace. members ( ) . filter ( |p| * p != exclude) . any ( |p| {
120
+ p. dependencies ( )
121
+ . iter ( )
122
+ . any ( |d| d. package_name ( ) . as_str ( ) == dep)
123
+ } )
124
+ }
125
+
126
+ /// Remove a dependency from a virtual workspace.
127
+ fn remove_dependency_from_workspace ( dep : & str , virtual_manifest : & mut toml_edit:: Document ) {
128
+ if let Some ( toml_edit:: Item :: Table ( table) ) = virtual_manifest
129
+ . get_mut ( "workspace" )
130
+ . and_then ( |t| t. get_mut ( "dependencies" ) )
131
+ {
132
+ table. set_implicit ( true ) ;
133
+ table. remove ( dep) ;
134
+ }
135
+ }
0 commit comments