Skip to content

Commit 6a82872

Browse files
committed
Merge branch 'kh/name-rev-custom-format' into seen
"git name-rev" learned to use custom format instead of the object name in an extended SHA-1 expression form. Comments? * kh/name-rev-custom-format: name-rev: learn --format=<pretty> name-rev: wrap both blocks in braces
2 parents e15d89c + 803e705 commit 6a82872

File tree

3 files changed

+202
-12
lines changed

3 files changed

+202
-12
lines changed

Documentation/git-name-rev.adoc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-name-rev - Find symbolic names for given revs
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'git name-rev' [--tags] [--refs=<pattern>]
12+
'git name-rev' [--tags] [--refs=<pattern>] [--format=<pretty>]
1313
( --all | --annotate-stdin | <commit-ish>... )
1414

1515
DESCRIPTION
@@ -21,6 +21,14 @@ format parsable by 'git rev-parse'.
2121
OPTIONS
2222
-------
2323

24+
--format=<pretty>::
25+
--no-format::
26+
Format revisions instead of outputting symbolic names. The
27+
default is `--no-format`.
28+
+
29+
Implies `--name-only`. The negation `--no-format` implies
30+
`--no-name-only` (the default for the command).
31+
2432
--tags::
2533
Do not use branch names, but only tags to name the commits
2634

builtin/name-rev.c

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "commit-graph.h"
1818
#include "wildmatch.h"
1919
#include "mem-pool.h"
20+
#include "pretty.h"
21+
#include "revision.h"
22+
#include "notes.h"
2023

