@@ -3,7 +3,7 @@ use clap::Parser;
33use flate2:: { write:: GzEncoder , Compression } ;
44use path_absolutize:: Absolutize ;
55use sha2:: { Sha256 , Digest } ;
6- use std:: { path :: PathBuf , io :: Write } ;
6+ use std:: { io :: Write , path :: { Path , PathBuf } } ;
77
88mod plugin_manifest;
99mod spin;
@@ -77,7 +77,7 @@ impl PluginifyCommand {
7777 let rnd: u16 = rand:: random ( ) ;
7878 let ps = PackagingSettings {
7979 name : binary. file_stem ( ) . context ( "no file stem" ) ?. to_string_lossy ( ) . to_string ( ) ,
80- version : format ! ( "99.99.99-pre{rnd}" ) ,
80+ version : PluginVersion :: Exact ( format ! ( "99.99.99-pre{rnd}" ) ) ,
8181 homepage : None ,
8282 description : None ,
8383 spin_compatibility : ">=2.0" . to_string ( ) ,
@@ -105,7 +105,7 @@ impl PluginifyCommand {
105105
106106 let manifest = plugin_manifest:: PluginManifest {
107107 name : ps. name . clone ( ) ,
108- version : ps. version . clone ( ) ,
108+ version : ps. version . resolve ( ) ? ,
109109 description : ps. description . clone ( ) ,
110110 homepage : ps. homepage . clone ( ) ,
111111 spin_compatibility : ps. spin_compatibility . clone ( ) ,
@@ -255,7 +255,7 @@ impl PluginifyCommand {
255255 eprintln ! ( "...package exists = {}" , package. exists( ) ) ;
256256 }
257257
258- let tar_path = PathBuf :: from ( format ! ( "{}-{}-{}-{}.tar.gz" , ps. name, ps. version, os, arch) ) . absolutize ( ) ?. to_path_buf ( ) ;
258+ let tar_path = PathBuf :: from ( format ! ( "{}-{}-{}-{}.tar.gz" , ps. name, ps. version. resolve ( ) ? , os, arch) ) . absolutize ( ) ?. to_path_buf ( ) ;
259259 if self . verbose {
260260 eprintln ! ( "About to create tar archive at {}" , tar_path. display( ) ) ;
261261 }
@@ -331,7 +331,7 @@ fn file_digest_string(path: &PathBuf) -> Result<String, Error> {
331331#[ serde( rename_all = "snake_case" ) ]
332332struct PackagingSettings {
333333 name : String ,
334- version : String ,
334+ version : PluginVersion ,
335335 // base_uri: String,
336336 homepage : Option < String > ,
337337 description : Option < String > ,
@@ -346,3 +346,40 @@ impl PackagingSettings {
346346 self . assets . as_deref ( ) . unwrap_or_default ( )
347347 }
348348}
349+
350+ #[ derive( Clone , Debug , serde:: Deserialize ) ]
351+ #[ serde( untagged) ]
352+ enum PluginVersion {
353+ Exact ( String ) ,
354+ Derived { from : String } ,
355+ }
356+
357+ impl PluginVersion {
358+ fn resolve ( & self ) -> anyhow:: Result < String > {
359+ match self {
360+ Self :: Exact ( ver) => Ok ( ver. clone ( ) ) ,
361+ Self :: Derived { from } => try_infer_version ( & from) ,
362+ }
363+ }
364+ }
365+
366+ fn try_infer_version ( file : impl AsRef < Path > ) -> anyhow:: Result < String > {
367+ let file = file. as_ref ( ) ;
368+ let filed = file. display ( ) ; // so tired of typing file.display()
369+
370+ if !file. is_file ( ) {
371+ anyhow:: bail!( "{filed} does not exist or is not a file: can't infer version" ) ;
372+ }
373+
374+ if file. file_name ( ) . is_some_and ( |name| name == "Cargo.toml" ) {
375+ // It's a Rust project, we know how to deal with those
376+ let text = std:: fs:: read_to_string ( file) . with_context ( || format ! ( "can't infer version from `{filed}`" ) ) ?;
377+ let toml: toml:: Table = toml:: from_str ( & text) . with_context ( || format ! ( "so-called Cargo.toml isn't TOML" ) ) ?;
378+ let pkgver = toml. get ( "package" ) . and_then ( |v| v. get ( "version" ) ) . and_then ( |v| v. as_str ( ) ) ;
379+ let wsver = toml. get ( "workspace" ) . and_then ( |v| v. get ( "package" ) ) . and_then ( |v| v. get ( "version" ) ) . and_then ( |v| v. as_str ( ) ) ;
380+ let ver = pkgver. or ( wsver) . context ( "can't infer version: Cargo.toml doesn't contain a version" ) ?;
381+ return Ok ( ver. to_string ( ) ) ;
382+ }
383+
384+ Err ( anyhow ! ( "`spin pluginify` doesn't know how to infer version from `{filed}`" ) )
385+ }
0 commit comments