@@ -4,6 +4,7 @@ pub mod install;
44pub mod resolver;
55
66use std:: borrow:: Borrow ;
7+ use std:: fs:: File ;
78use std:: io:: { ErrorKind , Read , Seek } ;
89use std:: path:: { Path , PathBuf } ;
910
@@ -23,6 +24,14 @@ use crate::TCLI_HOME;
2324
2425use self :: index:: PackageIndex ;
2526
27+ #[ derive( Serialize , Deserialize , Debug ) ]
28+ pub struct PackageMetadata {
29+ #[ serde( flatten) ]
30+ manifest : PackageManifestV1 ,
31+ reference : String ,
32+ icon : PathBuf ,
33+ }
34+
2635#[ derive( Serialize , Deserialize , Debug , Clone ) ]
2736pub enum PackageSource {
2837 Remote ( String ) ,
@@ -43,7 +52,7 @@ pub struct Package {
4352impl Package {
4453 /// Attempt to resolve the package from the local cache or remote.
4554 /// This does not download the package, it just finds its "source".
46- pub async fn resolve_new ( ident : impl Borrow < PackageReference > ) -> Result < Self , Error > {
55+ pub async fn from_any ( ident : impl Borrow < PackageReference > ) -> Result < Self , Error > {
4756 if cache:: get_cache_location ( ident. borrow ( ) ) . exists ( ) {
4857 return Package :: from_cache ( ident) . await ;
4958 }
@@ -110,7 +119,9 @@ impl Package {
110119 /// Load package metadata from an arbitrary path, extracting it into the cache if it passes
111120 // manifest validation.
112121 pub async fn from_path ( ident : PackageReference , path : & Path ) -> Result < Self , Error > {
113- let package = Package :: from_repo ( ident) . await ?;
122+ // let package = Package::from_repo(ident).await?;
123+ add_to_cache ( & ident, File :: open ( path) . map_fs_error ( path) ?) ?;
124+ let package = Package :: from_cache ( ident) . await ?;
114125
115126 Ok ( Package {
116127 identifier : package. identifier ,
@@ -119,64 +130,39 @@ impl Package {
119130 } )
120131 }
121132
122- /// Resolve the package into a discrete path. This will download the package if it is not cached,
123- // otherwise it will return its cached path.
124- pub async fn resolve ( & self , reporter : & dyn ProgressBarTrait ) -> Result < PathBuf , Error > {
133+ /// Resolve the package into a discrete path, returning None if it does not exist locally.
134+ pub async fn get_path ( & self ) -> Option < PathBuf > {
125135 match & self . source {
126136 PackageSource :: Local ( path) => add_to_cache (
127137 & self . identifier ,
128- std :: fs :: File :: open ( path) . map_fs_error ( path) ?,
129- ) ,
130- PackageSource :: Remote ( _ ) => self . download ( reporter ) . await ,
131- PackageSource :: Cache ( path ) => Ok ( path . clone ( ) ) ,
138+ File :: open ( path) . map_fs_error ( path) . ok ( ) ?,
139+ ) . ok ( ) ,
140+ PackageSource :: Cache ( path ) => Some ( path . clone ( ) ) ,
141+ PackageSource :: Remote ( _ ) => None ,
132142 }
133143 }
134144
135- pub async fn add (
136- & self ,
137- project_state : & Path ,
138- reporter : Box < dyn ProgressBarTrait > ,
139- ) -> Result < ( ) , Error > {
140- let cache_path = self . resolve ( reporter. as_ref ( ) ) . await ?;
141- let install_dir = project_state. join ( self . identifier . to_string ( ) ) ;
142-
143- if install_dir. is_dir ( ) {
144- fs:: remove_dir_all ( & install_dir)
145- . await
146- . map_fs_error ( & install_dir) ?;
147- }
148-
149- for item in walkdir:: WalkDir :: new ( & cache_path) . into_iter ( ) {
150- let item = item?;
151-
152- let dest_path = install_dir. join ( item. path ( ) . strip_prefix ( & cache_path) . unwrap ( ) ) ;
153-
154- if item. file_type ( ) . is_dir ( ) {
155- tokio:: fs:: create_dir_all ( & dest_path)
156- . await
157- . map_fs_error ( & dest_path) ?;
158- } else if item. file_type ( ) . is_file ( ) {
159- tokio:: fs:: copy ( item. path ( ) , & dest_path)
160- . await
161- . map_fs_error ( & dest_path) ?;
162- }
163- }
164-
165- let finished_msg = format ! (
166- "{} {}-{} ({})" ,
167- "[✓]" . green( ) ,
168- self . identifier. namespace. bold( ) ,
169- self . identifier. name. bold( ) ,
170- self . identifier. version. to_string( ) . truecolor( 90 , 90 , 90 )
171- ) ;
172-
173- reporter. println ( & finished_msg) ;
174- reporter. finish_and_clear ( ) ;
175-
176- Ok ( ( ) )
145+ /// Get the metadata associated with this package. This will return None
146+ /// the package does not exist locally.
147+ pub async fn get_metadata ( & self ) -> Result < Option < PackageMetadata > , Error > {
148+ let Some ( package_dir) = self . get_path ( ) . await else {
149+ return Ok ( None ) ;
150+ } ;
151+ let manifest = {
152+ let str = fs:: read_to_string ( package_dir. join ( "manifest.json" ) ) . await ?;
153+ serde_json:: from_str :: < PackageManifestV1 > ( & str) ?
154+ } ;
155+ let icon = package_dir. join ( "icon.png" ) ;
156+ let reference = package_dir. file_name ( ) . unwrap ( ) . to_string_lossy ( ) . to_string ( ) ;
157+
158+ Ok ( Some ( PackageMetadata {
159+ manifest,
160+ reference,
161+ icon,
162+ } ) )
177163 }
178164
179- async fn download ( & self , reporter : & dyn ProgressBarTrait ) -> Result < PathBuf , Error > {
165+ pub async fn download ( & self , reporter : & dyn ProgressBarTrait ) -> Result < PathBuf , Error > {
180166 let PackageSource :: Remote ( package_source) = & self . source else {
181167 panic ! ( "Invalid use, this is a local package." )
182168 } ;
0 commit comments