diff options
author | Jeff King <peff@peff.net> | 2015-08-10 05:36:19 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-08-10 15:37:13 -0700 |
commit | f5b2dec1657e09a22f8b2aefa25d022988e3e467 (patch) | |
tree | d52fffa732793ecf912cf9f8119a7f8df0a04051 /refs.c | |
parent | b21a5d66055e0a446e61a12d540406f2757f6263 (diff) | |
download | git-f5b2dec1657e09a22f8b2aefa25d022988e3e467.tar.gz |
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 <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 23 |
1 files changed, 13 insertions, 10 deletions
@@ -1352,19 +1352,23 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir) { struct ref_cache *refs = dir->ref_cache; DIR *d; - const char *path; struct dirent *de; int dirnamelen = strlen(dirname); struct strbuf refname; + struct strbuf path = STRBUF_INIT; + size_t path_baselen; if (*refs->name) - path = git_path_submodule(refs->name, "%s", dirname); + strbuf_git_path_submodule(&path, refs->name, "%s", dirname); else - path = git_path("%s", dirname); + strbuf_git_path(&path, "%s", dirname); + path_baselen = path.len; - d = opendir(path); - if (!d) + d = opendir(path.buf); + if (!d) { + strbuf_release(&path); return; + } strbuf_init(&refname, dirnamelen + 257); strbuf_add(&refname, dirname, dirnamelen); @@ -1373,17 +1377,14 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir) unsigned char sha1[20]; struct stat st; int flag; - const char *refdir; if (de->d_name[0] == '.') continue; if (ends_with(de->d_name, ".lock")) continue; strbuf_addstr(&refname, de->d_name); - refdir = *refs->name - ? git_path_submodule(refs->name, "%s", refname.buf) - : git_path("%s", refname.buf); - if (stat(refdir, &st) < 0) { + strbuf_addstr(&path, de->d_name); + if (stat(path.buf, &st) < 0) { ; /* silently ignore */ } else if (S_ISDIR(st.st_mode)) { strbuf_addch(&refname, '/'); @@ -1430,8 +1431,10 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir) create_ref_entry(refname.buf, sha1, flag, 0)); } strbuf_setlen(&refname, dirnamelen); + strbuf_setlen(&path, path_baselen); } strbuf_release(&refname); + strbuf_release(&path); closedir(d); } |