* [PATCH v2 11/51] resolve_gitlink_ref(): improve docstring
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.h | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/refs.h b/refs.h
index 4c5d570..d498291 100644
--- a/refs.h
+++ b/refs.h
@@ -133,8 +133,12 @@ extern char *shorten_unambiguous_ref(const char *refname, int strict);
/** rename ref, return 0 on success **/
extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
-/** resolve ref in nested "gitlink" repository */
-extern int resolve_gitlink_ref(const char *name, const char *refname, unsigned char *sha1);
+/**
+ * Resolve refname in the nested "gitlink" repository that is located
+ * at path. If the resolution is successful, return 0 and set sha1 to
+ * the name of the object; otherwise, return a non-zero value.
+ */
+extern int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1);
/** lock a ref and then write its file */
enum action_on_err { MSG_ON_ERR, DIE_ON_ERR, QUIET_ON_ERR };
--
1.7.8
^ permalink raw reply related
* [PATCH v2 10/51] get_ref_dir(): change signature
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Change get_ref_dir() to take a (struct ref_cache *) in place of the
submodule name.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/refs.c b/refs.c
index c62c682..91ec395 100644
--- a/refs.c
+++ b/refs.c
@@ -298,14 +298,14 @@ static struct ref_array *get_packed_refs(struct ref_cache *refs)
return &refs->packed;
}
-static void get_ref_dir(const char *submodule, const char *base,
+static void get_ref_dir(struct ref_cache *refs, const char *base,
struct ref_array *array)
{
DIR *dir;
const char *path;
- if (*submodule)
- path = git_path_submodule(submodule, "%s", base);
+ if (*refs->name)
+ path = git_path_submodule(refs->name, "%s", base);
else
path = git_path("%s", base);
@@ -336,19 +336,19 @@ static void get_ref_dir(const char *submodule, const char *base,
if (has_extension(de->d_name, ".lock"))
continue;
memcpy(refname + baselen, de->d_name, namelen+1);
- refdir = submodule
- ? git_path_submodule(submodule, "%s", refname)
+ 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(submodule, refname, array);
+ get_ref_dir(refs, refname, array);
continue;
}
- if (submodule) {
+ if (*refs->name) {
hashclr(sha1);
flag = 0;
- if (resolve_gitlink_ref(submodule, refname, sha1) < 0) {
+ if (resolve_gitlink_ref(refs->name, refname, sha1) < 0) {
hashclr(sha1);
flag |= REF_ISBROKEN;
}
@@ -400,7 +400,7 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
static struct ref_array *get_loose_refs(struct ref_cache *refs)
{
if (!refs->did_loose) {
- get_ref_dir(refs->name, "refs", &refs->loose);
+ get_ref_dir(refs, "refs", &refs->loose);
sort_ref_array(&refs->loose);
refs->did_loose = 1;
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 12/51] Pass a (ref_cache *) to the resolve_gitlink_*() helper functions
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
And remove some redundant arguments from resolve_gitlink_packed_ref().
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 40 ++++++++++++++++++++--------------------
1 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/refs.c b/refs.c
index 91ec395..bf1f164 100644
--- a/refs.c
+++ b/refs.c
@@ -413,30 +413,25 @@ static struct ref_array *get_loose_refs(struct ref_cache *refs)
/*
* Called by resolve_gitlink_ref_recursive() after it failed to read
- * from "name", which is "module/.git/<refname>". Find <refname> in
- * the packed-refs file for the submodule.
+ * from the loose refs in ref_cache refs. Find <refname> in the
+ * packed-refs file for the submodule.
*/
-static int resolve_gitlink_packed_ref(char *name, int pathlen,
+static int resolve_gitlink_packed_ref(struct ref_cache *refs,
const char *refname, unsigned char *sha1)
{
- int retval = -1;
struct ref_entry *ref;
- struct ref_array *array;
+ struct ref_array *array = get_packed_refs(refs);
- /* being defensive: resolve_gitlink_ref() did this for us */
- if (pathlen < 6 || memcmp(name + pathlen - 6, "/.git/", 6))
- die("Oops");
- name[pathlen - 6] = '\0'; /* make it path to the submodule */
- array = get_packed_refs(get_ref_cache(name));
ref = search_ref_array(array, refname);
- if (ref != NULL) {
- memcpy(sha1, ref->sha1, 20);
- retval = 0;
- }
- return retval;
+ if (ref == NULL)
+ return -1;
+
+ memcpy(sha1, ref->sha1, 20);
+ return 0;
}
-static int resolve_gitlink_ref_recursive(char *name, int pathlen,
+static int resolve_gitlink_ref_recursive(struct ref_cache *refs,
+ char *name, int pathlen,
const char *refname, unsigned char *sha1,
int recursion)
{
@@ -448,7 +443,7 @@ static int resolve_gitlink_ref_recursive(char *name, int pathlen,
memcpy(name + pathlen, refname, len+1);
fd = open(name, O_RDONLY);
if (fd < 0)
- return resolve_gitlink_packed_ref(name, pathlen, refname, sha1);
+ return resolve_gitlink_packed_ref(refs, refname, sha1);
len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
@@ -469,19 +464,24 @@ static int resolve_gitlink_ref_recursive(char *name, int pathlen,
while (isspace(*p))
p++;
- return resolve_gitlink_ref_recursive(name, pathlen, p, sha1, recursion+1);
+ return resolve_gitlink_ref_recursive(refs, name, pathlen, p, sha1, recursion+1);
}
int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
{
int len = strlen(path), retval;
- char *gitdir;
+ char *submodule, *gitdir;
+ struct ref_cache *refs;
const char *tmp;
while (len && path[len-1] == '/')
len--;
if (!len)
return -1;
+ submodule = xstrndup(path, len);
+ refs = get_ref_cache(submodule);
+ free(submodule);
+
gitdir = xmalloc(len + MAXREFLEN + 8);
memcpy(gitdir, path, len);
memcpy(gitdir + len, "/.git", 6);
@@ -496,7 +496,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
}
gitdir[len] = '/';
gitdir[++len] = '\0';
- retval = resolve_gitlink_ref_recursive(gitdir, len, refname, sha1, 0);
+ retval = resolve_gitlink_ref_recursive(refs, gitdir, len, refname, sha1, 0);
free(gitdir);
return retval;
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 13/51] resolve_gitlink_ref_recursive(): change to work with struct ref_cache
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
resolve_gitlink_ref() and resolve_gitlink_ref_recursive(), together,
basically duplicated the code in git_path_submodule(). So use that
function instead.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 34 ++++++++++------------------------
1 files changed, 10 insertions(+), 24 deletions(-)
diff --git a/refs.c b/refs.c
index bf1f164..ba7a8b0 100644
--- a/refs.c
+++ b/refs.c
@@ -431,17 +431,19 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
}
static int resolve_gitlink_ref_recursive(struct ref_cache *refs,
- char *name, int pathlen,
const char *refname, unsigned char *sha1,
int recursion)
{
- int fd, len = strlen(refname);
+ int fd, len;
char buffer[128], *p;
+ char *path;
- if (recursion > MAXDEPTH || len > MAXREFLEN)
+ if (recursion > MAXDEPTH || strlen(refname) > MAXREFLEN)
return -1;
- memcpy(name + pathlen, refname, len+1);
- fd = open(name, O_RDONLY);
+ path = *refs->name
+ ? git_path_submodule(refs->name, "%s", refname)
+ : git_path("%s", refname);
+ fd = open(path, O_RDONLY);
if (fd < 0)
return resolve_gitlink_packed_ref(refs, refname, sha1);
@@ -464,15 +466,14 @@ static int resolve_gitlink_ref_recursive(struct ref_cache *refs,
while (isspace(*p))
p++;
- return resolve_gitlink_ref_recursive(refs, name, pathlen, p, sha1, recursion+1);
+ return resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1);
}
int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
{
int len = strlen(path), retval;
- char *submodule, *gitdir;
+ char *submodule;
struct ref_cache *refs;
- const char *tmp;
while (len && path[len-1] == '/')
len--;
@@ -482,22 +483,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
refs = get_ref_cache(submodule);
free(submodule);
- gitdir = xmalloc(len + MAXREFLEN + 8);
- memcpy(gitdir, path, len);
- memcpy(gitdir + len, "/.git", 6);
- len += 5;
-
- tmp = read_gitfile(gitdir);
- if (tmp) {
- free(gitdir);
- len = strlen(tmp);
- gitdir = xmalloc(len + MAXREFLEN + 3);
- memcpy(gitdir, tmp, len);
- }
- gitdir[len] = '/';
- gitdir[++len] = '\0';
- retval = resolve_gitlink_ref_recursive(refs, gitdir, len, refname, sha1, 0);
- free(gitdir);
+ retval = resolve_gitlink_ref_recursive(refs, refname, sha1, 0);
return retval;
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 15/51] create_ref_entry(): extract function from add_ref()
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Separate the creation of the ref_entry from its addition to a ref_array.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 37 ++++++++++++++++++++++---------------
1 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/refs.c b/refs.c
index 2e7bc0c..442b87c 100644
--- a/refs.c
+++ b/refs.c
@@ -53,28 +53,35 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
return line;
}
-/* Add a ref_entry to the end of the ref_array (unsorted). */
-static void add_ref(const char *refname, const unsigned char *sha1,
- int flag, int check_name, struct ref_array *refs,
- struct ref_entry **new_entry)
+static struct ref_entry *create_ref_entry(const char *refname,
+ const unsigned char *sha1, int flag,
+ int check_name)
{
int len;
- struct ref_entry *entry;
+ struct ref_entry *ref;
- /* Allocate it and add it in.. */
- len = strlen(refname) + 1;
- entry = xmalloc(sizeof(struct ref_entry) + len);
- hashcpy(entry->sha1, sha1);
- hashclr(entry->peeled);
if (check_name &&
check_refname_format(refname, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
die("Reference has invalid format: '%s'", refname);
- memcpy(entry->name, refname, len);
- entry->flag = flag;
- if (new_entry)
- *new_entry = entry;
+ len = strlen(refname) + 1;
+ ref = xmalloc(sizeof(struct ref_entry) + len);
+ hashcpy(ref->sha1, sha1);
+ hashclr(ref->peeled);
+ memcpy(ref->name, refname, len);
+ ref->flag = flag;
+ return ref;
+}
+
+/* Add a ref_entry to the end of the ref_array (unsorted). */
+static void add_ref(const char *refname, const unsigned char *sha1,
+ int flag, int check_name, struct ref_array *refs,
+ struct ref_entry **new_ref)
+{
+ struct ref_entry *ref = create_ref_entry(refname, sha1, flag, check_name);
+ if (new_ref)
+ *new_ref = ref;
ALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);
- refs->refs[refs->nr++] = entry;
+ refs->refs[refs->nr++] = ref;
}
static int ref_entry_cmp(const void *a, const void *b)
--
1.7.8
^ permalink raw reply related
* [PATCH v2 17/51] do_for_each_ref(): correctly terminate while processesing extra_refs
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
If the user-supplied function returns a nonzero value while processing
extra_refs, terminate without processing the rest of the list.
This probably has no practical importance, but makes the handling of
extra_refs a little bit more consistent with the handling of other
refs.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/refs.c b/refs.c
index 579e4c3..fb6fe84 100644
--- a/refs.c
+++ b/refs.c
@@ -711,8 +711,11 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
struct ref_array *extra = &extra_refs;
- for (i = 0; i < extra->nr; i++)
+ for (i = 0; i < extra->nr; i++) {
retval = do_one_ref(base, fn, trim, flags, cb_data, extra->refs[i]);
+ if (retval)
+ goto end_each;
+ }
while (p < packed->nr && l < loose->nr) {
struct ref_entry *entry;
--
1.7.8
^ permalink raw reply related
* [PATCH v2 18/51] do_for_each_ref_in_array(): new function
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Extract function do_for_each_ref_in_array() from do_for_each_ref().
The new function will be a useful building block for storing refs
hierarchically.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 39 +++++++++++++++++++++++----------------
1 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/refs.c b/refs.c
index fb6fe84..bc14437 100644
--- a/refs.c
+++ b/refs.c
@@ -701,21 +701,31 @@ fallback:
return -1;
}
+static int do_for_each_ref_in_array(struct ref_array *array, int offset,
+ const char *base,
+ each_ref_fn fn, int trim, int flags, void *cb_data)
+{
+ int i;
+ for (i = offset; i < array->nr; i++) {
+ int retval = do_one_ref(base, fn, trim, flags, cb_data, array->refs[i]);
+ if (retval)
+ return retval;
+ }
+ return 0;
+}
+
static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
int trim, int flags, void *cb_data)
{
- int retval = 0, i, p = 0, l = 0;
+ int retval = 0, p = 0, l = 0;
struct ref_cache *refs = get_ref_cache(submodule);
struct ref_array *packed = get_packed_refs(refs);
struct ref_array *loose = get_loose_refs(refs);
- struct ref_array *extra = &extra_refs;
-
- for (i = 0; i < extra->nr; i++) {
- retval = do_one_ref(base, fn, trim, flags, cb_data, extra->refs[i]);
- if (retval)
- goto end_each;
- }
+ retval = do_for_each_ref_in_array(&extra_refs, 0,
+ base, fn, trim, flags, cb_data);
+ if (retval)
+ goto end_each;
while (p < packed->nr && l < loose->nr) {
struct ref_entry *entry;
@@ -735,14 +745,11 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
}
if (l < loose->nr) {
- p = l;
- packed = loose;
- }
-
- for (; p < packed->nr; p++) {
- retval = do_one_ref(base, fn, trim, flags, cb_data, packed->refs[p]);
- if (retval)
- goto end_each;
+ retval = do_for_each_ref_in_array(loose, l,
+ base, fn, trim, flags, cb_data);
+ } else {
+ retval = do_for_each_ref_in_array(packed, p,
+ base, fn, trim, flags, cb_data);
}
end_each:
--
1.7.8
^ permalink raw reply related
* [PATCH v2 23/51] is_refname_available(): reimplement using do_for_each_ref_in_array()
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
This implementation will survive upcoming changes to the ref_array
data structure.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 40 ++++++++++++++++++++++++++++++----------
1 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/refs.c b/refs.c
index 12a70c1..064a70f 100644
--- a/refs.c
+++ b/refs.c
@@ -1100,6 +1100,25 @@ static int names_conflict(const char *refname1, const char *refname2)
|| (*refname1 == '/' && *refname2 == '\0');
}
+struct name_conflict_cb {
+ const char *refname;
+ const char *oldrefname;
+ const char *conflicting_refname;
+};
+
+static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,
+ int flags, void *cb_data)
+{
+ struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
+ if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))
+ return 0;
+ if (names_conflict(data->refname, existingrefname)) {
+ data->conflicting_refname = existingrefname;
+ return 1;
+ }
+ return 0;
+}
+
/*
* Return true iff a reference named refname could be created without
* conflicting with the name of an existing reference. If oldrefname
@@ -1110,16 +1129,17 @@ static int names_conflict(const char *refname1, const char *refname2)
static int is_refname_available(const char *refname, const char *oldrefname,
struct ref_array *array)
{
- int i;
- for (i = 0; i < array->nr; i++ ) {
- struct ref_entry *entry = array->refs[i];
- if (oldrefname && !strcmp(oldrefname, entry->name))
- continue;
- if (names_conflict(refname, entry->name)) {
- error("'%s' exists; cannot create '%s'",
- entry->name, refname);
- return 0;
- }
+ struct name_conflict_cb data;
+ data.refname = refname;
+ data.oldrefname = oldrefname;
+ data.conflicting_refname = NULL;
+
+ if (do_for_each_ref_in_array(array, 0, "", name_conflict_fn,
+ 0, DO_FOR_EACH_INCLUDE_BROKEN,
+ &data)) {
+ error("'%s' exists; cannot create '%s'",
+ data.conflicting_refname, refname);
+ return 0;
}
return 1;
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 16/51] add_ref(): take a (struct ref_entry *) parameter
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Take a pointer to the ref_entry to add to the array, rather than
creating the ref_entry within the function. This opens the way to
having multiple kinds of ref_entries.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 14 +++++---------
1 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/refs.c b/refs.c
index 442b87c..579e4c3 100644
--- a/refs.c
+++ b/refs.c
@@ -73,13 +73,8 @@ static struct ref_entry *create_ref_entry(const char *refname,
}
/* Add a ref_entry to the end of the ref_array (unsorted). */
-static void add_ref(const char *refname, const unsigned char *sha1,
- int flag, int check_name, struct ref_array *refs,
- struct ref_entry **new_ref)
+static void add_ref(struct ref_array *refs, struct ref_entry *ref)
{
- struct ref_entry *ref = create_ref_entry(refname, sha1, flag, check_name);
- if (new_ref)
- *new_ref = ref;
ALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);
refs->refs[refs->nr++] = ref;
}
@@ -262,7 +257,8 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
refname = parse_ref_line(refline, sha1);
if (refname) {
- add_ref(refname, sha1, flag, 1, array, &last);
+ last = create_ref_entry(refname, sha1, flag, 1);
+ add_ref(array, last);
continue;
}
if (last &&
@@ -277,7 +273,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
{
- add_ref(refname, sha1, flag, 0, &extra_refs, NULL);
+ add_ref(&extra_refs, create_ref_entry(refname, sha1, flag, 0));
}
void clear_extra_refs(void)
@@ -363,7 +359,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
hashclr(sha1);
flag |= REF_ISBROKEN;
}
- add_ref(refname, sha1, flag, 1, array, NULL);
+ add_ref(array, create_ref_entry(refname, sha1, flag, 1));
}
free(refname);
closedir(dir);
--
1.7.8
^ permalink raw reply related
* [PATCH v2 21/51] names_conflict(): new function, extracted from is_refname_available()
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
This costs an extra strlen() in the loop, but even that small price
will be clawed back in the next patch.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 43 +++++++++++++++++++++++++++++++------------
1 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/refs.c b/refs.c
index 2cdedf8..c33e94a 100644
--- a/refs.c
+++ b/refs.c
@@ -1086,6 +1086,30 @@ static int remove_empty_directories(const char *file)
}
/*
+ * Return true iff refname1 and refname2 conflict with each other.
+ * Two reference names conflict if one of them exactly matches the
+ * leading components of the other; e.g., "foo/bar" conflicts with
+ * both "foo" and with "foo/bar/baz" but not with "foo/bar" or
+ * "foo/barbados".
+ */
+static int names_conflict(const char *refname1, const char *refname2)
+{
+ int len1 = strlen(refname1);
+ int len2 = strlen(refname2);
+ int cmplen;
+ const char *lead;
+
+ if (len1 < len2) {
+ cmplen = len1;
+ lead = refname2;
+ } else {
+ cmplen = len2;
+ lead = refname1;
+ }
+ return !strncmp(refname1, refname2, cmplen) && lead[cmplen] == '/';
+}
+
+/*
* Return true iff a reference named refname could be created without
* conflicting with the name of an existing reference. If oldrefname
* is non-NULL, ignore potential conflicts with oldrefname (e.g.,
@@ -1095,20 +1119,15 @@ static int remove_empty_directories(const char *file)
static int is_refname_available(const char *refname, const char *oldrefname,
struct ref_array *array)
{
- int i, namlen = strlen(refname); /* e.g. 'foo/bar' */
+ int i;
for (i = 0; i < array->nr; i++ ) {
struct ref_entry *entry = array->refs[i];
- /* entry->name could be 'foo' or 'foo/bar/baz' */
- if (!oldrefname || strcmp(oldrefname, entry->name)) {
- int len = strlen(entry->name);
- int cmplen = (namlen < len) ? namlen : len;
- const char *lead = (namlen < len) ? entry->name : refname;
- if (!strncmp(refname, entry->name, cmplen) &&
- lead[cmplen] == '/') {
- error("'%s' exists; cannot create '%s'",
- entry->name, refname);
- return 0;
- }
+ if (oldrefname && !strcmp(oldrefname, entry->name))
+ continue;
+ if (names_conflict(refname, entry->name)) {
+ error("'%s' exists; cannot create '%s'",
+ entry->name, refname);
+ return 0;
}
}
return 1;
--
1.7.8
^ permalink raw reply related
* [PATCH v2 25/51] free_ref_entry(): new function
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Add a function free_ref_entry(). This function will become nontrivial
when ref_entry (soon) becomes polymorphic.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 3cc3e4f..99667fc 100644
--- a/refs.c
+++ b/refs.c
@@ -136,6 +136,11 @@ static struct ref_entry *create_ref_entry(const char *refname,
return ref;
}
+static void free_ref_entry(struct ref_entry *entry)
+{
+ free(entry);
+}
+
/* Add a ref_entry to the end of the ref_array (unsorted). */
static void add_ref(struct ref_array *refs, struct ref_entry *ref)
{
@@ -147,7 +152,7 @@ static void clear_ref_array(struct ref_array *array)
{
int i;
for (i = 0; i < array->nr; i++)
- free(array->refs[i]);
+ free_ref_entry(array->refs[i]);
free(array->refs);
array->nr = array->alloc = 0;
array->refs = NULL;
@@ -218,7 +223,7 @@ static void sort_ref_array(struct ref_array *array)
i = 0;
for (j = 1; j < array->nr; j++) {
if (is_dup_ref(array->refs[i], array->refs[j])) {
- free(array->refs[j]);
+ free_ref_entry(array->refs[j]);
continue;
}
array->refs[++i] = array->refs[j];
--
1.7.8
^ permalink raw reply related
* [PATCH v2 26/51] check_refname_component(): return 0 for zero-length components
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Return 0 (instead of -1) for zero-length components. Move the
interpretation of zero-length components as illegal to
check_refname_format().
This will make it easier to extend check_refname_format() to also
check whether directory names are valid.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 99667fc..e29f76c 100644
--- a/refs.c
+++ b/refs.c
@@ -51,7 +51,7 @@ static int check_refname_component(const char *refname, int flags)
last = ch;
}
if (cp == refname)
- return -1; /* Component has zero length. */
+ return 0; /* Component has zero length. */
if (refname[0] == '.') {
if (!(flags & REFNAME_DOT_COMPONENT))
return -1; /* Component starts with '.'. */
@@ -74,7 +74,7 @@ int check_refname_format(const char *refname, int flags)
while (1) {
/* We are at the start of a path component. */
component_len = check_refname_component(refname, flags);
- if (component_len < 0) {
+ if (component_len <= 0) {
if ((flags & REFNAME_REFSPEC_PATTERN) &&
refname[0] == '*' &&
(refname[1] == '\0' || refname[1] == '/')) {
--
1.7.8
^ permalink raw reply related
* [PATCH v2 27/51] struct ref_entry: nest the value part in a union
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
This change is obviously silly by itself, but it is a step towards
adding a second member to the union.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 32 +++++++++++++++++++-------------
1 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/refs.c b/refs.c
index e29f76c..fe6d657 100644
--- a/refs.c
+++ b/refs.c
@@ -101,6 +101,11 @@ int check_refname_format(const char *refname, int flags)
struct ref_entry;
+struct ref_value {
+ unsigned char sha1[20];
+ unsigned char peeled[20];
+};
+
struct ref_array {
int nr, alloc;
struct ref_entry **refs;
@@ -111,8 +116,9 @@ struct ref_array {
struct ref_entry {
unsigned char flag; /* ISSYMREF? ISPACKED? */
- unsigned char sha1[20];
- unsigned char peeled[20];
+ union {
+ struct ref_value value;
+ } u;
/* The full name of the reference (e.g., "refs/heads/master"): */
char name[FLEX_ARRAY];
};
@@ -129,8 +135,8 @@ static struct ref_entry *create_ref_entry(const char *refname,
die("Reference has invalid format: '%s'", refname);
len = strlen(refname) + 1;
ref = xmalloc(sizeof(struct ref_entry) + len);
- hashcpy(ref->sha1, sha1);
- hashclr(ref->peeled);
+ hashcpy(ref->u.value.sha1, sha1);
+ hashclr(ref->u.value.peeled);
memcpy(ref->name, refname, len);
ref->flag = flag;
return ref;
@@ -199,7 +205,7 @@ static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2
{
if (!strcmp(ref1->name, ref2->name)) {
/* Duplicate name; make sure that the SHA1s match: */
- if (hashcmp(ref1->sha1, ref2->sha1))
+ if (hashcmp(ref1->u.value.sha1, ref2->u.value.sha1))
die("Duplicated ref, and SHA1s don't match: %s",
ref1->name);
warning("Duplicated ref: %s", ref1->name);
@@ -244,13 +250,13 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
if (entry->flag & REF_ISBROKEN)
return 0; /* ignore broken refs e.g. dangling symref */
- if (!has_sha1_file(entry->sha1)) {
+ if (!has_sha1_file(entry->u.value.sha1)) {
error("%s does not point to a valid object!", entry->name);
return 0;
}
}
current_ref = entry;
- return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
+ return fn(entry->name + trim, entry->u.value.sha1, entry->flag, cb_data);
}
static int do_for_each_ref_in_array(struct ref_array *array, int offset,
@@ -499,7 +505,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
strlen(refline) == 42 &&
refline[41] == '\n' &&
!get_sha1_hex(refline + 1, sha1))
- hashcpy(last->peeled, sha1);
+ hashcpy(last->u.value.peeled, sha1);
}
sort_ref_array(array);
}
@@ -628,7 +634,7 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
if (ref == NULL)
return -1;
- memcpy(sha1, ref->sha1, 20);
+ memcpy(sha1, ref->u.value.sha1, 20);
return 0;
}
@@ -698,7 +704,7 @@ static int get_packed_ref(const char *refname, unsigned char *sha1)
struct ref_array *packed = get_packed_refs(get_ref_cache(NULL));
struct ref_entry *entry = search_ref_array(packed, refname);
if (entry) {
- hashcpy(sha1, entry->sha1);
+ hashcpy(sha1, entry->u.value.sha1);
return 0;
}
return -1;
@@ -855,10 +861,10 @@ int peel_ref(const char *refname, unsigned char *sha1)
if (current_ref && (current_ref->name == refname
|| !strcmp(current_ref->name, refname))) {
if (current_ref->flag & REF_KNOWS_PEELED) {
- hashcpy(sha1, current_ref->peeled);
+ hashcpy(sha1, current_ref->u.value.peeled);
return 0;
}
- hashcpy(base, current_ref->sha1);
+ hashcpy(base, current_ref->u.value.sha1);
goto fallback;
}
@@ -870,7 +876,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
struct ref_entry *r = search_ref_array(array, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
- hashcpy(sha1, r->peeled);
+ hashcpy(sha1, r->u.value.peeled);
return 0;
}
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 24/51] refs.c: reorder definitions more logically
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Reorder definitions in file: first check_refname_format() and helper
functions, then the functions for managing the ref_entry and ref_array
data structures, then ref_cache, then the more "business-logicky"
stuff. No code is changed.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 655 ++++++++++++++++++++++++++++++++--------------------------------
1 files changed, 329 insertions(+), 326 deletions(-)
diff --git a/refs.c b/refs.c
index 064a70f..3cc3e4f 100644
--- a/refs.c
+++ b/refs.c
@@ -4,6 +4,108 @@
#include "tag.h"
#include "dir.h"
+/*
+ * Make sure "ref" is something reasonable to have under ".git/refs/";
+ * We do not like it if:
+ *
+ * - any path component of it begins with ".", or
+ * - it has double dots "..", or
+ * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
+ * - it ends with a "/".
+ * - it ends with ".lock"
+ * - it contains a "\" (backslash)
+ */
+
+/* Return true iff ch is not allowed in reference names. */
+static inline int bad_ref_char(int ch)
+{
+ if (((unsigned) ch) <= ' ' || ch == 0x7f ||
+ ch == '~' || ch == '^' || ch == ':' || ch == '\\')
+ return 1;
+ /* 2.13 Pattern Matching Notation */
+ if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
+ return 1;
+ return 0;
+}
+
+/*
+ * Try to read one refname component from the front of refname. Return
+ * the length of the component found, or -1 if the component is not
+ * legal.
+ */
+static int check_refname_component(const char *refname, int flags)
+{
+ const char *cp;
+ char last = '\0';
+
+ for (cp = refname; ; cp++) {
+ char ch = *cp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (bad_ref_char(ch))
+ return -1; /* Illegal character in refname. */
+ if (last == '.' && ch == '.')
+ return -1; /* Refname contains "..". */
+ if (last == '@' && ch == '{')
+ return -1; /* Refname contains "@{". */
+ last = ch;
+ }
+ if (cp == refname)
+ return -1; /* Component has zero length. */
+ if (refname[0] == '.') {
+ if (!(flags & REFNAME_DOT_COMPONENT))
+ return -1; /* Component starts with '.'. */
+ /*
+ * Even if leading dots are allowed, don't allow "."
+ * as a component (".." is prevented by a rule above).
+ */
+ if (refname[1] == '\0')
+ return -1; /* Component equals ".". */
+ }
+ if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
+ return -1; /* Refname ends with ".lock". */
+ return cp - refname;
+}
+
+int check_refname_format(const char *refname, int flags)
+{
+ int component_len, component_count = 0;
+
+ while (1) {
+ /* We are at the start of a path component. */
+ component_len = check_refname_component(refname, flags);
+ if (component_len < 0) {
+ if ((flags & REFNAME_REFSPEC_PATTERN) &&
+ refname[0] == '*' &&
+ (refname[1] == '\0' || refname[1] == '/')) {
+ /* Accept one wildcard as a full refname component. */
+ flags &= ~REFNAME_REFSPEC_PATTERN;
+ component_len = 1;
+ } else {
+ return -1;
+ }
+ }
+ component_count++;
+ if (refname[component_len] == '\0')
+ break;
+ /* Skip to next component. */
+ refname += component_len + 1;
+ }
+
+ if (refname[component_len - 1] == '.')
+ return -1; /* Refname ends with '.'. */
+ if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
+ return -1; /* Refname has only one component. */
+ return 0;
+}
+
+struct ref_entry;
+
+struct ref_array {
+ int nr, alloc;
+ struct ref_entry **refs;
+};
+
/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
#define REF_KNOWS_PEELED 0x10
@@ -15,44 +117,6 @@ struct ref_entry {
char name[FLEX_ARRAY];
};
-struct ref_array {
- int nr, alloc;
- struct ref_entry **refs;
-};
-
-/*
- * Parse one line from a packed-refs file. Write the SHA1 to sha1.
- * Return a pointer to the refname within the line (null-terminated),
- * or NULL if there was a problem.
- */
-static const char *parse_ref_line(char *line, unsigned char *sha1)
-{
- /*
- * 42: the answer to everything.
- *
- * In this case, it happens to be the answer to
- * 40 (length of sha1 hex representation)
- * +1 (space in between hex and name)
- * +1 (newline at the end of the line)
- */
- int len = strlen(line) - 42;
-
- if (len <= 0)
- return NULL;
- if (get_sha1_hex(line, sha1) < 0)
- return NULL;
- if (!isspace(line[40]))
- return NULL;
- line += 41;
- if (isspace(*line))
- return NULL;
- if (line[len] != '\n')
- return NULL;
- line[len] = 0;
-
- return line;
-}
-
static struct ref_entry *create_ref_entry(const char *refname,
const unsigned char *sha1, int flag,
int check_name)
@@ -79,6 +143,16 @@ static void add_ref(struct ref_array *refs, struct ref_entry *ref)
refs->refs[refs->nr++] = ref;
}
+static void clear_ref_array(struct ref_array *array)
+{
+ int i;
+ for (i = 0; i < array->nr; i++)
+ free(array->refs[i]);
+ free(array->refs);
+ array->nr = array->alloc = 0;
+ array->refs = NULL;
+}
+
static int ref_entry_cmp(const void *a, const void *b)
{
struct ref_entry *one = *(struct ref_entry **)a;
@@ -86,6 +160,31 @@ static int ref_entry_cmp(const void *a, const void *b)
return strcmp(one->name, two->name);
}
+static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
+{
+ struct ref_entry *e, **r;
+ int len;
+
+ if (refname == NULL)
+ return NULL;
+
+ if (!array->nr)
+ return NULL;
+
+ len = strlen(refname) + 1;
+ e = xmalloc(sizeof(struct ref_entry) + len);
+ memcpy(e->name, refname, len);
+
+ r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
+
+ free(e);
+
+ if (r == NULL)
+ return NULL;
+
+ return *r;
+}
+
/*
* Emit a warning and return true iff ref1 and ref2 have the same name
* and the same sha1. Die if they have the same name but different
@@ -127,29 +226,137 @@ static void sort_ref_array(struct ref_array *array)
array->nr = i + 1;
}
-static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
+#define DO_FOR_EACH_INCLUDE_BROKEN 01
+
+static struct ref_entry *current_ref;
+
+static int do_one_ref(const char *base, each_ref_fn fn, int trim,
+ int flags, void *cb_data, struct ref_entry *entry)
{
- struct ref_entry *e, **r;
- int len;
+ if (prefixcmp(entry->name, base))
+ return 0;
- if (refname == NULL)
- return NULL;
+ if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
+ if (entry->flag & REF_ISBROKEN)
+ return 0; /* ignore broken refs e.g. dangling symref */
+ if (!has_sha1_file(entry->sha1)) {
+ error("%s does not point to a valid object!", entry->name);
+ return 0;
+ }
+ }
+ current_ref = entry;
+ return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
+}
- if (!array->nr)
- return NULL;
+static int do_for_each_ref_in_array(struct ref_array *array, int offset,
+ const char *base,
+ each_ref_fn fn, int trim, int flags, void *cb_data)
+{
+ int i;
+ for (i = offset; i < array->nr; i++) {
+ int retval = do_one_ref(base, fn, trim, flags, cb_data, array->refs[i]);
+ if (retval)
+ return retval;
+ }
+ return 0;
+}
- len = strlen(refname) + 1;
- e = xmalloc(sizeof(struct ref_entry) + len);
- memcpy(e->name, refname, len);
+static int do_for_each_ref_in_arrays(struct ref_array *array1,
+ struct ref_array *array2,
+ const char *base, each_ref_fn fn, int trim,
+ int flags, void *cb_data)
+{
+ int retval;
+ int i1 = 0, i2 = 0;
- r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
+ while (1) {
+ struct ref_entry *e1, *e2;
+ int cmp;
+ if (i1 == array1->nr) {
+ return do_for_each_ref_in_array(array2, i2,
+ base, fn, trim, flags, cb_data);
+ }
+ if (i2 == array2->nr) {
+ return do_for_each_ref_in_array(array1, i1,
+ base, fn, trim, flags, cb_data);
+ }
+ e1 = array1->refs[i1];
+ e2 = array2->refs[i2];
+ cmp = strcmp(e1->name, e2->name);
+ if (cmp == 0) {
+ /* Two refs with the same name; ignore the one from array1. */
+ i1++;
+ continue;
+ }
+ if (cmp < 0) {
+ retval = do_one_ref(base, fn, trim, flags, cb_data, e1);
+ i1++;
+ } else {
+ retval = do_one_ref(base, fn, trim, flags, cb_data, e2);
+ i2++;
+ }
+ if (retval)
+ return retval;
+ }
+}
- free(e);
+/*
+ * Return true iff refname1 and refname2 conflict with each other.
+ * Two reference names conflict if one of them exactly matches the
+ * leading components of the other; e.g., "foo/bar" conflicts with
+ * both "foo" and with "foo/bar/baz" but not with "foo/bar" or
+ * "foo/barbados".
+ */
+static int names_conflict(const char *refname1, const char *refname2)
+{
+ for (; *refname1 && *refname1 == *refname2; refname1++, refname2++)
+ ;
+ return (*refname1 == '\0' && *refname2 == '/')
+ || (*refname1 == '/' && *refname2 == '\0');
+}
- if (r == NULL)
- return NULL;
+struct name_conflict_cb {
+ const char *refname;
+ const char *oldrefname;
+ const char *conflicting_refname;
+};
- return *r;
+static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,
+ int flags, void *cb_data)
+{
+ struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
+ if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))
+ return 0;
+ if (names_conflict(data->refname, existingrefname)) {
+ data->conflicting_refname = existingrefname;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Return true iff a reference named refname could be created without
+ * conflicting with the name of an existing reference. If oldrefname
+ * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
+ * because oldrefname is scheduled for deletion in the same
+ * operation).
+ */
+static int is_refname_available(const char *refname, const char *oldrefname,
+ struct ref_array *array)
+{
+ struct name_conflict_cb data;
+ data.refname = refname;
+ data.oldrefname = oldrefname;
+ data.conflicting_refname = NULL;
+
+ if (do_for_each_ref_in_array(array, 0, "", name_conflict_fn,
+ 0, DO_FOR_EACH_INCLUDE_BROKEN,
+ &data)) {
+ error("'%s' exists; cannot create '%s'",
+ data.conflicting_refname, refname);
+ return 0;
+ }
+ return 1;
}
/*
@@ -166,20 +373,8 @@ static struct ref_cache {
char name[FLEX_ARRAY];
} *ref_cache;
-static struct ref_entry *current_ref;
-
static struct ref_array extra_refs;
-static void clear_ref_array(struct ref_array *array)
-{
- int i;
- for (i = 0; i < array->nr; i++)
- free(array->refs[i]);
- free(array->refs);
- array->nr = array->alloc = 0;
- array->refs = NULL;
-}
-
static void clear_packed_ref_cache(struct ref_cache *refs)
{
if (refs->did_packed)
@@ -236,6 +431,39 @@ void invalidate_ref_cache(const char *submodule)
clear_loose_ref_cache(refs);
}
+/*
+ * Parse one line from a packed-refs file. Write the SHA1 to sha1.
+ * Return a pointer to the refname within the line (null-terminated),
+ * or NULL if there was a problem.
+ */
+static const char *parse_ref_line(char *line, unsigned char *sha1)
+{
+ /*
+ * 42: the answer to everything.
+ *
+ * In this case, it happens to be the answer to
+ * 40 (length of sha1 hex representation)
+ * +1 (space in between hex and name)
+ * +1 (newline at the end of the line)
+ */
+ int len = strlen(line) - 42;
+
+ if (len <= 0)
+ return NULL;
+ if (get_sha1_hex(line, sha1) < 0)
+ return NULL;
+ if (!isspace(line[40]))
+ return NULL;
+ line += 41;
+ if (isspace(*line))
+ return NULL;
+ if (line[len] != '\n')
+ return NULL;
+ line[len] = 0;
+
+ return line;
+}
+
static void read_packed_refs(FILE *f, struct ref_array *array)
{
struct ref_entry *last = NULL;
@@ -357,47 +585,13 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
}
} else if (read_ref_full(refname, sha1, 1, &flag)) {
hashclr(sha1);
- flag |= REF_ISBROKEN;
- }
- add_ref(array, create_ref_entry(refname, sha1, flag, 1));
- }
- free(refname);
- closedir(dir);
- }
-}
-
-struct warn_if_dangling_data {
- FILE *fp;
- const char *refname;
- const char *msg_fmt;
-};
-
-static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,
- int flags, void *cb_data)
-{
- struct warn_if_dangling_data *d = cb_data;
- const char *resolves_to;
- unsigned char junk[20];
-
- if (!(flags & REF_ISSYMREF))
- return 0;
-
- resolves_to = resolve_ref(refname, junk, 0, NULL);
- if (!resolves_to || strcmp(resolves_to, d->refname))
- return 0;
-
- fprintf(d->fp, d->msg_fmt, refname);
- return 0;
-}
-
-void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
-{
- struct warn_if_dangling_data data;
-
- data.fp = fp;
- data.refname = refname;
- data.msg_fmt = msg_fmt;
- for_each_rawref(warn_if_dangling_symref, &data);
+ flag |= REF_ISBROKEN;
+ }
+ add_ref(array, create_ref_entry(refname, sha1, flag, 1));
+ }
+ free(refname);
+ closedir(dir);
+ }
}
static struct ref_array *get_loose_refs(struct ref_cache *refs)
@@ -632,23 +826,10 @@ int read_ref(const char *refname, unsigned char *sha1)
return read_ref_full(refname, sha1, 1, NULL);
}
-#define DO_FOR_EACH_INCLUDE_BROKEN 01
-static int do_one_ref(const char *base, each_ref_fn fn, int trim,
- int flags, void *cb_data, struct ref_entry *entry)
+int ref_exists(const char *refname)
{
- if (prefixcmp(entry->name, base))
- return 0;
-
- if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
- if (entry->flag & REF_ISBROKEN)
- return 0; /* ignore broken refs e.g. dangling symref */
- if (!has_sha1_file(entry->sha1)) {
- error("%s does not point to a valid object!", entry->name);
- return 0;
- }
- }
- current_ref = entry;
- return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
+ unsigned char sha1[20];
+ return !!resolve_ref(refname, sha1, 1, NULL);
}
static int filter_refs(const char *refname, const unsigned char *sha1, int flags,
@@ -701,56 +882,38 @@ fallback:
return -1;
}
-static int do_for_each_ref_in_array(struct ref_array *array, int offset,
- const char *base,
- each_ref_fn fn, int trim, int flags, void *cb_data)
+struct warn_if_dangling_data {
+ FILE *fp;
+ const char *refname;
+ const char *msg_fmt;
+};
+
+static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,
+ int flags, void *cb_data)
{
- int i;
- for (i = offset; i < array->nr; i++) {
- int retval = do_one_ref(base, fn, trim, flags, cb_data, array->refs[i]);
- if (retval)
- return retval;
- }
+ struct warn_if_dangling_data *d = cb_data;
+ const char *resolves_to;
+ unsigned char junk[20];
+
+ if (!(flags & REF_ISSYMREF))
+ return 0;
+
+ resolves_to = resolve_ref(refname, junk, 0, NULL);
+ if (!resolves_to || strcmp(resolves_to, d->refname))
+ return 0;
+
+ fprintf(d->fp, d->msg_fmt, refname);
return 0;
}
-static int do_for_each_ref_in_arrays(struct ref_array *array1,
- struct ref_array *array2,
- const char *base, each_ref_fn fn, int trim,
- int flags, void *cb_data)
+void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
{
- int retval;
- int i1 = 0, i2 = 0;
+ struct warn_if_dangling_data data;
- while (1) {
- struct ref_entry *e1, *e2;
- int cmp;
- if (i1 == array1->nr) {
- return do_for_each_ref_in_array(array2, i2,
- base, fn, trim, flags, cb_data);
- }
- if (i2 == array2->nr) {
- return do_for_each_ref_in_array(array1, i1,
- base, fn, trim, flags, cb_data);
- }
- e1 = array1->refs[i1];
- e2 = array2->refs[i2];
- cmp = strcmp(e1->name, e2->name);
- if (cmp == 0) {
- /* Two refs with the same name; ignore the one from array1. */
- i1++;
- continue;
- }
- if (cmp < 0) {
- retval = do_one_ref(base, fn, trim, flags, cb_data, e1);
- i1++;
- } else {
- retval = do_one_ref(base, fn, trim, flags, cb_data, e2);
- i2++;
- }
- if (retval)
- return retval;
- }
+ data.fp = fp;
+ data.refname = refname;
+ data.msg_fmt = msg_fmt;
+ for_each_rawref(warn_if_dangling_symref, &data);
}
static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
@@ -921,101 +1084,6 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
-/*
- * Make sure "ref" is something reasonable to have under ".git/refs/";
- * We do not like it if:
- *
- * - any path component of it begins with ".", or
- * - it has double dots "..", or
- * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
- * - it ends with a "/".
- * - it ends with ".lock"
- * - it contains a "\" (backslash)
- */
-
-/* Return true iff ch is not allowed in reference names. */
-static inline int bad_ref_char(int ch)
-{
- if (((unsigned) ch) <= ' ' || ch == 0x7f ||
- ch == '~' || ch == '^' || ch == ':' || ch == '\\')
- return 1;
- /* 2.13 Pattern Matching Notation */
- if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
- return 1;
- return 0;
-}
-
-/*
- * Try to read one refname component from the front of refname. Return
- * the length of the component found, or -1 if the component is not
- * legal.
- */
-static int check_refname_component(const char *refname, int flags)
-{
- const char *cp;
- char last = '\0';
-
- for (cp = refname; ; cp++) {
- char ch = *cp;
- if (ch == '\0' || ch == '/')
- break;
- if (bad_ref_char(ch))
- return -1; /* Illegal character in refname. */
- if (last == '.' && ch == '.')
- return -1; /* Refname contains "..". */
- if (last == '@' && ch == '{')
- return -1; /* Refname contains "@{". */
- last = ch;
- }
- if (cp == refname)
- return -1; /* Component has zero length. */
- if (refname[0] == '.') {
- if (!(flags & REFNAME_DOT_COMPONENT))
- return -1; /* Component starts with '.'. */
- /*
- * Even if leading dots are allowed, don't allow "."
- * as a component (".." is prevented by a rule above).
- */
- if (refname[1] == '\0')
- return -1; /* Component equals ".". */
- }
- if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
- return -1; /* Refname ends with ".lock". */
- return cp - refname;
-}
-
-int check_refname_format(const char *refname, int flags)
-{
- int component_len, component_count = 0;
-
- while (1) {
- /* We are at the start of a path component. */
- component_len = check_refname_component(refname, flags);
- if (component_len < 0) {
- if ((flags & REFNAME_REFSPEC_PATTERN) &&
- refname[0] == '*' &&
- (refname[1] == '\0' || refname[1] == '/')) {
- /* Accept one wildcard as a full refname component. */
- flags &= ~REFNAME_REFSPEC_PATTERN;
- component_len = 1;
- } else {
- return -1;
- }
- }
- component_count++;
- if (refname[component_len] == '\0')
- break;
- /* Skip to next component. */
- refname += component_len + 1;
- }
-
- if (refname[component_len - 1] == '.')
- return -1; /* Refname ends with '.'. */
- if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
- return -1; /* Refname has only one component. */
- return 0;
-}
-
const char *prettify_refname(const char *name)
{
return name + (
@@ -1086,65 +1154,6 @@ static int remove_empty_directories(const char *file)
}
/*
- * Return true iff refname1 and refname2 conflict with each other.
- * Two reference names conflict if one of them exactly matches the
- * leading components of the other; e.g., "foo/bar" conflicts with
- * both "foo" and with "foo/bar/baz" but not with "foo/bar" or
- * "foo/barbados".
- */
-static int names_conflict(const char *refname1, const char *refname2)
-{
- for (; *refname1 && *refname1 == *refname2; refname1++, refname2++)
- ;
- return (*refname1 == '\0' && *refname2 == '/')
- || (*refname1 == '/' && *refname2 == '\0');
-}
-
-struct name_conflict_cb {
- const char *refname;
- const char *oldrefname;
- const char *conflicting_refname;
-};
-
-static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,
- int flags, void *cb_data)
-{
- struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
- if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))
- return 0;
- if (names_conflict(data->refname, existingrefname)) {
- data->conflicting_refname = existingrefname;
- return 1;
- }
- return 0;
-}
-
-/*
- * Return true iff a reference named refname could be created without
- * conflicting with the name of an existing reference. If oldrefname
- * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
- * because oldrefname is scheduled for deletion in the same
- * operation).
- */
-static int is_refname_available(const char *refname, const char *oldrefname,
- struct ref_array *array)
-{
- struct name_conflict_cb data;
- data.refname = refname;
- data.oldrefname = oldrefname;
- data.conflicting_refname = NULL;
-
- if (do_for_each_ref_in_array(array, 0, "", name_conflict_fn,
- 0, DO_FOR_EACH_INCLUDE_BROKEN,
- &data)) {
- error("'%s' exists; cannot create '%s'",
- data.conflicting_refname, refname);
- return 0;
- }
- return 1;
-}
-
-/*
* *string and *len will only be substituted, and *string returned (for
* later free()ing) if the string passed in is a magic short-hand form
* to name a branch.
@@ -2057,12 +2066,6 @@ int update_ref(const char *action, const char *refname,
return 0;
}
-int ref_exists(const char *refname)
-{
- unsigned char sha1[20];
- return !!resolve_ref(refname, sha1, 1, NULL);
-}
-
struct ref *find_ref_by_name(const struct ref *list, const char *name)
{
for ( ; list; list = list->next)
--
1.7.8
^ permalink raw reply related
* [PATCH v2 28/51] refs.c: rename ref_array -> ref_dir
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
This purely textual change is in preparation for storing references
hierarchically, when the old ref_array structure will represent one
"directory" of references. Rename functions that deal with this
structure analogously, and also rename the structure's "refs" member
to "entries".
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 166 ++++++++++++++++++++++++++++++++--------------------------------
1 files changed, 83 insertions(+), 83 deletions(-)
diff --git a/refs.c b/refs.c
index fe6d657..b74ef80 100644
--- a/refs.c
+++ b/refs.c
@@ -106,9 +106,9 @@ struct ref_value {
unsigned char peeled[20];
};
-struct ref_array {
+struct ref_dir {
int nr, alloc;
- struct ref_entry **refs;
+ struct ref_entry **entries;
};
/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
@@ -147,21 +147,21 @@ static void free_ref_entry(struct ref_entry *entry)
free(entry);
}
-/* Add a ref_entry to the end of the ref_array (unsorted). */
-static void add_ref(struct ref_array *refs, struct ref_entry *ref)
+/* Add a ref_entry to the end of the ref_dir (unsorted). */
+static void add_ref(struct ref_dir *refs, struct ref_entry *ref)
{
- ALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);
- refs->refs[refs->nr++] = ref;
+ ALLOC_GROW(refs->entries, refs->nr + 1, refs->alloc);
+ refs->entries[refs->nr++] = ref;
}
-static void clear_ref_array(struct ref_array *array)
+static void clear_ref_dir(struct ref_dir *dir)
{
int i;
- for (i = 0; i < array->nr; i++)
- free_ref_entry(array->refs[i]);
- free(array->refs);
- array->nr = array->alloc = 0;
- array->refs = NULL;
+ for (i = 0; i < dir->nr; i++)
+ free_ref_entry(dir->entries[i]);
+ free(dir->entries);
+ dir->nr = dir->alloc = 0;
+ dir->entries = NULL;
}
static int ref_entry_cmp(const void *a, const void *b)
@@ -171,7 +171,7 @@ static int ref_entry_cmp(const void *a, const void *b)
return strcmp(one->name, two->name);
}
-static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
+static struct ref_entry *search_ref_dir(struct ref_dir *dir, const char *refname)
{
struct ref_entry *e, **r;
int len;
@@ -179,14 +179,14 @@ static struct ref_entry *search_ref_array(struct ref_array *array, const char *r
if (refname == NULL)
return NULL;
- if (!array->nr)
+ if (!dir->nr)
return NULL;
len = strlen(refname) + 1;
e = xmalloc(sizeof(struct ref_entry) + len);
memcpy(e->name, refname, len);
- r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
+ r = bsearch(&e, dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
free(e);
@@ -215,26 +215,26 @@ static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2
}
}
-static void sort_ref_array(struct ref_array *array)
+static void sort_ref_dir(struct ref_dir *dir)
{
int i, j;
/* Nothing to sort unless there are at least two entries */
- if (array->nr < 2)
+ if (dir->nr < 2)
return;
- qsort(array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
+ qsort(dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
/* Remove any duplicates from the ref_array */
i = 0;
- for (j = 1; j < array->nr; j++) {
- if (is_dup_ref(array->refs[i], array->refs[j])) {
- free_ref_entry(array->refs[j]);
+ for (j = 1; j < dir->nr; j++) {
+ if (is_dup_ref(dir->entries[i], dir->entries[j])) {
+ free_ref_entry(dir->entries[j]);
continue;
}
- array->refs[++i] = array->refs[j];
+ dir->entries[++i] = dir->entries[j];
}
- array->nr = i + 1;
+ dir->nr = i + 1;
}
#define DO_FOR_EACH_INCLUDE_BROKEN 01
@@ -259,23 +259,23 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
return fn(entry->name + trim, entry->u.value.sha1, entry->flag, cb_data);
}
-static int do_for_each_ref_in_array(struct ref_array *array, int offset,
- const char *base,
- each_ref_fn fn, int trim, int flags, void *cb_data)
+static int do_for_each_ref_in_dir(struct ref_dir *dir, int offset,
+ const char *base,
+ each_ref_fn fn, int trim, int flags, void *cb_data)
{
int i;
- for (i = offset; i < array->nr; i++) {
- int retval = do_one_ref(base, fn, trim, flags, cb_data, array->refs[i]);
+ for (i = offset; i < dir->nr; i++) {
+ int retval = do_one_ref(base, fn, trim, flags, cb_data, dir->entries[i]);
if (retval)
return retval;
}
return 0;
}
-static int do_for_each_ref_in_arrays(struct ref_array *array1,
- struct ref_array *array2,
- const char *base, each_ref_fn fn, int trim,
- int flags, void *cb_data)
+static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
+ struct ref_dir *dir2,
+ const char *base, each_ref_fn fn, int trim,
+ int flags, void *cb_data)
{
int retval;
int i1 = 0, i2 = 0;
@@ -283,19 +283,19 @@ static int do_for_each_ref_in_arrays(struct ref_array *array1,
while (1) {
struct ref_entry *e1, *e2;
int cmp;
- if (i1 == array1->nr) {
- return do_for_each_ref_in_array(array2, i2,
- base, fn, trim, flags, cb_data);
+ if (i1 == dir1->nr) {
+ return do_for_each_ref_in_dir(dir2, i2,
+ base, fn, trim, flags, cb_data);
}
- if (i2 == array2->nr) {
- return do_for_each_ref_in_array(array1, i1,
- base, fn, trim, flags, cb_data);
+ if (i2 == dir2->nr) {
+ return do_for_each_ref_in_dir(dir1, i1,
+ base, fn, trim, flags, cb_data);
}
- e1 = array1->refs[i1];
- e2 = array2->refs[i2];
+ e1 = dir1->entries[i1];
+ e2 = dir2->entries[i2];
cmp = strcmp(e1->name, e2->name);
if (cmp == 0) {
- /* Two refs with the same name; ignore the one from array1. */
+ /* Two refs with the same name; ignore the one from dir1. */
i1++;
continue;
}
@@ -353,16 +353,16 @@ static int name_conflict_fn(const char *existingrefname, const unsigned char *sh
* operation).
*/
static int is_refname_available(const char *refname, const char *oldrefname,
- struct ref_array *array)
+ struct ref_dir *dir)
{
struct name_conflict_cb data;
data.refname = refname;
data.oldrefname = oldrefname;
data.conflicting_refname = NULL;
- if (do_for_each_ref_in_array(array, 0, "", name_conflict_fn,
- 0, DO_FOR_EACH_INCLUDE_BROKEN,
- &data)) {
+ if (do_for_each_ref_in_dir(dir, 0, "", name_conflict_fn,
+ 0, DO_FOR_EACH_INCLUDE_BROKEN,
+ &data)) {
error("'%s' exists; cannot create '%s'",
data.conflicting_refname, refname);
return 0;
@@ -378,25 +378,25 @@ static struct ref_cache {
struct ref_cache *next;
char did_loose;
char did_packed;
- struct ref_array loose;
- struct ref_array packed;
+ struct ref_dir loose;
+ struct ref_dir packed;
/* The submodule name, or "" for the main repo. */
char name[FLEX_ARRAY];
} *ref_cache;
-static struct ref_array extra_refs;
+static struct ref_dir extra_refs;
static void clear_packed_ref_cache(struct ref_cache *refs)
{
if (refs->did_packed)
- clear_ref_array(&refs->packed);
+ clear_ref_dir(&refs->packed);
refs->did_packed = 0;
}
static void clear_loose_ref_cache(struct ref_cache *refs)
{
if (refs->did_loose)
- clear_ref_array(&refs->loose);
+ clear_ref_dir(&refs->loose);
refs->did_loose = 0;
}
@@ -475,7 +475,7 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
return line;
}
-static void read_packed_refs(FILE *f, struct ref_array *array)
+static void read_packed_refs(FILE *f, struct ref_dir *dir)
{
struct ref_entry *last = NULL;
char refline[PATH_MAX];
@@ -497,7 +497,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
refname = parse_ref_line(refline, sha1);
if (refname) {
last = create_ref_entry(refname, sha1, flag, 1);
- add_ref(array, last);
+ add_ref(dir, last);
continue;
}
if (last &&
@@ -507,7 +507,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
!get_sha1_hex(refline + 1, sha1))
hashcpy(last->u.value.peeled, sha1);
}
- sort_ref_array(array);
+ sort_ref_dir(dir);
}
void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
@@ -517,10 +517,10 @@ void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
void clear_extra_refs(void)
{
- clear_ref_array(&extra_refs);
+ clear_ref_dir(&extra_refs);
}
-static struct ref_array *get_packed_refs(struct ref_cache *refs)
+static struct ref_dir *get_packed_refs(struct ref_cache *refs)
{
if (!refs->did_packed) {
const char *packed_refs_file;
@@ -541,9 +541,9 @@ static struct ref_array *get_packed_refs(struct ref_cache *refs)
}
static void get_ref_dir(struct ref_cache *refs, const char *base,
- struct ref_array *array)
+ struct ref_dir *dir)
{
- DIR *dir;
+ DIR *d;
const char *path;
if (*refs->name)
@@ -552,9 +552,9 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
path = git_path("%s", base);
- dir = opendir(path);
+ d = opendir(path);
- if (dir) {
+ if (d) {
struct dirent *de;
int baselen = strlen(base);
char *refname = xmalloc(baselen + 257);
@@ -563,7 +563,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
if (baselen && base[baselen-1] != '/')
refname[baselen++] = '/';
- while ((de = readdir(dir)) != NULL) {
+ while ((de = readdir(d)) != NULL) {
unsigned char sha1[20];
struct stat st;
int flag;
@@ -584,7 +584,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
if (stat(refdir, &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
- get_ref_dir(refs, refname, array);
+ get_ref_dir(refs, refname, dir);
continue;
}
if (*refs->name) {
@@ -598,18 +598,18 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
hashclr(sha1);
flag |= REF_ISBROKEN;
}
- add_ref(array, create_ref_entry(refname, sha1, flag, 1));
+ add_ref(dir, create_ref_entry(refname, sha1, flag, 1));
}
free(refname);
- closedir(dir);
+ closedir(d);
}
}
-static struct ref_array *get_loose_refs(struct ref_cache *refs)
+static struct ref_dir *get_loose_refs(struct ref_cache *refs)
{
if (!refs->did_loose) {
get_ref_dir(refs, "refs", &refs->loose);
- sort_ref_array(&refs->loose);
+ sort_ref_dir(&refs->loose);
refs->did_loose = 1;
}
return &refs->loose;
@@ -628,9 +628,9 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
const char *refname, unsigned char *sha1)
{
struct ref_entry *ref;
- struct ref_array *array = get_packed_refs(refs);
+ struct ref_dir *dir = get_packed_refs(refs);
- ref = search_ref_array(array, refname);
+ ref = search_ref_dir(dir, refname);
if (ref == NULL)
return -1;
@@ -701,8 +701,8 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
*/
static int get_packed_ref(const char *refname, unsigned char *sha1)
{
- struct ref_array *packed = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *entry = search_ref_array(packed, refname);
+ struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
+ struct ref_entry *entry = search_ref_dir(packed, refname);
if (entry) {
hashcpy(sha1, entry->u.value.sha1);
return 0;
@@ -872,8 +872,8 @@ int peel_ref(const char *refname, unsigned char *sha1)
return -1;
if ((flag & REF_ISPACKED)) {
- struct ref_array *array = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *r = search_ref_array(array, refname);
+ struct ref_dir *dir = get_packed_refs(get_ref_cache(NULL));
+ struct ref_entry *r = search_ref_dir(dir, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
hashcpy(sha1, r->u.value.peeled);
@@ -933,12 +933,12 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
int retval = 0;
struct ref_cache *refs = get_ref_cache(submodule);
- retval = do_for_each_ref_in_array(&extra_refs, 0,
- base, fn, trim, flags, cb_data);
+ retval = do_for_each_ref_in_dir(&extra_refs, 0,
+ base, fn, trim, flags, cb_data);
if (!retval)
- retval = do_for_each_ref_in_arrays(get_packed_refs(refs),
- get_loose_refs(refs),
- base, fn, trim, flags, cb_data);
+ retval = do_for_each_ref_in_dirs(get_packed_refs(refs),
+ get_loose_refs(refs),
+ base, fn, trim, flags, cb_data);
current_ref = NULL;
return retval;
@@ -1377,10 +1377,10 @@ static struct lock_file packlock;
static int repack_without_ref(const char *refname)
{
struct repack_without_ref_sb data;
- struct ref_array *packed;
+ struct ref_dir *packed;
packed = get_packed_refs(get_ref_cache(NULL));
- if (search_ref_array(packed, refname) == NULL)
+ if (search_ref_dir(packed, refname) == NULL)
return 0;
data.refname = refname;
data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
@@ -1388,7 +1388,7 @@ static int repack_without_ref(const char *refname)
unable_to_lock_error(git_path("packed-refs"), errno);
return error("cannot delete '%s' from packed refs", refname);
}
- do_for_each_ref_in_array(packed, 0, "", repack_without_ref_fn, 0, 0, &data);
+ do_for_each_ref_in_dir(packed, 0, "", repack_without_ref_fn, 0, 0, &data);
return commit_lock_file(&packlock);
}
@@ -1999,10 +1999,10 @@ int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_dat
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
{
- DIR *dir = opendir(git_path("logs/%s", base));
+ DIR *d = opendir(git_path("logs/%s", base));
int retval = 0;
- if (dir) {
+ if (d) {
struct dirent *de;
int baselen = strlen(base);
char *log = xmalloc(baselen + 257);
@@ -2011,7 +2011,7 @@ static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
if (baselen && base[baselen-1] != '/')
log[baselen++] = '/';
- while ((de = readdir(dir)) != NULL) {
+ while ((de = readdir(d)) != NULL) {
struct stat st;
int namelen;
@@ -2038,7 +2038,7 @@ static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
break;
}
free(log);
- closedir(dir);
+ closedir(d);
}
else if (*base)
return errno;
--
1.7.8
^ permalink raw reply related
* [PATCH v2 31/51] refs: sort ref_dirs lazily
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Sort ref_dirs lazily, when the ordering is needed: for searching via
search_ref_dir(), and when iterating over the references via
do_for_each_ref_in_dir() and do_for_each_ref_in_dirs().
This change means that we never have to sort directories recursively,
so change sort_ref_dirs() to not recurse.
NOTE: the dirs can now be sorted as a side-effect of other function
calls. Therefore, it would be problematic to do something from a
each_ref_fn callback that could provoke the sorting of the directory
that is currently being iterated over. This is not so likely, because
a directory is always sorted just before being iterated over and thus
can be searched through during the iteration without causing a
re-sort. But if a callback function would add a reference to a parent
directory of the reference in the iteration, then try to resolve a
reference under that directory, inconsistency could result.
Add a comment in refs.h warning against modifications during
iteration.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 35 +++++++++++++++--------------------
refs.h | 7 +++++--
2 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/refs.c b/refs.c
index ce141ea..f01da78 100644
--- a/refs.c
+++ b/refs.c
@@ -256,9 +256,14 @@ static struct ref_entry *search_ref_dir(struct ref_dir *dir, const char *refname
/*
* We need dir to be sorted so that binary search works.
- * Calling sort_ref_dir() here is not quite as terribly
- * inefficient as it looks, because directories that are
- * already sorted are not re-sorted.
+ * Calling sort_ref_dir() here is not as terribly inefficient
+ * as it looks. (1) If the directory is already sorted, it is
+ * not re-sorted. (2) When adding a reference,
+ * search_ref_dir() is only called to find the containing
+ * subdirectories; there is no search of the directory to
+ * which the reference will be stored. Thus adding a bunch of
+ * references one after the other to a single subdirectory
+ * doesn't require *any* intermediate sorting.
*/
sort_ref_dir(dir);
@@ -364,26 +369,16 @@ static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2
}
/*
- * Sort the entries in dir and its subdirectories (if they are not
- * already sorted).
+ * Sort the entries in dir (if they are not already sorted). Sort
+ * only dir itself, not its subdirectories.
*/
static void sort_ref_dir(struct ref_dir *dir)
{
int i, j;
struct ref_entry *last = NULL;
- if (dir->sorted == dir->nr) {
- /*
- * This directory is already sorted and de-duped, but
- * we still have to sort subdirectories.
- */
- for (i = 0; i < dir->nr; i++) {
- struct ref_entry *entry = dir->entries[i];
- if (entry->flag & REF_DIR)
- sort_ref_dir(&entry->u.subdir);
- }
- return;
- }
+ if (dir->sorted == dir->nr)
+ return; /* This directory is already sorted and de-duped */
qsort(dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
@@ -393,7 +388,6 @@ static void sort_ref_dir(struct ref_dir *dir)
if (last && is_dup_ref(last, entry)) {
free_ref_entry(entry);
} else if (entry->flag & REF_DIR) {
- sort_ref_dir(&entry->u.subdir);
dir->entries[i++] = entry;
last = NULL;
} else {
@@ -430,6 +424,7 @@ static int do_for_each_ref_in_dir(struct ref_dir *dir, int offset,
each_ref_fn fn, int trim, int flags, void *cb_data)
{
int i;
+ sort_ref_dir(dir);
for (i = offset; i < dir->nr; i++) {
struct ref_entry *entry = dir->entries[i];
int retval;
@@ -453,6 +448,8 @@ static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
int retval;
int i1 = 0, i2 = 0;
+ sort_ref_dir(dir1);
+ sort_ref_dir(dir2);
while (1) {
struct ref_entry *e1, *e2, *entry;
int cmp;
@@ -701,7 +698,6 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
!get_sha1_hex(refline + 1, sha1))
hashcpy(last->u.value.peeled, sha1);
}
- sort_ref_dir(dir);
}
void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
@@ -803,7 +799,6 @@ static struct ref_dir *get_loose_refs(struct ref_cache *refs)
{
if (!refs->did_loose) {
get_ref_dir(refs, "refs", &refs->loose);
- sort_ref_dir(&refs->loose);
refs->did_loose = 1;
}
return &refs->loose;
diff --git a/refs.h b/refs.h
index d498291..5bb4678 100644
--- a/refs.h
+++ b/refs.h
@@ -15,8 +15,11 @@ struct ref_lock {
#define REF_ISBROKEN 0x04
/*
- * Calls the specified function for each ref file until it returns nonzero,
- * and returns the value
+ * Calls the specified function for each ref file until it returns
+ * nonzero, and returns the value. Please note that it is not safe to
+ * modify references while an iteration is in progress, unless the
+ * same callback function invocation that modifies the reference also
+ * returns a nonzero value to immediately stop the iteration.
*/
typedef int each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
extern int head_ref(each_ref_fn, void *);
--
1.7.8
^ permalink raw reply related
* [PATCH v2 34/51] refs: wrap top-level ref_dirs in ref_entries
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Wrap the top-level ref_dirs in REF_DIR style ref_entries so that we
have the flag and name available when dealing with them. This
affects:
* cache_ref::loose
* cache_ref::packed
* extra_refs
The next several commits will expand the use of ref_entry as opposed
to ref_dir, culminating in the ability of a ref_entry representing a
directory of loose references to load itself only when used.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 52 +++++++++++++++++++++++++++++-----------------------
1 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/refs.c b/refs.c
index 6912db3..b4019e6 100644
--- a/refs.c
+++ b/refs.c
@@ -567,28 +567,28 @@ static int is_refname_available(const char *refname, const char *oldrefname,
*/
static struct ref_cache {
struct ref_cache *next;
- char did_loose;
- char did_packed;
- struct ref_dir loose;
- struct ref_dir packed;
+ struct ref_entry *loose;
+ struct ref_entry *packed;
/* The submodule name, or "" for the main repo. */
char name[FLEX_ARRAY];
} *ref_cache;
-static struct ref_dir extra_refs;
+static struct ref_entry *extra_refs;
static void clear_packed_ref_cache(struct ref_cache *refs)
{
- if (refs->did_packed)
- clear_ref_dir(&refs->packed);
- refs->did_packed = 0;
+ if (refs->packed) {
+ free_ref_entry(refs->packed);
+ refs->packed = NULL;
+ }
}
static void clear_loose_ref_cache(struct ref_cache *refs)
{
- if (refs->did_loose)
- clear_ref_dir(&refs->loose);
- refs->did_loose = 0;
+ if (refs->loose) {
+ free_ref_entry(refs->loose);
+ refs->loose = NULL;
+ }
}
static struct ref_cache *create_ref_cache(const char *submodule)
@@ -702,32 +702,37 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
{
- add_ref(&extra_refs, create_ref_entry(refname, sha1, flag, 0));
+ if (!extra_refs)
+ extra_refs = create_dir_entry("");
+ add_ref(&extra_refs->u.subdir, create_ref_entry(refname, sha1, flag, 0));
}
void clear_extra_refs(void)
{
- clear_ref_dir(&extra_refs);
+ if (extra_refs) {
+ free_ref_entry(extra_refs);
+ extra_refs = NULL;
+ }
}
static struct ref_dir *get_packed_refs(struct ref_cache *refs)
{
- if (!refs->did_packed) {
+ if (!refs->packed) {
const char *packed_refs_file;
FILE *f;
+ refs->packed = create_dir_entry("");
if (*refs->name)
packed_refs_file = git_path_submodule(refs->name, "packed-refs");
else
packed_refs_file = git_path("packed-refs");
f = fopen(packed_refs_file, "r");
if (f) {
- read_packed_refs(f, &refs->packed);
+ read_packed_refs(f, &refs->packed->u.subdir);
fclose(f);
}
- refs->did_packed = 1;
}
- return &refs->packed;
+ return &refs->packed->u.subdir;
}
/*
@@ -744,7 +749,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *dirname)
assert(dirnamelen && dirname[dirnamelen - 1] == '/');
- dir = find_containing_dir(&refs->loose, dirname, 1);
+ dir = find_containing_dir(&refs->loose->u.subdir, dirname, 1);
if (*refs->name)
path = git_path_submodule(refs->name, "%s", dirname);
@@ -806,11 +811,11 @@ static void get_ref_dir(struct ref_cache *refs, const char *dirname)
static struct ref_dir *get_loose_refs(struct ref_cache *refs)
{
- if (!refs->did_loose) {
+ if (!refs->loose) {
+ refs->loose = create_dir_entry("");
get_ref_dir(refs, "refs/");
- refs->did_loose = 1;
}
- return &refs->loose;
+ return &refs->loose->u.subdir;
}
/* We allow "recursive" symbolic refs. Only within reason, though */
@@ -1130,12 +1135,13 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
{
int retval = 0;
struct ref_cache *refs = get_ref_cache(submodule);
- struct ref_dir *extra_dir = &extra_refs;
+ struct ref_dir *extra_dir = extra_refs ? &extra_refs->u.subdir : NULL;
struct ref_dir *packed_dir = get_packed_refs(refs);
struct ref_dir *loose_dir = get_loose_refs(refs);
if (base && *base) {
- extra_dir = find_containing_dir(extra_dir, base, 0);
+ if (extra_dir)
+ extra_dir = find_containing_dir(extra_dir, base, 0);
packed_dir = find_containing_dir(packed_dir, base, 0);
loose_dir = find_containing_dir(loose_dir, base, 0);
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 29/51] refs: store references hierarchically
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Store references hierarchically in a tree that matches the
pseudo-directory structure of the reference names. Add a new kind of
ref_entry (with flag REF_DIR) to represent a whole subdirectory of
references.
Please note that this change causes some extra sorting to be required,
and therefore a performance regression. The old performance will be
regained in the next couple of commits by (1) keeping track of when a
directory is already sorted and not re-sorting it; (2) only sorting a
directory when the correct order needed; and (3) not sorting
directories recursively.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 220 insertions(+), 45 deletions(-)
diff --git a/refs.c b/refs.c
index b74ef80..ccd2806 100644
--- a/refs.c
+++ b/refs.c
@@ -111,15 +111,54 @@ struct ref_dir {
struct ref_entry **entries;
};
-/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
-#define REF_KNOWS_PEELED 0x10
+/* ISSYMREF=0x01, ISPACKED=0x02, and ISBROKEN=0x04 are public interfaces */
+#define REF_KNOWS_PEELED 0x08
+#define REF_DIR 0x10
+/*
+ * A ref_entry represents either a reference or a "subdirectory" of
+ * references. Each directory in the reference namespace is
+ * represented by a ref_entry with (flags & REF_DIR) set and
+ * containing a subdir member that holds the entries in that
+ * directory. References are represented by a ref_entry with (flags &
+ * REF_DIR) unset and a value member that describes the reference's
+ * value. The flag member is at the ref_entry level, but it is also
+ * needed to interpret the contents of the value field (in other
+ * words, a ref_value object is not very much use without the
+ * enclosing ref_entry).
+ *
+ * Reference names cannot end with slash and directories' names are
+ * always stored with a trailing slash (except for the top-level
+ * directory, which is always denoted by ""). This has two nice
+ * consequences: (1) when the entries in each subdir are sorted
+ * lexicographically by name (as they usually are), the references in
+ * a whole tree can be generated in lexicographic order by traversing
+ * the tree in left-to-right, depth-first order; (2) the names of
+ * references and subdirectories cannot conflict, and therefore the
+ * presence of an empty subdirectory does not block the creation of a
+ * similarly-named reference. (The fact that reference names with the
+ * same leading components can conflict *with each other* is a
+ * separate issue that is regulated by is_refname_available().)
+ *
+ * Please note that the name field contains the fully-qualified
+ * reference (or subdirectory) name. Space could be saved by only
+ * storing the relative names. But that would require the full names
+ * to be generated on the fly when iterating in do_for_each_ref(), and
+ * would break callback functions, who have always been able to assume
+ * that the name strings that they are passed will not be freed during
+ * the iteration.
+ */
struct ref_entry {
unsigned char flag; /* ISSYMREF? ISPACKED? */
union {
- struct ref_value value;
+ struct ref_value value; /* if not (flags&REF_DIR) */
+ struct ref_dir subdir; /* if (flags&REF_DIR) */
} u;
- /* The full name of the reference (e.g., "refs/heads/master"): */
+ /*
+ * The full name of the reference (e.g., "refs/heads/master")
+ * or the full name of the directory with a trailing slash
+ * (e.g., "refs/heads/"):
+ */
char name[FLEX_ARRAY];
};
@@ -142,18 +181,29 @@ static struct ref_entry *create_ref_entry(const char *refname,
return ref;
}
+static void clear_ref_dir(struct ref_dir *dir);
+
static void free_ref_entry(struct ref_entry *entry)
{
+ if (entry->flag & REF_DIR)
+ clear_ref_dir(&entry->u.subdir);
free(entry);
}
-/* Add a ref_entry to the end of the ref_dir (unsorted). */
-static void add_ref(struct ref_dir *refs, struct ref_entry *ref)
+/*
+ * Add a ref_entry to the end of dir (unsorted). Entry is always
+ * stored directly in dir; no recursion into subdirectories is
+ * done.
+ */
+static void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
{
- ALLOC_GROW(refs->entries, refs->nr + 1, refs->alloc);
- refs->entries[refs->nr++] = ref;
+ ALLOC_GROW(dir->entries, dir->nr + 1, dir->alloc);
+ dir->entries[dir->nr++] = entry;
}
+/*
+ * Clear and free all entries in dir, recursively.
+ */
static void clear_ref_dir(struct ref_dir *dir)
{
int i;
@@ -164,6 +214,21 @@ static void clear_ref_dir(struct ref_dir *dir)
dir->entries = NULL;
}
+/*
+ * Create a struct ref_entry object for the specified dirname.
+ * dirname is the name of the directory with a trailing slash (e.g.,
+ * "refs/heads/") or "" for the top-level directory.
+ */
+static struct ref_entry *create_dir_entry(const char *dirname)
+{
+ struct ref_entry *direntry;
+ int len = strlen(dirname);
+ direntry = xcalloc(1, sizeof(struct ref_entry) + len + 1);
+ memcpy(direntry->name, dirname, len + 1);
+ direntry->flag = REF_DIR;
+ return direntry;
+}
+
static int ref_entry_cmp(const void *a, const void *b)
{
struct ref_entry *one = *(struct ref_entry **)a;
@@ -171,16 +236,26 @@ static int ref_entry_cmp(const void *a, const void *b)
return strcmp(one->name, two->name);
}
+static void sort_ref_dir(struct ref_dir *dir);
+
+/*
+ * Return the entry with the given refname from the ref_dir
+ * (non-recursively). Return NULL if no such entry is found.
+ */
static struct ref_entry *search_ref_dir(struct ref_dir *dir, const char *refname)
{
struct ref_entry *e, **r;
int len;
- if (refname == NULL)
+ if (refname == NULL || !dir->nr)
return NULL;
- if (!dir->nr)
- return NULL;
+ /*
+ * We need dir to be sorted so that binary search works.
+ * FIXME: Sorting the array each time is terribly inefficient,
+ * and has to be changed.
+ */
+ sort_ref_dir(dir);
len = strlen(refname) + 1;
e = xmalloc(sizeof(struct ref_entry) + len);
@@ -197,44 +272,116 @@ static struct ref_entry *search_ref_dir(struct ref_dir *dir, const char *refname
}
/*
+ * If refname is a reference name, find the ref_dir within the dir
+ * tree that should hold refname. If refname is a directory name
+ * (i.e., ends in '/'), then return that ref_dir itself. dir must
+ * represent the top-level directory. Recurse into subdirectories as
+ * necessary. If mkdir is set, then create any missing directories;
+ * otherwise, return NULL if the desired directory cannot be found.
+ */
+static struct ref_dir *find_containing_dir(struct ref_dir *dir,
+ const char *refname, int mkdir)
+{
+ char *refname_copy = xstrdup(refname);
+ char *slash;
+ struct ref_entry *entry;
+ for (slash = strchr(refname_copy, '/'); slash; slash = strchr(slash + 1, '/')) {
+ char tmp = slash[1];
+ slash[1] = '\0';
+ entry = search_ref_dir(dir, refname_copy);
+ if (!entry) {
+ if (!mkdir) {
+ dir = NULL;
+ break;
+ }
+ entry = create_dir_entry(refname_copy);
+ add_entry_to_dir(dir, entry);
+ }
+ slash[1] = tmp;
+ assert(entry->flag & REF_DIR);
+ dir = &entry->u.subdir;
+ }
+
+ free(refname_copy);
+ return dir;
+}
+
+/*
+ * Find the value entry with the given name in dir, recursing into
+ * subdirectories as necessary. If the name is not found or it
+ * corresponds to a directory entry, return NULL.
+ */
+static struct ref_entry *find_ref(struct ref_dir *dir, const char *refname)
+{
+ struct ref_entry *entry;
+ dir = find_containing_dir(dir, refname, 0);
+ if (!dir)
+ return NULL;
+ entry = search_ref_dir(dir, refname);
+ return (entry && !(entry->flag & REF_DIR)) ? entry : NULL;
+}
+
+/*
+ * Add a ref_entry to the ref_dir (unsorted), recursing into
+ * subdirectories as necessary. dir must represent the top-level
+ * directory. Return 0 on success.
+ */
+static int add_ref(struct ref_dir *dir, struct ref_entry *ref)
+{
+ dir = find_containing_dir(dir, ref->name, 1);
+ if (!dir)
+ return -1;
+ add_entry_to_dir(dir, ref);
+ return 0;
+}
+
+/*
* Emit a warning and return true iff ref1 and ref2 have the same name
* and the same sha1. Die if they have the same name but different
* sha1s.
*/
static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
{
- if (!strcmp(ref1->name, ref2->name)) {
- /* Duplicate name; make sure that the SHA1s match: */
- if (hashcmp(ref1->u.value.sha1, ref2->u.value.sha1))
- die("Duplicated ref, and SHA1s don't match: %s",
- ref1->name);
- warning("Duplicated ref: %s", ref1->name);
- return 1;
- } else {
+ if (strcmp(ref1->name, ref2->name))
return 0;
- }
+
+ /* Duplicate name; make sure that they don't conflict: */
+
+ if ((ref1->flag & REF_DIR) || (ref2->flag & REF_DIR))
+ /* This is impossible by construction */
+ die("Reference directory conflict: %s", ref1->name);
+
+ if (hashcmp(ref1->u.value.sha1, ref2->u.value.sha1))
+ die("Duplicated ref, and SHA1s don't match: %s", ref1->name);
+
+ warning("Duplicated ref: %s", ref1->name);
+ return 1;
}
static void sort_ref_dir(struct ref_dir *dir)
{
int i, j;
+ struct ref_entry *last = NULL;
- /* Nothing to sort unless there are at least two entries */
- if (dir->nr < 2)
+ if (!dir->nr)
return;
qsort(dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
- /* Remove any duplicates from the ref_array */
- i = 0;
- for (j = 1; j < dir->nr; j++) {
- if (is_dup_ref(dir->entries[i], dir->entries[j])) {
- free_ref_entry(dir->entries[j]);
- continue;
+ /* Remove any duplicates and sort subdirectories: */
+ for (i = 0, j = 0; j < dir->nr; j++) {
+ struct ref_entry *entry = dir->entries[j];
+ if (last && is_dup_ref(last, entry)) {
+ free_ref_entry(entry);
+ } else if (entry->flag & REF_DIR) {
+ sort_ref_dir(&entry->u.subdir);
+ dir->entries[i++] = entry;
+ last = NULL;
+ } else {
+ last = dir->entries[i++] = entry;
}
- dir->entries[++i] = dir->entries[j];
}
- dir->nr = i + 1;
+ dir->nr = i;
}
#define DO_FOR_EACH_INCLUDE_BROKEN 01
@@ -265,7 +412,14 @@ static int do_for_each_ref_in_dir(struct ref_dir *dir, int offset,
{
int i;
for (i = offset; i < dir->nr; i++) {
- int retval = do_one_ref(base, fn, trim, flags, cb_data, dir->entries[i]);
+ struct ref_entry *entry = dir->entries[i];
+ int retval;
+ if (entry->flag & REF_DIR) {
+ retval = do_for_each_ref_in_dir(&entry->u.subdir, 0,
+ base, fn, trim, flags, cb_data);
+ } else {
+ retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
+ }
if (retval)
return retval;
}
@@ -281,7 +435,7 @@ static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
int i1 = 0, i2 = 0;
while (1) {
- struct ref_entry *e1, *e2;
+ struct ref_entry *e1, *e2, *entry;
int cmp;
if (i1 == dir1->nr) {
return do_for_each_ref_in_dir(dir2, i2,
@@ -295,16 +449,37 @@ static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
e2 = dir2->entries[i2];
cmp = strcmp(e1->name, e2->name);
if (cmp == 0) {
- /* Two refs with the same name; ignore the one from dir1. */
- i1++;
- continue;
- }
- if (cmp < 0) {
- retval = do_one_ref(base, fn, trim, flags, cb_data, e1);
- i1++;
+ if ((e1->flag & REF_DIR) && (e2->flag & REF_DIR)) {
+ /* Both are directories; descend them in parallel. */
+ retval = do_for_each_ref_in_dirs(
+ &e1->u.subdir, &e2->u.subdir,
+ base, fn, trim, flags, cb_data);
+ i1++;
+ i2++;
+ } else if (!(e1->flag & REF_DIR) && !(e2->flag & REF_DIR)) {
+ /* Both are references; ignore the one from dir1. */
+ retval = do_one_ref(base, fn, trim, flags, cb_data, e2);
+ i1++;
+ i2++;
+ } else {
+ die("conflict between reference and directory: %s",
+ e1->name);
+ }
} else {
- retval = do_one_ref(base, fn, trim, flags, cb_data, e2);
- i2++;
+ if (cmp < 0) {
+ entry = e1;
+ i1++;
+ } else {
+ entry = e2;
+ i2++;
+ }
+ if (entry->flag & REF_DIR) {
+ retval = do_for_each_ref_in_dir(
+ &entry->u.subdir, 0,
+ base, fn, trim, flags, cb_data);
+ } else {
+ retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
+ }
}
if (retval)
return retval;
@@ -630,7 +805,7 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
struct ref_entry *ref;
struct ref_dir *dir = get_packed_refs(refs);
- ref = search_ref_dir(dir, refname);
+ ref = find_ref(dir, refname);
if (ref == NULL)
return -1;
@@ -702,7 +877,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
static int get_packed_ref(const char *refname, unsigned char *sha1)
{
struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *entry = search_ref_dir(packed, refname);
+ struct ref_entry *entry = find_ref(packed, refname);
if (entry) {
hashcpy(sha1, entry->u.value.sha1);
return 0;
@@ -873,7 +1048,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
if ((flag & REF_ISPACKED)) {
struct ref_dir *dir = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *r = search_ref_dir(dir, refname);
+ struct ref_entry *r = find_ref(dir, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
hashcpy(sha1, r->u.value.peeled);
@@ -1380,7 +1555,7 @@ static int repack_without_ref(const char *refname)
struct ref_dir *packed;
packed = get_packed_refs(get_ref_cache(NULL));
- if (search_ref_dir(packed, refname) == NULL)
+ if (find_ref(packed, refname) == NULL)
return 0;
data.refname = refname;
data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
--
1.7.8
^ permalink raw reply related
* [PATCH v2 36/51] get_loose_refs(): return (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index 6a65a21..918b787 100644
--- a/refs.c
+++ b/refs.c
@@ -809,13 +809,13 @@ static void get_ref_dir(struct ref_cache *refs, const char *dirname)
}
}
-static struct ref_dir *get_loose_refs(struct ref_cache *refs)
+static struct ref_entry *get_loose_refs(struct ref_cache *refs)
{
if (!refs->loose) {
refs->loose = create_dir_entry("");
get_ref_dir(refs, "refs/");
}
- return &refs->loose->u.subdir;
+ return refs->loose;
}
/* We allow "recursive" symbolic refs. Only within reason, though */
@@ -1138,7 +1138,8 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
struct ref_dir *extra_dir = extra_refs ? &extra_refs->u.subdir : NULL;
struct ref_entry *packed_direntry = get_packed_refs(refs);
struct ref_dir *packed_dir = &packed_direntry->u.subdir;
- struct ref_dir *loose_dir = get_loose_refs(refs);
+ struct ref_entry *loose_direntry = get_loose_refs(refs);
+ struct ref_dir *loose_dir = &loose_direntry->u.subdir;
if (base && *base) {
if (extra_dir)
@@ -1688,7 +1689,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
if (!is_refname_available(newrefname, oldrefname, &get_packed_refs(refs)->u.subdir))
return 1;
- if (!is_refname_available(newrefname, oldrefname, get_loose_refs(refs)))
+ if (!is_refname_available(newrefname, oldrefname, &get_loose_refs(refs)->u.subdir))
return 1;
if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))
--
1.7.8
^ permalink raw reply related
* [PATCH v2 35/51] get_packed_refs(): return (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 33 +++++++++++++++++----------------
1 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/refs.c b/refs.c
index b4019e6..6a65a21 100644
--- a/refs.c
+++ b/refs.c
@@ -715,7 +715,7 @@ void clear_extra_refs(void)
}
}
-static struct ref_dir *get_packed_refs(struct ref_cache *refs)
+static struct ref_entry *get_packed_refs(struct ref_cache *refs)
{
if (!refs->packed) {
const char *packed_refs_file;
@@ -732,7 +732,7 @@ static struct ref_dir *get_packed_refs(struct ref_cache *refs)
fclose(f);
}
}
- return &refs->packed->u.subdir;
+ return refs->packed;
}
/*
@@ -831,9 +831,9 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
const char *refname, unsigned char *sha1)
{
struct ref_entry *ref;
- struct ref_dir *dir = get_packed_refs(refs);
+ struct ref_entry *direntry = get_packed_refs(refs);
- ref = find_ref(dir, refname);
+ ref = find_ref(&direntry->u.subdir, refname);
if (ref == NULL)
return -1;
@@ -904,8 +904,8 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
*/
static int get_packed_ref(const char *refname, unsigned char *sha1)
{
- struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *entry = find_ref(packed, refname);
+ struct ref_entry *packed = get_packed_refs(get_ref_cache(NULL));
+ struct ref_entry *entry = find_ref(&packed->u.subdir, refname);
if (entry) {
hashcpy(sha1, entry->u.value.sha1);
return 0;
@@ -1075,8 +1075,8 @@ int peel_ref(const char *refname, unsigned char *sha1)
return -1;
if ((flag & REF_ISPACKED)) {
- struct ref_dir *dir = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *r = find_ref(dir, refname);
+ struct ref_entry *direntry = get_packed_refs(get_ref_cache(NULL));
+ struct ref_entry *r = find_ref(&direntry->u.subdir, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
hashcpy(sha1, r->u.value.peeled);
@@ -1136,7 +1136,8 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
int retval = 0;
struct ref_cache *refs = get_ref_cache(submodule);
struct ref_dir *extra_dir = extra_refs ? &extra_refs->u.subdir : NULL;
- struct ref_dir *packed_dir = get_packed_refs(refs);
+ struct ref_entry *packed_direntry = get_packed_refs(refs);
+ struct ref_dir *packed_dir = &packed_direntry->u.subdir;
struct ref_dir *loose_dir = get_loose_refs(refs);
if (base && *base) {
@@ -1522,7 +1523,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
* name is a proper prefix of our refname.
*/
if (missing &&
- !is_refname_available(refname, NULL, get_packed_refs(get_ref_cache(NULL)))) {
+ !is_refname_available(refname, NULL,
+ &get_packed_refs(get_ref_cache(NULL))->u.subdir)) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -1602,10 +1604,8 @@ static struct lock_file packlock;
static int repack_without_ref(const char *refname)
{
struct repack_without_ref_sb data;
- struct ref_dir *packed;
-
- packed = get_packed_refs(get_ref_cache(NULL));
- if (find_ref(packed, refname) == NULL)
+ struct ref_entry *packed = get_packed_refs(get_ref_cache(NULL));
+ if (find_ref(&packed->u.subdir, refname) == NULL)
return 0;
data.refname = refname;
data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
@@ -1613,7 +1613,8 @@ static int repack_without_ref(const char *refname)
unable_to_lock_error(git_path("packed-refs"), errno);
return error("cannot delete '%s' from packed refs", refname);
}
- do_for_each_ref_in_dir(packed, 0, "", repack_without_ref_fn, 0, 0, &data);
+ do_for_each_ref_in_dir(&packed->u.subdir, 0,
+ "", repack_without_ref_fn, 0, 0, &data);
return commit_lock_file(&packlock);
}
@@ -1684,7 +1685,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
if (!symref)
return error("refname %s not found", oldrefname);
- if (!is_refname_available(newrefname, oldrefname, get_packed_refs(refs)))
+ if (!is_refname_available(newrefname, oldrefname, &get_packed_refs(refs)->u.subdir))
return 1;
if (!is_refname_available(newrefname, oldrefname, get_loose_refs(refs)))
--
1.7.8
^ permalink raw reply related
* [PATCH v2 37/51] is_refname_available(): take (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/refs.c b/refs.c
index 918b787..6b7d374 100644
--- a/refs.c
+++ b/refs.c
@@ -544,14 +544,16 @@ static int name_conflict_fn(const char *existingrefname, const unsigned char *sh
* operation).
*/
static int is_refname_available(const char *refname, const char *oldrefname,
- struct ref_dir *dir)
+ struct ref_entry *direntry)
{
struct name_conflict_cb data;
data.refname = refname;
data.oldrefname = oldrefname;
data.conflicting_refname = NULL;
- if (do_for_each_ref_in_dir(dir, 0, "", name_conflict_fn,
+ assert(direntry->flag & REF_DIR);
+
+ if (do_for_each_ref_in_dir(&direntry->u.subdir, 0, "", name_conflict_fn,
0, DO_FOR_EACH_INCLUDE_BROKEN,
&data)) {
error("'%s' exists; cannot create '%s'",
@@ -1525,7 +1527,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
*/
if (missing &&
!is_refname_available(refname, NULL,
- &get_packed_refs(get_ref_cache(NULL))->u.subdir)) {
+ get_packed_refs(get_ref_cache(NULL)))) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -1686,10 +1688,10 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
if (!symref)
return error("refname %s not found", oldrefname);
- if (!is_refname_available(newrefname, oldrefname, &get_packed_refs(refs)->u.subdir))
+ if (!is_refname_available(newrefname, oldrefname, get_packed_refs(refs)))
return 1;
- if (!is_refname_available(newrefname, oldrefname, &get_loose_refs(refs)->u.subdir))
+ if (!is_refname_available(newrefname, oldrefname, get_loose_refs(refs)))
return 1;
if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))
--
1.7.8
^ permalink raw reply related
* [PATCH v2 38/51] find_ref(): take (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/refs.c b/refs.c
index 6b7d374..df7416f 100644
--- a/refs.c
+++ b/refs.c
@@ -321,10 +321,12 @@ static struct ref_dir *find_containing_dir(struct ref_dir *dir,
* subdirectories as necessary. If the name is not found or it
* corresponds to a directory entry, return NULL.
*/
-static struct ref_entry *find_ref(struct ref_dir *dir, const char *refname)
+static struct ref_entry *find_ref(struct ref_entry *direntry, const char *refname)
{
struct ref_entry *entry;
- dir = find_containing_dir(dir, refname, 0);
+ struct ref_dir *dir;
+ assert(direntry->flag & REF_DIR);
+ dir = find_containing_dir(&direntry->u.subdir, refname, 0);
if (!dir)
return NULL;
entry = search_ref_dir(dir, refname);
@@ -835,7 +837,7 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
struct ref_entry *ref;
struct ref_entry *direntry = get_packed_refs(refs);
- ref = find_ref(&direntry->u.subdir, refname);
+ ref = find_ref(direntry, refname);
if (ref == NULL)
return -1;
@@ -907,7 +909,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
static int get_packed_ref(const char *refname, unsigned char *sha1)
{
struct ref_entry *packed = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *entry = find_ref(&packed->u.subdir, refname);
+ struct ref_entry *entry = find_ref(packed, refname);
if (entry) {
hashcpy(sha1, entry->u.value.sha1);
return 0;
@@ -1078,7 +1080,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
if ((flag & REF_ISPACKED)) {
struct ref_entry *direntry = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *r = find_ref(&direntry->u.subdir, refname);
+ struct ref_entry *r = find_ref(direntry, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
hashcpy(sha1, r->u.value.peeled);
@@ -1608,7 +1610,7 @@ static int repack_without_ref(const char *refname)
{
struct repack_without_ref_sb data;
struct ref_entry *packed = get_packed_refs(get_ref_cache(NULL));
- if (find_ref(&packed->u.subdir, refname) == NULL)
+ if (find_ref(packed, refname) == NULL)
return 0;
data.refname = refname;
data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
--
1.7.8
^ permalink raw reply related
* [PATCH v2 39/51] read_packed_refs(): take (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/refs.c b/refs.c
index df7416f..0d8fdf0 100644
--- a/refs.c
+++ b/refs.c
@@ -670,12 +670,13 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
return line;
}
-static void read_packed_refs(FILE *f, struct ref_dir *dir)
+static void read_packed_refs(FILE *f, struct ref_entry *direntry)
{
struct ref_entry *last = NULL;
char refline[PATH_MAX];
int flag = REF_ISPACKED;
+ assert(direntry->flag & REF_DIR);
while (fgets(refline, sizeof(refline), f)) {
unsigned char sha1[20];
const char *refname;
@@ -692,7 +693,7 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
refname = parse_ref_line(refline, sha1);
if (refname) {
last = create_ref_entry(refname, sha1, flag, 1);
- add_ref(dir, last);
+ add_ref(&direntry->u.subdir, last);
continue;
}
if (last &&
@@ -732,7 +733,7 @@ static struct ref_entry *get_packed_refs(struct ref_cache *refs)
packed_refs_file = git_path("packed-refs");
f = fopen(packed_refs_file, "r");
if (f) {
- read_packed_refs(f, &refs->packed->u.subdir);
+ read_packed_refs(f, refs->packed);
fclose(f);
}
}
--
1.7.8
^ permalink raw reply related
* [PATCH v2 40/51] add_ref(): take (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index 0d8fdf0..439545b 100644
--- a/refs.c
+++ b/refs.c
@@ -338,9 +338,11 @@ static struct ref_entry *find_ref(struct ref_entry *direntry, const char *refnam
* subdirectories as necessary. dir must represent the top-level
* directory. Return 0 on success.
*/
-static int add_ref(struct ref_dir *dir, struct ref_entry *ref)
+static int add_ref(struct ref_entry *direntry, struct ref_entry *ref)
{
- dir = find_containing_dir(dir, ref->name, 1);
+ struct ref_dir *dir;
+ assert(direntry->flag & REF_DIR);
+ dir = find_containing_dir(&direntry->u.subdir, ref->name, 1);
if (!dir)
return -1;
add_entry_to_dir(dir, ref);
@@ -693,7 +695,7 @@ static void read_packed_refs(FILE *f, struct ref_entry *direntry)
refname = parse_ref_line(refline, sha1);
if (refname) {
last = create_ref_entry(refname, sha1, flag, 1);
- add_ref(&direntry->u.subdir, last);
+ add_ref(direntry, last);
continue;
}
if (last &&
@@ -709,7 +711,7 @@ void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)
{
if (!extra_refs)
extra_refs = create_dir_entry("");
- add_ref(&extra_refs->u.subdir, create_ref_entry(refname, sha1, flag, 0));
+ add_ref(extra_refs, create_ref_entry(refname, sha1, flag, 0));
}
void clear_extra_refs(void)
--
1.7.8
^ permalink raw reply related
* [PATCH v2 41/51] find_containing_direntry(): use (ref_entry *) instead of (ref_dir *)
From: mhagger @ 2011-12-12 5:38 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
Johan Herland, Julian Phillips, Michael Haggerty
In-Reply-To: <1323668338-1764-1-git-send-email-mhagger@alum.mit.edu>
From: Michael Haggerty <mhagger@alum.mit.edu>
Change type of both argument and return value.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
refs.c | 78 ++++++++++++++++++++++++++++++++--------------------------------
1 files changed, 39 insertions(+), 39 deletions(-)
diff --git a/refs.c b/refs.c
index 439545b..d89c3d0 100644
--- a/refs.c
+++ b/refs.c
@@ -282,38 +282,40 @@ static struct ref_entry *search_ref_dir(struct ref_dir *dir, const char *refname
}
/*
- * If refname is a reference name, find the ref_dir within the dir
+ * If refname is a reference name, find the ref_entry within the dir
* tree that should hold refname. If refname is a directory name
- * (i.e., ends in '/'), then return that ref_dir itself. dir must
- * represent the top-level directory. Recurse into subdirectories as
- * necessary. If mkdir is set, then create any missing directories;
- * otherwise, return NULL if the desired directory cannot be found.
+ * (i.e., "" or ends in '/'), then return that ref_entry itself. dir
+ * must represent the top-level directory. Recurse into
+ * subdirectories as necessary. If mkdir is set, then create any
+ * missing directories; otherwise, return NULL if the desired
+ * directory cannot be found.
*/
-static struct ref_dir *find_containing_dir(struct ref_dir *dir,
- const char *refname, int mkdir)
+static struct ref_entry *find_containing_direntry(struct ref_entry *direntry,
+ const char *refname, int mkdir)
{
char *refname_copy = xstrdup(refname);
char *slash;
- struct ref_entry *entry;
+ assert(direntry->flag & REF_DIR);
for (slash = strchr(refname_copy, '/'); slash; slash = strchr(slash + 1, '/')) {
char tmp = slash[1];
+ struct ref_entry *entry;
slash[1] = '\0';
- entry = search_ref_dir(dir, refname_copy);
+ entry = search_ref_dir(&direntry->u.subdir, refname_copy);
if (!entry) {
if (!mkdir) {
- dir = NULL;
+ direntry = NULL;
break;
}
entry = create_dir_entry(refname_copy);
- add_entry_to_dir(dir, entry);
+ add_entry_to_dir(&direntry->u.subdir, entry);
}
slash[1] = tmp;
assert(entry->flag & REF_DIR);
- dir = &entry->u.subdir;
+ direntry = entry;
}
free(refname_copy);
- return dir;
+ return direntry;
}
/*
@@ -324,12 +326,11 @@ static struct ref_dir *find_containing_dir(struct ref_dir *dir,
static struct ref_entry *find_ref(struct ref_entry *direntry, const char *refname)
{
struct ref_entry *entry;
- struct ref_dir *dir;
assert(direntry->flag & REF_DIR);
- dir = find_containing_dir(&direntry->u.subdir, refname, 0);
- if (!dir)
+ direntry = find_containing_direntry(direntry, refname, 0);
+ if (!direntry)
return NULL;
- entry = search_ref_dir(dir, refname);
+ entry = search_ref_dir(&direntry->u.subdir, refname);
return (entry && !(entry->flag & REF_DIR)) ? entry : NULL;
}
@@ -340,12 +341,11 @@ static struct ref_entry *find_ref(struct ref_entry *direntry, const char *refnam
*/
static int add_ref(struct ref_entry *direntry, struct ref_entry *ref)
{
- struct ref_dir *dir;
assert(direntry->flag & REF_DIR);
- dir = find_containing_dir(&direntry->u.subdir, ref->name, 1);
- if (!dir)
+ direntry = find_containing_direntry(direntry, ref->name, 1);
+ if (!direntry)
return -1;
- add_entry_to_dir(dir, ref);
+ add_entry_to_dir(&direntry->u.subdir, ref);
return 0;
}
@@ -752,11 +752,11 @@ static void get_ref_dir(struct ref_cache *refs, const char *dirname)
char *path;
int dirnamelen = strlen(dirname);
int pathlen;
- struct ref_dir *dir;
+ struct ref_entry *direntry;
assert(dirnamelen && dirname[dirnamelen - 1] == '/');
- dir = find_containing_dir(&refs->loose->u.subdir, dirname, 1);
+ direntry = find_containing_direntry(refs->loose, dirname, 1);
if (*refs->name)
path = git_path_submodule(refs->name, "%s", dirname);
@@ -809,7 +809,8 @@ static void get_ref_dir(struct ref_cache *refs, const char *dirname)
hashclr(sha1);
flag |= REF_ISBROKEN;
}
- add_entry_to_dir(dir, create_ref_entry(refname, sha1, flag, 1));
+ add_entry_to_dir(&direntry->u.subdir,
+ create_ref_entry(refname, sha1, flag, 1));
}
free(refname);
closedir(d);
@@ -1142,35 +1143,34 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn
{
int retval = 0;
struct ref_cache *refs = get_ref_cache(submodule);
- struct ref_dir *extra_dir = extra_refs ? &extra_refs->u.subdir : NULL;
+ struct ref_entry *extra_direntry = extra_refs;
struct ref_entry *packed_direntry = get_packed_refs(refs);
- struct ref_dir *packed_dir = &packed_direntry->u.subdir;
struct ref_entry *loose_direntry = get_loose_refs(refs);
- struct ref_dir *loose_dir = &loose_direntry->u.subdir;
if (base && *base) {
- if (extra_dir)
- extra_dir = find_containing_dir(extra_dir, base, 0);
- packed_dir = find_containing_dir(packed_dir, base, 0);
- loose_dir = find_containing_dir(loose_dir, base, 0);
+ if (extra_direntry)
+ extra_direntry = find_containing_direntry(extra_direntry, base, 0);
+ packed_direntry = find_containing_direntry(packed_direntry, base, 0);
+ loose_direntry = find_containing_direntry(loose_direntry, base, 0);
}
- if (extra_dir)
+ if (extra_direntry)
retval = do_for_each_ref_in_dir(
- extra_dir, 0,
+ &extra_direntry->u.subdir, 0,
base, fn, trim, flags, cb_data);
if (!retval) {
- if (packed_dir && loose_dir)
+ if (packed_direntry && loose_direntry)
retval = do_for_each_ref_in_dirs(
- packed_dir, loose_dir,
+ &packed_direntry->u.subdir,
+ &loose_direntry->u.subdir,
base, fn, trim, flags, cb_data);
- else if (packed_dir)
+ else if (packed_direntry)
retval = do_for_each_ref_in_dir(
- packed_dir, 0,
+ &packed_direntry->u.subdir, 0,
base, fn, trim, flags, cb_data);
- else if (loose_dir)
+ else if (loose_direntry)
retval = do_for_each_ref_in_dir(
- loose_dir, 0,
+ &loose_direntry->u.subdir, 0,
base, fn, trim, flags, cb_data);
}
--
1.7.8
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox