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 <gitster@pobox.com>
Junio C Hamano committed
Jan 19, 2009 at 22:18 UTC
101d15e09712a0183db99d228d975c62970654cf
3 files changed
+24
-2
refs.c
+16
-1
@@ -1453,7 +1453,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
1453
return 1;
1454
}
1455
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)
1457
{
1458
const char *logfile;
1459
FILE *logfp;
@@ -1464,6 +1464,16 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
1464
logfp = fopen(logfile, "r");
1465
if (!logfp)
1466
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
+
1477
while (fgets(buf, sizeof(buf), logfp)) {
1478
unsigned char osha1[20], nsha1[20];
1479
char *email_end, *message;
@@ -1497,6 +1507,11 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
1507
return ret;
1508
}
1509
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
+
1515
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
1516
{
1517
DIR *dir = opendir(git_path("logs/%s", base));
refs.h
+1
@@ -60,6 +60,7 @@ extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned
60
/* iterate over reflog entries */
61
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
62
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);
64
65
/*
66
* Calls the specified function for each reflog file until it returns nonzero,
sha1_name.c
+7
-1
@@ -775,7 +775,13 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
775
strbuf_init(&cb.buf[i], 20);
776
cb.cnt = 0;
777
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
+ }
785
if (cb.cnt < nth)
786
goto release_return;
787
i = cb.cnt % nth;