1
1
use cargo:: core:: dependency:: DepKind ;
2
+ use cargo:: core:: PackageIdSpec ;
2
3
use cargo:: core:: Workspace ;
3
4
use cargo:: ops:: cargo_remove:: remove;
4
5
use cargo:: ops:: cargo_remove:: RemoveOptions ;
@@ -88,8 +89,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
88
89
remove ( & options) ?;
89
90
90
91
if !dry_run {
91
- // Clean up workspace dependencies
92
- gc_workspace ( & workspace, & options . dependencies ) ?;
92
+ // Clean up the workspace
93
+ gc_workspace ( & workspace) ?;
93
94
94
95
// Reload the workspace since we've changed dependencies
95
96
let ws = args. workspace ( config) ?;
@@ -121,8 +122,9 @@ fn parse_section(args: &ArgMatches) -> DepTable {
121
122
table
122
123
}
123
124
124
- /// Clean up workspace dependencies which no longer have a reference to them.
125
- fn gc_workspace ( workspace : & Workspace < ' _ > , dependencies : & [ String ] ) -> CargoResult < ( ) > {
125
+ /// Clean up the workspace.dependencies and replace sections of a root manifest
126
+ /// by removing dependencies which no longer have a reference to them.
127
+ fn gc_workspace ( workspace : & Workspace < ' _ > ) -> CargoResult < ( ) > {
126
128
let mut manifest: toml_edit:: Document =
127
129
cargo_util:: paths:: read ( workspace. root_manifest ( ) ) ?. parse ( ) ?;
128
130
@@ -131,39 +133,72 @@ fn gc_workspace(workspace: &Workspace<'_>, dependencies: &[String]) -> CargoResu
131
133
. map ( |p| LocalManifest :: try_new ( p. manifest_path ( ) ) )
132
134
. collect :: < CargoResult < Vec < _ > > > ( ) ?;
133
135
134
- for dep in dependencies {
135
- if !dep_in_workspace ( dep, & members) {
136
- remove_workspace_dep ( dep, & mut manifest) ;
137
- }
138
- }
136
+ gc_workspace_dependencies ( & mut manifest, & members) ;
137
+ gc_replace ( & mut manifest, & members) ;
139
138
140
139
cargo_util:: paths:: write ( workspace. root_manifest ( ) , manifest. to_string ( ) . as_bytes ( ) ) ?;
141
140
142
141
Ok ( ( ) )
143
142
}
144
143
145
- /// Get whether or not a dependency is depended upon in a workspace .
146
- fn dep_in_workspace ( dep : & str , members : & [ LocalManifest ] ) -> bool {
147
- members . iter ( ) . any ( |manifest | {
148
- manifest . get_sections ( ) . iter ( ) . any ( |( _ , table ) | {
149
- table
150
- . as_table_like ( )
151
- . unwrap ( )
152
- . get ( dep )
153
- . and_then ( |t| t . get ( "workspace" ) )
154
- . and_then ( |v| v . as_bool ( ) )
155
- . unwrap_or ( false )
144
+ /// Clean up the workspace.dependencies section in a root manifest .
145
+ fn gc_workspace_dependencies ( manifest : & mut toml_edit :: Document , members : & [ LocalManifest ] ) {
146
+ let in_workspace = | dep : & str | {
147
+ members . iter ( ) . any ( |manifest | {
148
+ manifest . get_sections ( ) . iter ( ) . any ( | ( _ , table) | {
149
+ let dep_item = table . as_table_like ( ) . unwrap ( ) . get ( dep ) ;
150
+ dep_item
151
+ . and_then ( |t| t . get ( "workspace" ) )
152
+ . and_then ( |i| i . as_bool ( ) )
153
+ . unwrap_or ( false )
154
+ } )
156
155
} )
157
- } )
158
- }
156
+ } ;
159
157
160
- /// Remove a dependency from a workspace manifest.
161
- fn remove_workspace_dep ( dep : & str , ws_manifest : & mut toml_edit:: Document ) {
162
- if let Some ( toml_edit:: Item :: Table ( table) ) = ws_manifest
158
+ if let Some ( toml_edit:: Item :: Table ( table) ) = manifest
163
159
. get_mut ( "workspace" )
164
160
. and_then ( |t| t. get_mut ( "dependencies" ) )
165
161
{
166
162
table. set_implicit ( true ) ;
167
- table. remove ( dep) ;
163
+
164
+ for ( key, item) in table. iter_mut ( ) {
165
+ if !in_workspace ( key. get ( ) ) {
166
+ * item = toml_edit:: Item :: None ;
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ /// Clean up the replace section in a root manifest.
173
+ fn gc_replace ( manifest : & mut toml_edit:: Document , members : & [ LocalManifest ] ) {
174
+ let in_workspace = |dep : & str , version : & Option < & semver:: Version > | {
175
+ members. iter ( ) . any ( |manifest| {
176
+ let mut deps = manifest
177
+ . get_dependency_versions ( dep)
178
+ . filter_map ( |( _, d) | d. ok ( ) )
179
+ . filter ( |d| d. name == dep) ;
180
+
181
+ if let Some ( version) = version {
182
+ deps. any ( |d| {
183
+ d. version ( )
184
+ . and_then ( |v| semver:: VersionReq :: parse ( v) . ok ( ) )
185
+ . map ( |vq| vq. matches ( version) )
186
+ . unwrap_or ( false )
187
+ } )
188
+ } else {
189
+ deps. next ( ) . is_some ( )
190
+ }
191
+ } )
192
+ } ;
193
+
194
+ if let Some ( toml_edit:: Item :: Table ( table) ) = manifest. get_mut ( "replace" ) {
195
+ table. set_implicit ( true ) ;
196
+ for ( key, item) in table. iter_mut ( ) {
197
+ if let Ok ( spec) = PackageIdSpec :: parse ( key. get ( ) ) {
198
+ if !in_workspace ( spec. name ( ) . as_str ( ) , & spec. version ( ) ) {
199
+ * item = toml_edit:: Item :: None ;
200
+ }
201
+ }
202
+ }
168
203
}
169
204
}
0 commit comments