1111#include "builtin.h"
1212
1313static const char builtin_branch_usage [] =
14- "git-branch (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | [-r]" ;
14+ "git-branch (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | [-r] | [-a] " ;
1515
1616
1717static const char * head ;
@@ -79,46 +79,100 @@ static void delete_branches(int argc, const char **argv, int force)
7979 }
8080}
8181
82- static int ref_index , ref_alloc ;
83- static char * * ref_list ;
82+ #define REF_UNKNOWN_TYPE 0x00
83+ #define REF_LOCAL_BRANCH 0x01
84+ #define REF_REMOTE_BRANCH 0x02
85+ #define REF_TAG 0x04
8486
85- static int append_ref (const char * refname , const unsigned char * sha1 , int flags ,
86- void * cb_data )
87+ struct ref_item {
88+ char * name ;
89+ unsigned int kind ;
90+ };
91+
92+ struct ref_list {
93+ int index , alloc ;
94+ struct ref_item * list ;
95+ int kinds ;
96+ };
97+
98+ static int append_ref (const char * refname , const unsigned char * sha1 , int flags , void * cb_data )
8799{
88- if (ref_index >= ref_alloc ) {
89- ref_alloc = alloc_nr (ref_alloc );
90- ref_list = xrealloc (ref_list , ref_alloc * sizeof (char * ));
100+ struct ref_list * ref_list = (struct ref_list * )(cb_data );
101+ struct ref_item * newitem ;
102+ int kind = REF_UNKNOWN_TYPE ;
103+
104+ /* Detect kind */
105+ if (!strncmp (refname , "refs/heads/" , 11 )) {
106+ kind = REF_LOCAL_BRANCH ;
107+ refname += 11 ;
108+ } else if (!strncmp (refname , "refs/remotes/" , 13 )) {
109+ kind = REF_REMOTE_BRANCH ;
110+ refname += 13 ;
111+ } else if (!strncmp (refname , "refs/tags/" , 10 )) {
112+ kind = REF_TAG ;
113+ refname += 10 ;
114+ }
115+
116+ /* Don't add types the caller doesn't want */
117+ if ((kind & ref_list -> kinds ) == 0 )
118+ return 0 ;
119+
120+ /* Resize buffer */
121+ if (ref_list -> index >= ref_list -> alloc ) {
122+ ref_list -> alloc = alloc_nr (ref_list -> alloc );
123+ ref_list -> list = xrealloc (ref_list -> list ,
124+ ref_list -> alloc * sizeof (struct ref_item ));
91125 }
92126
93- ref_list [ref_index ++ ] = xstrdup (refname );
127+ /* Record the new item */
128+ newitem = & (ref_list -> list [ref_list -> index ++ ]);
129+ newitem -> name = xstrdup (refname );
130+ newitem -> kind = kind ;
94131
95132 return 0 ;
96133}
97134
135+ static void free_ref_list (struct ref_list * ref_list )
136+ {
137+ int i ;
138+
139+ for (i = 0 ; i < ref_list -> index ; i ++ )
140+ free (ref_list -> list [i ].name );
141+ free (ref_list -> list );
142+ }
143+
98144static int ref_cmp (const void * r1 , const void * r2 )
99145{
100- return strcmp (* (char * * )r1 , * (char * * )r2 );
146+ struct ref_item * c1 = (struct ref_item * )(r1 );
147+ struct ref_item * c2 = (struct ref_item * )(r2 );
148+
149+ if (c1 -> kind != c2 -> kind )
150+ return c1 -> kind - c2 -> kind ;
151+ return strcmp (c1 -> name , c2 -> name );
101152}
102153
103- static void print_ref_list (int remote_only )
154+ static void print_ref_list (int kinds )
104155{
105156 int i ;
106157 char c ;
158+ struct ref_list ref_list ;
107159
108- if (remote_only )
109- for_each_remote_ref (append_ref , NULL );
110- else
111- for_each_branch_ref (append_ref , NULL );
160+ memset (& ref_list , 0 , sizeof (ref_list ));
161+ ref_list .kinds = kinds ;
162+ for_each_ref (append_ref , & ref_list );
112163
113- qsort (ref_list , ref_index , sizeof (char * ), ref_cmp );
164+ qsort (ref_list . list , ref_list . index , sizeof (struct ref_item ), ref_cmp );
114165
115- for (i = 0 ; i < ref_index ; i ++ ) {
166+ for (i = 0 ; i < ref_list . index ; i ++ ) {
116167 c = ' ' ;
117- if (!strcmp (ref_list [i ], head ))
168+ if (ref_list .list [i ].kind == REF_LOCAL_BRANCH &&
169+ !strcmp (ref_list .list [i ].name , head ))
118170 c = '*' ;
119171
120- printf ("%c %s\n" , c , ref_list [i ]);
172+ printf ("%c %s\n" , c , ref_list . list [i ]. name );
121173 }
174+
175+ free_ref_list (& ref_list );
122176}
123177
124178static void create_branch (const char * name , const char * start ,
@@ -160,8 +214,9 @@ static void create_branch(const char *name, const char *start,
160214
161215int cmd_branch (int argc , const char * * argv , const char * prefix )
162216{
163- int delete = 0 , force_delete = 0 , force_create = 0 , remote_only = 0 ;
217+ int delete = 0 , force_delete = 0 , force_create = 0 ;
164218 int reflog = 0 ;
219+ int kinds = REF_LOCAL_BRANCH ;
165220 int i ;
166221
167222 git_config (git_default_config );
@@ -189,7 +244,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
189244 continue ;
190245 }
191246 if (!strcmp (arg , "-r" )) {
192- remote_only = 1 ;
247+ kinds = REF_REMOTE_BRANCH ;
248+ continue ;
249+ }
250+ if (!strcmp (arg , "-a" )) {
251+ kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH ;
193252 continue ;
194253 }
195254 if (!strcmp (arg , "-l" )) {
@@ -209,7 +268,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
209268 if (delete )
210269 delete_branches (argc - i , argv + i , force_delete );
211270 else if (i == argc )
212- print_ref_list (remote_only );
271+ print_ref_list (kinds );
213272 else if (i == argc - 1 )
214273 create_branch (argv [i ], head , force_create , reflog );
215274 else if (i == argc - 2 )
0 commit comments