2124
/*
2225
* One day. See the 'name a rev shortly after epoch' test in t6120 when
@@ -32,6 +35,16 @@ struct rev_name {
3235
int from_tag;
3336
};
3437

38+
struct pretty_format {
39+
struct pretty_print_context ctx;
40+
struct userformat_want want;
41+
};
42+
43+
struct format_cb_data {
44+
const char *format;
45+
int *name_only;
46+
};
47+
3548
define_commit_slab(commit_rev_name, struct rev_name);
3649

3750
static timestamp_t generation_cutoff = GENERATION_NUMBER_INFINITY;
@@ -452,21 +465,42 @@ static const char *get_exact_ref_match(const struct object *o)
452465
}
453466

454467
/* may return a constant string or use "buf" as scratch space */
455-
static const char *get_rev_name(const struct object *o, struct strbuf *buf)
468+
static const char *get_rev_name(const struct object *o,
469+
struct pretty_format *format_ctx,
470+
struct strbuf *buf)
456471
{
457472
struct rev_name *n;
458473
const struct commit *c;
459474

460475
if (o->type != OBJ_COMMIT)
461476
return get_exact_ref_match(o);
462477
c = (const struct commit *) o;
478+
479+
if (format_ctx) {
480+
strbuf_reset(buf);
481+
482+
if (format_ctx->want.notes) {
483+
struct strbuf notebuf = STRBUF_INIT;
484+
485+
format_display_notes(&c->object.oid, &notebuf,
486+
get_log_output_encoding(),
487+
format_ctx->ctx.fmt == CMIT_FMT_USERFORMAT);
488+
format_ctx->ctx.notes_message = strbuf_detach(&notebuf, NULL);
489+
}
490+
491+
pretty_print_commit(&format_ctx->ctx, c, buf);
492+
FREE_AND_NULL(format_ctx->ctx.notes_message);
493+
494+
return buf->buf;
495+
}
496+
463497
n = get_commit_rev_name(c);
464498
if (!n)
465499
return NULL;
466500

467-
if (!n->generation)
501+
if (!n->generation) {
468502
return n->tip_name;
469-
else {
503+
} else {
470504
strbuf_reset(buf);
471505
strbuf_addstr(buf, n->tip_name);
472506
strbuf_strip_suffix(buf, "^0");
@@ -477,6 +511,7 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
477511

478512
static void show_name(const struct object *obj,
479513
const char *caller_name,
514+
struct pretty_format *format_ctx,
480515
int always, int allow_undefined, int name_only)
481516
{
482517
const char *name;
@@ -485,7 +520,7 @@ static void show_name(const struct object *obj,
485520

486521
if (!name_only)
487522
printf("%s ", caller_name ? caller_name : oid_to_hex(oid));
488-
name = get_rev_name(obj, &buf);
523+
name = get_rev_name(obj, format_ctx, &buf);
489524
if (name)
490525
printf("%s\n", name);
491526
else if (allow_undefined)
@@ -505,7 +540,9 @@ static char const * const name_rev_usage[] = {
505540
NULL
506541
};
507542

508-
static void name_rev_line(char *p, struct name_ref_data *data)
543+
static void name_rev_line(char *p,
544+
struct name_ref_data *data,
545+
struct pretty_format *format_ctx)
509546
{
510547
struct strbuf buf = STRBUF_INIT;
511548
int counter = 0;
@@ -514,9 +551,9 @@ static void name_rev_line(char *p, struct name_ref_data *data)
514551

515552
for (p_start = p; *p; p++) {
516553
#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f'))
517-
if (!ishex(*p))
554+
if (!ishex(*p)) {
518555
counter = 0;
519-
else if (++counter == hexsz &&
556+
} else if (++counter == hexsz &&
520557
!ishex(*(p+1))) {
521558
struct object_id oid;
522559
const char *name = NULL;
@@ -530,7 +567,7 @@ static void name_rev_line(char *p, struct name_ref_data *data)
530567
struct object *o =
531568
lookup_object(the_repository, &oid);
532569
if (o)
533-
name = get_rev_name(o, &buf);
570+
name = get_rev_name(o, format_ctx, &buf);
534571
}
535572
*(p+1) = c;
536573

@@ -552,6 +589,16 @@ static void name_rev_line(char *p, struct name_ref_data *data)
552589
strbuf_release(&buf);
553590
}
554591

592+
static int format_cb(const struct option *option,
593+
const char *arg,
594+
int unset)
595+
{
596+
struct format_cb_data *data = option->value;
597+
data->format = arg;
598+
*data->name_only = !unset;
599+
return 0;
600+
}
601+
555602
int cmd_name_rev(int argc,
556603
const char **argv,
557604
const char *prefix,
@@ -565,6 +612,12 @@ int cmd_name_rev(int argc,
565612
#endif
566613
int all = 0, annotate_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
567614
struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
615+
static struct format_cb_data format_cb_data = { 0 };
616+
struct display_notes_opt format_notes_opt;
617+
struct rev_info format_rev = REV_INFO_INIT;
618+
struct pretty_format *format_ctx = NULL;
619+
struct pretty_format format_pp = { 0 };
620+
struct string_list notes = STRING_LIST_INIT_NODUP;
568621
struct option opts[] = {
569622
OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")),
570623
OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
@@ -582,6 +635,10 @@ int cmd_name_rev(int argc,
582635
PARSE_OPT_HIDDEN),
583636
#endif /* WITH_BREAKING_CHANGES */
584637
OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
638+
OPT_CALLBACK(0, "format", &format_cb_data, N_("format"),
639+
N_("pretty-print output instead"), format_cb),
640+
OPT_STRING_LIST(0, "notes", &notes, N_("notes"),
641+
N_("display notes for --format")),
585642
OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
586643
OPT_BOOL(0, "always", &always,
587644
N_("show abbreviated commit object as fallback")),
@@ -590,6 +647,8 @@ int cmd_name_rev(int argc,
590647
OPT_END(),
591648
};
592649

650+
init_display_notes(&format_notes_opt);
651+
format_cb_data.name_only = &data.name_only;
593652
mem_pool_init(&string_pool, 0);
594653
init_commit_rev_name(&rev_names);
595654
repo_config(the_repository, git_default_config, NULL);
@@ -604,6 +663,31 @@ int cmd_name_rev(int argc,
604663
}
605664
#endif
606665

666+
if (format_cb_data.format) {
667+
get_commit_format(format_cb_data.format, &format_rev);
668+
format_pp.ctx.rev = &format_rev;
669+
format_pp.ctx.fmt = format_rev.commit_format;
670+
format_pp.ctx.abbrev = format_rev.abbrev;
671+
format_pp.ctx.date_mode_explicit = format_rev.date_mode_explicit;
672+
format_pp.ctx.date_mode = format_rev.date_mode;
673+
format_pp.ctx.color = GIT_COLOR_AUTO;
674+
675+
userformat_find_requirements(format_cb_data.format,
676+
&format_pp.want);
677+
if (format_pp.want.notes) {
678+
int ignore_show_notes = 0;
679+
struct string_list_item *n;
680+
681+
for_each_string_list_item(n, &notes)
682+
enable_ref_display_notes(&format_notes_opt,
683+
&ignore_show_notes,
684+
n->string);
685+
load_display_notes(&format_notes_opt);
686+
}
687+
688+
format_ctx = &format_pp;
689+
}
690+
607691
if (all + annotate_stdin + !!argc > 1) {
608692
error("Specify either a list, or --all, not both!");
609693
usage_with_options(name_rev_usage, opts);
@@ -661,7 +745,7 @@ int cmd_name_rev(int argc,
661745

662746
while (strbuf_getline(&sb, stdin) != EOF) {
663747
strbuf_addch(&sb, '\n');
664-
name_rev_line(sb.buf, &data);
748+
name_rev_line(sb.buf, &data, format_ctx);
665749
}
666750
strbuf_release(&sb);
667751
} else if (all) {
@@ -672,18 +756,20 @@ int cmd_name_rev(int argc,
672756
struct object *obj = get_indexed_object(the_repository, i);
673757
if (!obj || obj->type != OBJ_COMMIT)
674758
continue;
675-
show_name(obj, NULL,
759+
show_name(obj, NULL, format_ctx,
676760
always, allow_undefined, data.name_only);
677761
}
678762
} else {
679763
int i;
680764
for (i = 0; i < revs.nr; i++)
681-
show_name(revs.objects[i].item, revs.objects[i].name,
765+
show_name(revs.objects[i].item, revs.objects[i].name, format_ctx,
682766
always, allow_undefined, data.name_only);
683767
}
684768

685769
string_list_clear(&data.ref_filters, 0);
686770
string_list_clear(&data.exclude_filters, 0);
771+
string_list_clear(&notes, 0);
772+
release_display_notes(&format_notes_opt);
687773
mem_pool_discard(&string_pool, 0);
688774
object_array_clear(&revs);
689775
return 0;

t/t6120-describe.sh

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,102 @@ test_expect_success 'name-rev --annotate-stdin works with commitGraph' '
658658
)
659659
'
660660

661+
test_expect_success 'name-rev --format setup' '
662+
mkdir repo-format &&
663+
git -C repo-format init &&
664+
test_commit -C repo-format first &&
665+
test_commit -C repo-format second &&
666+
test_commit -C repo-format third &&
667+
test_commit -C repo-format fourth &&
668+
test_commit -C repo-format fifth &&
669+
test_commit -C repo-format sixth &&
670+
test_commit -C repo-format seventh &&
671+
test_commit -C repo-format eighth
672+
'
673+
674+
test_expect_success 'name-rev --format --no-name-only' '
675+
cat >expect <<-\EOF &&
676+
HEAD~3 [fifth]
677+
HEAD [eighth]
678+
HEAD~5 [third]
679+
EOF
680+
git -C repo-format name-rev --format="[%s]" \
681+
--no-name-only HEAD~3 HEAD HEAD~5 >actual &&
682+
test_cmp expect actual
683+
'
684+
685+
test_expect_success 'name-rev --format --no-format is the same as regular name-rev' '
686+
git -C repo-format name-rev HEAD~2 HEAD~3 >expect &&
687+
test_file_not_empty expect &&
688+
git -C repo-format name-rev --format="huh?" \
689+
--no-format HEAD~2 HEAD~3 >actual &&
690+
test_cmp expect actual
691+
'
692+
693+
test_expect_success 'name-rev --format=%s for argument revs' '
694+
cat >expect <<-\EOF &&
695+
eighth
696+
seventh
697+
fifth
698+
EOF
699+
git -C repo-format name-rev --format=%s \
700+
HEAD HEAD~ HEAD~3 >actual &&
701+
test_cmp expect actual
702+
'
703+
704+
test_expect_success '--name-rev --format=reference --annotate-stdin from rev-list same as log' '
705+
git -C repo-format log --format=reference >expect &&
706+
test_file_not_empty expect &&
707+
git -C repo-format rev-list HEAD >list &&
708+
git -C repo-format name-rev --format=reference \
709+
--annotate-stdin <list >actual &&
710+
test_cmp expect actual
711+
'
712+
713+
test_expect_success '--name-rev --format=<pretty> --annotate-stdin with running text and tree oid' '
714+
cmit_oid=$(git -C repo-format rev-parse :/fifth) &&
715+
reference=$(git -C repo-format log -n1 --format=reference :/fifth) &&
716+
tree=$(git -C repo-format rev-parse HEAD^{tree}) &&
717+
cat >expect <<-EOF &&
718+
We thought we fixed this in ${reference}.
719+
But look at this tree: ${tree}.
720+
EOF
721+
git -C repo-format name-rev --format=reference --annotate-stdin \
722+
>actual <<-EOF &&
723+
We thought we fixed this in ${cmit_oid}.
724+
But look at this tree: ${tree}.
725+
EOF
726+
test_cmp expect actual
727+
'
728+
729+
test_expect_success 'name-rev --format=<pretty> with %N (note)' '
730+
test_when_finished "git -C repo-format notes remove" &&
731+
git -C repo-format notes add -m"Make a note" &&
732+
printf "Make a note\n\n\n" >expect &&
733+
git -C repo-format name-rev --format="tformat:%N" \
734+
HEAD HEAD~ >actual &&
735+
test_cmp expect actual
736+
'
737+
738+
test_expect_success 'name-rev --format=<pretty> --notes<ref>' '
739+
# One custom notes ref
740+
test_when_finished "git -C repo-format notes remove" &&
741+
test_when_finished "git -C repo-format notes --ref=word remove" &&
742+
git -C repo-format notes add -m"default" &&
743+
git -C repo-format notes --ref=word add -m"custom" &&
744+
printf "custom\n\n" >expect &&
745+
git -C repo-format name-rev --format="tformat:%N" \
746+
--notes=word \
747+
HEAD >actual &&
748+
test_cmp expect actual &&
749+
# Glob all
750+
printf "default\ncustom\n\n" >expect &&
751+
git -C repo-format name-rev --format="tformat:%N" \
752+
--notes=* \
753+
HEAD >actual &&
754+
test_cmp expect actual
755+
'
756+
661757
# B
662758
# o
663759
# H \

0 commit comments

Comments
 (0)