ref-filter: modify "%(objectname:short)" to take length

Add support for %(objectname:short=<length>) which would print the abbreviated unique objectname of given length. When no length is specified, the length is 'DEFAULT_ABBREV'. The minimum length is 'MINIMUM_ABBREV'. The length may be exceeded to ensure that the provided object name is unique. Add tests and documentation for the same. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr> Helped-by: Jacob Keller <jacob.keller@gmail.com> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karthik Nayak committed Jan 10, 2017 at 14:19 UTC 42d0eb05eed8e6c66d93091f5b0ece3a1872246c
3 files changed +32 -6
Documentation/git-for-each-ref.txt
+3
@@ -110,6 +110,9 @@ objectsize::
110 objectname::
111 The object name (aka SHA-1).
112 For a non-ambiguous abbreviation of the object name append `:short`.
113 + For an abbreviation of the object name with desired length append
114 + `:short=<length>`, where the minimum length is MINIMUM_ABBREV. The
115 + length may be exceeded to ensure unique object names.
116
117 upstream::
118 The name of a local ref which can be considered ``upstream''
ref-filter.c
+19 -6
@@ -57,7 +57,10 @@ static struct used_atom {
57 cmp_status cmp_status;
58 const char *str;
59 } if_then_else;
60 - enum { O_FULL, O_SHORT } objectname;
60 + struct {
61 + enum { O_FULL, O_LENGTH, O_SHORT } option;
62 + unsigned int length;
63 + } objectname;
64 } u;
65 } *used_atom;
66 static int used_atom_cnt, need_tagged, need_symref;
@@ -129,10 +132,17 @@ static void contents_atom_parser(struct used_atom *atom, const char *arg)
132 static void objectname_atom_parser(struct used_atom *atom, const char *arg)
133 {
134 if (!arg)
132 - atom->u.objectname = O_FULL;
135 + atom->u.objectname.option = O_FULL;
136 else if (!strcmp(arg, "short"))
134 - atom->u.objectname = O_SHORT;
135 - else
137 + atom->u.objectname.option = O_SHORT;
138 + else if (skip_prefix(arg, "short=", &arg)) {
139 + atom->u.objectname.option = O_LENGTH;
140 + if (strtoul_ui(arg, 10, &atom->u.objectname.length) ||
141 + atom->u.objectname.length == 0)
142 + die(_("positive value expected objectname:short=%s"), arg);
143 + if (atom->u.objectname.length < MINIMUM_ABBREV)
144 + atom->u.objectname.length = MINIMUM_ABBREV;
145 + } else
146 die(_("unrecognized %%(objectname) argument: %s"), arg);
147 }
148
@@ -606,12 +616,15 @@ static int grab_objectname(const char *name, const unsigned char *sha1,
616 struct atom_value *v, struct used_atom *atom)
617 {
618 if (starts_with(name, "objectname")) {
609 - if (atom->u.objectname == O_SHORT) {
619 + if (atom->u.objectname.option == O_SHORT) {
620 v->s = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
621 return 1;
612 - } else if (atom->u.objectname == O_FULL) {
622 + } else if (atom->u.objectname.option == O_FULL) {
623 v->s = xstrdup(sha1_to_hex(sha1));
624 return 1;
625 + } else if (atom->u.objectname.option == O_LENGTH) {
626 + v->s = xstrdup(find_unique_abbrev(sha1, atom->u.objectname.length));
627 + return 1;
628 } else
629 die("BUG: unknown %%(objectname) option");
630 }
t/t6300-for-each-ref.sh
+10
@@ -60,6 +60,8 @@ test_atom head objecttype commit
60 test_atom head objectsize 171
61 test_atom head objectname $(git rev-parse refs/heads/master)
62 test_atom head objectname:short $(git rev-parse --short refs/heads/master)
63 +test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master)
64 +test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/master)
65 test_atom head tree $(git rev-parse refs/heads/master^{tree})
66 test_atom head parent ''
67 test_atom head numparent 0
@@ -99,6 +101,8 @@ test_atom tag objecttype tag
101 test_atom tag objectsize 154
102 test_atom tag objectname $(git rev-parse refs/tags/testtag)
103 test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
104 +test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master)
105 +test_atom head objectname:short=10 $(git rev-parse --short=10 refs/heads/master)
106 test_atom tag tree ''
107 test_atom tag parent ''
108 test_atom tag numparent ''
@@ -164,6 +168,12 @@ test_expect_success 'Check invalid format specifiers are errors' '
168 test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
169 '
170
171 +test_expect_success 'arguments to %(objectname:short=) must be positive integers' '
172 + test_must_fail git for-each-ref --format="%(objectname:short=0)" &&
173 + test_must_fail git for-each-ref --format="%(objectname:short=-1)" &&
174 + test_must_fail git for-each-ref --format="%(objectname:short=foo)"
175 +'
176 +
177 test_date () {
178 f=$1 &&
179 committer_date=$2 &&