rerere: fix an off-by-one non-bug
[gitweb.git] / builtin / for-each-ref.c
index 5ff51d1d322c554fc906a78b7b88130d7a8dd60e..008513c2f135b5a77d1642ff88e272a7e2f9f9d5 100644 (file)
@@ -92,7 +92,7 @@ static struct {
  */
 static const char **used_atom;
 static cmp_type *used_atom_type;
-static int used_atom_cnt, sort_atom_limit, need_tagged, need_symref;
+static int used_atom_cnt, need_tagged, need_symref;
 static int need_color_reset_at_eol;
 
 /*
@@ -138,10 +138,8 @@ static int parse_atom(const char *atom, const char *ep)
        /* Add it in, including the deref prefix */
        at = used_atom_cnt;
        used_atom_cnt++;
-       used_atom = xrealloc(used_atom,
-                            (sizeof *used_atom) * used_atom_cnt);
-       used_atom_type = xrealloc(used_atom_type,
-                                 (sizeof(*used_atom_type) * used_atom_cnt));
+       REALLOC_ARRAY(used_atom, used_atom_cnt);
+       REALLOC_ARRAY(used_atom_type, used_atom_cnt);
        used_atom[at] = xmemdupz(atom, ep - atom);
        used_atom_type[at] = valid_atom[i].cmp_type;
        if (*atom == '*')
@@ -180,11 +178,10 @@ static const char *find_next(const char *cp)
 static int verify_format(const char *format)
 {
        const char *cp, *sp;
-       static const char color_reset[] = "color:reset";
 
        need_color_reset_at_eol = 0;
        for (cp = format; *cp && (sp = find_next(cp)); ) {
-               const char *ep = strchr(sp, ')');
+               const char *color, *ep = strchr(sp, ')');
                int at;
 
                if (!ep)
@@ -193,8 +190,8 @@ static int verify_format(const char *format)
                at = parse_atom(sp + 2, ep);
                cp = ep + 1;
 
-               if (!memcmp(used_atom[at], "color:", 6))
-                       need_color_reset_at_eol = !!strcmp(used_atom[at], color_reset);
+               if (skip_prefix(used_atom[at], "color:", &color))
+                       need_color_reset_at_eol = !!strcmp(color, "reset");
        }
        return 0;
 }
@@ -217,6 +214,22 @@ static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned lo
        return buf;
 }
 
+static int grab_objectname(const char *name, const unsigned char *sha1,
+                           struct atom_value *v)
+{
+       if (!strcmp(name, "objectname")) {
+               char *s = xmalloc(41);
+               strcpy(s, sha1_to_hex(sha1));
+               v->s = s;
+               return 1;
+       }
+       if (!strcmp(name, "objectname:short")) {
+               v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
+               return 1;
+       }
+       return 0;
+}
+
 /* See grab_values */
 static void grab_common_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 {
@@ -237,15 +250,8 @@ static void grab_common_values(struct atom_value *val, int deref, struct object
                        v->ul = sz;
                        v->s = s;
                }
-               else if (!strcmp(name, "objectname")) {
-                       char *s = xmalloc(41);
-                       strcpy(s, sha1_to_hex(obj->sha1));
-                       v->s = s;
-               }
-               else if (!strcmp(name, "objectname:short")) {
-                       v->s = xstrdup(find_unique_abbrev(obj->sha1,
-                                                         DEFAULT_ABBREV));
-               }
+               else if (deref)
+                       grab_objectname(name, obj->sha1, v);
        }
 }
 
@@ -274,18 +280,6 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
        }
 }
 
-static int num_parents(struct commit *commit)
-{
-       struct commit_list *parents;
-       int i;
-
-       for (i = 0, parents = commit->parents;
-            parents;
-            parents = parents->next)
-               i++;
-       return i;
-}
-
 /* See grab_values */
 static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
 {
@@ -306,12 +300,12 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
                }
                if (!strcmp(name, "numparent")) {
                        char *s = xmalloc(40);
-                       v->ul = num_parents(commit);
+                       v->ul = commit_list_count(commit->parents);
                        sprintf(s, "%lu", v->ul);
                        v->s = s;
                }
                else if (!strcmp(name, "parent")) {
-                       int num = num_parents(commit);
+                       int num = commit_list_count(commit->parents);
                        int i;
                        struct commit_list *parents;
                        char *s = xmalloc(41 * num + 1);
@@ -444,7 +438,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
                if (name[wholen] != 0 &&
                    strcmp(name + wholen, "name") &&
                    strcmp(name + wholen, "email") &&
-                   prefixcmp(name + wholen, "date"))
+                   !starts_with(name + wholen, "date"))
                        continue;
                if (!wholine)
                        wholine = find_wholine(who, wholen, buf, sz);
@@ -456,7 +450,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
                        v->s = copy_name(wholine);
                else if (!strcmp(name + wholen, "email"))
                        v->s = copy_email(wholine);
-               else if (!prefixcmp(name + wholen, "date"))
+               else if (starts_with(name + wholen, "date"))
                        grab_date(wholine, v, name);
        }
 
@@ -478,7 +472,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
                if (deref)
                        name++;
 
-               if (!prefixcmp(name, "creatordate"))
+               if (starts_with(name, "creatordate"))
                        grab_date(wholine, v, name);
                else if (!strcmp(name, "creator"))
                        v->s = copy_line(wholine);
