Skip to content

Commit f5b2dec

Browse files
peffgitster
authored andcommitted
refs.c: remove extra git_path calls from read_loose_refs
In iterating over the loose refs in "refs/foo/", we keep a running strbuf with "refs/foo/one", "refs/foo/two", etc. But we also need to access these files in the filesystem, as ".git/refs/foo/one", etc. For this latter purpose, we make a series of independent calls to git_path(). These are safe (we only use the result to call stat()), but assigning the result of git_path is a suspicious pattern that we'd rather avoid. This patch keeps a running buffer with ".git/refs/foo/", and we can just append/reset each directory element as we loop. This matches how we handle the refnames. It should also be more efficient, as we do not keep formatting the same ".git/refs/foo" prefix (which can be arbitrarily deep). Technically we are dropping a call to strbuf_cleanup() on each generated filename, but that's OK; it wasn't doing anything, as we are putting in single-level names we read from the filesystem (so it could not possibly be cleaning up cruft like "./" in this instance). A clever reader may also note that the running refname buffer ("refs/foo/") is actually a subset of the filesystem path buffer (".git/refs/foo/"). We could get by with one buffer, indexing the length of $GIT_DIR when we want the refname. However, having tried this, the resulting code actually ends up a little more confusing, and the efficiency improvement is tiny (and almost certainly dwarfed by the system calls we are making). Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b21a5d6 commit f5b2dec

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

refs.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,19 +1352,23 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
13521352
{
13531353
struct ref_cache *refs = dir->ref_cache;
13541354
DIR *d;
1355-
const char *path;
13561355
struct dirent *de;
13571356
int dirnamelen = strlen(dirname);
13581357
struct strbuf refname;
1358+
struct strbuf path = STRBUF_INIT;
1359+
size_t path_baselen;
13591360

13601361
if (*refs->name)
1361-
path = git_path_submodule(refs->name, "%s", dirname);
1362+
strbuf_git_path_submodule(&path, refs->name, "%s", dirname);
13621363
else
1363-
path = git_path("%s", dirname);
1364+
strbuf_git_path(&path, "%s", dirname);
1365+
path_baselen = path.len;
13641366

1365-
d = opendir(path);
1366-
if (!d)
1367+
d = opendir(path.buf);
1368+
if (!d) {
1369+
strbuf_release(&path);
13671370
return;
1371+
}
13681372

13691373
strbuf_init(&refname, dirnamelen + 257);
13701374
strbuf_add(&refname, dirname, dirnamelen);
@@ -1373,17 +1377,14 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
13731377
unsigned char sha1[20];
13741378
struct stat st;
13751379
int flag;
1376-
const char *refdir;
13771380

13781381
if (de->d_name[0] == '.')
13791382
continue;
13801383
if (ends_with(de->d_name, ".lock"))
13811384
continue;
13821385
strbuf_addstr(&refname, de->d_name);
1383-
refdir = *refs->name
1384-
? git_path_submodule(refs->name, "%s", refname.buf)
1385-
: git_path("%s", refname.buf);
1386-
if (stat(refdir, &st) < 0) {
1386+
strbuf_addstr(&path, de->d_name);
1387+
if (stat(path.buf, &st) < 0) {
13871388
; /* silently ignore */
13881389
} else if (S_ISDIR(st.st_mode)) {
13891390
strbuf_addch(&refname, '/');
@@ -1430,8 +1431,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
14301431
create_ref_entry(refname.buf, sha1, flag, 0));
14311432
}
14321433
strbuf_setlen(&refname, dirnamelen);
1434+
strbuf_setlen(&path, path_baselen);
14331435
}
14341436
strbuf_release(&refname);
1437+
strbuf_release(&path);
14351438
closedir(d);
14361439
}
14371440

0 commit comments

Comments
 (0)