Skip to content

Commit

Permalink
Introduce for_each_recent_reflog_ent().
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Junio C Hamano committed Jan 20, 2009
1 parent 39765e5 commit 101d15e
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 2 deletions.
17 changes: 16 additions & 1 deletion refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
return 1;
}

int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, void *cb_data)
{
const char *logfile;
FILE *logfp;
Expand All @@ -1464,6 +1464,16 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
logfp = fopen(logfile, "r");
if (!logfp)
return -1;

if (ofs) {
struct stat statbuf;
if (fstat(fileno(logfp), &statbuf) ||
statbuf.st_size < ofs ||
fseek(logfp, -ofs, SEEK_END) ||
fgets(buf, sizeof(buf), logfp))
return -1;
}

while (fgets(buf, sizeof(buf), logfp)) {
unsigned char osha1[20], nsha1[20];
char *email_end, *message;
Expand Down Expand Up @@ -1497,6 +1507,11 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
return ret;
}

int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
{
return for_each_recent_reflog_ent(ref, fn, 0, cb_data);
}

static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
{
DIR *dir = opendir(git_path("logs/%s", base));
Expand Down
1 change: 1 addition & 0 deletions refs.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned
/* iterate over reflog entries */
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long, void *cb_data);

/*
* Calls the specified function for each reflog file until it returns nonzero,
Expand Down
8 changes: 7 additions & 1 deletion sha1_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,13 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
strbuf_init(&cb.buf[i], 20);
cb.cnt = 0;
retval = 0;
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
if (cb.cnt < nth) {
cb.cnt = 0;
for (i = 0; i < nth; i++)
strbuf_release(&cb.buf[i]);
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
}
if (cb.cnt < nth)
goto release_return;
i = cb.cnt % nth;
Expand Down

0 comments on commit 101d15e

Please sign in to comment.