зеркало из https://github.com/microsoft/git.git
Merge branch 'zh/ref-filter-raw-data'
Prepare the "ref-filter" machinery that drives the "--format" option of "git for-each-ref" and its friends to be used in "git cat-file --batch". * zh/ref-filter-raw-data: ref-filter: add %(rest) atom ref-filter: use non-const ref_format in *_atom_parser() ref-filter: --format=%(raw) support --perl ref-filter: add %(raw) atom ref-filter: add obj-type check in grab contents
This commit is contained in:
Коммит
bda891e664
|
@ -235,6 +235,15 @@ and `date` to extract the named component. For email fields (`authoremail`,
|
|||
without angle brackets, and `:localpart` to get the part before the `@` symbol
|
||||
out of the trimmed email.
|
||||
|
||||
The raw data in an object is `raw`.
|
||||
|
||||
raw:size::
|
||||
The raw data size of the object.
|
||||
|
||||
Note that `--format=%(raw)` can not be used with `--python`, `--shell`, `--tcl`,
|
||||
because such language may not support arbitrary binary data in their string
|
||||
variable type.
|
||||
|
||||
The message in a commit or a tag object is `contents`, from which
|
||||
`contents:<part>` can be used to extract various parts out of:
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ static int verify_tag(const char *name, const char *ref,
|
|||
const struct object_id *oid, void *cb_data)
|
||||
{
|
||||
int flags;
|
||||
const struct ref_format *format = cb_data;
|
||||
struct ref_format *format = cb_data;
|
||||
flags = GPG_VERIFY_VERBOSE;
|
||||
|
||||
if (format->format)
|
||||
|
|
17
quote.c
17
quote.c
|
@ -471,6 +471,23 @@ void perl_quote_buf(struct strbuf *sb, const char *src)
|
|||
strbuf_addch(sb, sq);
|
||||
}
|
||||
|
||||
void perl_quote_buf_with_len(struct strbuf *sb, const char *src, size_t len)
|
||||
{
|
||||
const char sq = '\'';
|
||||
const char bq = '\\';
|
||||
const char *c = src;
|
||||
const char *end = src + len;
|
||||
|
||||
strbuf_addch(sb, sq);
|
||||
while (c != end) {
|
||||
if (*c == sq || *c == bq)
|
||||
strbuf_addch(sb, bq);
|
||||
strbuf_addch(sb, *c);
|
||||
c++;
|
||||
}
|
||||
strbuf_addch(sb, sq);
|
||||
}
|
||||
|
||||
void python_quote_buf(struct strbuf *sb, const char *src)
|
||||
{
|
||||
const char sq = '\'';
|
||||
|
|
1
quote.h
1
quote.h
|
@ -95,6 +95,7 @@ char *quote_path(const char *in, const char *prefix, struct strbuf *out, unsigne
|
|||
|
||||
/* quoting as a string literal for other languages */
|
||||
void perl_quote_buf(struct strbuf *sb, const char *src);
|
||||
void perl_quote_buf_with_len(struct strbuf *sb, const char *src, size_t len);
|
||||
void python_quote_buf(struct strbuf *sb, const char *src);
|
||||
void tcl_quote_buf(struct strbuf *sb, const char *src);
|
||||
void basic_regex_quote_buf(struct strbuf *sb, const char *src);
|
||||
|
|
243
ref-filter.c
243
ref-filter.c
|
@ -144,6 +144,7 @@ enum atom_type {
|
|||
ATOM_BODY,
|
||||
ATOM_TRAILERS,
|
||||
ATOM_CONTENTS,
|
||||
ATOM_RAW,
|
||||
ATOM_UPSTREAM,
|
||||
ATOM_PUSH,
|
||||
ATOM_SYMREF,
|
||||
|
@ -156,6 +157,7 @@ enum atom_type {
|
|||
ATOM_IF,
|
||||
ATOM_THEN,
|
||||
ATOM_ELSE,
|
||||
ATOM_REST,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -189,6 +191,9 @@ static struct used_atom {
|
|||
struct process_trailer_options trailer_opts;
|
||||
unsigned int nlines;
|
||||
} contents;
|
||||
struct {
|
||||
enum { RAW_BARE, RAW_LENGTH } option;
|
||||
} raw_data;
|
||||
struct {
|
||||
cmp_status cmp_status;
|
||||
const char *str;
|
||||
|
@ -223,7 +228,7 @@ static int strbuf_addf_ret(struct strbuf *sb, int ret, const char *fmt, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int color_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int color_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *color_value, struct strbuf *err)
|
||||
{
|
||||
if (!color_value)
|
||||
|
@ -261,7 +266,7 @@ static int refname_atom_parser_internal(struct refname_atom *atom, const char *a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int remote_ref_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int remote_ref_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
struct string_list params = STRING_LIST_INIT_DUP;
|
||||
|
@ -308,7 +313,7 @@ static int remote_ref_atom_parser(const struct ref_format *format, struct used_a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int objecttype_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int objecttype_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (arg)
|
||||
|
@ -320,7 +325,7 @@ static int objecttype_atom_parser(const struct ref_format *format, struct used_a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int objectsize_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int objectsize_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg) {
|
||||
|
@ -340,7 +345,7 @@ static int objectsize_atom_parser(const struct ref_format *format, struct used_a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int deltabase_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int deltabase_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (arg)
|
||||
|
@ -352,7 +357,7 @@ static int deltabase_atom_parser(const struct ref_format *format, struct used_at
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int body_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int body_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (arg)
|
||||
|
@ -361,7 +366,7 @@ static int body_atom_parser(const struct ref_format *format, struct used_atom *a
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int subject_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int subject_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg)
|
||||
|
@ -373,7 +378,7 @@ static int subject_atom_parser(const struct ref_format *format, struct used_atom
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int trailers_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int trailers_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
atom->u.contents.trailer_opts.no_divider = 1;
|
||||
|
@ -399,7 +404,7 @@ static int trailers_atom_parser(const struct ref_format *format, struct used_ato
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int contents_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int contents_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg)
|
||||
|
@ -427,7 +432,19 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int oid_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg)
|
||||
atom->u.raw_data.option = RAW_BARE;
|
||||
else if (!strcmp(arg, "size"))
|
||||
atom->u.raw_data.option = RAW_LENGTH;
|
||||
else
|
||||
return strbuf_addf_ret(err, -1, _("unrecognized %%(raw) argument: %s"), arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oid_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg)
|
||||
|
@ -446,7 +463,7 @@ static int oid_atom_parser(const struct ref_format *format, struct used_atom *at
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int person_email_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int person_email_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg)
|
||||
|
@ -460,7 +477,7 @@ static int person_email_atom_parser(const struct ref_format *format, struct used
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int refname_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int refname_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
return refname_atom_parser_internal(&atom->u.refname, arg, atom->name, err);
|
||||
|
@ -477,7 +494,7 @@ static align_type parse_align_position(const char *s)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int align_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int align_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
struct align *align = &atom->u.align;
|
||||
|
@ -529,7 +546,7 @@ static int align_atom_parser(const struct ref_format *format, struct used_atom *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int if_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int if_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (!arg) {
|
||||
|
@ -544,7 +561,16 @@ static int if_atom_parser(const struct ref_format *format, struct used_atom *ato
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int head_atom_parser(const struct ref_format *format, struct used_atom *atom,
|
||||
static int rest_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err)
|
||||
{
|
||||
if (arg)
|
||||
return strbuf_addf_ret(err, -1, _("%%(rest) does not take arguments"));
|
||||
format->use_rest = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int head_atom_parser(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *unused_err)
|
||||
{
|
||||
atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
|
||||
|
@ -555,7 +581,7 @@ static struct {
|
|||
const char *name;
|
||||
info_source source;
|
||||
cmp_type cmp_type;
|
||||
int (*parser)(const struct ref_format *format, struct used_atom *atom,
|
||||
int (*parser)(struct ref_format *format, struct used_atom *atom,
|
||||
const char *arg, struct strbuf *err);
|
||||
} valid_atom[] = {
|
||||
[ATOM_REFNAME] = { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser },
|
||||
|
@ -587,6 +613,7 @@ static struct {
|
|||
[ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
|
||||
[ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
|
||||
[ATOM_CONTENTS] = { "contents", SOURCE_OBJ, FIELD_STR, contents_atom_parser },
|
||||
[ATOM_RAW] = { "raw", SOURCE_OBJ, FIELD_STR, raw_atom_parser },
|
||||
[ATOM_UPSTREAM] = { "upstream", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
|
||||
[ATOM_PUSH] = { "push", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },
|
||||
[ATOM_SYMREF] = { "symref", SOURCE_NONE, FIELD_STR, refname_atom_parser },
|
||||
|
@ -599,6 +626,7 @@ static struct {
|
|||
[ATOM_IF] = { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
|
||||
[ATOM_THEN] = { "then", SOURCE_NONE },
|
||||
[ATOM_ELSE] = { "else", SOURCE_NONE },
|
||||
[ATOM_REST] = { "rest", SOURCE_NONE, FIELD_STR, rest_atom_parser },
|
||||
/*
|
||||
* Please update $__git_ref_fieldlist in git-completion.bash
|
||||
* when you add new atoms
|
||||
|
@ -621,16 +649,23 @@ struct ref_formatting_state {
|
|||
|
||||
struct atom_value {
|
||||
const char *s;
|
||||
ssize_t s_size;
|
||||
int (*handler)(struct atom_value *atomv, struct ref_formatting_state *state,
|
||||
struct strbuf *err);
|
||||
uintmax_t value; /* used for sorting when not FIELD_STR */
|
||||
struct used_atom *atom;
|
||||
};
|
||||
|
||||
#define ATOM_SIZE_UNSPECIFIED (-1)
|
||||
|
||||
#define ATOM_VALUE_INIT { \
|
||||
.s_size = ATOM_SIZE_UNSPECIFIED \
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to parse format string and sort specifiers
|
||||
*/
|
||||
static int parse_ref_filter_atom(const struct ref_format *format,
|
||||
static int parse_ref_filter_atom(struct ref_format *format,
|
||||
const char *atom, const char *ep,
|
||||
struct strbuf *err)
|
||||
{
|
||||
|
@ -645,13 +680,6 @@ static int parse_ref_filter_atom(const struct ref_format *format,
|
|||
return strbuf_addf_ret(err, -1, _("malformed field name: %.*s"),
|
||||
(int)(ep-atom), atom);
|
||||
|
||||
/* Do we have the atom already used elsewhere? */
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
int len = strlen(used_atom[i].name);
|
||||
if (len == ep - atom && !memcmp(used_atom[i].name, atom, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the atom name has a colon, strip it and everything after
|
||||
* it off - it specifies the format for this entry, and
|
||||
|
@ -661,6 +689,13 @@ static int parse_ref_filter_atom(const struct ref_format *format,
|
|||
arg = memchr(sp, ':', ep - sp);
|
||||
atom_len = (arg ? arg : ep) - sp;
|
||||
|
||||
/* Do we have the atom already used elsewhere? */
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
int len = strlen(used_atom[i].name);
|
||||
if (len == ep - atom && !memcmp(used_atom[i].name, atom, len))
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Is the atom a valid one? */
|
||||
for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
|
||||
int len = strlen(valid_atom[i].name);
|
||||
|
@ -710,17 +745,23 @@ static int parse_ref_filter_atom(const struct ref_format *format,
|
|||
return at;
|
||||
}
|
||||
|
||||
static void quote_formatting(struct strbuf *s, const char *str, int quote_style)
|
||||
static void quote_formatting(struct strbuf *s, const char *str, ssize_t len, int quote_style)
|
||||
{
|
||||
switch (quote_style) {
|
||||
case QUOTE_NONE:
|
||||
strbuf_addstr(s, str);
|
||||
if (len < 0)
|
||||
strbuf_addstr(s, str);
|
||||
else
|
||||
strbuf_add(s, str, len);
|
||||
break;
|
||||
case QUOTE_SHELL:
|
||||
sq_quote_buf(s, str);
|
||||
break;
|
||||
case QUOTE_PERL:
|
||||
perl_quote_buf(s, str);
|
||||
if (len < 0)
|
||||
perl_quote_buf(s, str);
|
||||
else
|
||||
perl_quote_buf_with_len(s, str, len);
|
||||
break;
|
||||
case QUOTE_PYTHON:
|
||||
python_quote_buf(s, str);
|
||||
|
@ -741,9 +782,11 @@ static int append_atom(struct atom_value *v, struct ref_formatting_state *state,
|
|||
* encountered.
|
||||
*/
|
||||
if (!state->stack->prev)
|
||||
quote_formatting(&state->stack->output, v->s, state->quote_style);
|
||||
else
|
||||
quote_formatting(&state->stack->output, v->s, v->s_size, state->quote_style);
|
||||
else if (v->s_size < 0)
|
||||
strbuf_addstr(&state->stack->output, v->s);
|
||||
else
|
||||
strbuf_add(&state->stack->output, v->s, v->s_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -843,21 +886,23 @@ static int if_atom_handler(struct atom_value *atomv, struct ref_formatting_state
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int is_empty(const char *s)
|
||||
static int is_empty(struct strbuf *buf)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
if (!isspace(*s))
|
||||
return 0;
|
||||
s++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
const char *cur = buf->buf;
|
||||
const char *end = buf->buf + buf->len;
|
||||
|
||||
while (cur != end && (isspace(*cur)))
|
||||
cur++;
|
||||
|
||||
return cur == end;
|
||||
}
|
||||
|
||||
static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_state *state,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct ref_formatting_stack *cur = state->stack;
|
||||
struct if_then_else *if_then_else = NULL;
|
||||
size_t str_len = 0;
|
||||
|
||||
if (cur->at_end == if_then_else_handler)
|
||||
if_then_else = (struct if_then_else *)cur->at_end_data;
|
||||
|
@ -868,18 +913,22 @@ static int then_atom_handler(struct atom_value *atomv, struct ref_formatting_sta
|
|||
if (if_then_else->else_atom_seen)
|
||||
return strbuf_addf_ret(err, -1, _("format: %%(then) atom used after %%(else)"));
|
||||
if_then_else->then_atom_seen = 1;
|
||||
if (if_then_else->str)
|
||||
str_len = strlen(if_then_else->str);
|
||||
/*
|
||||
* If the 'equals' or 'notequals' attribute is used then
|
||||
* perform the required comparison. If not, only non-empty
|
||||
* strings satisfy the 'if' condition.
|
||||
*/
|
||||
if (if_then_else->cmp_status == COMPARE_EQUAL) {
|
||||
if (!strcmp(if_then_else->str, cur->output.buf))
|
||||
if (str_len == cur->output.len &&
|
||||
!memcmp(if_then_else->str, cur->output.buf, cur->output.len))
|
||||
if_then_else->condition_satisfied = 1;
|
||||
} else if (if_then_else->cmp_status == COMPARE_UNEQUAL) {
|
||||
if (strcmp(if_then_else->str, cur->output.buf))
|
||||
if (str_len != cur->output.len ||
|
||||
memcmp(if_then_else->str, cur->output.buf, cur->output.len))
|
||||
if_then_else->condition_satisfied = 1;
|
||||
} else if (cur->output.len && !is_empty(cur->output.buf))
|
||||
} else if (cur->output.len && !is_empty(&cur->output))
|
||||
if_then_else->condition_satisfied = 1;
|
||||
strbuf_reset(&cur->output);
|
||||
return 0;
|
||||
|
@ -925,7 +974,7 @@ static int end_atom_handler(struct atom_value *atomv, struct ref_formatting_stat
|
|||
* only on the topmost supporting atom.
|
||||
*/
|
||||
if (!current->prev->prev) {
|
||||
quote_formatting(&s, current->output.buf, state->quote_style);
|
||||
quote_formatting(&s, current->output.buf, current->output.len, state->quote_style);
|
||||
strbuf_swap(¤t->output, &s);
|
||||
}
|
||||
strbuf_release(&s);
|
||||
|
@ -955,6 +1004,11 @@ static const char *find_next(const char *cp)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int reject_atom(enum atom_type atom_type)
|
||||
{
|
||||
return atom_type == ATOM_REST;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the format string is well formed, and parse out
|
||||
* the used atoms.
|
||||
|
@ -975,6 +1029,16 @@ int verify_ref_format(struct ref_format *format)
|
|||
at = parse_ref_filter_atom(format, sp + 2, ep, &err);
|
||||
if (at < 0)
|
||||
die("%s", err.buf);
|
||||
if (reject_atom(used_atom[at].atom_type))
|
||||
die(_("this command reject atom %%(%.*s)"), (int)(ep - sp - 2), sp + 2);
|
||||
|
||||
if ((format->quote_style == QUOTE_PYTHON ||
|
||||
format->quote_style == QUOTE_SHELL ||
|
||||
format->quote_style == QUOTE_TCL) &&
|
||||
used_atom[at].atom_type == ATOM_RAW &&
|
||||
used_atom[at].u.raw_data.option == RAW_BARE)
|
||||
die(_("--format=%.*s cannot be used with"
|
||||
"--python, --shell, --tcl"), (int)(ep - sp - 2), sp + 2);
|
||||
cp = ep + 1;
|
||||
|
||||
if (skip_prefix(used_atom[at].name, "color:", &color))
|
||||
|
@ -1357,25 +1421,42 @@ static void append_lines(struct strbuf *out, const char *buf, unsigned long size
|
|||
}
|
||||
|
||||
/* See grab_values */
|
||||
static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
|
||||
static void grab_sub_body_contents(struct atom_value *val, int deref, struct expand_data *data)
|
||||
{
|
||||
int i;
|
||||
const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL;
|
||||
size_t sublen = 0, bodylen = 0, nonsiglen = 0, siglen = 0;
|
||||
void *buf = data->content;
|
||||
|
||||
for (i = 0; i < used_atom_cnt; i++) {
|
||||
struct used_atom *atom = &used_atom[i];
|
||||
const char *name = atom->name;
|
||||
struct atom_value *v = &val[i];
|
||||
enum atom_type atom_type = atom->atom_type;
|
||||
|
||||
if (!!deref != (*name == '*'))
|
||||
continue;
|
||||
if (deref)
|
||||
name++;
|
||||
if (strcmp(name, "body") &&
|
||||
!starts_with(name, "subject") &&
|
||||
!starts_with(name, "trailers") &&
|
||||
!starts_with(name, "contents"))
|
||||
|
||||
if (atom_type == ATOM_RAW) {
|
||||
unsigned long buf_size = data->size;
|
||||
|
||||
if (atom->u.raw_data.option == RAW_BARE) {
|
||||
v->s = xmemdupz(buf, buf_size);
|
||||
v->s_size = buf_size;
|
||||
} else if (atom->u.raw_data.option == RAW_LENGTH) {
|
||||
v->s = xstrfmt("%"PRIuMAX, (uintmax_t)buf_size);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((data->type != OBJ_TAG &&
|
||||
data->type != OBJ_COMMIT) ||
|
||||
(strcmp(name, "body") &&
|
||||
!starts_with(name, "subject") &&
|
||||
!starts_with(name, "trailers") &&
|
||||
!starts_with(name, "contents")))
|
||||
continue;
|
||||
if (!subpos)
|
||||
find_subpos(buf,
|
||||
|
@ -1439,25 +1520,29 @@ static void fill_missing_values(struct atom_value *val)
|
|||
* pointed at by the ref itself; otherwise it is the object the
|
||||
* ref (which is a tag) refers to.
|
||||
*/
|
||||
static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf)
|
||||
static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data)
|
||||
{
|
||||
void *buf = data->content;
|
||||
|
||||
switch (obj->type) {
|
||||
case OBJ_TAG:
|
||||
grab_tag_values(val, deref, obj);
|
||||
grab_sub_body_contents(val, deref, buf);
|
||||
grab_sub_body_contents(val, deref, data);
|
||||
grab_person("tagger", val, deref, buf);
|
||||
break;
|
||||
case OBJ_COMMIT:
|
||||
grab_commit_values(val, deref, obj);
|
||||
grab_sub_body_contents(val, deref, buf);
|
||||
grab_sub_body_contents(val, deref, data);
|
||||
grab_person("author", val, deref, buf);
|
||||
grab_person("committer", val, deref, buf);
|
||||
break;
|
||||
case OBJ_TREE:
|
||||
/* grab_tree_values(val, deref, obj, buf, sz); */
|
||||
grab_sub_body_contents(val, deref, data);
|
||||
break;
|
||||
case OBJ_BLOB:
|
||||
/* grab_blob_values(val, deref, obj, buf, sz); */
|
||||
grab_sub_body_contents(val, deref, data);
|
||||
break;
|
||||
default:
|
||||
die("Eh? Object of type %d?", obj->type);
|
||||
|
@ -1679,7 +1764,7 @@ static int get_object(struct ref_array_item *ref, int deref, struct object **obj
|
|||
return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
|
||||
oid_to_hex(&oi->oid), ref->refname);
|
||||
}
|
||||
grab_values(ref->value, deref, *obj, oi->content);
|
||||
grab_values(ref->value, deref, *obj, oi);
|
||||
}
|
||||
|
||||
grab_common_values(ref->value, deref, oi);
|
||||
|
@ -1761,6 +1846,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
|||
const char *refname;
|
||||
struct branch *branch = NULL;
|
||||
|
||||
v->s_size = ATOM_SIZE_UNSPECIFIED;
|
||||
v->handler = append_atom;
|
||||
v->atom = atom;
|
||||
|
||||
|
@ -1864,6 +1950,12 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
|||
v->handler = else_atom_handler;
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
} else if (atom_type == ATOM_REST) {
|
||||
if (ref->rest)
|
||||
v->s = xstrdup(ref->rest);
|
||||
else
|
||||
v->s = xstrdup("");
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
|
||||
|
@ -2081,6 +2173,7 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
|
|||
|
||||
FLEX_ALLOC_STR(ref, refname, refname);
|
||||
oidcpy(&ref->objectname, oid);
|
||||
ref->rest = NULL;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
@ -2368,6 +2461,19 @@ static int compare_detached_head(struct ref_array_item *a, struct ref_array_item
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int memcasecmp(const void *vs1, const void *vs2, size_t n)
|
||||
{
|
||||
const char *s1 = vs1, *s2 = vs2;
|
||||
const char *end = s1 + n;
|
||||
|
||||
for (; s1 < end; s1++, s2++) {
|
||||
int diff = tolower(*s1) - tolower(*s2);
|
||||
if (diff)
|
||||
return diff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
|
||||
{
|
||||
struct atom_value *va, *vb;
|
||||
|
@ -2388,10 +2494,29 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru
|
|||
} else if (s->sort_flags & REF_SORTING_VERSION) {
|
||||
cmp = versioncmp(va->s, vb->s);
|
||||
} else if (cmp_type == FIELD_STR) {
|
||||
int (*cmp_fn)(const char *, const char *);
|
||||
cmp_fn = s->sort_flags & REF_SORTING_ICASE
|
||||
? strcasecmp : strcmp;
|
||||
cmp = cmp_fn(va->s, vb->s);
|
||||
if (va->s_size < 0 && vb->s_size < 0) {
|
||||
int (*cmp_fn)(const char *, const char *);
|
||||
cmp_fn = s->sort_flags & REF_SORTING_ICASE
|
||||
? strcasecmp : strcmp;
|
||||
cmp = cmp_fn(va->s, vb->s);
|
||||
} else {
|
||||
size_t a_size = va->s_size < 0 ?
|
||||
strlen(va->s) : va->s_size;
|
||||
size_t b_size = vb->s_size < 0 ?
|
||||
strlen(vb->s) : vb->s_size;
|
||||
int (*cmp_fn)(const void *, const void *, size_t);
|
||||
cmp_fn = s->sort_flags & REF_SORTING_ICASE
|
||||
? memcasecmp : memcmp;
|
||||
|
||||
cmp = cmp_fn(va->s, vb->s, b_size > a_size ?
|
||||
a_size : b_size);
|
||||
if (!cmp) {
|
||||
if (a_size > b_size)
|
||||
cmp = 1;
|
||||
else if (a_size < b_size)
|
||||
cmp = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (va->value < vb->value)
|
||||
cmp = -1;
|
||||
|
@ -2461,9 +2586,9 @@ static void append_literal(const char *cp, const char *ep, struct ref_formatting
|
|||
}
|
||||
|
||||
int format_ref_array_item(struct ref_array_item *info,
|
||||
const struct ref_format *format,
|
||||
struct strbuf *final_buf,
|
||||
struct strbuf *error_buf)
|
||||
struct ref_format *format,
|
||||
struct strbuf *final_buf,
|
||||
struct strbuf *error_buf)
|
||||
{
|
||||
const char *cp, *sp, *ep;
|
||||
struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
|
||||
|
@ -2490,7 +2615,7 @@ int format_ref_array_item(struct ref_array_item *info,
|
|||
append_literal(cp, sp, &state);
|
||||
}
|
||||
if (format->need_color_reset_at_eol) {
|
||||
struct atom_value resetv;
|
||||
struct atom_value resetv = ATOM_VALUE_INIT;
|
||||
resetv.s = GIT_COLOR_RESET;
|
||||
if (append_atom(&resetv, &state, error_buf)) {
|
||||
pop_stack_element(&state.stack);
|
||||
|
@ -2507,7 +2632,7 @@ int format_ref_array_item(struct ref_array_item *info,
|
|||
}
|
||||
|
||||
void pretty_print_ref(const char *name, const struct object_id *oid,
|
||||
const struct ref_format *format)
|
||||
struct ref_format *format)
|
||||
{
|
||||
struct ref_array_item *ref_item;
|
||||
struct strbuf output = STRBUF_INIT;
|
||||
|
|
|
@ -38,6 +38,7 @@ struct ref_sorting {
|
|||
|
||||
struct ref_array_item {
|
||||
struct object_id objectname;
|
||||
const char *rest;
|
||||
int flag;
|
||||
unsigned int kind;
|
||||
const char *symref;
|
||||
|
@ -76,14 +77,16 @@ struct ref_format {
|
|||
* verify_ref_format() afterwards to finalize.
|
||||
*/
|
||||
const char *format;
|
||||
const char *rest;
|
||||
int quote_style;
|
||||
int use_rest;
|
||||
int use_color;
|
||||
|
||||
/* Internal state to ref-filter */
|
||||
int need_color_reset_at_eol;
|
||||
};
|
||||
|
||||
#define REF_FORMAT_INIT { NULL, 0, -1 }
|
||||
#define REF_FORMAT_INIT { .use_color = -1 }
|
||||
|
||||
/* Macros for checking --merged and --no-merged options */
|
||||
#define _OPT_MERGED_NO_MERGED(option, filter, h) \
|
||||
|
@ -116,7 +119,7 @@ void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
|
|||
void ref_sorting_set_sort_flags_all(struct ref_sorting *sorting, unsigned int mask, int on);
|
||||
/* Based on the given format and quote_style, fill the strbuf */
|
||||
int format_ref_array_item(struct ref_array_item *info,
|
||||
const struct ref_format *format,
|
||||
struct ref_format *format,
|
||||
struct strbuf *final_buf,
|
||||
struct strbuf *error_buf);
|
||||
/* Parse a single sort specifier and add it to the list */
|
||||
|
@ -137,7 +140,7 @@ void setup_ref_filter_porcelain_msg(void);
|
|||
* name must be a fully qualified refname.
|
||||
*/
|
||||
void pretty_print_ref(const char *name, const struct object_id *oid,
|
||||
const struct ref_format *format);
|
||||
struct ref_format *format);
|
||||
|
||||
/*
|
||||
* Push a single ref onto the array; this can be used to construct your own
|
||||
|
|
|
@ -340,6 +340,10 @@ test_expect_success 'git branch --format option' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'git branch with --format=%(rest) must fail' '
|
||||
test_must_fail git branch --format="%(rest)" >actual
|
||||
'
|
||||
|
||||
test_expect_success 'worktree colors correct' '
|
||||
cat >expect <<-EOF &&
|
||||
* <GREEN>(HEAD detached from fromtag)<RESET>
|
||||
|
|
|
@ -130,6 +130,8 @@ test_atom head parent:short=10 ''
|
|||
test_atom head numparent 0
|
||||
test_atom head object ''
|
||||
test_atom head type ''
|
||||
test_atom head raw "$(git cat-file commit refs/heads/main)
|
||||
"
|
||||
test_atom head '*objectname' ''
|
||||
test_atom head '*objecttype' ''
|
||||
test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
|
||||
|
@ -221,6 +223,15 @@ test_atom tag contents 'Tagging at 1151968727
|
|||
'
|
||||
test_atom tag HEAD ' '
|
||||
|
||||
test_expect_success 'basic atom: refs/tags/testtag *raw' '
|
||||
git cat-file commit refs/tags/testtag^{} >expected &&
|
||||
git for-each-ref --format="%(*raw)" refs/tags/testtag >actual &&
|
||||
sanitize_pgp <expected >expected.clean &&
|
||||
echo >>expected.clean &&
|
||||
sanitize_pgp <actual >actual.clean &&
|
||||
test_cmp expected.clean actual.clean
|
||||
'
|
||||
|
||||
test_expect_success 'Check invalid atoms names are errors' '
|
||||
test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
|
||||
'
|
||||
|
@ -686,6 +697,15 @@ test_atom refs/tags/signed-empty contents:body ''
|
|||
test_atom refs/tags/signed-empty contents:signature "$sig"
|
||||
test_atom refs/tags/signed-empty contents "$sig"
|
||||
|
||||
test_expect_success GPG 'basic atom: refs/tags/signed-empty raw' '
|
||||
git cat-file tag refs/tags/signed-empty >expected &&
|
||||
git for-each-ref --format="%(raw)" refs/tags/signed-empty >actual &&
|
||||
sanitize_pgp <expected >expected.clean &&
|
||||
echo >>expected.clean &&
|
||||
sanitize_pgp <actual >actual.clean &&
|
||||
test_cmp expected.clean actual.clean
|
||||
'
|
||||
|
||||
test_atom refs/tags/signed-short subject 'subject line'
|
||||
test_atom refs/tags/signed-short subject:sanitize 'subject-line'
|
||||
test_atom refs/tags/signed-short contents:subject 'subject line'
|
||||
|
@ -695,6 +715,15 @@ test_atom refs/tags/signed-short contents:signature "$sig"
|
|||
test_atom refs/tags/signed-short contents "subject line
|
||||
$sig"
|
||||
|
||||
test_expect_success GPG 'basic atom: refs/tags/signed-short raw' '
|
||||
git cat-file tag refs/tags/signed-short >expected &&
|
||||
git for-each-ref --format="%(raw)" refs/tags/signed-short >actual &&
|
||||
sanitize_pgp <expected >expected.clean &&
|
||||
echo >>expected.clean &&
|
||||
sanitize_pgp <actual >actual.clean &&
|
||||
test_cmp expected.clean actual.clean
|
||||
'
|
||||
|
||||
test_atom refs/tags/signed-long subject 'subject line'
|
||||
test_atom refs/tags/signed-long subject:sanitize 'subject-line'
|
||||
test_atom refs/tags/signed-long contents:subject 'subject line'
|
||||
|
@ -708,6 +737,15 @@ test_atom refs/tags/signed-long contents "subject line
|
|||
body contents
|
||||
$sig"
|
||||
|
||||
test_expect_success GPG 'basic atom: refs/tags/signed-long raw' '
|
||||
git cat-file tag refs/tags/signed-long >expected &&
|
||||
git for-each-ref --format="%(raw)" refs/tags/signed-long >actual &&
|
||||
sanitize_pgp <expected >expected.clean &&
|
||||
echo >>expected.clean &&
|
||||
sanitize_pgp <actual >actual.clean &&
|
||||
test_cmp expected.clean actual.clean
|
||||
'
|
||||
|
||||
test_expect_success 'set up refs pointing to tree and blob' '
|
||||
git update-ref refs/mytrees/first refs/heads/main^{tree} &&
|
||||
git update-ref refs/myblobs/first refs/heads/main:one
|
||||
|
@ -720,6 +758,16 @@ test_atom refs/mytrees/first contents:body ""
|
|||
test_atom refs/mytrees/first contents:signature ""
|
||||
test_atom refs/mytrees/first contents ""
|
||||
|
||||
test_expect_success 'basic atom: refs/mytrees/first raw' '
|
||||
git cat-file tree refs/mytrees/first >expected &&
|
||||
echo >>expected &&
|
||||
git for-each-ref --format="%(raw)" refs/mytrees/first >actual &&
|
||||
test_cmp expected actual &&
|
||||
git cat-file -s refs/mytrees/first >expected &&
|
||||
git for-each-ref --format="%(raw:size)" refs/mytrees/first >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_atom refs/myblobs/first subject ""
|
||||
test_atom refs/myblobs/first contents:subject ""
|
||||
test_atom refs/myblobs/first body ""
|
||||
|
@ -727,6 +775,189 @@ test_atom refs/myblobs/first contents:body ""
|
|||
test_atom refs/myblobs/first contents:signature ""
|
||||
test_atom refs/myblobs/first contents ""
|
||||
|
||||
test_expect_success 'basic atom: refs/myblobs/first raw' '
|
||||
git cat-file blob refs/myblobs/first >expected &&
|
||||
echo >>expected &&
|
||||
git for-each-ref --format="%(raw)" refs/myblobs/first >actual &&
|
||||
test_cmp expected actual &&
|
||||
git cat-file -s refs/myblobs/first >expected &&
|
||||
git for-each-ref --format="%(raw:size)" refs/myblobs/first >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'set up refs pointing to binary blob' '
|
||||
printf "a\0b\0c" >blob1 &&
|
||||
printf "a\0c\0b" >blob2 &&
|
||||
printf "\0a\0b\0c" >blob3 &&
|
||||
printf "abc" >blob4 &&
|
||||
printf "\0 \0 \0 " >blob5 &&
|
||||
printf "\0 \0a\0 " >blob6 &&
|
||||
printf " " >blob7 &&
|
||||
>blob8 &&
|
||||
obj=$(git hash-object -w blob1) &&
|
||||
git update-ref refs/myblobs/blob1 "$obj" &&
|
||||
obj=$(git hash-object -w blob2) &&
|
||||
git update-ref refs/myblobs/blob2 "$obj" &&
|
||||
obj=$(git hash-object -w blob3) &&
|
||||
git update-ref refs/myblobs/blob3 "$obj" &&
|
||||
obj=$(git hash-object -w blob4) &&
|
||||
git update-ref refs/myblobs/blob4 "$obj" &&
|
||||
obj=$(git hash-object -w blob5) &&
|
||||
git update-ref refs/myblobs/blob5 "$obj" &&
|
||||
obj=$(git hash-object -w blob6) &&
|
||||
git update-ref refs/myblobs/blob6 "$obj" &&
|
||||
obj=$(git hash-object -w blob7) &&
|
||||
git update-ref refs/myblobs/blob7 "$obj" &&
|
||||
obj=$(git hash-object -w blob8) &&
|
||||
git update-ref refs/myblobs/blob8 "$obj"
|
||||
'
|
||||
|
||||
test_expect_success 'Verify sorts with raw' '
|
||||
cat >expected <<-EOF &&
|
||||
refs/myblobs/blob8
|
||||
refs/myblobs/blob5
|
||||
refs/myblobs/blob6
|
||||
refs/myblobs/blob3
|
||||
refs/myblobs/blob7
|
||||
refs/mytrees/first
|
||||
refs/myblobs/first
|
||||
refs/myblobs/blob1
|
||||
refs/myblobs/blob2
|
||||
refs/myblobs/blob4
|
||||
refs/heads/main
|
||||
EOF
|
||||
git for-each-ref --format="%(refname)" --sort=raw \
|
||||
refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'Verify sorts with raw:size' '
|
||||
cat >expected <<-EOF &&
|
||||
refs/myblobs/blob8
|
||||
refs/myblobs/first
|
||||
refs/myblobs/blob7
|
||||
refs/heads/main
|
||||
refs/myblobs/blob4
|
||||
refs/myblobs/blob1
|
||||
refs/myblobs/blob2
|
||||
refs/myblobs/blob3
|
||||
refs/myblobs/blob5
|
||||
refs/myblobs/blob6
|
||||
refs/mytrees/first
|
||||
EOF
|
||||
git for-each-ref --format="%(refname)" --sort=raw:size \
|
||||
refs/heads/main refs/myblobs/ refs/mytrees/first >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'validate raw atom with %(if:equals)' '
|
||||
cat >expected <<-EOF &&
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
refs/myblobs/blob4
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
not equals
|
||||
EOF
|
||||
git for-each-ref --format="%(if:equals=abc)%(raw)%(then)%(refname)%(else)not equals%(end)" \
|
||||
refs/myblobs/ refs/heads/ >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'validate raw atom with %(if:notequals)' '
|
||||
cat >expected <<-EOF &&
|
||||
refs/heads/ambiguous
|
||||
refs/heads/main
|
||||
refs/heads/newtag
|
||||
refs/myblobs/blob1
|
||||
refs/myblobs/blob2
|
||||
refs/myblobs/blob3
|
||||
equals
|
||||
refs/myblobs/blob5
|
||||
refs/myblobs/blob6
|
||||
refs/myblobs/blob7
|
||||
refs/myblobs/blob8
|
||||
refs/myblobs/first
|
||||
EOF
|
||||
git for-each-ref --format="%(if:notequals=abc)%(raw)%(then)%(refname)%(else)equals%(end)" \
|
||||
refs/myblobs/ refs/heads/ >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'empty raw refs with %(if)' '
|
||||
cat >expected <<-EOF &&
|
||||
refs/myblobs/blob1 not empty
|
||||
refs/myblobs/blob2 not empty
|
||||
refs/myblobs/blob3 not empty
|
||||
refs/myblobs/blob4 not empty
|
||||
refs/myblobs/blob5 not empty
|
||||
refs/myblobs/blob6 not empty
|
||||
refs/myblobs/blob7 empty
|
||||
refs/myblobs/blob8 empty
|
||||
refs/myblobs/first not empty
|
||||
EOF
|
||||
git for-each-ref --format="%(refname) %(if)%(raw)%(then)not empty%(else)empty%(end)" \
|
||||
refs/myblobs/ >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success '%(raw) with --python must fail' '
|
||||
test_must_fail git for-each-ref --format="%(raw)" --python
|
||||
'
|
||||
|
||||
test_expect_success '%(raw) with --tcl must fail' '
|
||||
test_must_fail git for-each-ref --format="%(raw)" --tcl
|
||||
'
|
||||
|
||||
test_expect_success '%(raw) with --perl' '
|
||||
git for-each-ref --format="\$name= %(raw);
|
||||
print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual &&
|
||||
cmp blob1 actual &&
|
||||
git for-each-ref --format="\$name= %(raw);
|
||||
print \"\$name\"" refs/myblobs/blob3 --perl | perl >actual &&
|
||||
cmp blob3 actual &&
|
||||
git for-each-ref --format="\$name= %(raw);
|
||||
print \"\$name\"" refs/myblobs/blob8 --perl | perl >actual &&
|
||||
cmp blob8 actual &&
|
||||
git for-each-ref --format="\$name= %(raw);
|
||||
print \"\$name\"" refs/myblobs/first --perl | perl >actual &&
|
||||
cmp one actual &&
|
||||
git cat-file tree refs/mytrees/first > expected &&
|
||||
git for-each-ref --format="\$name= %(raw);
|
||||
print \"\$name\"" refs/mytrees/first --perl | perl >actual &&
|
||||
cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success '%(raw) with --shell must fail' '
|
||||
test_must_fail git for-each-ref --format="%(raw)" --shell
|
||||
'
|
||||
|
||||
test_expect_success '%(raw) with --shell and --sort=raw must fail' '
|
||||
test_must_fail git for-each-ref --format="%(raw)" --sort=raw --shell
|
||||
'
|
||||
|
||||
test_expect_success '%(raw:size) with --shell' '
|
||||
git for-each-ref --format="%(raw:size)" | while read line
|
||||
do
|
||||
echo "'\''$line'\''" >>expect
|
||||
done &&
|
||||
git for-each-ref --format="%(raw:size)" --shell >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'for-each-ref --format compare with cat-file --batch' '
|
||||
git rev-parse refs/mytrees/first | git cat-file --batch >expected &&
|
||||
git for-each-ref --format="%(objectname) %(objecttype) %(objectsize)
|
||||
%(raw)" refs/mytrees/first >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'set up multiple-sort tags' '
|
||||
for when in 100000 200000
|
||||
do
|
||||
|
@ -980,6 +1211,10 @@ test_expect_success 'basic atom: head contents:trailers' '
|
|||
test_cmp expect actual.clean
|
||||
'
|
||||
|
||||
test_expect_success 'basic atom: rest must fail' '
|
||||
test_must_fail git for-each-ref --format="%(rest)" refs/heads/main
|
||||
'
|
||||
|
||||
test_expect_success 'trailer parsing not fooled by --- line' '
|
||||
git commit --allow-empty -F - <<-\EOF &&
|
||||
this is the subject
|
||||
|
|
|
@ -1998,6 +1998,10 @@ test_expect_success '--format should list tags as per format given' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'git tag -l with --format="%(rest)" must fail' '
|
||||
test_must_fail git tag -l --format="%(rest)" "v1*"
|
||||
'
|
||||
|
||||
test_expect_success "set up color tests" '
|
||||
echo "<RED>v1.0<RESET>" >expect.color &&
|
||||
echo "v1.0" >expect.bare &&
|
||||
|
|
|
@ -194,6 +194,10 @@ test_expect_success GPG 'verifying tag with --format' '
|
|||
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"
|
||||
'
|
||||
|
||||
test_expect_success GPG 'verifying a forged tag with --format should fail silently' '
|
||||
test_must_fail git verify-tag --format="tagname : %(tag)" $(cat forged1.tag) >actual-forged &&
|
||||
test_must_be_empty actual-forged
|
||||
|
|
Загрузка…
Ссылка в новой задаче