@ -270,125 +270,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
@@ -270,125 +270,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
return(ret);
}
static char *resolve_symref(const char *src, const char *prefix)
{
unsigned char sha1[20];
int flag;
const char *dst;
dst = resolve_ref_unsafe(src, 0, sha1, &flag);
if (!(dst && (flag & REF_ISSYMREF)))
return NULL;
if (prefix)
skip_prefix(dst, prefix, &dst);
return xstrdup(dst);
}
static int match_patterns(const char **pattern, const char *refname)
{
if (!*pattern)
return 1; /* no pattern always matches */
while (*pattern) {
if (!wildmatch(*pattern, refname, 0, NULL))
return 1;
pattern++;
}
return 0;
}
/*
* Allocate memory for a new ref_array_item and insert that into the
* given ref_array. Doesn't take the objectname unlike
* new_ref_array_item(). This is a temporary function which will be
* removed when we port branch.c to use ref-filter APIs.
*/
static struct ref_array_item *ref_array_append(struct ref_array *array, const char *refname)
{
size_t len = strlen(refname);
struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + len + 1);
memcpy(ref->refname, refname, len);
ref->refname[len] = '\0';
REALLOC_ARRAY(array->items, array->nr + 1);
array->items[array->nr++] = ref;
return ref;
}
static int append_ref(const char *refname, const struct object_id *oid, int flags, void *cb_data)
{
struct ref_filter_cbdata *cb = (struct ref_filter_cbdata *)(cb_data);
struct ref_filter *filter = cb->filter;
struct ref_array *array = cb->array;
struct ref_array_item *item;
struct commit *commit;
int kind, i;
const char *prefix, *orig_refname = refname;
static struct {
int kind;
const char *prefix;
} ref_kind[] = {
{ FILTER_REFS_BRANCHES, "refs/heads/" },
{ FILTER_REFS_REMOTES, "refs/remotes/" },
};
/* Detect kind */
for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
prefix = ref_kind[i].prefix;
if (skip_prefix(refname, prefix, &refname)) {
kind = ref_kind[i].kind;
break;
}
}
if (ARRAY_SIZE(ref_kind) <= i) {
if (!strcmp(refname, "HEAD"))
kind = FILTER_REFS_DETACHED_HEAD;
else
return 0;
}
/* Don't add types the caller doesn't want */
if ((kind & filter->kind) == 0)
return 0;
if (!match_patterns(filter->name_patterns, refname))
return 0;
commit = NULL;
if (filter->verbose || filter->with_commit || filter->merge != REF_FILTER_MERGED_NONE) {
commit = lookup_commit_reference_gently(oid->hash, 1);
if (!commit)
return 0;
/* Filter with with_commit if specified */
if (!is_descendant_of(commit, filter->with_commit))
return 0;
if (filter->merge != REF_FILTER_MERGED_NONE)
add_pending_object(array->revs,
(struct object *)commit, refname);
}
item = ref_array_append(array, refname);
/* Record the new item */
item->kind = kind;
item->commit = commit;
item->symref = resolve_symref(orig_refname, prefix);
item->ignore = 0;
return 0;
}
static int ref_cmp(const void *r1, const void *r2)
{
struct ref_array_item *c1 = *((struct ref_array_item **)r1);
struct ref_array_item *c2 = *((struct ref_array_item **)r2);
if (c1->kind != c2->kind)
return c1->kind - c2->kind;
return strcmp(c1->refname, c2->refname);
}
static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
int show_upstream_ref)
{
@ -452,7 +333,7 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
@@ -452,7 +333,7 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
}
static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,
struct ref_filter *filter)
struct ref_filter *filter, const char *refname)
{
struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
const char *sub = _(" **** invalid ref ****");
@ -464,7 +345,7 @@ static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,
@@ -464,7 +345,7 @@ static void add_verbose_info(struct strbuf *out, struct ref_array_item *item,
}
if (item->kind == FILTER_REFS_BRANCHES)
fill_tracking_info(&stat, item->refname, filter->verbose > 1);
fill_tracking_info(&stat, refname, filter->verbose > 1);
strbuf_addf(out, " %s %s%s",
find_unique_abbrev(item->commit->object.sha1, filter->abbrev),
@ -504,8 +385,8 @@ static char *get_head_description(void)
@@ -504,8 +385,8 @@ static char *get_head_description(void)
return strbuf_detach(&desc, NULL);
}
static void print_ref_item(struct ref_array_item *item, int maxwidth,
struct ref_filter *filter, const char *remote_prefix)
static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth,
struct ref_filter *filter, const char *remote_prefix)
{
char c;
int current = 0;
@ -515,17 +396,16 @@ static void print_ref_item(struct ref_array_item *item, int maxwidth,
@@ -515,17 +396,16 @@ static void print_ref_item(struct ref_array_item *item, int maxwidth,
const char *desc = item->refname;
char *to_free = NULL;
if (item->ignore)
return;
switch (item->kind) {
case FILTER_REFS_BRANCHES:
if (!filter->detached && !strcmp(item->refname, head))
skip_prefix(desc, "refs/heads/", &desc);
if (!filter->detached && !strcmp(desc, head))
current = 1;
else
color = BRANCH_COLOR_LOCAL;
break;
case FILTER_REFS_REMOTES:
skip_prefix(desc, "refs/remotes/", &desc);
color = BRANCH_COLOR_REMOTE;
prefix = remote_prefix;
break;
@ -554,11 +434,13 @@ static void print_ref_item(struct ref_array_item *item, int maxwidth,
@@ -554,11 +434,13 @@ static void print_ref_item(struct ref_array_item *item, int maxwidth,
strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
name.buf, branch_get_color(BRANCH_COLOR_RESET));
if (item->symref)
strbuf_addf(&out, " -> %s", item->symref);
if (item->symref) {
skip_prefix(item->symref, "refs/remotes/", &desc);
strbuf_addf(&out, " -> %s", desc);
}
else if (filter->verbose)
/* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
add_verbose_info(&out, item, filter);
add_verbose_info(&out, item, filter, desc);
if (column_active(colopts)) {
assert(!filter->verbose && "--column and --verbose are incompatible");
string_list_append(&output, out.buf);
@ -575,11 +457,13 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
@@ -575,11 +457,13 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
int i, max = 0;
for (i = 0; i < refs->nr; i++) {
struct ref_array_item *it = refs->items[i];
const char *desc = it->refname;
int w;
if (it->ignore)
continue;
w = utf8_strwidth(it->refname);
skip_prefix(it->refname, "refs/heads/", &desc);
skip_prefix(it->refname, "refs/remotes/", &desc);
w = utf8_strwidth(desc);
if (it->kind == FILTER_REFS_REMOTES)
w += remote_bonus;
if (w > max)
@ -588,14 +472,12 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
@@ -588,14 +472,12 @@ static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
return max;
}
static void print_ref_list(struct ref_filter *filter)
static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting)
{
int i;
struct ref_array array;
struct ref_filter_cbdata data;
int maxwidth = 0;
const char *remote_prefix = "";
struct rev_info revs;
/*
* If we are listing more than just remote branches,
@ -606,54 +488,26 @@ static void print_ref_list(struct ref_filter *filter)
@@ -606,54 +488,26 @@ static void print_ref_list(struct ref_filter *filter)
remote_prefix = "remotes/";
memset(&array, 0, sizeof(array));
if (filter->merge != REF_FILTER_MERGED_NONE)
init_revisions(&revs, NULL);
data.array = &array;
data.filter = filter;
array.revs = &revs;
/*
* First we obtain all regular branch refs and if the HEAD is
* detached then we insert that ref to the end of the ref_fist
* so that it can be printed and removed first.
*/
for_each_rawref(append_ref, &data);
if (filter->detached)
head_ref(append_ref, &data);
/*
* The following implementation is currently duplicated in ref-filter. It
* will eventually be removed when we port branch.c to use ref-filter APIs.
*/
if (filter->merge != REF_FILTER_MERGED_NONE) {
filter->merge_commit->object.flags |= UNINTERESTING;
add_pending_object(&revs, &filter->merge_commit->object, "");
revs.limited = 1;
if (prepare_revision_walk(&revs))
die(_("revision walk setup failed"));
for (i = 0; i < array.nr; i++) {
struct ref_array_item *item = array.items[i];
struct commit *commit = item->commit;
int is_merged = !!(commit->object.flags & UNINTERESTING);
item->ignore = is_merged != (filter->merge == REF_FILTER_MERGED_INCLUDE);
}
for (i = 0; i < array.nr; i++) {
struct ref_array_item *item = array.items[i];
clear_commit_marks(item->commit, ALL_REV_FLAGS);
}
clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
}
verify_ref_format("%(refname)%(symref)");
filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
if (filter->verbose)
maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
qsort(array.items, array.nr, sizeof(struct ref_array_item *), ref_cmp);
/*
* If no sorting parameter is given then we default to sorting
* by 'refname'. This would give us an alphabetically sorted
* array with the 'HEAD' ref at the beginning followed by
* local branches 'refs/heads/...' and finally remote-tacking
* branches 'refs/remotes/...'.
*/
if (!sorting)
sorting = ref_default_sorting();
ref_array_sort(sorting, &array);
for (i = 0; i < array.nr; i++)
print_ref_item(array.items[i], maxwidth, filter, remote_prefix);
format_and_print_ref_item(array.items[i], maxwidth, filter, remote_prefix);
ref_array_clear(&array);
}
@ -755,6 +609,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
@@ -755,6 +609,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
const char *new_upstream = NULL;
enum branch_track track;
struct ref_filter filter;
static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
struct option options[] = {
OPT_GROUP(N_("Generic options")),
@ -789,6 +644,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
@@ -789,6 +644,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_MERGED(&filter, N_("print only branches that are merged")),
OPT_NO_MERGED(&filter, N_("print only branches that are not merged")),
OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
N_("field name to sort on"), &parse_opt_ref_sorting),
OPT_END(),
};
@ -847,7 +704,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
@@ -847,7 +704,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached)
filter.kind |= FILTER_REFS_DETACHED_HEAD;
filter.name_patterns = argv;
print_ref_list(&filter);
print_ref_list(&filter, sorting);
print_columns(&output, colopts, NULL);
string_list_clear(&output, 0);
return 0;