@@ -217,6 +217,11 @@ function createCheckoutItems(repository: Repository): CheckoutItem[] {
217217 return [ ...heads , ...tags , ...remoteHeads ] ;
218218}
219219
220+ function sanitizeRemoteName ( name : string ) {
221+ name = name . trim ( ) ;
222+ return name && name . replace ( / ^ \. | \/ \. | \. \. | ~ | \^ | : | \/ $ | \. l o c k $ | \. l o c k \/ | \\ | \* | \s | ^ \s * $ | \. $ | \[ | \] $ / g, '-' ) ;
223+ }
224+
220225class TagItem implements QuickPickItem {
221226 get label ( ) : string { return this . ref . name ?? '' ; }
222227 get description ( ) : string { return this . ref . commit ?. substr ( 0 , 8 ) ?? '' ; }
@@ -529,7 +534,7 @@ export class CommandCenter {
529534 . map ( provider => ( { label : ( provider . icon ? `$(${ provider . icon } ) ` : '' ) + localize ( 'clonefrom' , "Clone from {0}" , provider . name ) , alwaysShow : true , provider } ) ) ;
530535
531536 quickpick . placeholder = providers . length === 0
532- ? localize ( 'provide url' , "Provide repository URL. " )
537+ ? localize ( 'provide url' , "Provide repository URL" )
533538 : localize ( 'provide url or pick' , "Provide repository URL or pick a repository source." ) ;
534539
535540 const updatePicks = ( value ?: string ) => {
@@ -2119,48 +2124,79 @@ export class CommandCenter {
21192124
21202125 @command ( 'git.addRemote' , { repository : true } )
21212126 async addRemote ( repository : Repository ) : Promise < string | undefined > {
2122- const remotes = repository . remotes ;
2123-
2124- const sanitize = ( name : string ) => {
2125- name = name . trim ( ) ;
2126- return name && name . replace ( / ^ \. | \/ \. | \. \. | ~ | \^ | : | \/ $ | \. l o c k $ | \. l o c k \/ | \\ | \* | \s | ^ \s * $ | \. $ | \[ | \] $ / g, '-' ) ;
2127+ const quickpick = window . createQuickPick < ( QuickPickItem & { provider ?: RemoteSourceProvider , url ?: string } ) > ( ) ;
2128+ quickpick . ignoreFocusOut = true ;
2129+
2130+ const providers = this . model . getRemoteProviders ( )
2131+ . map ( provider => ( { label : ( provider . icon ? `$(${ provider . icon } ) ` : '' ) + localize ( 'addfrom' , "Add remote from {0}" , provider . name ) , alwaysShow : true , provider } ) ) ;
2132+
2133+ quickpick . placeholder = providers . length === 0
2134+ ? localize ( 'provide url' , "Provide repository URL" )
2135+ : localize ( 'provide url or pick' , "Provide repository URL or pick a repository source." ) ;
2136+
2137+ const updatePicks = ( value ?: string ) => {
2138+ if ( value ) {
2139+ quickpick . items = [ {
2140+ label : localize ( 'addFrom' , "Add remote from URL" ) ,
2141+ description : value ,
2142+ alwaysShow : true ,
2143+ url : value
2144+ } ,
2145+ ...providers ] ;
2146+ } else {
2147+ quickpick . items = providers ;
2148+ }
21272149 } ;
21282150
2151+ quickpick . onDidChangeValue ( updatePicks ) ;
2152+ updatePicks ( ) ;
2153+
2154+ const result = await getQuickPickResult ( quickpick ) ;
2155+ let url : string | undefined ;
2156+
2157+ if ( result ) {
2158+ if ( result . url ) {
2159+ url = result . url ;
2160+ } else if ( result . provider ) {
2161+ const quickpick = new RemoteSourceProviderQuickPick ( result . provider ) ;
2162+ const remote = await quickpick . pick ( ) ;
2163+
2164+ if ( remote ) {
2165+ if ( typeof remote . url === 'string' ) {
2166+ url = remote . url ;
2167+ } else if ( remote . url . length > 0 ) {
2168+ url = await window . showQuickPick ( remote . url , { ignoreFocusOut : true , placeHolder : localize ( 'pick url' , "Choose a URL to clone from." ) } ) ;
2169+ }
2170+ }
2171+ }
2172+ }
2173+
2174+ if ( ! url ) {
2175+ return ;
2176+ }
2177+
21292178 const resultName = await window . showInputBox ( {
21302179 placeHolder : localize ( 'remote name' , "Remote name" ) ,
21312180 prompt : localize ( 'provide remote name' , "Please provide a remote name" ) ,
21322181 ignoreFocusOut : true ,
21332182 validateInput : ( name : string ) => {
2134- if ( sanitize ( name ) ) {
2135- return null ;
2183+ if ( ! sanitizeRemoteName ( name ) ) {
2184+ return localize ( 'remote name format invalid' , "Remote name format invalid" ) ;
2185+ } else if ( repository . remotes . find ( r => r . name === name ) ) {
2186+ return localize ( 'remote already exists' , "Remote '{0}' already exists." , name ) ;
21362187 }
2137- return localize ( 'remote name format invalid' , "Remote name format invalid" ) ;
2188+
2189+ return null ;
21382190 }
21392191 } ) ;
21402192
2141- const name = sanitize ( resultName || '' ) ;
2193+ const name = sanitizeRemoteName ( resultName || '' ) ;
21422194
21432195 if ( ! name ) {
21442196 return ;
21452197 }
21462198
2147- if ( remotes . find ( r => r . name === name ) ) {
2148- window . showErrorMessage ( localize ( 'remote already exists' , "Remote '{0}' already exists." , name ) ) ;
2149- return ;
2150- }
2151-
2152- const url = await window . showInputBox ( {
2153- placeHolder : localize ( 'remote url' , "Remote URL" ) ,
2154- prompt : localize ( 'provide remote URL' , "Enter URL for remote \"{0}\"" , name ) ,
2155- ignoreFocusOut : true
2156- } ) ;
2157-
2158- if ( ! url ) {
2159- return ;
2160- }
2161-
21622199 await repository . addRemote ( name , url ) ;
2163-
21642200 return name ;
21652201 }
21662202
0 commit comments