unsigned reverse : 1;
};
-struct refinfo {
- char *refname;
+struct ref_array_item {
unsigned char objectname[20];
int flag;
const char *symref;
struct atom_value *value;
+ char *refname;
};
static struct {
{ "contents:body" },
{ "contents:signature" },
{ "upstream" },
+ { "push" },
{ "symref" },
{ "flag" },
{ "HEAD" },
* a "*" to denote deref_tag().
*
* We parse given format string and sort specifiers, and make a list
- * of properties that we need to extract out of objects. refinfo
+ * of properties that we need to extract out of objects. ref_array_item
* structure will hold an array of values extracted that can be
* indexed with the "atom number", which is an index into this
* array.
/*
* Parse the object referred by ref, and grab needed value.
*/
-static void populate_value(struct refinfo *ref)
+static void populate_value(struct ref_array_item *ref)
{
void *buf;
struct object *obj;
else if (starts_with(name, "symref"))
refname = ref->symref ? ref->symref : "";
else if (starts_with(name, "upstream")) {
+ const char *branch_name;
/* only local branches may have an upstream */
- if (!starts_with(ref->refname, "refs/heads/"))
+ if (!skip_prefix(ref->refname, "refs/heads/",
+ &branch_name))
+ continue;
+ branch = branch_get(branch_name);
+
+ refname = branch_get_upstream(branch, NULL);
+ if (!refname)
+ continue;
+ } else if (starts_with(name, "push")) {
+ const char *branch_name;
+ if (!skip_prefix(ref->refname, "refs/heads/",
+ &branch_name))
continue;
- branch = branch_get(ref->refname + 11);
+ branch = branch_get(branch_name);
- refname = branch_get_upstream(branch);
+ refname = branch_get_push(branch, NULL);
if (!refname)
continue;
} else if (starts_with(name, "color:")) {
refname = shorten_unambiguous_ref(refname,
warn_ambiguous_refs);
else if (!strcmp(formatp, "track") &&
- starts_with(name, "upstream")) {
+ (starts_with(name, "upstream") ||
+ starts_with(name, "push"))) {
char buf[40];
if (stat_tracking_info(branch, &num_ours,
- &num_theirs) != 1)
+ &num_theirs, NULL))
continue;
if (!num_ours && !num_theirs)
}
continue;
} else if (!strcmp(formatp, "trackshort") &&
- starts_with(name, "upstream")) {
+ (starts_with(name, "upstream") ||
+ starts_with(name, "push"))) {
assert(branch);
if (stat_tracking_info(branch, &num_ours,
- &num_theirs) != 1)
+ &num_theirs, NULL))
continue;
if (!num_ours && !num_theirs)
* Given a ref, return the value for the atom. This lazily gets value
* out of the object by calling populate value.
*/
-static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
+static void get_value(struct ref_array_item *ref, int atom, struct atom_value **v)
{
if (!ref->value) {
populate_value(ref);
}
struct grab_ref_cbdata {
- struct refinfo **grab_array;
+ struct ref_array_item **grab_array;
const char **grab_pattern;
int grab_cnt;
};
+/*
+ * Return 1 if the refname matches one of the patterns, otherwise 0.
+ * A pattern can be path prefix (e.g. a refname "refs/heads/master"
+ * matches a pattern "refs/heads/") or a wildcard (e.g. the same ref
+ * matches "refs/heads/m*",too).
+ */
+static int match_name_as_path(const char **pattern, const char *refname)
+{
+ int namelen = strlen(refname);
+ for (; *pattern; pattern++) {
+ const char *p = *pattern;
+ int plen = strlen(p);
+
+ if ((plen <= namelen) &&
+ !strncmp(refname, p, plen) &&
+ (refname[plen] == '\0' ||
+ refname[plen] == '/' ||
+ p[plen-1] == '/'))
+ return 1;
+ if (!wildmatch(p, refname, WM_PATHNAME, NULL))
+ return 1;
+ }
+ return 0;
+}
+
+/* Allocate space for a new ref_array_item and copy the objectname and flag to it */
+static struct ref_array_item *new_ref_array_item(const char *refname,
+ const unsigned char *objectname,
+ int flag)
+{
+ struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item));
+ ref->refname = xstrdup(refname);
+ hashcpy(ref->objectname, objectname);
+ ref->flag = flag;
+
+ return ref;
+}
+
/*
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+static int grab_single_ref(const char *refname, const struct object_id *oid,
+ int flag, void *cb_data)
{
struct grab_ref_cbdata *cb = cb_data;
- struct refinfo *ref;
- int cnt;
+ struct ref_array_item *ref;
if (flag & REF_BAD_NAME) {
warning("ignoring ref with broken name %s", refname);
return 0;
}
- if (*cb->grab_pattern) {
- const char **pattern;
- int namelen = strlen(refname);
- for (pattern = cb->grab_pattern; *pattern; pattern++) {
- const char *p = *pattern;
- int plen = strlen(p);
-
- if ((plen <= namelen) &&
- !strncmp(refname, p, plen) &&
- (refname[plen] == '\0' ||
- refname[plen] == '/' ||
- p[plen-1] == '/'))
- break;
- if (!wildmatch(p, refname, WM_PATHNAME, NULL))
- break;
- }
- if (!*pattern)
- return 0;
- }
+ if (*cb->grab_pattern && !match_name_as_path(cb->grab_pattern, refname))
+ return 0;
/*
* We do not open the object yet; sort may only need refname
* to do its job and the resulting list may yet to be pruned
* by maxcount logic.
*/
- ref = xcalloc(1, sizeof(*ref));
- ref->refname = xstrdup(refname);
- hashcpy(ref->objectname, sha1);
- ref->flag = flag;
+ ref = new_ref_array_item(refname, oid->hash, flag);
- cnt = cb->grab_cnt;
- REALLOC_ARRAY(cb->grab_array, cnt + 1);
- cb->grab_array[cnt++] = ref;
- cb->grab_cnt = cnt;
+ REALLOC_ARRAY(cb->grab_array, cb->grab_cnt + 1);
+ cb->grab_array[cb->grab_cnt++] = ref;
return 0;
}
-static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
+static int cmp_ref_sort(struct ref_sort *s, struct ref_array_item *a, struct ref_array_item *b)
{
struct atom_value *va, *vb;
int cmp;
static struct ref_sort *ref_sort;
static int compare_refs(const void *a_, const void *b_)
{
- struct refinfo *a = *((struct refinfo **)a_);
- struct refinfo *b = *((struct refinfo **)b_);
+ struct ref_array_item *a = *((struct ref_array_item **)a_);
+ struct ref_array_item *b = *((struct ref_array_item **)b_);
struct ref_sort *s;
for (s = ref_sort; s; s = s->next) {
return 0;
}
-static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs)
+static void sort_refs(struct ref_sort *sort, struct ref_array_item **refs, int num_refs)
{
ref_sort = sort;
- qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
+ qsort(refs, num_refs, sizeof(struct ref_array_item *), compare_refs);
}
static void print_value(struct atom_value *v, int quote_style)
}
}
-static void show_ref(struct refinfo *info, const char *format, int quote_style)
+static void show_ref(struct ref_array_item *info, const char *format, int quote_style)
{
const char *cp, *sp, *ep;
const char *format = "%(objectname) %(objecttype)\t%(refname)";
struct ref_sort *sort = NULL, **sort_tail = &sort;
int maxcount = 0, quote_style = 0;
- struct refinfo **refs;
+ struct ref_array_item **refs;
struct grab_ref_cbdata cbdata;
struct option opts[] = {