11use std:: {
22 cmp:: Ordering ,
33 collections:: BTreeSet ,
4+ fmt:: { self , Display } ,
45 path:: { Path , PathBuf } ,
56 process:: Command ,
67 str,
@@ -12,6 +13,9 @@ use url::Url;
1213
1314use crate :: package:: Package ;
1415
16+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
17+ pub struct GitUrl ( Url ) ;
18+
1519#[ derive( Debug ) ]
1620pub struct GitRepository {
1721 repo_dir : PathBuf ,
@@ -32,21 +36,15 @@ pub struct GitTag<'a> {
3236}
3337
3438impl GitRepository {
35- pub fn obtain ( dir : & Path , url : Url ) -> Result < Self > {
36- let normalized_url = normalize_url ( url) ?;
37-
38- let name = format ! (
39- "{}-{}" ,
40- normalized_url. host( ) . unwrap( ) ,
41- normalized_url. path( ) . replace( '/' , "-" )
42- ) ;
39+ pub fn obtain ( dir : & Path , GitUrl ( url) : GitUrl ) -> Result < Self > {
40+ let name = format ! ( "{}-{}" , url. host( ) . unwrap( ) , url. path( ) . replace( '/' , "-" ) ) ;
4341 let repo_dir = dir. join ( name) ;
4442 if !repo_dir. try_exists ( ) ? {
4543 let out = Command :: new ( "git" )
4644 . arg ( "clone" )
4745 . arg ( "--filter=blob:none" )
4846 . arg ( "--" )
49- . arg ( normalized_url . to_string ( ) )
47+ . arg ( url . to_string ( ) )
5048 . arg ( & repo_dir)
5149 . env ( "GIT_TERMINAL_PROMPT" , "0" )
5250 . output ( ) ?;
@@ -228,28 +226,40 @@ impl<'a> Ord for GitTag<'a> {
228226 }
229227}
230228
231- fn normalize_url ( url : Url ) -> Result < Url > {
232- ensure ! (
233- matches!( url. scheme( ) , "http" | "https" ) ,
234- "Bad repository scheme"
235- ) ;
236- let host = url
237- . host ( )
238- . context ( "repository doesn't have a `host`" ) ?
239- . to_string ( ) ;
240-
241- Ok ( if host == "github.com" || host. starts_with ( "gitlab." ) {
242- let mut url = url;
243- let mut path = url. path ( ) . strip_prefix ( '/' ) . unwrap ( ) . split ( '/' ) ;
244- url. set_path ( & format ! (
245- "/{}/{}.git" ,
246- path. next( ) . context( "repository is missing user/org" ) ?,
247- path. next( )
248- . context( "repository is missing repo name" ) ?
249- . trim_end_matches( ".git" )
250- ) ) ;
251- url
252- } else {
253- url
254- } )
229+ impl TryFrom < Url > for GitUrl {
230+ type Error = anyhow:: Error ;
231+
232+ fn try_from ( url : Url ) -> Result < Self , Self :: Error > {
233+ ensure ! (
234+ matches!( url. scheme( ) , "http" | "https" ) ,
235+ "Bad repository scheme"
236+ ) ;
237+ let host = url
238+ . host ( )
239+ . context ( "repository doesn't have a `host`" ) ?
240+ . to_string ( ) ;
241+
242+ Ok ( Self (
243+ if host == "github.com" || host. starts_with ( "gitlab." ) {
244+ let mut url = url;
245+ let mut path = url. path ( ) . strip_prefix ( '/' ) . unwrap ( ) . split ( '/' ) ;
246+ url. set_path ( & format ! (
247+ "/{}/{}.git" ,
248+ path. next( ) . context( "repository is missing user/org" ) ?,
249+ path. next( )
250+ . context( "repository is missing repo name" ) ?
251+ . trim_end_matches( ".git" )
252+ ) ) ;
253+ url
254+ } else {
255+ url
256+ } ,
257+ ) )
258+ }
259+ }
260+
261+ impl Display for GitUrl {
262+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
263+ Display :: fmt ( & self . 0 , f)
264+ }
255265}
0 commit comments