Skip to content

Commit 101d15e

Browse files
committed
Introduce for_each_recent_reflog_ent().
This can be used to scan only the last few kilobytes of a reflog, as a cheap optimization when the data you are looking for is likely to be found near the end of it. The caller is expected to fall back to the full scan if that is not the case. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 39765e5 commit 101d15e

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

refs.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1453,7 +1453,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
14531453
return 1;
14541454
}
14551455

1456-
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
1456+
int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, void *cb_data)
14571457
{
14581458
const char *logfile;
14591459
FILE *logfp;
@@ -1464,6 +1464,16 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
14641464
logfp = fopen(logfile, "r");
14651465
if (!logfp)
14661466
return -1;
1467+
1468+
if (ofs) {
1469+
struct stat statbuf;
1470+
if (fstat(fileno(logfp), &statbuf) ||
1471+
statbuf.st_size < ofs ||
1472+
fseek(logfp, -ofs, SEEK_END) ||
1473+
fgets(buf, sizeof(buf), logfp))
1474+
return -1;
1475+
}
1476+
14671477
while (fgets(buf, sizeof(buf), logfp)) {
14681478
unsigned char osha1[20], nsha1[20];
14691479
char *email_end, *message;
@@ -1497,6 +1507,11 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
14971507
return ret;
14981508
}
14991509

1510+
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
1511+
{
1512+
return for_each_recent_reflog_ent(ref, fn, 0, cb_data);
1513+
}
1514+
15001515
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
15011516
{
15021517
DIR *dir = opendir(git_path("logs/%s", base));

refs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned
6060
/* iterate over reflog entries */
6161
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
6262
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
63+
int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long, void *cb_data);
6364

6465
/*
6566
* Calls the specified function for each reflog file until it returns nonzero,

sha1_name.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,13 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
775775
strbuf_init(&cb.buf[i], 20);
776776
cb.cnt = 0;
777777
retval = 0;
778-
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
778+
for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
779+
if (cb.cnt < nth) {
780+
cb.cnt = 0;
781+
for (i = 0; i < nth; i++)
782+
strbuf_release(&cb.buf[i]);
783+
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
784+
}
779785
if (cb.cnt < nth)
780786
goto release_return;
781787
i = cb.cnt % nth;

0 commit comments

Comments
 (0)