11use std:: {
2- collections:: { HashMap , HashSet } ,
2+ collections:: { HashMap , HashSet , VecDeque } ,
33 path:: PathBuf ,
44} ;
55
@@ -82,39 +82,39 @@ pub struct Artifact {
8282}
8383
8484#[ derive( serde:: Deserialize ) ]
85- struct CargoManifest {
86- package : CargoPackage ,
85+ pub struct CargoManifest {
86+ pub package : CargoPackage ,
8787}
8888
8989#[ derive( serde:: Deserialize ) ]
90- struct CargoPackage {
91- name : String ,
92- description : Option < String > ,
93- metadata : CargoPackageMetadata ,
90+ pub struct CargoPackage {
91+ pub name : String ,
92+ pub description : Option < String > ,
93+ pub metadata : Option < CargoPackageMetadata > ,
9494}
9595
9696#[ derive( serde:: Deserialize ) ]
97- struct CargoPackageMetadata {
98- oro : CargoPackageMetadataOro ,
97+ pub struct CargoPackageMetadata {
98+ pub oro : CargoPackageMetadataOro ,
9999}
100100
101101#[ derive( serde:: Deserialize ) ]
102- struct CargoPackageMetadataOro {
103- arch : Arch ,
104- component : Component ,
102+ pub struct CargoPackageMetadataOro {
103+ pub arch : Arch ,
104+ pub component : Component ,
105105}
106106
107107#[ derive( serde:: Deserialize ) ]
108- struct CargoLockfile {
109- version : u32 ,
110- package : Vec < CargoLockfilePackage > ,
108+ pub struct CargoLockfile {
109+ pub version : u32 ,
110+ pub package : Vec < CargoLockfilePackage > ,
111111}
112112
113113#[ derive( serde:: Deserialize ) ]
114- struct CargoLockfilePackage {
115- name : String ,
116- source : Option < String > ,
117- dependencies : Option < Vec < String > > ,
114+ pub struct CargoLockfilePackage {
115+ pub name : String ,
116+ pub source : Option < String > ,
117+ pub dependencies : Option < Vec < String > > ,
118118}
119119
120120impl Vfs {
@@ -140,16 +140,16 @@ impl Vfs {
140140 self . read_artifact_dir ( ) . filter_map ( |path| {
141141 let manifest = std:: fs:: read_to_string ( path. join ( "Cargo.toml" ) ) . ok ( ) ?;
142142 let manifest: CargoManifest = toml:: from_str ( & manifest) . ok ( ) ?;
143- let target_triple = format ! ( "{}-unknown-oro" , manifest. package. metadata. oro. arch) ;
143+ let Some ( metadata) = & manifest. package . metadata else {
144+ return None ;
145+ } ;
146+ let target_triple = format ! ( "{}-unknown-oro" , metadata. oro. arch) ;
144147 Some ( Artifact {
145148 path,
146- name : format ! (
147- "{}-{}" ,
148- manifest. package. metadata. oro. arch, manifest. package. metadata. oro. component
149- ) ,
149+ name : format ! ( "{}-{}" , metadata. oro. arch, metadata. oro. component) ,
150150 description : manifest. package . description ,
151- architecture : manifest . package . metadata . oro . arch ,
152- component : manifest . package . metadata . oro . component ,
151+ architecture : metadata. oro . arch ,
152+ component : metadata. oro . component ,
153153 target_relative_path : PathBuf :: from ( & manifest. package . name ) ,
154154 package_name : manifest. package . name ,
155155 target_triple,
@@ -170,6 +170,14 @@ impl Vfs {
170170 . map ( |entry| entry. path ( ) )
171171 }
172172
173+ /// # Panics
174+ /// Panics if the root `Cargo.toml` cannot be read.
175+ pub fn root_cargo_toml ( & self ) -> CargoManifest {
176+ let contents = std:: fs:: read_to_string ( self . root_dir . join ( "Cargo.toml" ) )
177+ . expect ( "failed to read root Cargo.toml" ) ;
178+ toml:: from_str ( & contents) . expect ( "failed to parse root Cargo.toml" )
179+ }
180+
173181 /// # Panics
174182 /// Panics if the lockfile cannot be read.
175183 pub fn lockfile ( & self ) -> impl Iterator < Item = LockEntry > {
@@ -181,12 +189,15 @@ impl Vfs {
181189 lockfile. version, 4 ,
182190 "Cargo.lock version 4 is the only version supported"
183191 ) ;
184- lockfile. package . into_iter ( ) . map ( |e| {
185- LockEntry {
186- package_name : e. name ,
187- is_registry : e. source . is_some_and ( |s| s. starts_with ( "registry+" ) ) ,
188- dependencies : e. dependencies . unwrap_or_default ( ) ,
189- }
192+ let root_package_name = self . root_cargo_toml ( ) . package . name ;
193+ lockfile. package . into_iter ( ) . filter_map ( move |e| {
194+ ( e. name != root_package_name) . then ( || {
195+ LockEntry {
196+ package_name : e. name ,
197+ is_registry : e. source . is_some_and ( |s| s. starts_with ( "registry+" ) ) ,
198+ dependencies : e. dependencies . unwrap_or_default ( ) ,
199+ }
200+ } )
190201 } )
191202 }
192203
@@ -224,44 +235,33 @@ pub trait Lockfile: IntoIterator<Item = LockEntry> + Sized {
224235 . collect ( )
225236 }
226237
227- fn used ( self ) -> impl Iterator < Item = LockEntry >
228- where
229- Self : Clone ,
230- {
238+ fn used ( self ) -> impl Iterator < Item = LockEntry > {
239+ let map = self . into_map ( ) ;
231240 let mut seen = HashSet :: new ( ) ;
241+ let mut queue = map
242+ . iter ( )
243+ . filter_map ( |( n, e) | ( !e. is_registry ) . then ( || n. to_string ( ) ) )
244+ . collect :: < VecDeque < _ > > ( ) ;
245+
246+ while let Some ( name) = queue. pop_back ( ) {
247+ if !seen. insert ( name. clone ( ) ) {
248+ continue ;
249+ }
232250
233- for item in self . clone ( ) . into_iter ( ) {
234- if item. is_registry {
235- for dep in item. dependencies {
236- seen. insert ( dep) ;
237- }
238- } else {
239- seen. insert ( item. package_name ) ;
251+ for dep in & map[ & name] . dependencies {
252+ queue. push_back ( dep. into ( ) ) ;
240253 }
241254 }
242255
243- self . into_iter ( )
244- . filter ( move |e | seen. contains ( & e . package_name ) )
256+ map . into_iter ( )
257+ . filter_map ( move |( k , e ) | seen. contains ( & k ) . then ( move || e ) )
245258 }
246259
247- fn unused ( self ) -> impl Iterator < Item = LockEntry >
248- where
249- Self : Clone ,
250- {
251- let mut seen = HashSet :: new ( ) ;
252-
253- for item in self . clone ( ) . into_iter ( ) {
254- if item. is_registry {
255- for dep in item. dependencies {
256- seen. insert ( dep) ;
257- }
258- } else {
259- seen. insert ( item. package_name ) ;
260- }
261- }
262-
263- self . into_iter ( )
264- . filter ( move |e| !seen. contains ( & e. package_name ) )
260+ fn unused ( self ) -> impl Iterator < Item = LockEntry > {
261+ let all: Vec < LockEntry > = self . into_iter ( ) . collect ( ) ;
262+ let used: HashSet < String > = all. iter ( ) . cloned ( ) . used ( ) . map ( |e| e. package_name ) . collect ( ) ;
263+ all. into_iter ( )
264+ . filter ( move |e| !used. contains ( & e. package_name ) )
265265 }
266266
267267 fn dependencies ( self ) -> impl Iterator < Item = LockEntry > {
0 commit comments