@@ -16,6 +16,8 @@ import { GitErrorHandling } from '../../../git/commandOptions';
1616import {
1717 BlameIgnoreRevsFileBadRevisionError ,
1818 BlameIgnoreRevsFileError ,
19+ BranchError ,
20+ BranchErrorReason ,
1921 FetchError ,
2022 FetchErrorReason ,
2123 PullError ,
@@ -75,6 +77,8 @@ export const GitErrors = {
7577 alreadyExists : / a l r e a d y e x i s t s / i,
7678 ambiguousArgument : / f a t a l : \s * a m b i g u o u s a r g u m e n t [ ' " ] .+ [ ' " ] : u n k n o w n r e v i s i o n o r p a t h n o t i n t h e w o r k i n g t r e e / i,
7779 badRevision : / b a d r e v i s i o n ' ( .* ?) ' / i,
80+ branchAlreadyExists : / f a t a l : A b r a n c h n a m e d ' .+ ?' a l r e a d y e x i s t s / i,
81+ branchNotFullyMerged : / e r r o r : T h e b r a n c h ' .+ ?' i s n o t f u l l y m e r g e d / i,
7882 cantLockRef : / c a n n o t l o c k r e f | u n a b l e t o u p d a t e l o c a l r e f / i,
7983 changesWouldBeOverwritten :
8084 / Y o u r l o c a l c h a n g e s t o t h e f o l l o w i n g f i l e s w o u l d b e o v e r w r i t t e n | Y o u r l o c a l c h a n g e s w o u l d b e o v e r w r i t t e n / i,
@@ -84,13 +88,15 @@ export const GitErrors = {
8488 emptyPreviousCherryPick : / T h e p r e v i o u s c h e r r y - p i c k i s n o w e m p t y / i,
8589 entryNotUpToDate : / e r r o r : \s * E n t r y [ ' " ] .+ [ ' " ] n o t u p t o d a t e \. C a n n o t m e r g e \. / i,
8690 failedToDeleteDirectoryNotEmpty : / f a i l e d t o d e l e t e ' ( .* ?) ' : D i r e c t o r y n o t e m p t y / i,
91+ invalidBranchName : / f a t a l : ' .+ ?' i s n o t a v a l i d b r a n c h n a m e / i,
8792 invalidLineCount : / f i l e .+ ? h a s o n l y ( \d + ) l i n e s / i,
8893 invalidObjectName : / i n v a l i d o b j e c t n a m e : ( .* ) \s / i,
8994 invalidObjectNameList : / c o u l d n o t o p e n o b j e c t n a m e l i s t : ( .* ) \s / i,
9095 invalidTagName : / i n v a l i d t a g n a m e / i,
9196 mainWorkingTree : / i s a m a i n w o r k i n g t r e e / i,
9297 noFastForward : / \( n o n - f a s t - f o r w a r d \) / i,
9398 noMergeBase : / n o m e r g e b a s e / i,
99+ noRemoteReference : / u n a b l e t o d e l e t e ' .+ ?' : r e m o t e r e f d o e s n o t e x i s t / i,
94100 noRemoteRepositorySpecified : / N o r e m o t e r e p o s i t o r y s p e c i f i e d \. / i,
95101 noUpstream : / ^ f a t a l : T h e c u r r e n t b r a n c h .* h a s n o u p s t r e a m b r a n c h / i,
96102 notAValidObjectName : / N o t a v a l i d o b j e c t n a m e / i,
@@ -169,15 +175,14 @@ const uniqueCounterForStdin = getScopedCounter();
169175type ExitCodeOnlyGitCommandOptions = GitCommandOptions & { exitCodeOnly : true } ;
170176export type PushForceOptions = { withLease : true ; ifIncludes ?: boolean } | { withLease : false ; ifIncludes ?: never } ;
171177
172- const tagErrorAndReason : [ RegExp , TagErrorReason ] [ ] = [
173- [ GitErrors . tagAlreadyExists , TagErrorReason . TagAlreadyExists ] ,
174- [ GitErrors . tagNotFound , TagErrorReason . TagNotFound ] ,
175- [ GitErrors . invalidTagName , TagErrorReason . InvalidTagName ] ,
176- [ GitErrors . permissionDenied , TagErrorReason . PermissionDenied ] ,
177- [ GitErrors . remoteRejected , TagErrorReason . RemoteRejected ] ,
178+ const branchErrorsToReasons : [ RegExp , BranchErrorReason ] [ ] = [
179+ [ GitErrors . noRemoteReference , BranchErrorReason . NoRemoteReference ] ,
180+ [ GitErrors . invalidBranchName , BranchErrorReason . InvalidBranchName ] ,
181+ [ GitErrors . branchAlreadyExists , BranchErrorReason . BranchAlreadyExists ] ,
182+ [ GitErrors . branchNotFullyMerged , BranchErrorReason . BranchNotFullyMerged ] ,
178183] ;
179184
180- const resetErrorAndReason : [ RegExp , ResetErrorReason ] [ ] = [
185+ const resetErrorsToReasons : [ RegExp , ResetErrorReason ] [ ] = [
181186 [ GitErrors . ambiguousArgument , ResetErrorReason . AmbiguousArgument ] ,
182187 [ GitErrors . changesWouldBeOverwritten , ResetErrorReason . ChangesWouldBeOverwritten ] ,
183188 [ GitErrors . detachedHead , ResetErrorReason . DetachedHead ] ,
@@ -187,6 +192,14 @@ const resetErrorAndReason: [RegExp, ResetErrorReason][] = [
187192 [ GitErrors . unmergedChanges , ResetErrorReason . UnmergedChanges ] ,
188193] ;
189194
195+ const tagErrorsToReasons : [ RegExp , TagErrorReason ] [ ] = [
196+ [ GitErrors . tagAlreadyExists , TagErrorReason . TagAlreadyExists ] ,
197+ [ GitErrors . tagNotFound , TagErrorReason . TagNotFound ] ,
198+ [ GitErrors . invalidTagName , TagErrorReason . InvalidTagName ] ,
199+ [ GitErrors . permissionDenied , TagErrorReason . PermissionDenied ] ,
200+ [ GitErrors . remoteRejected , TagErrorReason . RemoteRejected ] ,
201+ ] ;
202+
190203export class GitError extends Error {
191204 readonly cmd : string | undefined ;
192205 readonly exitCode : number | string | undefined ;
@@ -705,6 +718,21 @@ export class Git implements Disposable {
705718 }
706719 }
707720
721+ async branch ( repoPath : string , ...args : string [ ] ) : Promise < GitResult < string > > {
722+ try {
723+ const result = await this . exec ( { cwd : repoPath } , 'branch' , ...args ) ;
724+ return result ;
725+ } catch ( ex ) {
726+ const msg : string = ex ?. toString ( ) ?? '' ;
727+ for ( const [ error , reason ] of branchErrorsToReasons ) {
728+ if ( error . test ( msg ) || error . test ( ex . stderr ?? '' ) ) {
729+ throw new BranchError ( reason , ex ) ;
730+ }
731+ }
732+ throw new BranchError ( BranchErrorReason . Other , ex ) ;
733+ }
734+ }
735+
708736 async branchOrTag__containsOrPointsAt (
709737 repoPath : string ,
710738 refs : string [ ] ,
@@ -991,6 +1019,10 @@ export class Git implements Disposable {
9911019 publish ?: boolean ;
9921020 remote ?: string ;
9931021 upstream ?: string ;
1022+ delete ?: {
1023+ remote : string ;
1024+ branch : string ;
1025+ } ;
9941026 } ,
9951027 ) : Promise < void > {
9961028 const params = [ 'push' ] ;
@@ -1018,6 +1050,8 @@ export class Git implements Disposable {
10181050 }
10191051 } else if ( options . remote ) {
10201052 params . push ( options . remote ) ;
1053+ } else if ( options . delete ) {
1054+ params . push ( options . delete . remote , `:${ options . delete . branch } ` ) ;
10211055 }
10221056
10231057 try {
@@ -1038,12 +1072,16 @@ export class Git implements Disposable {
10381072 / ! \[ r e j e c t e d \] .* \( r e m o t e r e f u p d a t e d s i n c e c h e c k o u t \) / m. test ( ex . stderr || '' )
10391073 ) {
10401074 reason = PushErrorReason . PushRejectedWithLeaseIfIncludes ;
1075+ } else if ( / e r r o r : u n a b l e t o d e l e t e ' ( .* ?) ' : r e m o t e r e f d o e s n o t e x i s t / m. test ( ex . stderr || '' ) ) {
1076+ reason = PushErrorReason . PushRejectedRefNotExists ;
10411077 } else {
10421078 reason = PushErrorReason . PushRejected ;
10431079 }
10441080 } else {
10451081 reason = PushErrorReason . PushRejected ;
10461082 }
1083+ } else if ( / e r r o r : u n a b l e t o d e l e t e ' ( .* ?) ' : r e m o t e r e f d o e s n o t e x i s t / m. test ( ex . stderr || '' ) ) {
1084+ reason = PushErrorReason . PushRejectedRefNotExists ;
10471085 } else if ( GitErrors . permissionDenied . test ( msg ) || GitErrors . permissionDenied . test ( ex . stderr ?? '' ) ) {
10481086 reason = PushErrorReason . PermissionDenied ;
10491087 } else if ( GitErrors . remoteConnection . test ( msg ) || GitErrors . remoteConnection . test ( ex . stderr ?? '' ) ) {
@@ -1052,7 +1090,12 @@ export class Git implements Disposable {
10521090 reason = PushErrorReason . NoUpstream ;
10531091 }
10541092
1055- throw new PushError ( reason , ex , options ?. branch , options ?. remote ) ;
1093+ throw new PushError (
1094+ reason ,
1095+ ex ,
1096+ options ?. branch || options ?. delete ?. branch ,
1097+ options ?. remote || options ?. delete ?. remote ,
1098+ ) ;
10561099 }
10571100 }
10581101
@@ -1126,7 +1169,7 @@ export class Git implements Disposable {
11261169 await this . exec ( { cwd : repoPath } , 'reset' , '-q' , ...flags , '--' , ...pathspecs ) ;
11271170 } catch ( ex ) {
11281171 const msg : string = ex ?. toString ( ) ?? '' ;
1129- for ( const [ error , reason ] of resetErrorAndReason ) {
1172+ for ( const [ error , reason ] of resetErrorsToReasons ) {
11301173 if ( error . test ( msg ) || error . test ( ex . stderr ?? '' ) ) {
11311174 throw new ResetError ( reason , ex ) ;
11321175 }
@@ -1542,7 +1585,7 @@ export class Git implements Disposable {
15421585 return result ;
15431586 } catch ( ex ) {
15441587 const msg : string = ex ?. toString ( ) ?? '' ;
1545- for ( const [ error , reason ] of tagErrorAndReason ) {
1588+ for ( const [ error , reason ] of tagErrorsToReasons ) {
15461589 if ( error . test ( msg ) || error . test ( ex . stderr ?? '' ) ) {
15471590 throw new TagError ( reason , ex ) ;
15481591 }
0 commit comments