git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v5 00/11] port tag.c to use ref-filter APIs

From
Karthik Nayak <karthik.188@gmail.com>
Date
Jul 27, 2015, 07:26 UTC
Message-ID
<CAOLa=ZTtAepdO5U8zo62VBn_z4-LcKoguPxVGaAnNZULEwzrQQ@mail.gmail.com>

This is part of my GSoC project to unify git tag -l, git branch -l, git for-each-ref. This patch series is continued from: Git (next) https://github.com/git/git/commit/bf5418f49ff0cebc6e5ce04ad1417e1a47c81b61

Version 4 can be found here http://article.gmane.org/gmane.comp.version-control.git/274579

Changes in this version (interdiff at the end):
* Change the way ref_formatting_state is used and the sequence of its
usage in the
series.
* Separate the introduction of ref_formatting_state from its usage.
* Removed the inefficient removal of path in match_pattern().
* Improve coding style in the implementation of sorting based on version.
* Changed the tests for sorting based on version, to use
'for-each-ref' rather than 'tag.c'
which already has a working sort based on version.
* Other small grammatical changes.
* Change the atom name from 'align' to 'padright'.

[PATCH v5 01/11] ref-filter: introduce 'ref_formatting_state' [PATCH v5 02/11] ref-filter: make `color` use `ref_formatting_state` [PATCH v5 03/11] ref-filter: add option to pad atoms to the right [PATCH v5 04/11] ref-filter: add option to filter only tags [PATCH v5 05/11] ref-filter: support printing N lines from tag [PATCH v5 06/11] ref-filter: add support to sort by version [PATCH v5 07/11] ref-filter: add option to match literal pattern [PATCH v5 08/11] tag.c: use 'ref-filter' data structures [PATCH v5 09/11] tag.c: use 'ref-filter' APIs [PATCH v5 10/11] tag.c: implement '--format' option [PATCH v5 11/11] tag.c: implement '--merged' and '--no-merged'

Interdiff:
diff --git a/Documentation/git-for-each-ref.txt
b/Documentation/git-for-each-ref.txt
index 224dc8c..2b60aee 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -127,6 +127,12 @@ color::
     Change output color.  Followed by `:<colorname>`, where names
     are described in `color.branch.*`.

+padright::
+    Pad succeeding atom to the right. Followed by `:<value>`,
+    where `value` states the total length of atom including the
+    padding. If the `value` is greater than the atom length, then
+    no padding is performed.
+
 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
 be used to specify the value in the header field.
