willbe/entity/
dependency.rs1mod private
2{
3
4
5 use crate :: *;
6
7 use error ::
10 {
11 untyped ::format_err,
14 };
15
16 #[ derive( Debug, Clone, Copy ) ]
18 #[ repr( transparent ) ]
19 pub struct DependencyRef< 'a >
20 {
21 inner: &'a cargo_metadata ::Dependency,
22 }
23 impl DependencyRef< '_ >
25 {
26
27 #[ must_use ]
30 pub fn crate_dir( &self ) -> Option< CrateDir >
31 {
32 match &self.inner.path
33 {
34 Some( path ) => path.as_path().try_into().ok(),
35 None => None,
36 }
37 }
38
39 #[ must_use ]
41 pub fn name( &self ) -> String
42 {
43 self.inner.name.clone()
44 }
45
46 #[ must_use ]
48 pub fn kind( &self ) -> DependencyKind
49 {
50 match self.inner.kind
51 {
52 cargo_metadata ::DependencyKind ::Normal => DependencyKind ::Normal,
53 cargo_metadata ::DependencyKind ::Development => DependencyKind ::Development,
54 cargo_metadata ::DependencyKind ::Build => DependencyKind ::Build,
55 cargo_metadata ::DependencyKind ::Unknown => DependencyKind ::Unknown,
56 }
57 }
58
59 #[ must_use ]
61 pub fn req( &self ) -> semver ::VersionReq
62 {
63 self.inner.req.clone()
64 }
65 }
66
67 impl< 'a > From< &'a cargo_metadata ::Dependency > for DependencyRef< 'a >
68 {
69 #[ inline( always ) ]
70 fn from( inner: &'a cargo_metadata ::Dependency ) -> Self
71 {
72 Self { inner }
73 }
74 }
75
76 #[ derive( Eq, PartialEq, Debug, Clone, Copy ) ]
78 pub enum DependencyKind
79 {
80 Normal,
82 Development,
84 Build,
86 Unknown,
88 }
89
90 #[ derive( Debug, Clone, Hash, Eq, PartialEq ) ]
94 pub struct CrateId
95 {
96 pub name: String, pub crate_dir: Option< CrateDir >, }
102
103 impl< 'a > From< &WorkspacePackageRef< 'a > > for CrateId
104 {
105 fn from( value: &WorkspacePackageRef< 'a > ) -> Self
106 {
107 Self
108 {
109 name: value.name().into(),
110 crate_dir: Some( value.crate_dir().unwrap() )
111 }
113 }
114 }
115
116 impl From< &DependencyRef< '_ > > for CrateId
117 {
118 fn from( value: &DependencyRef< '_ > ) -> Self
119 {
120 Self
121 {
122 name: value.name(),
123 crate_dir: value.crate_dir(),
124 }
126 }
127 }
128
129 #[ derive( Debug, Copy, Clone ) ]
131 pub enum DependenciesSort
132 {
133 Topological,
135 Unordered,
137 }
138
139 #[ derive( Debug, Clone ) ]
140 pub struct DependenciesOptions
142 {
143 pub recursive: bool,
145 pub sort: DependenciesSort,
147 pub with_dev: bool,
149 pub with_remote: bool,
151 }
152
153 impl Default for DependenciesOptions
154 {
155 fn default() -> Self
156 {
157 Self
158 {
159 recursive: true,
160 sort: DependenciesSort ::Unordered,
161 with_dev: false,
162 with_remote: false,
163 }
164 }
165 }
166
167 #[ allow( clippy ::needless_pass_by_value, clippy ::implicit_hasher ) ]
175 pub fn list_rec
176 (
177 workspace: &Workspace, package: &Package< '_ >,
179 graph: &mut collection ::HashMap< CrateId, collection ::HashSet< CrateId > >,
180 opts: DependenciesOptions
181 )
182 -> error ::untyped ::Result< CrateId >
184 {
185 let DependenciesOptions
186 {
187 recursive,
188 sort: _,
189 with_dev,
190 with_remote,
191 } = opts;
192 if recursive && with_remote { unimplemented!( "`recursive` + `with_remote` options") }
193
194 let manifest_file = &package.manifest_file();
195
196 let package = workspace
197 .package_find_by_manifest( manifest_file )
198 .ok_or( format_err!( "Package not found in the workspace with path: `{}`", manifest_file.as_ref().display() ) )?;
199
200 let deps: collection ::HashSet< _ > = package
201 .dependencies()
202 .filter( | dep | ( with_remote || dep.crate_dir().is_some() ) && ( with_dev || dep.kind() != DependencyKind ::Development ) )
204 .map( | dep | CrateId ::from( &dep ) )
205 .collect();
206
207 let package = CrateId ::from( &package );
208 graph.insert( package.clone(), deps.clone() );
209
210 if recursive
211 {
212 for dep in deps
213 {
214 if graph.get( &dep ).is_none()
215 {
216 list_rec
218 (
219 workspace,
220 &dep.crate_dir.unwrap().try_into()?,
221 graph,
223 opts.clone(),
224 )?;
225 }
226 }
227 }
228
229 Ok( package )
230 }
231
232 #[ allow( clippy ::needless_pass_by_value ) ]
247 pub fn list
248 (
249 workspace: &mut Workspace,
250 package: &Package< '_ >,
251 opts: DependenciesOptions
252 )
253 -> error ::untyped ::Result< Vec< CrateId > >
255 {
256 let mut graph = collection ::HashMap ::new();
257 let root = list_rec( workspace, package, &mut graph, opts.clone() )?;
258
259 let output = match opts.sort
260 {
261 DependenciesSort ::Unordered =>
262 {
263 graph
264 .into_iter()
265 .flat_map( | ( id, dependency ) |
266 {
267 dependency
268 .into_iter()
269 .chain( Some( id ) )
270 })
271 .unique()
272 .filter( | x | x != &root )
273 .collect()
274 }
275 DependenciesSort ::Topological =>
276 {
277 graph ::toposort( graph ::construct( &graph ) )
280 .map_err( | err | format_err!( "{err}" ) )?
281 .into_iter()
282 .filter( | x | x != &root )
283 .collect()
284 },
285 };
286
287 Ok( output )
288 }
289
290}
291
292crate ::mod_interface!
295{
296
297 exposed use DependencyRef;
298 exposed use DependencyKind;
299
300 own use CrateId;
301 own use DependenciesSort;
302 own use DependenciesOptions;
303 own use list_rec;
304 own use list;
305
306}