181
182
struct ref_item {
183
char *name;
184
- unsigned int kind;
184
+ char *dest;
185
+ unsigned int kind, len;
186
struct commit *commit;
187
};
188
194
int kinds;
195
};
196
197
+static char *resolve_symref(const char *src, const char *prefix)
198
+{
199
+ unsigned char sha1[20];
200
+ int flag;
201
+ const char *dst, *cp;
202
+
203
+ dst = resolve_ref(src, sha1, 0, &flag);
204
+ if (!(dst && (flag & REF_ISSYMREF)))
205
+ return NULL;
206
+ if (prefix && (cp = skip_prefix(dst, prefix)))
207
+ dst = cp;
208
+ return xstrdup(dst);
209
+}
210
+
211
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
212
{
213
struct ref_list *ref_list = (struct ref_list*)(cb_data);
214
struct ref_item *newitem;
215
struct commit *commit;
201
- int kind;
202
- int len;
216
+ int kind, i;
217
+ const char *prefix, *orig_refname = refname;
218
+
219
+ static struct {
220
+ int kind;
221
+ const char *prefix;
222
+ int pfxlen;
223
+ } ref_kind[] = {
224
+ { REF_LOCAL_BRANCH, "refs/heads/", 11 },
225
+ { REF_REMOTE_BRANCH, "refs/remotes/", 13 },
226
+ };
227
228
/* Detect kind */
205
- if (!prefixcmp(refname, "refs/heads/")) {
206
- kind = REF_LOCAL_BRANCH;
207
- refname += 11;
208
- } else if (!prefixcmp(refname, "refs/remotes/")) {
209
- kind = REF_REMOTE_BRANCH;
210
- refname += 13;
211
- } else
229
+ for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
230
+ prefix = ref_kind[i].prefix;
231
+ if (strncmp(refname, prefix, ref_kind[i].pfxlen))
232
+ continue;
233
+ kind = ref_kind[i].kind;
234
+ refname += ref_kind[i].pfxlen;
235
+ break;
236
+ }
237
+ if (ARRAY_SIZE(ref_kind) <= i)
238
return 0;
239
240
commit = lookup_commit_reference_gently(sha1, 1);
265
newitem->name = xstrdup(refname);
266
newitem->kind = kind;
267
newitem->commit = commit;
242
- len = strlen(newitem->name);
243
- if (len > ref_list->maxwidth)
244
- ref_list->maxwidth = len;
268
+ newitem->len = strlen(refname);
269
+ newitem->dest = resolve_symref(orig_refname, prefix);
270
+ /* adjust for "remotes/" */
271
+ if (newitem->kind == REF_REMOTE_BRANCH &&
272
+ ref_list->kinds != REF_REMOTE_BRANCH)
273
+ newitem->len += 8;
274
+ if (newitem->len > ref_list->maxwidth)
275
+ ref_list->maxwidth = newitem->len;
276
277
return 0;
278
}
281
{
282
int i;
283
253
- for (i = 0; i < ref_list->index; i++)
284
+ for (i = 0; i < ref_list->index; i++) {
285
free(ref_list->list[i].name);
286
+ free(ref_list->list[i].dest);
287
+ }
288
free(ref_list->list);
289
}
290
325
}
326
327
static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
295
- int abbrev, int current)
328
+ int abbrev, int current, char *prefix)
329
{
330
char c;
331
int color;
332
struct commit *commit = item->commit;
333
+ struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
334
335
if (!matches_merge_filter(commit))
336
return;
353
color = COLOR_BRANCH_CURRENT;
354
}
355
322
- if (verbose) {
356
+ strbuf_addf(&name, "%s%s", prefix, item->name);
357
+ if (verbose)
358
+ strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
359
+ maxwidth, name.buf,
360
+ branch_get_color(COLOR_BRANCH_RESET));
361
+ else
362
+ strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
363
+ name.buf, branch_get_color(COLOR_BRANCH_RESET));
364
+
365
+ if (item->dest)
366
+ strbuf_addf(&out, " -> %s", item->dest);
367
+ else if (verbose) {
368
struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
369
const char *sub = " **** invalid ref ****";
370
378
if (item->kind == REF_LOCAL_BRANCH)
379
fill_tracking_info(&stat, item->name);
380
336
- printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
337
- maxwidth, item->name,
338
- branch_get_color(COLOR_BRANCH_RESET),
339
- find_unique_abbrev(item->commit->object.sha1, abbrev),
340
- stat.buf, sub);
381
+ strbuf_addf(&out, " %s %s%s",
382
+ find_unique_abbrev(item->commit->object.sha1, abbrev),
383
+ stat.buf, sub);
384
strbuf_release(&stat);
385
strbuf_release(&subject);
343
- } else {
344
- printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
345
- branch_get_color(COLOR_BRANCH_RESET));
386
}
387
+ printf("%s\n", out.buf);
388
+ strbuf_release(&name);
389
+ strbuf_release(&out);
390
}
391
392
static int calc_maxwidth(struct ref_list *refs)
393
{
351
- int i, l, w = 0;
394
+ int i, w = 0;
395
for (i = 0; i < refs->index; i++) {
396
if (!matches_merge_filter(refs->list[i].commit))
397
continue;
355
- l = strlen(refs->list[i].name);
356
- if (l > w)
357
- w = l;
398
+ if (refs->list[i].len > w)
399
+ w = refs->list[i].len;
400
}
401
return w;
402
}
436
item.commit = head_commit;
437
if (strlen(item.name) > ref_list.maxwidth)
438
ref_list.maxwidth = strlen(item.name);
397
- print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
439
+ print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1, "");
440
free(item.name);
441
}
442
444
int current = !detached &&
445
(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
446
!strcmp(ref_list.list[i].name, head);
447
+ char *prefix = (kinds != REF_REMOTE_BRANCH &&
448
+ ref_list.list[i].kind == REF_REMOTE_BRANCH)
449
+ ? "remotes/" : "";
450
print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
406
- abbrev, current);
451
+ abbrev, current, prefix);
452
}
453
454
free_ref_list(&ref_list);