From: Michael Haggerty <mhagger@xxxxxxxxxxxx> Look up the ref_dir that will hold the new entries once at the start of processing of a directory. This eliminates the need to search down the reference tree to find the place to put each new reference. Signed-off-by: Michael Haggerty <mhagger@xxxxxxxxxxxx> --- refs.c | 43 ++++++++++++++++++++++++++----------------- 1 files changed, 26 insertions(+), 17 deletions(-) diff --git a/refs.c b/refs.c index 6a11235..6912db3 100644 --- a/refs.c +++ b/refs.c @@ -730,29 +730,36 @@ static struct ref_dir *get_packed_refs(struct ref_cache *refs) return &refs->packed; } -static void get_ref_dir(struct ref_cache *refs, const char *base, - struct ref_dir *dir) +/* + * dirname must match the name associated with dir; in particular, it + * must end with '/'. + */ +static void get_ref_dir(struct ref_cache *refs, const char *dirname) { DIR *d; - const char *path; + char *path; + int dirnamelen = strlen(dirname); + int pathlen; + struct ref_dir *dir; + + assert(dirnamelen && dirname[dirnamelen - 1] == '/'); + + dir = find_containing_dir(&refs->loose, dirname, 1); if (*refs->name) - path = git_path_submodule(refs->name, "%s", base); + path = git_path_submodule(refs->name, "%s", dirname); else - path = git_path("%s", base); - + path = git_path("%s", dirname); + pathlen = strlen(path); + assert(pathlen && path[pathlen - 1] == '/'); + path[pathlen - 1] = '\0'; d = opendir(path); if (d) { struct dirent *de; - int baselen = strlen(base); - char *refname = xmalloc(baselen + 257); - - memcpy(refname, base, baselen); - if (baselen && base[baselen-1] != '/') - refname[baselen++] = '/'; - + char *refname = xmalloc(dirnamelen + 257); + memcpy(refname, dirname, dirnamelen); while ((de = readdir(d)) != NULL) { unsigned char sha1[20]; struct stat st; @@ -767,14 +774,16 @@ static void get_ref_dir(struct ref_cache *refs, const char *base, continue; if (has_extension(de->d_name, ".lock")) continue; - memcpy(refname + baselen, de->d_name, namelen+1); + memcpy(refname + dirnamelen, de->d_name, namelen+1); refdir = *refs->name ? git_path_submodule(refs->name, "%s", refname) : git_path("%s", refname); if (stat(refdir, &st) < 0) continue; if (S_ISDIR(st.st_mode)) { - get_ref_dir(refs, refname, dir); + refname[dirnamelen + namelen] = '/'; + refname[dirnamelen + namelen + 1] = '\0'; + get_ref_dir(refs, refname); continue; } if (*refs->name) { @@ -788,7 +797,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base, hashclr(sha1); flag |= REF_ISBROKEN; } - add_ref(dir, create_ref_entry(refname, sha1, flag, 1)); + add_entry_to_dir(dir, create_ref_entry(refname, sha1, flag, 1)); } free(refname); closedir(d); @@ -798,7 +807,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base, static struct ref_dir *get_loose_refs(struct ref_cache *refs) { if (!refs->did_loose) { - get_ref_dir(refs, "refs", &refs->loose); + get_ref_dir(refs, "refs/"); refs->did_loose = 1; } return &refs->loose; -- 1.7.8 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html