diff --git a/builtin/tag.c b/builtin/tag.c
index 8a7f684..fc01117 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -41,13 +41,11 @@ static int list_tags(struct ref_filter *filter,
struct ref_sorting *sorting, con
         filter->lines = 0;

     if (filter->lines)
-        format = "%(align:16)%(refname:short)";
+        format = "%(padright:16)%(refname:short)";
     else if (!format)
         format = "%(refname:short)";

     verify_ref_format(format);
-    if (!sorting)
-        sorting = ref_default_sorting();
     filter_refs(&array, filter, FILTER_REFS_TAGS);
     ref_array_sort(sorting, &array);

@@ -134,7 +132,7 @@ static int parse_sorting_string(const char *arg,
struct ref_sorting **sorting_ta
     if (*arg == '-') {
         s->reverse = 1;
         arg++;
-     }
+    }
     if (skip_prefix(arg, "version:", &arg) ||
         skip_prefix(arg, "v:", &arg))
         s->version = 1;
diff --git a/ref-filter.c b/ref-filter.c
index c686c03..597b189 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -56,7 +56,7 @@ static struct {
     { "flag" },
     { "HEAD" },
     { "color" },
-    { "align" },
+    { "padright" },
 };

 /*
@@ -601,8 +601,7 @@ static inline char *copy_advance(char *dst, const char *src)
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-static void populate_value(struct ref_formatting_state *state,
-               struct ref_array_item *ref)
+static void populate_value(struct ref_array_item *ref)
 {
     void *buf;
     struct object *obj;
@@ -664,8 +663,9 @@ static void populate_value(struct
ref_formatting_state *state,

             if (color_parse(name + 6, color) < 0)
                 die(_("unable to parse format"));
-            state->color = xstrdup(color);
+            v->s = xstrdup(color);
             v->pseudo_atom = 1;
+            v->color = 1;
             continue;
         } else if (!strcmp(name, "flag")) {
             char buf[256], *cp = buf;
@@ -693,17 +693,17 @@ static void populate_value(struct
ref_formatting_state *state,
             else
                 v->s = " ";
             continue;
-        } else if (starts_with(name, "align:")) {
+        } else if (starts_with(name, "padright:")) {
             const char *valp = NULL;

-            skip_prefix(name, "align:", &valp);
+            skip_prefix(name, "padright:", &valp);
             if (!valp[0])
-                die(_("no value given with 'align:'"));
-            if (strtoul_ui(valp, 10, &state->pad_to_right))
-                die(_("positive integer expected after ':' in align:%u\n"),
-                    state->pad_to_right);
+                die(_("no value given with 'padright:'"));
+            if (strtoul_ui(valp, 10, (unsigned int *)&v->ul))
+                die(_("positive integer expected after ':' in padright:%u\n"),
+                    (unsigned int)v->ul);
             v->pseudo_atom = 1;
-            v->s = "";
+            v->pad_to_right = 1;
             continue;
         } else
             continue;
@@ -827,15 +827,10 @@ static void populate_value(struct
ref_formatting_state *state,
  * Given a ref, return the value for the atom.  This lazily gets value
  * out of the object by calling populate value.
  */
-static void get_ref_atom_value(struct ref_formatting_state *state,
-                   struct ref_array_item *ref, int atom, struct atom_value **v)
+static void get_ref_atom_value(struct ref_array_item *ref, int atom,
struct atom_value **v)
 {
-    /*
-     * If the atom is a pseudo_atom then we re-populate the value
-     * into the ref_formatting_state stucture.
-     */
-    if (!ref->value || ref->value[atom].pseudo_atom) {
-        populate_value(state, ref);
+    if (!ref->value) {
+        populate_value(ref);
         fill_missing_values(ref->value);
     }
     *v = &ref->value[atom];
@@ -957,17 +952,18 @@ static int commit_contains(struct ref_filter
*filter, struct commit *commit)
  */
 static int match_pattern(const char **patterns, const char *refname)
 {
+    /*
+     * When no '--format' option is given we need to skip the prefix
+     * for matching refs of tags and branches.
+     */
+    if (skip_prefix(refname, "refs/tags/", &refname))
+        ;
+    else if (skip_prefix(refname, "refs/heads/", &refname))
+        ;
+    else if (skip_prefix(refname, "refs/remotes/", &refname))
+        ;
+
     for (; *patterns; patterns++) {
-        /*
-         * When no '--format' option is given we need to skip the prefix
-         * for listing tags and branches.
-         */
-        if (!starts_with(*pattern, "refs/tags/"))
-            skip_prefix(refname, "refs/tags/", &refname);
-        else if (!starts_with(*pattern, "refs/heads/"))
-            skip_prefix(refname, "refs/heads/", &refname);
-        else if (!starts_with(refname, "refs/remotes/"))
-            skip_prefix(refname, "refs/remotes/", &refname);
         if (!wildmatch(*patterns, refname, 0, NULL))
             return 1;
     }
@@ -978,7 +974,7 @@ static int match_pattern(const char **patterns,
const char *refname)
  * 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).
+ * matches "refs/heads/m*",too).
  */
 static int match_name_as_path(const char **pattern, const char *refname)
 {
@@ -1210,22 +1206,21 @@ static int cmp_ref_sorting(struct ref_sorting
*s, struct ref_array_item *a, stru
     struct atom_value *va, *vb;
     int cmp;
     cmp_type cmp_type = used_atom_type[s->atom];
-    struct ref_formatting_state state;

-    memset(&state, 0, sizeof(state));
-
-    get_ref_atom_value(&state, a, s->atom, &va);
-    get_ref_atom_value(&state, b, s->atom, &vb);
+    get_ref_atom_value(a, s->atom, &va);
+    get_ref_atom_value(b, s->atom, &vb);
     if (s->version)
         cmp = versioncmp(va->s, vb->s);
     else if (cmp_type == FIELD_STR)
         cmp = strcmp(va->s, vb->s);
-    else if (va->ul < vb->ul)
-        cmp = -1;
-    else if (va->ul == vb->ul)
-        cmp = 0;
-    else
-        cmp = 1;
+    else {
+        if (va->ul < vb->ul)
+            cmp = -1;
+        else if (va->ul == vb->ul)
+            cmp = 0;
+        else
+            cmp = 1;
+    }

     return (s->reverse) ? -cmp : cmp;
 }
@@ -1251,20 +1246,20 @@ void ref_array_sort(struct ref_sorting
*sorting, struct ref_array *array)
     qsort(array->items, array->nr, sizeof(struct ref_array_item *),
compare_refs);
 }

-static void ref_formatting(struct ref_formatting_state *state, struct
atom_value *v,
-               struct strbuf *value)
+static void ref_formatting(struct ref_formatting_state *state,
+               struct atom_value *v, struct strbuf *value)
 {
     if (state->color) {
         strbuf_addstr(value, state->color);
-        free((void *)state->color);
+        free(state->color);
         state->color = NULL;
     }
     if (state->pad_to_right) {
         if (!is_utf8(v->s))
             strbuf_addf(value, "%-*s", state->pad_to_right, v->s);
         else {
-            int len = strlen(v->s) - utf8_strwidth(v->s);
-            strbuf_addf(value, "%-*s", state->pad_to_right + len, v->s);
+            int utf8_compensation = strlen(v->s) - utf8_strwidth(v->s);
+            strbuf_addf(value, "%-*s", state->pad_to_right +
utf8_compensation, v->s);
         }
         return;
     }
@@ -1276,8 +1271,6 @@ static void print_value(struct
ref_formatting_state *state, struct atom_value *v
     struct strbuf value = STRBUF_INIT;
     struct strbuf formatted = STRBUF_INIT;

-    if (v->pseudo_atom)
-        return;
     ref_formatting(state, v, &value);

     switch (state->quote_style) {
@@ -1341,6 +1334,15 @@ static void emit(const char *cp, const char *ep)
     }
 }

+static void apply_pseudo_state(struct ref_formatting_state *state,
+                   struct atom_value *v)
+{
+    if (v->color)
+        state->color = (char *)v->s;
+    if (v->pad_to_right)
+        state->pad_to_right = v->ul;
+}
+
 /*
  * If 'lines' is greater than 0, print that many lines from the given
  * object_id 'oid'.
@@ -1399,9 +1401,11 @@ void show_ref_array_item(struct ref_array_item
*info, const char *format,
         ep = strchr(sp, ')');
         if (cp < sp)
             emit(cp, sp);
-        get_ref_atom_value(&state, info,
-                   parse_ref_filter_atom(sp + 2, ep), &atomv);
-        print_value(&state, atomv);
+        get_ref_atom_value(info, parse_ref_filter_atom(sp + 2, ep), &atomv);
+        if (atomv->pseudo_atom)
+            apply_pseudo_state(&state, atomv);
+        else
+            print_value(&state, atomv);
     }
     if (*cp) {
         sp = cp + strlen(cp);
@@ -1413,8 +1417,7 @@ void show_ref_array_item(struct ref_array_item
*info, const char *format,

         if (color_parse("reset", color) < 0)
             die("BUG: couldn't parse 'reset' as a color");
-        resetv.s = "";
-        state.color = xstrdup(color);
+        resetv.s = color;
         print_value(&state, &resetv);
     }
     if (lines > 0) {
diff --git a/ref-filter.h b/ref-filter.h
index f1933e0..a27745f 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -20,7 +20,15 @@
 struct atom_value {
     const char *s;
     unsigned long ul; /* used for sorting when not FIELD_STR */
-    unsigned int pseudo_atom : 1; /*  atoms which aren't placeholders
for ref attributes */
+    unsigned int pseudo_atom : 1, /*  atoms which aren't placeholders
for ref attributes */
+        color : 1,
+        pad_to_right : 1;
+};
+
+struct ref_formatting_state {
+    int quote_style;
+    char *color;
+    unsigned int pad_to_right;
 };

 struct ref_sorting {
@@ -30,12 +38,6 @@ struct ref_sorting {
         version : 1;
 };

-struct ref_formatting_state {
-    unsigned int pad_to_right; /*pad atoms to the right*/
-    int quote_style;
-    const char *color;
-};
-
 struct ref_array_item {
     unsigned char objectname[20];
     int flag;
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 5017032..de872db 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -81,6 +81,22 @@ test_expect_success 'filtering with --contains' '
     test_cmp expect actual
 '

+test_expect_success 'padding to the right using `padright`' '
+    cat >expect <<-\EOF &&
+    refs/heads/master        |
+    refs/heads/side          |
+    refs/odd/spot            |
+    refs/tags/double-tag     |
+    refs/tags/four           |
+    refs/tags/one            |
+    refs/tags/signed-tag     |
+    refs/tags/three          |
+    refs/tags/two            |
+    EOF
+    git for-each-ref --format="%(padright:25)%(refname)|" >actual &&
+    test_cmp expect actual
+'
+
 test_expect_success 'setup for version sort' '
     test_commit foo1.3 &&
     test_commit foo1.6 &&
@@ -88,7 +104,7 @@ test_expect_success 'setup for version sort' '
 '

 test_expect_success 'version sort' '
-    git tag -l --sort=version:refname | grep "foo" >actual &&
+    git for-each-ref --sort=version:refname
--format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
     cat >expect <<-\EOF &&
     foo1.3
     foo1.6
@@ -98,7 +114,7 @@ test_expect_success 'version sort' '
 '

 test_expect_success 'version sort (shortened)' '
-    git tag -l --sort=v:refname | grep "foo" >actual &&
+    git for-each-ref --sort=v:refname --format="%(refname:short)"
refs/tags/ | grep "foo" >actual &&
     cat >expect <<-\EOF &&
     foo1.3
     foo1.6
@@ -108,7 +124,7 @@ test_expect_success 'version sort (shortened)' '
 '

 test_expect_success 'reverse version sort' '
-    git tag -l --sort=-version:refname | grep "foo" >actual &&
+    git for-each-ref --sort=-version:refname
--format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
     cat >expect <<-\EOF &&
     foo1.10
     foo1.6
diff --git a/v3-0001-ref-filter-add-option-to-align-atoms-to-the-left.patch
b/v3-0001-ref-filter-add-option-to-align-atoms-to-the-left.patch
deleted file mode 100644
index 350acae..0000000
--- a/v3-0001-ref-filter-add-option-to-align-atoms-to-the-left.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-From 3a07ca1f56f74ca54b7f3c30e3dfd9fe2fed1cc3 Mon Sep 17 00:00:00 2001
-From: Karthik Nayak <karthik.188@gmail.com>
-Date: Wed, 10 Jun 2015 17:19:55 +0530
-Subject: [PATCH v3 1/9] ref-filter: add option to align atoms to the left
-
-Add a new atom "align" and support %(align:X) where X is a number.
-This will align the preceeding atom value to the left followed by
-spaces for a total length of X characters. If X is less than the item
-size, the entire atom value is printed.
-
-Helped-by: Duy Nguyen <pclouds@gmail.com>
-Mentored-by: Christian Couder <christian.couder@gmail.com>
-Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr>
-Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
----
- ref-filter.c | 41 +++++++++++++++++++++++++++++++++++++++--
- ref-filter.h |  1 +
- 2 files changed, 40 insertions(+), 2 deletions(-)
-
-diff --git a/ref-filter.c b/ref-filter.c
-index 7561727..93f59aa 100644
---- a/ref-filter.c
-+++ b/ref-filter.c
-@@ -10,6 +10,8 @@
- #include "quote.h"
- #include "ref-filter.h"
- #include "revision.h"
-+#include "utf8.h"
-+#include "git-compat-util.h"
-
- typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
-
-@@ -53,6 +55,7 @@ static struct {
-     { "flag" },
-     { "HEAD" },
-     { "color" },
-+    { "align" },
- };
-
- /*
-@@ -620,7 +623,7 @@ static void populate_value(struct ref_array_item *ref)
-         const char *name = used_atom[i];
-         struct atom_value *v = &ref->value[i];
-         int deref = 0;
--        const char *refname;
-+        const char *refname = NULL;
-         const char *formatp;
-         struct branch *branch = NULL;
-
-@@ -687,6 +690,17 @@ static void populate_value(struct ref_array_item *ref)
-             else
-                 v->s = " ";
-             continue;
-+        } else if (starts_with(name, "align:")) {
-+            const char *valp = NULL;
-+
-+            skip_prefix(name, "align:", &valp);
-+            if (!valp[0])
-+                die(_("no value given with 'align:'"));
-+            strtoul_ui(valp, 10, &ref->align_value);
-+            if (ref->align_value < 1)
-+                die(_("value should be greater than zero:
align:%u"), ref->align_value);
-+            v->s = "";
-+            continue;
-         } else
-             continue;
-
-@@ -1254,17 +1268,40 @@ static void emit(const char *cp, const char *ep)
-     }
- }
-
-+static void assign_formating(struct ref_array_item *ref, int
parsed_atom, struct atom_value *v)
-+{
-+    if (ref->align_value && !starts_with(used_atom[parsed_atom], "align")) {
-+        unsigned int len = 0;
-+
-+        if (*v->s)
-+            len = utf8_strwidth(v->s);
-+        if (ref->align_value > len) {
-+            struct strbuf buf = STRBUF_INIT;
-+            if (*v->s)
-+                strbuf_addstr(&buf, v->s);
-+            if (*v->s && v->s[0] == '\0')
-+                free((char *)v->s);
-+            strbuf_addchars(&buf, ' ', ref->align_value - len);
-+            v->s = strbuf_detach(&buf, NULL);
-+        }
-+        ref->align_value = 0;
-+    }
-+}
-+
- void show_ref_array_item(struct ref_array_item *info, const char
*format, int quote_style)
- {
-     const char *cp, *sp, *ep;
-
-     for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
-         struct atom_value *atomv;
-+        int parsed_atom;
-
-         ep = strchr(sp, ')');
-         if (cp < sp)
-             emit(cp, sp);
--        get_ref_atom_value(info, parse_ref_filter_atom(sp + 2, ep), &atomv);
-+        parsed_atom = parse_ref_filter_atom(sp + 2, ep);
-+        get_ref_atom_value(info, parsed_atom, &atomv);
-+        assign_formating(info, parsed_atom, atomv);
-         print_value(atomv, quote_style);
-     }
-     if (*cp) {
-diff --git a/ref-filter.h b/ref-filter.h
-index 6bf27d8..12ffbc5 100644
---- a/ref-filter.h
-+++ b/ref-filter.h
-@@ -30,6 +30,7 @@ struct ref_sorting {
- struct ref_array_item {
-     unsigned char objectname[20];
-     int flag;
-+    unsigned int align_value;
-     const char *symref;
-     struct commit *commit;
-     struct atom_value *value;
---
-2.4.6
-

Thanks to everyone for suggestions on the previous version.
-- 
Regards,
Karthik Nayak
Next: Karthik Nayak
Message 1 of 38 in “port tag.c to use ref-filter APIs”
  1. 00/11 port tag.c to use ref-filter APIsKarthik Nayak, Jul 27, 2015
  2. 01/11 ref-filter: introduce 'ref_formatting_state'Karthik Nayak, Jul 27, 2015
  3. 02/11 ref-filter: make `color` use `ref_formatting_state`Karthik Nayak, Jul 27, 2015
  4. Matthieu MoyJul 27, 2015
  5. Junio C HamanoJul 27, 2015
  6. Karthik NayakJul 27, 2015
  7. Karthik NayakJul 27, 2015
  8. Matthieu MoyJul 27, 2015
  9. Karthik NayakJul 27, 2015
  10. 03/11 ref-filter: add option to pad atoms to the rightKarthik Nayak, Jul 27, 2015
  11. Matthieu MoyJul 27, 2015
  12. Junio C HamanoJul 27, 2015
  13. Matthieu MoyJul 27, 2015
  14. Karthik NayakJul 27, 2015
  15. Matthieu MoyJul 27, 2015
  16. Karthik NayakJul 27, 2015
  17. Junio C HamanoJul 27, 2015
  18. Karthik NayakJul 27, 2015
  19. Eric SunshineJul 28, 2015
  20. Karthik NayakJul 29, 2015
  21. 04/11 ref-filter: add option to filter only tagsKarthik Nayak, Jul 27, 2015
  22. 05/11 ref-filter: support printing N lines from tag annotationKarthik Nayak, Jul 27, 2015
  23. 06/11 ref-filter: add support to sort by versionKarthik Nayak, Jul 27, 2015
  24. 07/11 ref-filter: add option to match literal patternKarthik Nayak, Jul 27, 2015
  25. Matthieu MoyJul 27, 2015
  26. Karthik NayakJul 27, 2015
  27. Karthik NayakJul 27, 2015
  28. Matthieu MoyJul 27, 2015
  29. Karthik NayakJul 27, 2015
  30. Eric SunshineJul 28, 2015
  31. Karthik NayakJul 29, 2015
  32. Karthik NayakJul 30, 2015
  33. 08/11 tag.c: use 'ref-filter' data structuresKarthik Nayak, Jul 27, 2015
  34. 09/11 tag.c: use 'ref-filter' APIsKarthik Nayak, Jul 27, 2015
  35. 10/11 tag.c: implement '--format' optionKarthik Nayak, Jul 27, 2015
  36. 11/11 tag.c: implement '--merged' and '--no-merged' optionsKarthik Nayak, Jul 27, 2015
  37. Matthieu MoyJul 27, 2015
  38. Karthik NayakJul 27, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.