Skip to content

Commit 8f8f547

Browse files
trastgitster
authored andcommitted
Introduce new pretty formats %g[sdD] for reflog information
Add three new --pretty=format escapes: %gD long reflog descriptor (e.g. refs/stash@{0}) %gd short reflog descriptor (e.g. stash@{0}) %gs reflog message This is achieved by passing down the reflog info, if any, inside the pretty_print_context struct. We use the newly refactored get_reflog_selector(), and give it some extra functionality to extract a shortened ref. The shortening is cached inside the commit_reflogs struct; the only allocation of it happens in read_complete_reflog(), where it is initialised to 0. Also add another helper get_reflog_message() for the message extraction. Note that the --format="%h %gD: %gs" tests may not work in real repositories, as the --pretty formatter doesn't know to leave away the ": " on the last commit in an incomplete (because git-gc removed the old part) reflog. This equivalence is nevertheless the main goal of this patch. Thanks to Jeff King for reviews, the %gd testcase and documentation. Signed-off-by: Thomas Rast <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 72b103f commit 8f8f547

File tree

7 files changed

+86
-3
lines changed

7 files changed

+86
-3
lines changed

Documentation/pretty-formats.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ The placeholders are:
123123
- '%s': subject
124124
- '%f': sanitized subject line, suitable for a filename
125125
- '%b': body
126+
- '%gD': reflog selector, e.g., `refs/stash@\{1\}`
127+
- '%gd': shortened reflog selector, e.g., `stash@\{1\}`
128+
- '%gs': reflog subject
126129
- '%Cred': switch color to red
127130
- '%Cgreen': switch color to green
128131
- '%Cblue': switch color to blue
@@ -132,6 +135,12 @@ The placeholders are:
132135
- '%n': newline
133136
- '%x00': print a byte from a hex code
134137

138+
NOTE: Some placeholders may depend on other options given to the
139+
revision traversal engine. For example, the `%g*` reflog options will
140+
insert an empty string unless we are traversing reflog entries (e.g., by
141+
`git log -g`). The `%d` placeholder will use the "short" decoration
142+
format if `--decorate` was not already provided on the command line.
143+
135144
* 'tformat:'
136145
+
137146
The 'tformat:' format works exactly like 'format:', except that it

commit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct pretty_print_context
7070
const char *after_subject;
7171
enum date_mode date_mode;
7272
int need_8bit_cte;
73+
struct reflog_walk_info *reflog_info;
7374
};
7475

7576
extern int non_ascii(int);

log-tree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ void show_log(struct rev_info *opt)
411411
ctx.date_mode = opt->date_mode;
412412
ctx.abbrev = opt->diffopt.abbrev;
413413
ctx.after_subject = extra_headers;
414+
ctx.reflog_info = opt->reflog_info;
414415
pretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);
415416

416417
if (opt->add_signoff)

pretty.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "mailmap.h"
88
#include "log-tree.h"
99
#include "color.h"
10+
#include "reflog-walk.h"
1011

1112
static char *user_format;
1213

@@ -701,6 +702,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
701702
case 'd':
702703
format_decoration(sb, commit);
703704
return 1;
705+
case 'g': /* reflog info */
706+
switch(placeholder[1]) {
707+
case 'd': /* reflog selector */
708+
case 'D':
709+
if (c->pretty_ctx->reflog_info)
710+
get_reflog_selector(sb,
711+
c->pretty_ctx->reflog_info,
712+
c->pretty_ctx->date_mode,
713+
(placeholder[1] == 'd'));
714+
return 2;
715+
case 's': /* reflog message */
716+
if (c->pretty_ctx->reflog_info)
717+
get_reflog_message(sb, c->pretty_ctx->reflog_info);
718+
return 2;
719+
}
720+
return 0; /* unknown %g placeholder */
704721
}
705722

706723
/* For the rest we have to parse the commit header. */

