diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2012-04-25 00:45:14 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-05-03 13:15:35 -0700 |
commit | 989c0e5d02b1844b44e5ea2ff61a2cbd2f054a25 (patch) | |
tree | 9d6ff905abc1f7b2979fe0f4f3b52df4ddccc0b1 /refs.c | |
parent | 93c603fcb7bfbe3d4bfb108463166b850de638f3 (diff) | |
download | git-989c0e5d02b1844b44e5ea2ff61a2cbd2f054a25.tar.gz git-989c0e5d02b1844b44e5ea2ff61a2cbd2f054a25.tar.xz |
do_for_each_reflog(): use a strbuf to hold logfile name
This simplifies the bookkeeping and allows an (artificial) restriction
on refname component length to be removed.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 60 |
1 files changed, 31 insertions, 29 deletions
@@ -2242,57 +2242,59 @@ int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_dat return for_each_recent_reflog_ent(refname, fn, 0, cb_data); } -static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data) +/* + * Call fn for each reflog in the namespace indicated by name. name + * must be empty or end with '/'. Name will be used as a scratch + * space, but its contents will be restored before return. + */ +static int do_for_each_reflog(struct strbuf *name, each_ref_fn fn, void *cb_data) { - DIR *d = opendir(git_path("logs/%s", base)); + DIR *d = opendir(git_path("logs/%s", name->buf)); int retval = 0; struct dirent *de; - int baselen; - char *log; + int oldlen = name->len; if (!d) - return *base ? errno : 0; - - baselen = strlen(base); - log = xmalloc(baselen + 257); - memcpy(log, base, baselen); - if (baselen && base[baselen-1] != '/') - log[baselen++] = '/'; + return name->len ? errno : 0; while ((de = readdir(d)) != NULL) { struct stat st; - int namelen; if (de->d_name[0] == '.') continue; - namelen = strlen(de->d_name); - if (namelen > 255) - continue; if (has_extension(de->d_name, ".lock")) continue; - memcpy(log + baselen, de->d_name, namelen+1); - if (stat(git_path("logs/%s", log), &st) < 0) - continue; - if (S_ISDIR(st.st_mode)) { - retval = do_for_each_reflog(log, fn, cb_data); + strbuf_addstr(name, de->d_name); + if (stat(git_path("logs/%s", name->buf), &st) < 0) { + ; /* silently ignore */ } else { - unsigned char sha1[20]; - if (read_ref_full(log, sha1, 0, NULL)) - retval = error("bad ref for %s", log); - else - retval = fn(log, sha1, 0, cb_data); + if (S_ISDIR(st.st_mode)) { + strbuf_addch(name, '/'); + retval = do_for_each_reflog(name, fn, cb_data); + } else { + unsigned char sha1[20]; + if (read_ref_full(name->buf, sha1, 0, NULL)) + retval = error("bad ref for %s", name->buf); + else + retval = fn(name->buf, sha1, 0, cb_data); + } + if (retval) + break; } - if (retval) - break; + strbuf_setlen(name, oldlen); } - free(log); closedir(d); return retval; } int for_each_reflog(each_ref_fn fn, void *cb_data) { - return do_for_each_reflog("", fn, cb_data); + int retval; + struct strbuf name; + strbuf_init(&name, PATH_MAX); + retval = do_for_each_reflog(&name, fn, cb_data); + strbuf_release(&name); + return retval; } int update_ref(const char *action, const char *refname, |