@@ -7,7 +7,7 @@ use crate::cmd::CmdLineRunner;
77use crate :: config:: { Config , Settings } ;
88use crate :: env;
99use crate :: file;
10- use crate :: github;
10+ use crate :: github:: { self , GithubRelease } ;
1111use crate :: http:: HTTP_FETCH ;
1212use crate :: install_context:: InstallContext ;
1313use crate :: timeout;
@@ -122,20 +122,9 @@ impl Backend for PIPXBackend {
122122 PipxRequest :: Git ( url) if url. starts_with ( "https://github.com/" ) => {
123123 let repo = url. strip_prefix ( "https://github.com/" ) . unwrap ( ) ;
124124 let data = github:: list_releases ( repo) . await ?;
125- Ok ( data
126- . into_iter ( )
127- . rev ( )
128- . map ( |r| VersionInfo {
129- version : r. tag_name ,
130- created_at : Some ( r. created_at ) ,
131- ..Default :: default ( )
132- } )
133- . collect ( ) )
125+ Ok ( Self :: versions_from_github_releases ( data) )
134126 }
135- PipxRequest :: Git { .. } => Ok ( vec ! [ VersionInfo {
136- version: "latest" . to_string( ) ,
137- ..Default :: default ( )
138- } ] ) ,
127+ PipxRequest :: Git { .. } => Ok ( vec ! [ ] ) ,
139128 }
140129 }
141130
@@ -195,6 +184,13 @@ impl Backend for PIPXBackend {
195184 . cloned ( )
196185 }
197186
187+ fn unresolved_latest_version ( & self ) -> Option < String > {
188+ match self . tool_name ( ) . parse ( ) {
189+ Ok ( PipxRequest :: Git ( _) ) => Some ( "latest" . to_string ( ) ) ,
190+ _ => None ,
191+ }
192+ }
193+
198194 async fn install_version_ ( & self , ctx : & InstallContext , tv : ToolVersion ) -> Result < ToolVersion > {
199195 // Check if pipx is available (unless uvx is being used)
200196 let use_uvx = self . uv_is_installed ( & ctx. config ) . await
@@ -292,6 +288,18 @@ pub fn install_time_option_keys() -> Vec<String> {
292288}
293289
294290impl PIPXBackend {
291+ fn versions_from_github_releases ( releases : Vec < GithubRelease > ) -> Vec < VersionInfo > {
292+ releases
293+ . into_iter ( )
294+ . rev ( )
295+ . map ( |r| VersionInfo {
296+ version : r. tag_name ,
297+ created_at : Some ( r. created_at ) ,
298+ ..Default :: default ( )
299+ } )
300+ . collect ( )
301+ }
302+
295303 fn uv_exclude_newer_args ( before_date : Option < Timestamp > ) -> Vec < OsString > {
296304 match before_date {
297305 Some ( before_date) => vec ! [ "--exclude-newer" . into( ) , before_date. to_string( ) . into( ) ] ,
@@ -666,9 +674,36 @@ fn fix_venv_python_symlink(_install_path: &Path, _pkg_name: &str) -> Result<()>
666674#[ cfg( test) ]
667675mod tests {
668676 use super :: PIPXBackend ;
677+ use crate :: github:: GithubRelease ;
669678 use pretty_assertions:: assert_eq;
670679 use std:: ffi:: OsString ;
671680
681+ #[ test]
682+ fn test_versions_from_empty_github_releases_stays_empty ( ) {
683+ let versions = PIPXBackend :: versions_from_github_releases ( vec ! [ ] ) ;
684+
685+ assert ! ( versions. is_empty( ) ) ;
686+ }
687+
688+ #[ test]
689+ fn test_versions_from_github_releases_preserves_tags ( ) {
690+ let versions = PIPXBackend :: versions_from_github_releases ( vec ! [
691+ github_release( "2.0.0" , "2024-02-01T00:00:00Z" ) ,
692+ github_release( "1.0.0" , "2024-01-01T00:00:00Z" ) ,
693+ ] ) ;
694+
695+ assert_eq ! (
696+ versions
697+ . iter( )
698+ . map( |v| ( v. version. as_str( ) , v. created_at. as_deref( ) ) )
699+ . collect:: <Vec <_>>( ) ,
700+ vec![
701+ ( "1.0.0" , Some ( "2024-01-01T00:00:00Z" ) ) ,
702+ ( "2.0.0" , Some ( "2024-02-01T00:00:00Z" ) ) ,
703+ ]
704+ ) ;
705+ }
706+
672707 #[ test]
673708 fn test_uv_exclude_newer_args_with_cutoff ( ) {
674709 let before_date = "2024-01-02T03:04:05Z" . parse ( ) . unwrap ( ) ;
@@ -712,4 +747,14 @@ mod tests {
712747 Vec :: <OsString >:: new( )
713748 ) ;
714749 }
750+
751+ fn github_release ( tag_name : & str , created_at : & str ) -> GithubRelease {
752+ GithubRelease {
753+ tag_name : tag_name. to_string ( ) ,
754+ draft : false ,
755+ prerelease : false ,
756+ created_at : created_at. to_string ( ) ,
757+ assets : vec ! [ ] ,
758+ }
759+ }
715760}
0 commit comments