Merge branch 'st/verify-tag'
"git tag" and "git verify-tag" learned to put GPG verification status in their "--format=<placeholders>" output format. * st/verify-tag: t/t7004-tag: Add --format specifier tests t/t7030-verify-tag: Add --format specifier tests builtin/tag: add --format argument for tag -v builtin/verify-tag: add --format to verify-tag ref-filter: add function to print single ref_array_item gpg-interface, tag: add GPG_VERIFY_OMIT_STATUS flag
This commit is contained in:
commit
237bdd9ddb
@ -15,7 +15,7 @@ SYNOPSIS
|
|||||||
'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
|
'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
|
||||||
[--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>]
|
[--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>]
|
||||||
[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]
|
[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]
|
||||||
'git tag' -v <tagname>...
|
'git tag' -v [--format=<format>] <tagname>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -8,7 +8,7 @@ git-verify-tag - Check the GPG signature of tags
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git verify-tag' <tag>...
|
'git verify-tag' [--format=<format>] <tag>...
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -24,7 +24,7 @@ static const char * const git_tag_usage[] = {
|
|||||||
N_("git tag -d <tagname>..."),
|
N_("git tag -d <tagname>..."),
|
||||||
N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]"
|
N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]"
|
||||||
"\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
|
"\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
|
||||||
N_("git tag -v <tagname>..."),
|
N_("git tag -v [--format=<format>] <tagname>..."),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,9 +66,10 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef int (*each_tag_name_fn)(const char *name, const char *ref,
|
typedef int (*each_tag_name_fn)(const char *name, const char *ref,
|
||||||
const unsigned char *sha1);
|
const unsigned char *sha1, const void *cb_data);
|
||||||
|
|
||||||
static int for_each_tag_name(const char **argv, each_tag_name_fn fn)
|
static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
|
||||||
|
const void *cb_data)
|
||||||
{
|
{
|
||||||
const char **p;
|
const char **p;
|
||||||
char ref[PATH_MAX];
|
char ref[PATH_MAX];
|
||||||
@ -87,14 +88,14 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn)
|
|||||||
had_error = 1;
|
had_error = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fn(*p, ref, sha1))
|
if (fn(*p, ref, sha1, cb_data))
|
||||||
had_error = 1;
|
had_error = 1;
|
||||||
}
|
}
|
||||||
return had_error;
|
return had_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int delete_tag(const char *name, const char *ref,
|
static int delete_tag(const char *name, const char *ref,
|
||||||
const unsigned char *sha1)
|
const unsigned char *sha1, const void *cb_data)
|
||||||
{
|
{
|
||||||
if (delete_ref(ref, sha1, 0))
|
if (delete_ref(ref, sha1, 0))
|
||||||
return 1;
|
return 1;
|
||||||
@ -103,9 +104,22 @@ static int delete_tag(const char *name, const char *ref,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int verify_tag(const char *name, const char *ref,
|
static int verify_tag(const char *name, const char *ref,
|
||||||
const unsigned char *sha1)
|
const unsigned char *sha1, const void *cb_data)
|
||||||
{
|
{
|
||||||
return gpg_verify_tag(sha1, name, GPG_VERIFY_VERBOSE);
|
int flags;
|
||||||
|
const char *fmt_pretty = cb_data;
|
||||||
|
flags = GPG_VERIFY_VERBOSE;
|
||||||
|
|
||||||
|
if (fmt_pretty)
|
||||||
|
flags = GPG_VERIFY_OMIT_STATUS;
|
||||||
|
|
||||||
|
if (gpg_verify_tag(sha1, name, flags))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (fmt_pretty)
|
||||||
|
pretty_print_ref(name, sha1, fmt_pretty);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_sign(struct strbuf *buffer)
|
static int do_sign(struct strbuf *buffer)
|
||||||
@ -428,9 +442,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
|||||||
if (filter.merge_commit)
|
if (filter.merge_commit)
|
||||||
die(_("--merged and --no-merged option are only allowed with -l"));
|
die(_("--merged and --no-merged option are only allowed with -l"));
|
||||||
if (cmdmode == 'd')
|
if (cmdmode == 'd')
|
||||||
return for_each_tag_name(argv, delete_tag);
|
return for_each_tag_name(argv, delete_tag, NULL);
|
||||||
if (cmdmode == 'v')
|
if (cmdmode == 'v') {
|
||||||
return for_each_tag_name(argv, verify_tag);
|
if (format)
|
||||||
|
verify_ref_format(format);
|
||||||
|
return for_each_tag_name(argv, verify_tag, format);
|
||||||
|
}
|
||||||
|
|
||||||
if (msg.given || msgfile) {
|
if (msg.given || msgfile) {
|
||||||
if (msg.given && msgfile)
|
if (msg.given && msgfile)
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
#include "gpg-interface.h"
|
#include "gpg-interface.h"
|
||||||
|
#include "ref-filter.h"
|
||||||
|
|
||||||
static const char * const verify_tag_usage[] = {
|
static const char * const verify_tag_usage[] = {
|
||||||
N_("git verify-tag [-v | --verbose] <tag>..."),
|
N_("git verify-tag [-v | --verbose] [--format=<format>] <tag>..."),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,9 +31,11 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
|
|||||||
{
|
{
|
||||||
int i = 1, verbose = 0, had_error = 0;
|
int i = 1, verbose = 0, had_error = 0;
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
|
char *fmt_pretty = NULL;
|
||||||
const struct option verify_tag_options[] = {
|
const struct option verify_tag_options[] = {
|
||||||
OPT__VERBOSE(&verbose, N_("print tag contents")),
|
OPT__VERBOSE(&verbose, N_("print tag contents")),
|
||||||
OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
|
OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
|
||||||
|
OPT_STRING( 0 , "format", &fmt_pretty, N_("format"), N_("format to use for the output")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,13 +49,26 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
flags |= GPG_VERIFY_VERBOSE;
|
flags |= GPG_VERIFY_VERBOSE;
|
||||||
|
|
||||||
|
if (fmt_pretty) {
|
||||||
|
verify_ref_format(fmt_pretty);
|
||||||
|
flags |= GPG_VERIFY_OMIT_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
while (i < argc) {
|
while (i < argc) {
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
const char *name = argv[i++];
|
const char *name = argv[i++];
|
||||||
if (get_sha1(name, sha1))
|
if (get_sha1(name, sha1)) {
|
||||||
had_error = !!error("tag '%s' not found.", name);
|
had_error = !!error("tag '%s' not found.", name);
|
||||||
else if (gpg_verify_tag(sha1, name, flags))
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpg_verify_tag(sha1, name, flags)) {
|
||||||
had_error = 1;
|
had_error = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmt_pretty)
|
||||||
|
pretty_print_ref(name, sha1, fmt_pretty);
|
||||||
}
|
}
|
||||||
return had_error;
|
return had_error;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef GPG_INTERFACE_H
|
#ifndef GPG_INTERFACE_H
|
||||||
#define GPG_INTERFACE_H
|
#define GPG_INTERFACE_H
|
||||||
|
|
||||||
#define GPG_VERIFY_VERBOSE 1
|
#define GPG_VERIFY_VERBOSE 1
|
||||||
#define GPG_VERIFY_RAW 2
|
#define GPG_VERIFY_RAW 2
|
||||||
|
#define GPG_VERIFY_OMIT_STATUS 4
|
||||||
|
|
||||||
struct signature_check {
|
struct signature_check {
|
||||||
char *payload;
|
char *payload;
|
||||||
|
27
ref-filter.c
27
ref-filter.c
@ -1361,7 +1361,7 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int filter_ref_kind(struct ref_filter *filter, const char *refname)
|
static int ref_kind_from_refname(const char *refname)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -1374,11 +1374,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
|
|||||||
{ "refs/tags/", FILTER_REFS_TAGS}
|
{ "refs/tags/", FILTER_REFS_TAGS}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (filter->kind == FILTER_REFS_BRANCHES ||
|
if (!strcmp(refname, "HEAD"))
|
||||||
filter->kind == FILTER_REFS_REMOTES ||
|
|
||||||
filter->kind == FILTER_REFS_TAGS)
|
|
||||||
return filter->kind;
|
|
||||||
else if (!strcmp(refname, "HEAD"))
|
|
||||||
return FILTER_REFS_DETACHED_HEAD;
|
return FILTER_REFS_DETACHED_HEAD;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
|
for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
|
||||||
@ -1389,6 +1385,15 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
|
|||||||
return FILTER_REFS_OTHERS;
|
return FILTER_REFS_OTHERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int filter_ref_kind(struct ref_filter *filter, const char *refname)
|
||||||
|
{
|
||||||
|
if (filter->kind == FILTER_REFS_BRANCHES ||
|
||||||
|
filter->kind == FILTER_REFS_REMOTES ||
|
||||||
|
filter->kind == FILTER_REFS_TAGS)
|
||||||
|
return filter->kind;
|
||||||
|
return ref_kind_from_refname(refname);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A call-back given to for_each_ref(). Filter refs and keep them for
|
* A call-back given to for_each_ref(). Filter refs and keep them for
|
||||||
* later object processing.
|
* later object processing.
|
||||||
@ -1671,6 +1676,16 @@ void show_ref_array_item(struct ref_array_item *info, const char *format, int qu
|
|||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pretty_print_ref(const char *name, const unsigned char *sha1,
|
||||||
|
const char *format)
|
||||||
|
{
|
||||||
|
struct ref_array_item *ref_item;
|
||||||
|
ref_item = new_ref_array_item(name, sha1, 0);
|
||||||
|
ref_item->kind = ref_kind_from_refname(name);
|
||||||
|
show_ref_array_item(ref_item, format, 0);
|
||||||
|
free_array_item(ref_item);
|
||||||
|
}
|
||||||
|
|
||||||
/* If no sorting option is given, use refname to sort as default */
|
/* If no sorting option is given, use refname to sort as default */
|
||||||
struct ref_sorting *ref_default_sorting(void)
|
struct ref_sorting *ref_default_sorting(void)
|
||||||
{
|
{
|
||||||
|
@ -109,4 +109,11 @@ struct ref_sorting *ref_default_sorting(void);
|
|||||||
/* Function to parse --merged and --no-merged options */
|
/* Function to parse --merged and --no-merged options */
|
||||||
int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset);
|
int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a single ref, outside of any ref-filter. Note that the
|
||||||
|
* name must be a fully qualified refname.
|
||||||
|
*/
|
||||||
|
void pretty_print_ref(const char *name, const unsigned char *sha1,
|
||||||
|
const char *format);
|
||||||
|
|
||||||
#endif /* REF_FILTER_H */
|
#endif /* REF_FILTER_H */
|
||||||
|
@ -871,6 +871,22 @@ test_expect_success GPG 'verifying a forged tag should fail' '
|
|||||||
test_must_fail git tag -v forged-tag
|
test_must_fail git tag -v forged-tag
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'verifying a proper tag with --format pass and format accordingly' '
|
||||||
|
cat >expect <<-\EOF
|
||||||
|
tagname : signed-tag
|
||||||
|
EOF &&
|
||||||
|
git tag -v --format="tagname : %(tag)" "signed-tag" >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'verifying a forged tag with --format fail and format accordingly' '
|
||||||
|
cat >expect <<-\EOF
|
||||||
|
tagname : forged-tag
|
||||||
|
EOF &&
|
||||||
|
test_must_fail git tag -v --format="tagname : %(tag)" "forged-tag" >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
# blank and empty messages for signed tags:
|
# blank and empty messages for signed tags:
|
||||||
|
|
||||||
get_tag_header empty-signed-tag $commit commit $time >expect
|
get_tag_header empty-signed-tag $commit commit $time >expect
|
||||||
|
@ -125,4 +125,20 @@ test_expect_success GPG 'verify multiple tags' '
|
|||||||
test_cmp expect.stderr actual.stderr
|
test_cmp expect.stderr actual.stderr
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'verifying tag with --format' '
|
||||||
|
cat >expect <<-\EOF
|
||||||
|
tagname : fourth-signed
|
||||||
|
EOF &&
|
||||||
|
git verify-tag --format="tagname : %(tag)" "fourth-signed" >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'verifying a forged tag with --format fail and format accordingly' '
|
||||||
|
cat >expect <<-\EOF
|
||||||
|
tagname : 7th forged-signed
|
||||||
|
EOF &&
|
||||||
|
test_must_fail git verify-tag --format="tagname : %(tag)" $(cat forged1.tag) >actual-forged &&
|
||||||
|
test_cmp expect actual-forged
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
5
tag.c
5
tag.c
@ -3,6 +3,7 @@
|
|||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
|
#include "gpg-interface.h"
|
||||||
|
|
||||||
const char *tag_type = "tag";
|
const char *tag_type = "tag";
|
||||||
|
|
||||||
@ -24,7 +25,9 @@ static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
|
|||||||
|
|
||||||
ret = check_signature(buf, payload_size, buf + payload_size,
|
ret = check_signature(buf, payload_size, buf + payload_size,
|
||||||
size - payload_size, &sigc);
|
size - payload_size, &sigc);
|
||||||
print_signature_buffer(&sigc, flags);
|
|
||||||
|
if (!(flags & GPG_VERIFY_OMIT_STATUS))
|
||||||
|
print_signature_buffer(&sigc, flags);
|
||||||
|
|
||||||
signature_check_clear(&sigc);
|
signature_check_clear(&sigc);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user