pretty: allow %(trailers) options with explicit value
[gitweb.git] / ref-filter.c
index 2a056192117b0d119dcd4cf9da0de982a0444b33..0c45ed9d94a4bd4bfab6c9d441ca9bc7de7ebf31 100644 (file)
@@ -875,7 +875,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
                if (deref)
                        name++;
                if (!strcmp(name, "objecttype"))
-                       v->s = type_name(oi->type);
+                       v->s = xstrdup(type_name(oi->type));
                else if (!strcmp(name, "objectsize")) {
                        v->value = oi->size;
                        v->s = xstrfmt("%lu", oi->size);
@@ -899,9 +899,9 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
                if (deref)
                        name++;
                if (!strcmp(name, "tag"))
-                       v->s = tag->tag;
+                       v->s = xstrdup(tag->tag);
                else if (!strcmp(name, "type") && tag->tagged)
-                       v->s = type_name(tag->tagged->type);
+                       v->s = xstrdup(type_name(tag->tagged->type));
                else if (!strcmp(name, "object") && tag->tagged)
                        v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
        }
@@ -1032,7 +1032,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
        v->value = timestamp;
        return;
  bad:
-       v->s = "";
+       v->s = xstrdup("");
        v->value = 0;
 }
 
@@ -1227,7 +1227,7 @@ static void fill_missing_values(struct atom_value *val)
        for (i = 0; i < used_atom_cnt; i++) {
                struct atom_value *v = &val[i];
                if (v->s == NULL)
-                       v->s = "";
+                       v->s = xstrdup("");
        }
 }
 
@@ -1273,7 +1273,8 @@ static inline char *copy_advance(char *dst, const char *src)
 static const char *lstrip_ref_components(const char *refname, int len)
 {
        long remaining = len;
-       const char *start = refname;
+       const char *start = xstrdup(refname);
+       const char *to_free = start;
 
        if (len < 0) {
                int i;
@@ -1294,20 +1295,24 @@ static const char *lstrip_ref_components(const char *refname, int len)
        while (remaining > 0) {
                switch (*start++) {
                case '\0':
-                       return "";
+                       free((char *)to_free);
+                       return xstrdup("");
                case '/':
                        remaining--;
                        break;
                }
        }
 
+       start = xstrdup(start);
+       free((char *)to_free);
        return start;
 }
 
 static const char *rstrip_ref_components(const char *refname, int len)
 {
        long remaining = len;
-       char *start = xstrdup(refname);
+       const char *start = xstrdup(refname);
+       const char *to_free = start;
 
        if (len < 0) {
                int i;
@@ -1327,9 +1332,10 @@ static const char *rstrip_ref_components(const char *refname, int len)
 
        while (remaining-- > 0) {
                char *p = strrchr(start, '/');
-               if (p == NULL)
-                       return "";
-               else
+               if (p == NULL) {
+                       free((char *)to_free);
+                       return xstrdup("");
+               } else
                        p[0] = '\0';
        }
        return start;
@@ -1344,7 +1350,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname)
        else if (atom->option == R_RSTRIP)
                return rstrip_ref_components(refname, atom->rstrip);
        else
-               return refname;
+               return xstrdup(refname);
 }
 
 static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
@@ -1358,7 +1364,7 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
                                       NULL, AHEAD_BEHIND_FULL) < 0) {
                        *s = xstrdup(msgs.gone);
                } else if (!num_ours && !num_theirs)
-                       *s = "";
+                       *s = xstrdup("");
                else if (!num_ours)
                        *s = xstrfmt(msgs.behind, num_theirs);
                else if (!num_theirs)
@@ -1373,36 +1379,31 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
                }
        } else if (atom->u.remote_ref.option == RR_TRACKSHORT) {
                if (stat_tracking_info(branch, &num_ours, &num_theirs,
-                                      NULL, AHEAD_BEHIND_FULL) < 0)
+                                      NULL, AHEAD_BEHIND_FULL) < 0) {
+                       *s = xstrdup("");
                        return;
-
+               }
                if (!num_ours && !num_theirs)
-                       *s = "=";
+                       *s = xstrdup("=");
                else if (!num_ours)
-                       *s = "<";
+                       *s = xstrdup("<");
                else if (!num_theirs)
-                       *s = ">";
+                       *s = xstrdup(">");
                else
-                       *s = "<>";
+                       *s = xstrdup("<>");
        } else if (atom->u.remote_ref.option == RR_REMOTE_NAME) {
                int explicit;
                const char *remote = atom->u.remote_ref.push ?
                        pushremote_for_branch(branch, &explicit) :
                        remote_for_branch(branch, &explicit);
-               if (explicit)
-                       *s = xstrdup(remote);
-               else
-                       *s = "";
+               *s = xstrdup(explicit ? remote : "");
        } else if (atom->u.remote_ref.option == RR_REMOTE_REF) {
                int explicit;
                const char *merge;
 
                merge = remote_ref_for_branch(branch, atom->u.remote_ref.push,
                                              &explicit);
-               if (explicit)
-                       *s = xstrdup(merge);
-               else
-                       *s = "";
+               *s = xstrdup(explicit ? merge : "");
        } else
                BUG("unhandled RR_* enum");
 }
