From: ZheNing Hu <adlternative@xxxxxxxxx> Because git verify-tag or git tag --verify are using command line parameters we pass as the %(refname) output (e.g. `git verify-tag --format="verify: %(refname)" c06b72d02` will output "verify: c06b72d02"). This is an design error, but it is widely used by some scripts. After we fix the bug that git verify_tag and git tag --verify cannot use %(symref) correctly, we still need to make %(refname) keep the same output as in the past. So add special_tag_verify to ref_array_item and ref_format, when this flag is setted and we are using refname atom default output formats such as %(refname), %(symref), modify the attribute of the atom corresponding to %(refname) in get_refname() and get_symref() and fill_remote_ref_details(), which let show_ref() output something like %(refname:lstrip=2). After show_ref() completes, restore the atom attribute as their origin state. We can set special_tag_verify flag directly in tag.c, but in verify_tag.c, if we didn't get a refname from repo_dwim_ref(), we don’t need to set special_tag_verify of ref_format and change its output form, otherwise, set it. Signed-off-by: ZheNing Hu <adlternative@xxxxxxxxx> --- builtin/tag.c | 1 + builtin/verify-tag.c | 5 ++++- ref-filter.c | 44 +++++++++++++++++++++++++++++++++---------- ref-filter.h | 2 ++ t/t7030-verify-tag.sh | 23 ++++++++++++++++++++++ 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/builtin/tag.c b/builtin/tag.c index ce5678d179f..bf2acb9f832 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -149,6 +149,7 @@ static int verify_tag(const char *name, const char *ref, int flags; struct ref_format *format = cb_data; flags = GPG_VERIFY_VERBOSE; + format->special_tag_verify = 1; if (format->format) flags = GPG_VERIFY_OMIT_STATUS; diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index efc8282782a..dd2ff94eac9 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -61,6 +61,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) const char *name = argv[i++]; char *refname; int ref_flags; + format.special_tag_verify = 0; if (get_oid(name, &oid)) { had_error = !!error("tag '%s' not found.", name); @@ -72,8 +73,10 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) continue; } - if (repo_dwim_ref(the_repository, name, strlen(name), &oid, &refname, 0, &ref_flags, 1)) + if (repo_dwim_ref(the_repository, name, strlen(name), &oid, &refname, 0, &ref_flags, 1)) { name = refname; + format.special_tag_verify = 1; + } if (format.format) pretty_print_ref(name, &oid, &format, ref_flags); } diff --git a/ref-filter.c b/ref-filter.c index 6c51ef25136..c7c3182ab5b 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -1640,12 +1640,19 @@ static const char *show_ref(struct refname_atom *atom, const char *refname) } static void fill_remote_ref_details(struct used_atom *atom, const char *refname, - struct branch *branch, const char **s) + struct branch *branch, const char **s, struct ref_array_item *ref) { int num_ours, num_theirs; - if (atom->u.remote_ref.option == RR_REF) - *s = show_ref(&atom->u.remote_ref.refname, refname); - else if (atom->u.remote_ref.option == RR_TRACK) { + if (atom->u.remote_ref.option == RR_REF) { + if (ref->special_tag_verify && atom->u.remote_ref.refname.option == R_NORMAL) { + atom->u.remote_ref.refname.option = R_LSTRIP; + atom->u.remote_ref.refname.lstrip = 2; + *s = show_ref(&atom->u.remote_ref.refname, refname); + atom->u.remote_ref.refname.option = R_NORMAL; + } else { + *s = show_ref(&atom->u.remote_ref.refname, refname); + } + } else if (atom->u.remote_ref.option == RR_TRACK) { if (stat_tracking_info(branch, &num_ours, &num_theirs, NULL, atom->u.remote_ref.push, AHEAD_BEHIND_FULL) < 0) { @@ -1726,17 +1733,33 @@ char *get_head_description(void) static const char *get_symref(struct used_atom *atom, struct ref_array_item *ref) { - if (!ref->symref) + if (!ref->symref) { return xstrdup(""); - else + } else if (ref->special_tag_verify && atom->u.refname.option == R_NORMAL) { + atom->u.refname.option = R_LSTRIP; + atom->u.refname.lstrip = 2; + return show_ref(&atom->u.refname, ref->symref); + atom->u.refname.option = R_NORMAL; + } else { return show_ref(&atom->u.refname, ref->symref); + } } static const char *get_refname(struct used_atom *atom, struct ref_array_item *ref) { - if (ref->kind & FILTER_REFS_DETACHED_HEAD) + if (ref->kind & FILTER_REFS_DETACHED_HEAD) { return get_head_description(); - return show_ref(&atom->u.refname, ref->refname); + } else if (ref->special_tag_verify && atom->u.refname.option == R_NORMAL) { + const char * refname; + + atom->u.refname.option = R_LSTRIP; + atom->u.refname.lstrip = 2; + refname = show_ref(&atom->u.refname, ref->refname); + atom->u.refname.option = R_NORMAL; + return refname; + } else { + return show_ref(&atom->u.refname, ref->refname); + } } static int get_object(struct ref_array_item *ref, int deref, struct object **obj, @@ -1878,7 +1901,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) refname = branch_get_upstream(branch, NULL); if (refname) - fill_remote_ref_details(atom, refname, branch, &v->s); + fill_remote_ref_details(atom, refname, branch, &v->s, ref); else v->s = xstrdup(""); continue; @@ -1899,7 +1922,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) } /* We will definitely re-init v->s on the next line. */ free((char *)v->s); - fill_remote_ref_details(atom, refname, branch, &v->s); + fill_remote_ref_details(atom, refname, branch, &v->s, ref); continue; } else if (atom_type == ATOM_COLOR) { v->s = xstrdup(atom->u.color); @@ -2641,6 +2664,7 @@ void pretty_print_ref(const char *name, const struct object_id *oid, ref_item = new_ref_array_item(name, oid); ref_item->kind = ref_kind_from_refname(name); ref_item->flag = ref_flags; + ref_item->special_tag_verify = format->special_tag_verify; if (format_ref_array_item(ref_item, format, &output, &err)) die("%s", err.buf); fwrite(output.buf, 1, output.len, stdout); diff --git a/ref-filter.h b/ref-filter.h index edd9a3b6652..63c8d24a6fc 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -42,6 +42,7 @@ struct ref_array_item { int flag; unsigned int kind; const char *symref; + int special_tag_verify; struct commit *commit; struct atom_value *value; char refname[FLEX_ARRAY]; @@ -84,6 +85,7 @@ struct ref_format { /* Internal state to ref-filter */ int need_color_reset_at_eol; + int special_tag_verify; }; #define REF_FORMAT_INIT { .use_color = -1 } diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 10faa645157..85e2a653ed8 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -194,6 +194,29 @@ test_expect_success GPG 'verifying tag with --format' ' test_cmp expect actual ' +test_expect_success GPG 'verifying tag with --format="%(refname) %(symref)"' ' + git tag -s -m bar annotated && + git symbolic-ref refs/tags/symref refs/tags/annotated && + sha=$(git rev-parse symref) && + SP=" " && + cat >expect <<-EOF && + verify: annotated$SP + verify: symref annotated + verify: $sha$SP + EOF + git verify-tag --format="verify: %(refname) %(symref)" annotated symref $sha >actual && + test_cmp expect actual +' + +test_expect_success GPG 'tag verify with --format="%(refname) %(symref)"' ' + cat >expect <<-EOF && + verify: annotated$SP + verify: symref annotated + EOF + git tag --verify --format="verify: %(refname) %(symref)" annotated symref >actual && + test_cmp expect actual +' + test_expect_success GPG 'verifying tag with --format="%(rest)" must fail' ' test_must_fail git verify-tag --format="%(rest)" "fourth-signed" ' -- gitgitgadget