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>
Michael Haggerty committed
Apr 25, 2012 at 00:45 UTC
989c0e5d02b1844b44e5ea2ff61a2cbd2f054a25
1 file changed
+31
-29
refs.c
+31
-29
@@ -2242,57 +2242,59 @@ int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_dat
2242
return for_each_recent_reflog_ent(refname, fn, 0, cb_data);
2243
}
2244
2245
-static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
2245
+/*
2246
+ * Call fn for each reflog in the namespace indicated by name. name
2247
+ * must be empty or end with '/'. Name will be used as a scratch
2248
+ * space, but its contents will be restored before return.
2249
+ */
2250
+static int do_for_each_reflog(struct strbuf *name, each_ref_fn fn, void *cb_data)
2251
{
2247
- DIR *d = opendir(git_path("logs/%s", base));
2252
+ DIR *d = opendir(git_path("logs/%s", name->buf));
2253
int retval = 0;
2254
struct dirent *de;
2250
- int baselen;
2251
- char *log;
2255
+ int oldlen = name->len;
2256
2257
if (!d)
2254
- return *base ? errno : 0;
2255
-
2256
- baselen = strlen(base);
2257
- log = xmalloc(baselen + 257);
2258
- memcpy(log, base, baselen);
2259
- if (baselen && base[baselen-1] != '/')
2260
- log[baselen++] = '/';
2258
+ return name->len ? errno : 0;
2259
2260
while ((de = readdir(d)) != NULL) {
2261
struct stat st;
2264
- int namelen;
2262
2263
if (de->d_name[0] == '.')
2264
continue;
2268
- namelen = strlen(de->d_name);
2269
- if (namelen > 255)
2270
- continue;
2265
if (has_extension(de->d_name, ".lock"))
2266
continue;
2273
- memcpy(log + baselen, de->d_name, namelen+1);
2274
- if (stat(git_path("logs/%s", log), &st) < 0)
2275
- continue;
2276
- if (S_ISDIR(st.st_mode)) {
2277
- retval = do_for_each_reflog(log, fn, cb_data);
2267
+ strbuf_addstr(name, de->d_name);
2268
+ if (stat(git_path("logs/%s", name->buf), &st) < 0) {
2269
+ ; /* silently ignore */
2270
} else {
2279
- unsigned char sha1[20];
2280
- if (read_ref_full(log, sha1, 0, NULL))
2281
- retval = error("bad ref for %s", log);
2282
- else
2283
- retval = fn(log, sha1, 0, cb_data);
2271
+ if (S_ISDIR(st.st_mode)) {
2272
+ strbuf_addch(name, '/');
2273
+ retval = do_for_each_reflog(name, fn, cb_data);
2274
+ } else {
2275
+ unsigned char sha1[20];
2276
+ if (read_ref_full(name->buf, sha1, 0, NULL))
2277
+ retval = error("bad ref for %s", name->buf);
2278
+ else
2279
+ retval = fn(name->buf, sha1, 0, cb_data);
2280
+ }
2281
+ if (retval)
2282
+ break;
2283
}
2285
- if (retval)
2286
- break;
2284
+ strbuf_setlen(name, oldlen);
2285
}
2288
- free(log);
2286
closedir(d);
2287
return retval;
2288
}
2289
2290
int for_each_reflog(each_ref_fn fn, void *cb_data)
2291
{
2295
- return do_for_each_reflog("", fn, cb_data);
2292
+ int retval;
2293
+ struct strbuf name;
2294
+ strbuf_init(&name, PATH_MAX);
2295
+ retval = do_for_each_reflog(&name, fn, cb_data);
2296
+ strbuf_release(&name);
2297
+ return retval;
2298
}
2299
2300
int update_ref(const char *action, const char *refname,