@@ -6,8 +6,7 @@ use serde::Deserialize;
66
77use std:: {
88 collections:: HashMap ,
9- fmt:: Write ,
10- fs:: read_to_string,
9+ fs,
1110 path:: { Path , PathBuf } ,
1211} ;
1312
@@ -50,9 +49,63 @@ pub struct CargoManifest {
5049 pub dependencies : HashMap < String , CargoManifestDependency > ,
5150}
5251
52+ #[ derive( Default ) ]
5353pub struct CrateVersion {
54- pub version : String ,
55- pub found_crate_versions : Vec < String > ,
54+ pub version : Option < String > ,
55+ pub git : Option < String > ,
56+ pub git_branch : Option < String > ,
57+ pub git_rev : Option < String > ,
58+ pub path : Option < PathBuf > ,
59+ pub lock_version : Option < String > ,
60+ }
61+
62+ impl CrateVersion {
63+ pub fn has_version ( & self ) -> bool {
64+ self . version . is_some ( ) || self . git . is_some ( ) || self . path . is_some ( )
65+ }
66+ }
67+
68+ impl std:: fmt:: Display for CrateVersion {
69+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
70+ if let Some ( g) = & self . git {
71+ if let Some ( version) = & self . version {
72+ write ! ( f, "{g} ({version})" ) ?;
73+ } else {
74+ write ! ( f, "git:{g}" ) ?;
75+ if let Some ( branch) = & self . git_branch {
76+ write ! ( f, "&branch={branch}" ) ?;
77+ } else if let Some ( rev) = & self . git_rev {
78+ write ! ( f, "#rev={rev}" ) ?;
79+ }
80+ }
81+ } else if let Some ( p) = & self . path {
82+ write ! ( f, "path:{}" , p. display( ) ) ?;
83+ if let Some ( version) = & self . version {
84+ write ! ( f, " ({version})" ) ?;
85+ }
86+ } else if let Some ( version) = & self . version {
87+ write ! ( f, "{version}" ) ?;
88+ } else {
89+ return write ! ( f, "No version detected" ) ;
90+ }
91+
92+ if let Some ( lock_version) = & self . lock_version {
93+ write ! ( f, " ({lock_version})" ) ?;
94+ }
95+
96+ Ok ( ( ) )
97+ }
98+ }
99+
100+ pub fn crate_latest_version ( name : & str ) -> Option < String > {
101+ let url = format ! ( "https://docs.rs/crate/{name}/" ) ;
102+ match ureq:: get ( & url) . call ( ) {
103+ Ok ( response) => match ( response. status ( ) , response. header ( "location" ) ) {
104+ ( 302 , Some ( location) ) => Some ( location. replace ( & url, "" ) ) ,
105+ _ => None ,
106+ } ,
107+ Err ( _) => None ,
108+ }
56109}
57110
58111pub fn crate_version (
@@ -61,6 +114,8 @@ pub fn crate_version(
61114 lock : Option < & CargoLock > ,
62115 name : & str ,
63116) -> CrateVersion {
117+ let mut version = CrateVersion :: default ( ) ;
118+
64119 let crate_lock_packages: Vec < CargoLockPackage > = lock
65120 . as_ref ( )
66121 . map ( |lock| {
@@ -72,101 +127,54 @@ pub fn crate_version(
72127 . collect ( )
73128 } )
74129 . unwrap_or_default ( ) ;
75- let ( crate_version_string, found_crate_versions) =
76- match ( & manifest, & lock, crate_lock_packages. len ( ) ) {
77- ( Some ( _manifest) , Some ( _lock) , 1 ) => {
78- let crate_lock_package = crate_lock_packages. first ( ) . unwrap ( ) ;
79- let version_string = if let Some ( s) = & crate_lock_package. source {
80- if s. starts_with ( "git" ) {
81- format ! ( "{} ({})" , s, crate_lock_package. version)
82- } else {
83- crate_lock_package. version . clone ( )
84- }
85- } else {
86- crate_lock_package. version . clone ( )
87- } ;
88- ( version_string, vec ! [ crate_lock_package. version. clone( ) ] )
89- }
90- ( None , Some ( _lock) , 1 ) => {
91- let crate_lock_package = crate_lock_packages. first ( ) . unwrap ( ) ;
92- let version_string = if let Some ( s) = & crate_lock_package. source {
93- if s. starts_with ( "git" ) {
94- format ! ( "{} ({})" , s, crate_lock_package. version)
95- } else {
96- crate_lock_package. version . clone ( )
130+
131+ if crate_lock_packages. len ( ) == 1 {
132+ let crate_lock_package = crate_lock_packages. first ( ) . unwrap ( ) ;
133+ if let Some ( s) = crate_lock_package
134+ . source
135+ . as_ref ( )
136+ . filter ( |s| s. starts_with ( "git" ) )
137+ {
138+ version. git = Some ( s. clone ( ) ) ;
139+ }
140+
141+ version. version = Some ( crate_lock_package. version . clone ( ) ) ;
142+ } else {
143+ if let Some ( dep) = manifest. and_then ( |m| m. dependencies . get ( name) . cloned ( ) ) {
144+ match dep {
145+ CargoManifestDependency :: Version ( v) => version. version = Some ( v) ,
146+ CargoManifestDependency :: Package ( p) => {
147+ if let Some ( v) = p. version {
148+ version. version = Some ( v) ;
149+ } else if let Some ( p) = p. path {
150+ let manifest_path = tauri_dir. join ( & p) . join ( "Cargo.toml" ) ;
151+ let v = fs:: read_to_string ( manifest_path)
152+ . ok ( )
153+ . and_then ( |m| toml:: from_str :: < CargoManifest > ( & m) . ok ( ) )
154+ . map ( |m| m. package . version ) ;
155+ version. version = v;
156+ version. path = Some ( p) ;
157+ } else if let Some ( g) = p. git {
158+ version. git = Some ( g) ;
159+ version. git_branch = p. branch ;
160+ version. git_rev = p. rev ;
97161 }
98- } else {
99- crate_lock_package. version . clone ( )
100- } ;
101- (
102- format ! ( "{version_string} (no manifest)" ) ,
103- vec ! [ crate_lock_package. version. clone( ) ] ,
104- )
105- }
106- _ => {
107- let mut found_crate_versions = Vec :: new ( ) ;
108- let mut is_git = false ;
109- let manifest_version = match manifest. and_then ( |m| m. dependencies . get ( name) . cloned ( ) ) {
110- Some ( tauri) => match tauri {
111- CargoManifestDependency :: Version ( v) => {
112- found_crate_versions. push ( v. clone ( ) ) ;
113- v
114- }
115- CargoManifestDependency :: Package ( p) => {
116- if let Some ( v) = p. version {
117- found_crate_versions. push ( v. clone ( ) ) ;
118- v
119- } else if let Some ( p) = p. path {
120- let manifest_path = tauri_dir. join ( & p) . join ( "Cargo.toml" ) ;
121- let v = match read_to_string ( manifest_path)
122- . map_err ( |_| ( ) )
123- . and_then ( |m| toml:: from_str :: < CargoManifest > ( & m) . map_err ( |_| ( ) ) )
124- {
125- Ok ( manifest) => manifest. package . version ,
126- Err ( _) => "unknown version" . to_string ( ) ,
127- } ;
128- format ! ( "path:{p:?} [{v}]" )
129- } else if let Some ( g) = p. git {
130- is_git = true ;
131- let mut v = format ! ( "git:{g}" ) ;
132- if let Some ( branch) = p. branch {
133- let _ = write ! ( v, "&branch={branch}" ) ;
134- } else if let Some ( rev) = p. rev {
135- let _ = write ! ( v, "#{rev}" ) ;
136- }
137- v
138- } else {
139- "unknown manifest" . to_string ( )
140- }
141- }
142- } ,
143- None => "no manifest" . to_string ( ) ,
144- } ;
145-
146- let lock_version = match ( lock, crate_lock_packages. is_empty ( ) ) {
147- ( Some ( _lock) , false ) => crate_lock_packages
148- . iter ( )
149- . map ( |p| p. version . clone ( ) )
150- . collect :: < Vec < String > > ( )
151- . join ( ", " ) ,
152- ( Some ( _lock) , true ) => "unknown lockfile" . to_string ( ) ,
153- _ => "no lockfile" . to_string ( ) ,
154- } ;
155-
156- (
157- format ! (
158- "{} {}({})" ,
159- manifest_version,
160- if is_git { "(git manifest)" } else { "" } ,
161- lock_version
162- ) ,
163- found_crate_versions,
164- )
162+ }
165163 }
166- } ;
164+ }
165+
166+ if lock. is_some ( ) && crate_lock_packages. is_empty ( ) {
167+ let lock_version = crate_lock_packages
168+ . iter ( )
169+ . map ( |p| p. version . clone ( ) )
170+ . collect :: < Vec < String > > ( )
171+ . join ( ", " ) ;
167172
168- CrateVersion {
169- found_crate_versions,
170- version : crate_version_string,
173+ if !lock_version. is_empty ( ) {
174+ version. lock_version = Some ( lock_version) ;
175+ }
176+ }
171177 }
178+
179+ version
172180}
0 commit comments