@@ -636,11 +630,12 @@ static void populate_value(struct refinfo *ref)
        unsigned long size;
        const unsigned char *tagged;
 
-       ref->value = xcalloc(sizeof(struct atom_value), used_atom_cnt);
+       ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 
        if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
                unsigned char unused1[20];
-               ref->symref = resolve_refdup(ref->refname, unused1, 1, NULL);
+               ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
+                                            unused1, NULL);
                if (!ref->symref)
                        ref->symref = "";
        }
@@ -659,13 +654,13 @@ static void populate_value(struct refinfo *ref)
                        name++;
                }
 
-               if (!prefixcmp(name, "refname"))
+               if (starts_with(name, "refname"))
                        refname = ref->refname;
-               else if (!prefixcmp(name, "symref"))
+               else if (starts_with(name, "symref"))
                        refname = ref->symref ? ref->symref : "";
-               else if (!prefixcmp(name, "upstream")) {
+               else if (starts_with(name, "upstream")) {
                        /* only local branches may have an upstream */
-                       if (prefixcmp(ref->refname, "refs/heads/"))
+                       if (!starts_with(ref->refname, "refs/heads/"))
                                continue;
                        branch = branch_get(ref->refname + 11);
 
@@ -673,10 +668,11 @@ static void populate_value(struct refinfo *ref)
                            !branch->merge[0]->dst)
                                continue;
                        refname = branch->merge[0]->dst;
-               } else if (!prefixcmp(name, "color:")) {
+               } else if (starts_with(name, "color:")) {
                        char color[COLOR_MAXLEN] = "";
 
-                       color_parse(name + 6, "--format", color);
+                       if (color_parse(name + 6, color) < 0)
+                               die(_("unable to parse format"));
                        v->s = xstrdup(color);
                        continue;
                } else if (!strcmp(name, "flag")) {
@@ -692,11 +688,14 @@ static void populate_value(struct refinfo *ref)
                                v->s = xstrdup(buf + 1);
                        }
                        continue;
+               } else if (!deref && grab_objectname(name, ref->objectname, v)) {
+                       continue;
                } else if (!strcmp(name, "HEAD")) {
                        const char *head;
                        unsigned char sha1[20];
 
-                       head = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
+                       head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
+                                                 sha1, NULL);
                        if (!strcmp(ref->refname, head))
                                v->s = "*";
                        else
@@ -714,10 +713,13 @@ static void populate_value(struct refinfo *ref)
                                refname = shorten_unambiguous_ref(refname,
                                                      warn_ambiguous_refs);
                        else if (!strcmp(formatp, "track") &&
-                               !prefixcmp(name, "upstream")) {
+                                starts_with(name, "upstream")) {
                                char buf[40];
 
-                               stat_tracking_info(branch, &num_ours, &num_theirs);
+                               if (stat_tracking_info(branch, &num_ours,
+                                                      &num_theirs) != 1)
+                                       continue;
+
                                if (!num_ours && !num_theirs)
                                        v->s = "";
                                else if (!num_ours) {
@@ -733,9 +735,13 @@ static void populate_value(struct refinfo *ref)
                                }
                                continue;
                        } else if (!strcmp(formatp, "trackshort") &&
-                               !prefixcmp(name, "upstream")) {
+                                  starts_with(name, "upstream")) {
                                assert(branch);
-                               stat_tracking_info(branch, &num_ours, &num_theirs);
+
+                               if (stat_tracking_info(branch, &num_ours,
+                                                       &num_theirs) != 1)
+                                       continue;
+
                                if (!num_ours && !num_theirs)
                                        v->s = "=";
                                else if (!num_ours)
@@ -840,6 +846,11 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
        struct refinfo *ref;
        int cnt;
 
+       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);
@@ -853,7 +864,7 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
                             refname[plen] == '/' ||
                             p[plen-1] == '/'))
                                break;
-                       if (!fnmatch(p, refname, FNM_PATHNAME))
+                       if (!wildmatch(p, refname, WM_PATHNAME, NULL))
                                break;
                }
                if (!*pattern)
@@ -871,8 +882,7 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
        ref->flag = flag;
 
        cnt = cb->grab_cnt;
-       cb->grab_array = xrealloc(cb->grab_array,
-                                 sizeof(*cb->grab_array) * (cnt + 1));
+       REALLOC_ARRAY(cb->grab_array, cnt + 1);
        cb->grab_array[cnt++] = ref;
        cb->grab_cnt = cnt;
        return 0;
@@ -1008,7 +1018,8 @@ static void show_ref(struct refinfo *info, const char *format, int quote_style)
                struct atom_value resetv;
                char color[COLOR_MAXLEN] = "";
 
-               color_parse("reset", "--format", color);
+               if (color_parse("reset", color) < 0)
+                       die("BUG: couldn't parse 'reset' as a color");
                resetv.s = color;
                print_value(&resetv, quote_style);
        }
@@ -1070,7 +1081,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
                OPT_BIT(0 , "python", &quote_style,
                        N_("quote placeholders suitably for python"), QUOTE_PYTHON),
                OPT_BIT(0 , "tcl",  &quote_style,
-                       N_("quote placeholders suitably for tcl"), QUOTE_TCL),
+                       N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
 
                OPT_GROUP(""),
                OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
@@ -1094,7 +1105,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 
        if (!sort)
                sort = default_sort();
-       sort_atom_limit = used_atom_cnt;
 
        /* for warn_ambiguous_refs */
        git_config(git_default_config, NULL);