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}