willbe/entity/
workspace.rs

1#[ allow( clippy ::std_instead_of_alloc, clippy ::std_instead_of_core ) ]
2mod private
3{
4
5  use crate :: *;
6  // qqq: for Bohdan: bad
7  // use std :: *;
8  use std ::slice;
9  use former ::Former;
10
11  /// Stores information about the current workspace.
12  #[ derive( Debug, Clone ) ]
13  pub struct Workspace
14  {
15  /// Metadata of the workspace, containing detailed information about the packages, dependencies, and other workspace-related data.
16  pub metadata: cargo_metadata ::Metadata,
17  /// The directory containing the manifest file (`Cargo.toml`) of the workspace.
18  pub crate_dir: CrateDir,
19 }
20
21  /// Represents errors related to workspace operations.
22  #[ derive( Debug, error ::typed ::Error ) ]
23  pub enum WorkspaceInitError
24  {
25  /// Something went wrong with path to a workspace.
26  #[ error( "Path error. Details: {0}" ) ]
27  Path( #[ from ] PathError ),
28  /// Something went wrong with the workspace' data
29  #[ error( "Can not load workspace data. Details: {0}" ) ]
30  Metadata( #[ from ] cargo_metadata ::Error ),
31  /// Files error
32  #[ error( "I/O error: {0}" ) ]
33  IO( #[ from ] std ::io ::Error ),
34 }
35
36  impl TryFrom< CrateDir > for Workspace
37  {
38  type Error = WorkspaceInitError;
39
40  /// Load data from current directory
41  fn try_from( mut crate_dir: CrateDir ) -> Result< Self, Self ::Error >
42  {
43   let metadata = cargo_metadata ::MetadataCommand ::new()
44   .current_dir( crate_dir.as_ref() )
45   .no_deps()
46   .exec()?;
47   // inout crate dir may refer on crate's manifest dir, not workspace's manifest dir
48   crate_dir = ( &metadata.workspace_root ).try_into()?;
49   Result ::Ok( Self
50   {
51  metadata,
52  crate_dir,
53 })
54 }
55
56 }
57
58  impl TryFrom< CurrentPath > for Workspace
59  {
60  type Error = WorkspaceInitError;
61
62  /// Load data from current directory
63  fn try_from( _cd: CurrentPath ) -> Result< Self, Self ::Error >
64  {
65   let abs_path = AbsolutePath ::try_from( std ::env ::current_dir()? )?;
66   let crate_dir = CrateDir ::try_from( abs_path )?;
67   Self ::try_from( crate_dir )
68 }
69
70 }
71
72  impl From< cargo_metadata ::Metadata > for Workspace
73  {
74  fn from( metadata: cargo_metadata ::Metadata ) -> Self
75  {
76   // SAFE: `workspace_root` is a path to a`Cargo.toml` file, therefor the parent is the directory
77   let path = metadata.workspace_root.as_std_path().parent().unwrap().to_path_buf();
78   let crate_dir = CrateDir ::try_from( path ).unwrap();
79   Self
80   {
81  metadata,
82  crate_dir,
83 }
84 }
85 }
86
87  impl Workspace
88  {
89
90  /// Returns list of all packages
91  pub fn packages< 'a >( &'a self )
92  -> core ::iter ::Map
93  <
94   slice ::Iter< 'a, cargo_metadata ::Package >,
95   impl Fn( &'a cargo_metadata ::Package ) -> WorkspacePackageRef< 'a > + Clone,
96 >
97  {
98   self.metadata.packages.iter().map( WorkspacePackageRef ::from )
99 }
100
101  /// Returns the path to workspace root
102  ///
103  /// # Panics
104  /// qqq: doc
105  #[ must_use ]
106  pub fn workspace_root( &self ) -> CrateDir
107  {
108   // Safe because workspace_root.as_std_path() is always a path to a directory
109   CrateDir ::try_from( self.metadata.workspace_root.as_std_path() ).unwrap()
110 }
111
112  /// Returns the path to target directory
113  #[ must_use ]
114  pub fn target_directory( &self ) -> &std ::path ::Path
115  {
116   self.metadata.target_directory.as_std_path()
117 }
118
119  /// Find a package by its manifest file path
120  ///
121  /// # Panics
122  /// qqq: doc
123  pub fn package_find_by_manifest< P >( &self, manifest_file: P ) -> Option< WorkspacePackageRef< '_ > >
124  where
125   P: AsRef< std ::path ::Path >,
126  {
127   self
128   .packages()
129   .find( | &p | p.manifest_file().unwrap().as_ref() == manifest_file.as_ref() )
130 }
131
132  /// Filter of packages.
133  #[ must_use ]
134  pub fn packages_which( &self ) -> PackagesFilterFormer< '_ >
135  {
136   // PackagesFilter ::new( self )
137   PackagesFilter ::former().workspace( self )
138 }
139
140 }
141
142
143  #[ derive( Former ) ]
144  // #[ debug ]
145  #[ allow( missing_debug_implementations ) ]
146  pub struct PackagesFilter< 'a >
147  {
148  workspace: &'a Workspace,
149  crate_dir: Box< dyn PackageFilter >,
150  manifest_file: Box< dyn PackageFilter >,
151 }
152
153  pub trait PackageFilter
154  {
155  fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool;
156 }
157
158  impl Default for Box< dyn PackageFilter >
159  {
160  fn default() -> Self
161  {
162   Box ::new( PackageFilterAll )
163 }
164 }
165
166  pub struct PackageFilterAll;
167  impl PackageFilter for PackageFilterAll
168  {
169  #[ inline( always ) ]
170  fn include( &self, _package: WorkspacePackageRef< '_ > ) -> bool
171  {
172   true
173 }
174 }
175
176  pub struct PackageFilterCrateDir( CrateDir );
177  impl PackageFilter for PackageFilterCrateDir
178  {
179  #[ inline( always ) ]
180  fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool
181  {
182   self.0 == package.crate_dir().unwrap()
183 }
184 }
185
186  impl From< CrateDir > for Box< dyn PackageFilter >
187  {
188  #[ inline( always ) ]
189  fn from( src: CrateDir ) -> Self
190  {
191   Box ::new( PackageFilterCrateDir( src ) )
192 }
193 }
194
195  pub struct PackageFilterManifestFile( ManifestFile );
196  impl PackageFilter for PackageFilterManifestFile
197  {
198  #[ inline( always ) ]
199  fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool
200  {
201   self.0 == package.manifest_file().unwrap()
202 }
203 }
204
205  impl From< ManifestFile > for Box< dyn PackageFilter >
206  {
207  #[ inline( always ) ]
208  fn from( src: ManifestFile ) -> Self
209  {
210   Box ::new( PackageFilterManifestFile( src ) )
211 }
212 }
213
214  impl< 'a > PackagesFilter< 'a >
215  {
216
217  pub fn new( workspace: &'a Workspace ) -> Self
218  {
219   Self
220   {
221  workspace,
222  crate_dir: Box ::default(),
223  manifest_file: Box ::default(),
224 }
225 }
226
227  #[ inline( always ) ]
228  #[ allow( clippy ::unused_self ) ]
229  pub fn iter( &'a self ) -> impl Iterator< Item = WorkspacePackageRef< 'a > > + Clone
230  {
231
232   // self
233   // .workspace
234   // .packages()
235   // .find( | &p | p.manifest_file().unwrap().as_ref() == manifest_file.as_ref() )
236
237   // let filter_crate_dir = if Some( crate_dir ) = self.crate_dir
238   // {
239   //   | p | p.manifest_file().unwrap().as_ref() == manifest_file.as_ref()
240   // }
241
242   std ::iter ::empty()
243 }
244
245 }
246
247  impl< 'a > PackagesFilterFormer< 'a >
248  {
249  #[ inline( always ) ]
250  // pub fn find< 'a >( self ) -> impl Iterator< Item = WorkspacePackageRef< 'a > > + Clone
251  pub fn find( self ) -> Option< WorkspacePackageRef< 'a > >
252  {
253   let formed = self.form();
254
255   formed
256   .workspace
257   .packages()
258   .find( | &p |
259   {
260  if !formed.crate_dir.include( p ) { return false }
261  if !formed.manifest_file.include( p ) { return false }
262  true
263 })
264   // .unwrap()
265
266   // let filter_crate_dir = if Some( crate_dir ) = self.crate_dir
267   // {
268   //   | p | p.manifest_file().unwrap().as_ref() == manifest_file.as_ref()
269   // }
270
271   // std ::iter ::empty()
272 }
273 }
274
275  impl Entries for Workspace
276  {
277  fn entries( &self ) -> impl IterTrait< '_, SourceFile >
278  {
279   self
280   .packages()
281   .flat_map( | package | package.entries().collect :: < Vec< _ > >() )
282   .collect :: < Vec< _ > >()
283   .into_iter()
284 }
285 }
286
287  impl Sources for Workspace
288  {
289  fn sources( &self ) -> impl IterTrait< '_, SourceFile >
290  {
291   self
292   .packages()
293   .flat_map( | package | package.sources().collect :: < Vec< _ > >() )
294   .collect :: < Vec< _ > >().into_iter()
295   // .into_iter()
296 }
297 }
298
299}
300
301//
302
303crate ::mod_interface!
304{
305  exposed use WorkspaceInitError;
306  exposed use Workspace;
307}