reflog-walk.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
struct complete_reflogs {
1010
char *ref;
11+
const char *short_ref;
1112
struct reflog_info {
1213
unsigned char osha1[20], nsha1[20];
1314
char *email;
@@ -243,15 +244,26 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
243244

244245
void get_reflog_selector(struct strbuf *sb,
245246
struct reflog_walk_info *reflog_info,
246-
enum date_mode dmode)
247+
enum date_mode dmode,
248+
int shorten)
247249
{
248250
struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
249251
struct reflog_info *info;
252+
const char *printed_ref;
250253

251254
if (!commit_reflog)
252255
return;
253256

254-
strbuf_addf(sb, "%s@{", commit_reflog->reflogs->ref);
257+
if (shorten) {
258+
if (!commit_reflog->reflogs->short_ref)
259+
commit_reflog->reflogs->short_ref
260+
= shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);
261+
printed_ref = commit_reflog->reflogs->short_ref;
262+
} else {
263+
printed_ref = commit_reflog->reflogs->ref;
264+
}
265+
266+
strbuf_addf(sb, "%s@{", printed_ref);
255267
if (commit_reflog->flag || dmode) {
256268
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
257269
strbuf_addstr(sb, show_date(info->timestamp, info->tz, dmode));
@@ -263,6 +275,23 @@ void get_reflog_selector(struct strbuf *sb,
263275
strbuf_addch(sb, '}');
264276
}
265277

278+
void get_reflog_message(struct strbuf *sb,
279+
struct reflog_walk_info *reflog_info)
280+
{
281+
struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
282+
struct reflog_info *info;
283+
size_t len;
284+
285+
if (!commit_reflog)
286+
return;
287+
288+
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
289+
len = strlen(info->message);
290+
if (len > 0)
291+
len--; /* strip away trailing newline */
292+
strbuf_add(sb, info->message, len);
293+
}
294+
266295
void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
267296
enum date_mode dmode)
268297
{
@@ -272,7 +301,7 @@ void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
272301
struct strbuf selector = STRBUF_INIT;
273302

274303
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
275-
get_reflog_selector(&selector, reflog_info, dmode);
304+
get_reflog_selector(&selector, reflog_info, dmode, 0);
276305
if (oneline) {
277306
printf("%s: %s", selector.buf, info->message);
278307
}

reflog-walk.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,20 @@
33

44
#include "cache.h"
55

6+
struct reflog_walk_info;
7+
68
extern void init_reflog_walk(struct reflog_walk_info** info);
79
extern int add_reflog_for_walk(struct reflog_walk_info *info,
810
struct commit *commit, const char *name);
911
extern void fake_reflog_parent(struct reflog_walk_info *info,
1012
struct commit *commit);
1113
extern void show_reflog_message(struct reflog_walk_info *info, int,
1214
enum date_mode);
15+
extern void get_reflog_message(struct strbuf *sb,
16+
struct reflog_walk_info *reflog_info);
17+
extern void get_reflog_selector(struct strbuf *sb,
18+
struct reflog_walk_info *reflog_info,
19+
enum date_mode dmode,
20+
int shorten);
1321

1422
#endif

t/t6006-rev-list-format.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,22 @@ test_expect_success 'empty email' '
162162
}
163163
'
164164

165+
test_expect_success '"%h %gD: %gs" is same as git-reflog' '
166+
git reflog >expect &&
167+
git log -g --format="%h %gD: %gs" >actual &&
168+
test_cmp expect actual
169+
'
170+
171+
test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
172+
git reflog --date=raw >expect &&
173+
git log -g --format="%h %gD: %gs" --date=raw >actual &&
174+
test_cmp expect actual
175+
'
176+
177+
test_expect_success '%gd shortens ref name' '
178+
echo "master@{0}" >expect.gd-short &&
179+
git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
180+
test_cmp expect.gd-short actual.gd-short
181+
'
182+
165183
test_done

0 commit comments

Comments
 (0)