11
11
#include "builtin.h"
12
12
13
13
static 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] [-v] [--abbrev=<length>] " ;
15
15
16
16
17
17
static const char * head ;
@@ -38,12 +38,16 @@ static int in_merge_bases(const unsigned char *sha1,
38
38
39
39
static void delete_branches (int argc , const char * * argv , int force )
40
40
{
41
- struct commit * rev , * head_rev ;
41
+ struct commit * rev , * head_rev = head_rev ;
42
42
unsigned char sha1 [20 ];
43
43
char * name ;
44
44
int i ;
45
45
46
- head_rev = lookup_commit_reference (head_sha1 );
46
+ if (!force ) {
47
+ head_rev = lookup_commit_reference (head_sha1 );
48
+ if (!head_rev )
49
+ die ("Couldn't look up commit object for HEAD" );
50
+ }
47
51
for (i = 0 ; i < argc ; i ++ ) {
48
52
if (!strcmp (head , argv [i ]))
49
53
die ("Cannot delete the branch you are currently on." );
@@ -53,8 +57,8 @@ static void delete_branches(int argc, const char **argv, int force)
53
57
die ("Branch '%s' not found." , argv [i ]);
54
58
55
59
rev = lookup_commit_reference (sha1 );
56
- if (!rev || ! head_rev )
57
- die ("Couldn't look up commit objects." );
60
+ if (!rev )
61
+ die ("Couldn't look up commit object for '%s'" , name );
58
62
59
63
/* This checks whether the merge bases of branch and
60
64
* HEAD contains branch -- which means that the HEAD
@@ -79,46 +83,129 @@ static void delete_branches(int argc, const char **argv, int force)
79
83
}
80
84
}
81
85
82
- static int ref_index , ref_alloc ;
83
- static char * * ref_list ;
86
+ #define REF_UNKNOWN_TYPE 0x00
87
+ #define REF_LOCAL_BRANCH 0x01
88
+ #define REF_REMOTE_BRANCH 0x02
89
+ #define REF_TAG 0x04
90
+
91
+ struct ref_item {
92
+ char * name ;
93
+ unsigned int kind ;
94
+ unsigned char sha1 [20 ];
95
+ };
96
+
97
+ struct ref_list {
98
+ int index , alloc , maxwidth ;
99
+ struct ref_item * list ;
100
+ int kinds ;
101
+ };
84
102
85
- static int append_ref (const char * refname , const unsigned char * sha1 , int flags ,
86
- void * cb_data )
103
+ static int append_ref (const char * refname , const unsigned char * sha1 , int flags , void * cb_data )
87
104
{
88
- if (ref_index >= ref_alloc ) {
89
- ref_alloc = alloc_nr (ref_alloc );
90
- ref_list = xrealloc (ref_list , ref_alloc * sizeof (char * ));
105
+ struct ref_list * ref_list = (struct ref_list * )(cb_data );
106
+ struct ref_item * newitem ;
107
+ int kind = REF_UNKNOWN_TYPE ;
108
+ int len ;
109
+
110
+ /* Detect kind */
111
+ if (!strncmp (refname , "refs/heads/" , 11 )) {
112
+ kind = REF_LOCAL_BRANCH ;
113
+ refname += 11 ;
114
+ } else if (!strncmp (refname , "refs/remotes/" , 13 )) {
115
+ kind = REF_REMOTE_BRANCH ;
116
+ refname += 13 ;
117
+ } else if (!strncmp (refname , "refs/tags/" , 10 )) {
118
+ kind = REF_TAG ;
119
+ refname += 10 ;
120
+ }
121
+
122
+ /* Don't add types the caller doesn't want */
123
+ if ((kind & ref_list -> kinds ) == 0 )
124
+ return 0 ;
125
+
126
+ /* Resize buffer */
127
+ if (ref_list -> index >= ref_list -> alloc ) {
128
+ ref_list -> alloc = alloc_nr (ref_list -> alloc );
129
+ ref_list -> list = xrealloc (ref_list -> list ,
130
+ ref_list -> alloc * sizeof (struct ref_item ));
91
131
}
92
132
93
- ref_list [ref_index ++ ] = xstrdup (refname );
133
+ /* Record the new item */
134
+ newitem = & (ref_list -> list [ref_list -> index ++ ]);
135
+ newitem -> name = xstrdup (refname );
136
+ newitem -> kind = kind ;
137
+ hashcpy (newitem -> sha1 , sha1 );
138
+ len = strlen (newitem -> name );
139
+ if (len > ref_list -> maxwidth )
140
+ ref_list -> maxwidth = len ;
94
141
95
142
return 0 ;
96
143
}
97
144
145
+ static void free_ref_list (struct ref_list * ref_list )
146
+ {
147
+ int i ;
148
+
149
+ for (i = 0 ; i < ref_list -> index ; i ++ )
150
+ free (ref_list -> list [i ].name );
151
+ free (ref_list -> list );
152
+ }
153
+
98
154
static int ref_cmp (const void * r1 , const void * r2 )
99
155
{
100
- return strcmp (* (char * * )r1 , * (char * * )r2 );
156
+ struct ref_item * c1 = (struct ref_item * )(r1 );
157
+ struct ref_item * c2 = (struct ref_item * )(r2 );
158
+
159
+ if (c1 -> kind != c2 -> kind )
160
+ return c1 -> kind - c2 -> kind ;
161
+ return strcmp (c1 -> name , c2 -> name );
162
+ }
163
+
164
+ static void print_ref_info (const unsigned char * sha1 , int abbrev )
165
+ {
166
+ struct commit * commit ;
167
+ char subject [256 ];
168
+
169
+
170
+ commit = lookup_commit (sha1 );
171
+ if (commit && !parse_commit (commit ))
172
+ pretty_print_commit (CMIT_FMT_ONELINE , commit , ~0 ,
173
+ subject , sizeof (subject ), 0 ,
174
+ NULL , NULL , 0 );
175
+ else
176
+ strcpy (subject , " **** invalid ref ****" );
177
+
178
+ printf (" %s %s\n" , find_unique_abbrev (sha1 , abbrev ), subject );
101
179
}
102
180
103
- static void print_ref_list (int remote_only )
181
+ static void print_ref_list (int kinds , int verbose , int abbrev )
104
182
{
105
183
int i ;
106
184
char c ;
185
+ struct ref_list ref_list ;
107
186
108
- if (remote_only )
109
- for_each_remote_ref (append_ref , NULL );
110
- else
111
- for_each_branch_ref (append_ref , NULL );
187
+ memset (& ref_list , 0 , sizeof (ref_list ));
188
+ ref_list .kinds = kinds ;
189
+ for_each_ref (append_ref , & ref_list );
112
190
113
- qsort (ref_list , ref_index , sizeof (char * ), ref_cmp );
191
+ qsort (ref_list . list , ref_list . index , sizeof (struct ref_item ), ref_cmp );
114
192
115
- for (i = 0 ; i < ref_index ; i ++ ) {
193
+ for (i = 0 ; i < ref_list . index ; i ++ ) {
116
194
c = ' ' ;
117
- if (!strcmp (ref_list [i ], head ))
195
+ if (ref_list .list [i ].kind == REF_LOCAL_BRANCH &&
196
+ !strcmp (ref_list .list [i ].name , head ))
118
197
c = '*' ;
119
198
120
- printf ("%c %s\n" , c , ref_list [i ]);
199
+ if (verbose ) {
200
+ printf ("%c %-*s" , c , ref_list .maxwidth ,
201
+ ref_list .list [i ].name );
202
+ print_ref_info (ref_list .list [i ].sha1 , abbrev );
203
+ }
204
+ else
205
+ printf ("%c %s\n" , c , ref_list .list [i ].name );
121
206
}
207
+
208
+ free_ref_list (& ref_list );
122
209
}
123
210
124
211
static void create_branch (const char * name , const char * start ,
@@ -160,8 +247,10 @@ static void create_branch(const char *name, const char *start,
160
247
161
248
int cmd_branch (int argc , const char * * argv , const char * prefix )
162
249
{
163
- int delete = 0 , force_delete = 0 , force_create = 0 , remote_only = 0 ;
250
+ int delete = 0 , force_delete = 0 , force_create = 0 ;
251
+ int verbose = 0 , abbrev = DEFAULT_ABBREV ;
164
252
int reflog = 0 ;
253
+ int kinds = REF_LOCAL_BRANCH ;
165
254
int i ;
166
255
167
256
git_config (git_default_config );
@@ -189,13 +278,25 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
189
278
continue ;
190
279
}
191
280
if (!strcmp (arg , "-r" )) {
192
- remote_only = 1 ;
281
+ kinds = REF_REMOTE_BRANCH ;
282
+ continue ;
283
+ }
284
+ if (!strcmp (arg , "-a" )) {
285
+ kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH ;
193
286
continue ;
194
287
}
195
288
if (!strcmp (arg , "-l" )) {
196
289
reflog = 1 ;
197
290
continue ;
198
291
}
292
+ if (!strncmp (arg , "--abbrev=" , 9 )) {
293
+ abbrev = atoi (arg + 9 );
294
+ continue ;
295
+ }
296
+ if (!strcmp (arg , "-v" )) {
297
+ verbose = 1 ;
298
+ continue ;
299
+ }
199
300
usage (builtin_branch_usage );
200
301
}
201
302
@@ -209,7 +310,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
209
310
if (delete )
210
311
delete_branches (argc - i , argv + i , force_delete );
211
312
else if (i == argc )
212
- print_ref_list (remote_only );
313
+ print_ref_list (kinds , verbose , abbrev );
213
314
else if (i == argc - 1 )
214
315
create_branch (argv [i ], head , force_create , reflog );
215
316
else if (i == argc - 2 )
0 commit comments