@@ -1451,7 +1452,7 @@ char *get_head_description(void)
 static const char *get_symref(struct used_atom *atom, struct ref_array_item *ref)
 {
        if (!ref->symref)
-               return "";
+               return xstrdup("");
        else
                return show_ref(&atom->u.refname, ref->symref);
 }
@@ -1510,7 +1511,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
                ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
                                             NULL, NULL);
                if (!ref->symref)
-                       ref->symref = "";
+                       ref->symref = xstrdup("");
        }
 
        /* Fill in specials first */
@@ -1536,20 +1537,23 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
                        refname = get_symref(atom, ref);
                else if (starts_with(name, "upstream")) {
                        const char *branch_name;
-                       v->s = "";
                        /* only local branches may have an upstream */
                        if (!skip_prefix(ref->refname, "refs/heads/",
-                                        &branch_name))
+                                        &branch_name)) {
+                               v->s = xstrdup("");
                                continue;
+                       }
                        branch = branch_get(branch_name);
 
                        refname = branch_get_upstream(branch, NULL);
                        if (refname)
                                fill_remote_ref_details(atom, refname, branch, &v->s);
+                       else
+                               v->s = xstrdup("");
                        continue;
                } else if (atom->u.remote_ref.push) {
                        const char *branch_name;
-                       v->s = "";
+                       v->s = xstrdup("");
                        if (!skip_prefix(ref->refname, "refs/heads/",
                                         &branch_name))
                                continue;
@@ -1562,10 +1566,12 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
                                if (!refname)
                                        continue;
                        }
+                       /* We will definitely re-init v->s on the next line. */
+                       free((char *)v->s);
                        fill_remote_ref_details(atom, refname, branch, &v->s);
                        continue;
                } else if (starts_with(name, "color:")) {
-                       v->s = atom->u.color;
+                       v->s = xstrdup(atom->u.color);
                        continue;
                } else if (!strcmp(name, "flag")) {
                        char buf[256], *cp = buf;
@@ -1574,7 +1580,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
                        if (ref->flag & REF_ISPACKED)
                                cp = copy_advance(cp, ",packed");
                        if (cp == buf)
-                               v->s = "";
+                               v->s = xstrdup("");
                        else {
                                *cp = '\0';
                                v->s = xstrdup(buf + 1);
@@ -1584,40 +1590,42 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
                        continue;
                } else if (!strcmp(name, "HEAD")) {
                        if (atom->u.head && !strcmp(ref->refname, atom->u.head))
-                               v->s = "*";
+                               v->s = xstrdup("*");
                        else
-                               v->s = " ";
+                               v->s = xstrdup(" ");
                        continue;
                } else if (starts_with(name, "align")) {
                        v->handler = align_atom_handler;
-                       v->s = "";
+                       v->s = xstrdup("");
                        continue;
                } else if (!strcmp(name, "end")) {
                        v->handler = end_atom_handler;
-                       v->s = "";
+                       v->s = xstrdup("");
                        continue;
                } else if (starts_with(name, "if")) {
                        const char *s;
-                       v->s = "";
                        if (skip_prefix(name, "if:", &s))
                                v->s = xstrdup(s);
+                       else
+                               v->s = xstrdup("");
                        v->handler = if_atom_handler;
                        continue;
                } else if (!strcmp(name, "then")) {
                        v->handler = then_atom_handler;
-                       v->s = "";
+                       v->s = xstrdup("");
                        continue;
                } else if (!strcmp(name, "else")) {
                        v->handler = else_atom_handler;
-                       v->s = "";
+                       v->s = xstrdup("");
                        continue;
                } else
                        continue;
 
                if (!deref)
-                       v->s = refname;
+                       v->s = xstrdup(refname);
                else
                        v->s = xstrfmt("%s^{}", refname);
+               free((char *)refname);
        }
 
        for (i = 0; i < used_atom_cnt; i++) {
@@ -1988,6 +1996,10 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
 static void free_array_item(struct ref_array_item *item)
 {
        free((char *)item->symref);
+       if (item->value) {
+               free((char *)item->value->s);
+               free(item->value);
+       }
        free(item);
 }
 
@@ -1996,6 +2008,10 @@ void ref_array_clear(struct ref_array *array)
 {
        int i;
 
+       for (i = 0; i < used_atom_cnt; i++)
+               free((char *)used_atom[i].name);
+       FREE_AND_NULL(used_atom);
+       used_atom_cnt = 0;
        for (i = 0; i < array->nr; i++)
                free_array_item(array->items[i]);
        FREE_AND_NULL(array->items);