2318
return fn(osha1, nsha1, sb->buf + 82, timestamp, tz, message, cb_data);
2319
}
2320
2321
-int for_each_recent_reflog_ent(const char *refname, each_reflog_ent_fn fn, long ofs, void *cb_data)
2321
+static char *find_beginning_of_line(char *bob, char *scan)
2322
+{
2323
+ while (bob < scan && *(--scan) != '\n')
2324
+ ; /* keep scanning backwards */
2325
+ /*
2326
+ * Return either beginning of the buffer, or LF at the end of
2327
+ * the previous line.
2328
+ */
2329
+ return scan;
2330
+}
2331
+
2332
+int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data)
2333
{
2323
- FILE *logfp;
2334
struct strbuf sb = STRBUF_INIT;
2325
- int ret = 0;
2335
+ FILE *logfp;
2336
+ long pos;
2337
+ int ret = 0, at_tail = 1;
2338
2339
logfp = fopen(git_path("logs/%s", refname), "r");
2340
if (!logfp)
2341
return -1;
2342
2331
- if (ofs) {
2332
- struct stat statbuf;
2333
- if (fstat(fileno(logfp), &statbuf) ||
2334
- statbuf.st_size < ofs ||
2335
- fseek(logfp, -ofs, SEEK_END) ||
2336
- strbuf_getwholeline(&sb, logfp, '\n')) {
2337
- fclose(logfp);
2338
- strbuf_release(&sb);
2339
- return -1;
2343
+ /* Jump to the end */
2344
+ if (fseek(logfp, 0, SEEK_END) < 0)
2345
+ return error("cannot seek back reflog for %s: %s",
2346
+ refname, strerror(errno));
2347
+ pos = ftell(logfp);
2348
+ while (!ret && 0 < pos) {
2349
+ int cnt;
2350
+ size_t nread;
2351
+ char buf[BUFSIZ];
2352
+ char *endp, *scanp;
2353
+
2354
+ /* Fill next block from the end */
2355
+ cnt = (sizeof(buf) < pos) ? sizeof(buf) : pos;
2356
+ if (fseek(logfp, pos - cnt, SEEK_SET))
2357
+ return error("cannot seek back reflog for %s: %s",
2358
+ refname, strerror(errno));
2359
+ nread = fread(buf, cnt, 1, logfp);
2360
+ if (nread < 0)
2361
+ return error("cannot read %d bytes from reflog for %s: %s",
2362
+ cnt, refname, strerror(errno));
2363
+ pos -= cnt;
2364
+
2365
+ scanp = endp = buf + cnt;
2366
+ if (at_tail && scanp[-1] == '\n')
2367
+ /* Looking at the final LF at the end of the file */
2368
+ scanp--;
2369
+ at_tail = 0;
2370
+
2371
+ while (buf < scanp) {
2372
+ /*
2373
+ * terminating LF of the previous line, or the beginning
2374
+ * of the buffer.
2375
+ */
2376
+ char *bp;
2377
+
2378
+ bp = find_beginning_of_line(buf, scanp);
2379
+
2380
+ if (*bp != '\n') {
2381
+ strbuf_splice(&sb, 0, 0, buf, endp - buf);
2382
+ if (pos)
2383
+ break; /* need to fill another block */
2384
+ scanp = buf - 1; /* leave loop */
2385
+ } else {
2386
+ /*
2387
+ * (bp + 1) thru endp is the beginning of the
2388
+ * current line we have in sb
2389
+ */
2390
+ strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
2391
+ scanp = bp;
2392
+ endp = bp + 1;
2393
+ }
2394
+ ret = show_one_reflog_ent(&sb, fn, cb_data);
2395
+ strbuf_reset(&sb);
2396
+ if (ret)
2397
+ break;
2398
}
2341
- }
2399
2343
- while (!ret && !strbuf_getwholeline(&sb, logfp, '\n'))
2400
+ }
2401
+ if (!ret && sb.len)
2402
ret = show_one_reflog_ent(&sb, fn, cb_data);
2403
+
2404
fclose(logfp);
2405
strbuf_release(&sb);
2406
return ret;
2408
2409
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data)
2410
{
2352
- return for_each_recent_reflog_ent(refname, fn, 0, cb_data);
2353
-}
2411
+ FILE *logfp;
2412
+ struct strbuf sb = STRBUF_INIT;
2413
+ int ret = 0;
2414
+
2415
+ logfp = fopen(git_path("logs/%s", refname), "r");
2416
+ if (!logfp)
2417
+ return -1;
2418
2419
+ while (!ret && !strbuf_getwholeline(&sb, logfp, '\n'))
2420
+ ret = show_one_reflog_ent(&sb, fn, cb_data);
2421
+ fclose(logfp);
2422
+ strbuf_release(&sb);
2423
+ return ret;
2424
+}
2425
/*
2426
* Call fn for each reflog in the namespace indicated by name. name
2427
* must be empty or end with '/'. Name will be used as a scratch