{"thread":{"id":"28784","subject":"[PATCH v2 08/12] do_for_each_ref_in_arrays(): new function","startedAt":"2011-10-28T11:27:52Z","lastAt":"2011-10-28T11:28:04Z","messageCount":13,"participants":["mhagger@alum.mit.edu"],"isPatch":true,"patchVersion":2,"patchTotal":12},"messages":[{"id":"178426","messageId":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":null,"subject":"[PATCH v2 00/12] Use refs API more consistently","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:52Z","receivedAt":"2011-10-28T11:27:52Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nThis is a re-roll of the patch series on top of v3 of \"Tidying up\nreferences code\", which in turn applies to gitster/master.\n\nThis series conflicts with the \"Checking full vs. partial refnames\"\nseries but not in a fundamental way.  Unless there is an important\nreason to merge the latter to master before this patch series, I\nsuggest that I reroll \"Checking full vs. partial refnames\" on top of\nthese ref-api changes after they hit master.\n\nThis patch series primarily has to do with using the refs API more\nconsistently within refs.c itself.  We want to minimize the surface\narea for accessing the ref_cache data structure so that when it is\nchanged into a tree (we're on the verge of that change now, I\npromise!) we don't have to change callers more than necessary.  There\nis also a bit of an eat-your-own-dogfood thing going on here; if\nfor_each_ref() and its friends are good enough for \"outsiders\", they\nshould be good enough for most internal use.\n\nThe first two patches are trivial preparation cleanups.\n\nThe third verifies that refnames read from packed-ref files are\nproperly formatted.  When the REFNAME_FULL changes become available,\nthis check can be tightened up.\n\nThe do_for_each_ref_in_{array,arrays}() functions provide an\niterator-like interface to iterating over a single ref_array and\niterating over two ref_arrays in parallel.  These are useful\nabstractions in and of themselves (the former is used to reimplement\nrepack_without_ref() and is_refname_available() in patches 9 and 12\nrespectively).  And they will be even more useful when references are\nstored hierarchically.\n\nMichael Haggerty (12):\n  Rename another local variable name -> refname\n  repack_without_ref(): remove temporary\n  parse_ref_line(): add a check that the refname is properly formatted\n  create_ref_entry(): extract function from add_ref()\n  add_ref(): take a (struct ref_entry *) parameter\n  do_for_each_ref(): correctly terminate while processesing extra_refs\n  do_for_each_ref_in_array(): new function\n  do_for_each_ref_in_arrays(): new function\n  repack_without_ref(): reimplement using do_for_each_ref_in_array()\n  names_conflict(): new function, extracted from is_refname_available()\n  names_conflict(): simplify implementation\n  is_refname_available(): reimplement using do_for_each_ref_in_array()\n\n refs.c |  255 ++++++++++++++++++++++++++++++++++++++++------------------------\n 1 files changed, 160 insertions(+), 95 deletions(-)\n\n-- \n1.7.7\n"},{"id":"178422","messageId":"1319801284-15625-2-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 01/12] Rename another local variable name -> refname","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:53Z","receivedAt":"2011-10-28T11:27:53Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   22 +++++++++++-----------\n 1 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 1c6de61..855c791 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -316,11 +316,11 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,\n \tif (dir) {\n \t\tstruct dirent *de;\n \t\tint baselen = strlen(base);\n-\t\tchar *ref = xmalloc(baselen + 257);\n+\t\tchar *refname = xmalloc(baselen + 257);\n \n-\t\tmemcpy(ref, base, baselen);\n+\t\tmemcpy(refname, base, baselen);\n \t\tif (baselen && base[baselen-1] != '/')\n-\t\t\tref[baselen++] = '/';\n+\t\t\trefname[baselen++] = '/';\n \n \t\twhile ((de = readdir(dir)) != NULL) {\n \t\t\tunsigned char sha1[20];\n@@ -336,31 +336,31 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,\n \t\t\t\tcontinue;\n \t\t\tif (has_extension(de->d_name, \".lock\"))\n \t\t\t\tcontinue;\n-\t\t\tmemcpy(ref + baselen, de->d_name, namelen+1);\n+\t\t\tmemcpy(refname + baselen, de->d_name, namelen+1);\n \t\t\trefdir = *refs->name\n-\t\t\t\t? git_path_submodule(refs->name, \"%s\", ref)\n-\t\t\t\t: git_path(\"%s\", ref);\n+\t\t\t\t? git_path_submodule(refs->name, \"%s\", refname)\n+\t\t\t\t: git_path(\"%s\", refname);\n \t\t\tif (stat(refdir, &st) < 0)\n \t\t\t\tcontinue;\n \t\t\tif (S_ISDIR(st.st_mode)) {\n-\t\t\t\tget_ref_dir(refs, ref, array);\n+\t\t\t\tget_ref_dir(refs, refname, array);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (*refs->name) {\n \t\t\t\thashclr(sha1);\n \t\t\t\tflag = 0;\n-\t\t\t\tif (resolve_gitlink_ref(refs->name, ref, sha1) < 0) {\n+\t\t\t\tif (resolve_gitlink_ref(refs->name, refname, sha1) < 0) {\n \t\t\t\t\thashclr(sha1);\n \t\t\t\t\tflag |= REF_ISBROKEN;\n \t\t\t\t}\n \t\t\t} else\n-\t\t\t\tif (!resolve_ref(ref, sha1, 1, &flag)) {\n+\t\t\t\tif (!resolve_ref(refname, sha1, 1, &flag)) {\n \t\t\t\t\thashclr(sha1);\n \t\t\t\t\tflag |= REF_ISBROKEN;\n \t\t\t\t}\n-\t\t\tadd_ref(ref, sha1, flag, array, NULL);\n+\t\t\tadd_ref(refname, sha1, flag, array, NULL);\n \t\t}\n-\t\tfree(ref);\n+\t\tfree(refname);\n \t\tclosedir(dir);\n \t}\n }\n-- \n1.7.7\n"},{"id":"178421","messageId":"1319801284-15625-3-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 02/12] repack_without_ref(): remove temporary","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:54Z","receivedAt":"2011-10-28T11:27:54Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |    7 ++-----\n 1 files changed, 2 insertions(+), 5 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 855c791..7191437 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1282,12 +1282,10 @@ static struct lock_file packlock;\n static int repack_without_ref(const char *refname)\n {\n \tstruct ref_array *packed;\n-\tstruct ref_entry *ref;\n \tint fd, i;\n \n \tpacked = get_packed_refs(get_ref_cache(NULL));\n-\tref = search_ref_array(packed, refname);\n-\tif (ref == NULL)\n+\tif (search_ref_array(packed, refname) == NULL)\n \t\treturn 0;\n \tfd = hold_lock_file_for_update(&packlock, git_path(\"packed-refs\"), 0);\n \tif (fd < 0) {\n@@ -1298,8 +1296,7 @@ static int repack_without_ref(const char *refname)\n \tfor (i = 0; i < packed->nr; i++) {\n \t\tchar line[PATH_MAX + 100];\n \t\tint len;\n-\n-\t\tref = packed->refs[i];\n+\t\tstruct ref_entry *ref = packed->refs[i];\n \n \t\tif (!strcmp(refname, ref->name))\n \t\t\tcontinue;\n-- \n1.7.7\n"},{"id":"178428","messageId":"1319801284-15625-4-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 03/12] parse_ref_line(): add a check that the refname is properly formatted","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:55Z","receivedAt":"2011-10-28T11:27:55Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 7191437..080e277 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -50,6 +50,9 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)\n \t\treturn NULL;\n \tline[len] = 0;\n \n+\tif (check_refname_format(line, REFNAME_ALLOW_ONELEVEL))\n+\t\treturn NULL;\n+\n \treturn line;\n }\n \n-- \n1.7.7\n"},{"id":"178420","messageId":"1319801284-15625-5-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 04/12] create_ref_entry(): extract function from add_ref()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:56Z","receivedAt":"2011-10-28T11:27:56Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nSeparate the creation of the ref_entry from its addition to a ref_array.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   36 +++++++++++++++++++++---------------\n 1 files changed, 21 insertions(+), 15 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 080e277..163ce91 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -56,27 +56,33 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)\n \treturn line;\n }\n \n-/* Add a ref_entry to the end of the ref_array (unsorted). */\n-static void add_ref(const char *refname, const unsigned char *sha1,\n-\t\t    int flag, struct ref_array *refs,\n-\t\t    struct ref_entry **new_entry)\n+static struct ref_entry *create_ref_entry(const char *refname,\n+\t\t\t\t\t  const unsigned char *sha1, int flag)\n {\n \tint len;\n-\tstruct ref_entry *entry;\n+\tstruct ref_entry *ref;\n \n-\t/* Allocate it and add it in.. */\n-\tlen = strlen(refname) + 1;\n-\tentry = xmalloc(sizeof(struct ref_entry) + len);\n-\thashcpy(entry->sha1, sha1);\n-\thashclr(entry->peeled);\n \tif (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))\n \t\tdie(\"Reference has invalid format: '%s'\", refname);\n-\tmemcpy(entry->name, refname, len);\n-\tentry->flag = flag;\n-\tif (new_entry)\n-\t\t*new_entry = entry;\n+\tlen = strlen(refname) + 1;\n+\tref = xmalloc(sizeof(struct ref_entry) + len);\n+\thashcpy(ref->sha1, sha1);\n+\thashclr(ref->peeled);\n+\tmemcpy(ref->name, refname, len);\n+\tref->flag = flag;\n+\treturn ref;\n+}\n+\n+/* Add a ref_entry to the end of the ref_array (unsorted). */\n+static void add_ref(const char *refname, const unsigned char *sha1,\n+\t\t    int flag, struct ref_array *refs,\n+\t\t    struct ref_entry **new_ref)\n+{\n+\tstruct ref_entry *ref = create_ref_entry(refname, sha1, flag);\n+\tif (new_ref)\n+\t\t*new_ref = ref;\n \tALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);\n-\trefs->refs[refs->nr++] = entry;\n+\trefs->refs[refs->nr++] = ref;\n }\n \n static int ref_entry_cmp(const void *a, const void *b)\n-- \n1.7.7\n"},{"id":"178427","messageId":"1319801284-15625-6-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 05/12] add_ref(): take a (struct ref_entry *) parameter","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:57Z","receivedAt":"2011-10-28T11:27:57Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nTake a pointer to the ref_entry to add to the array, rather than\ncreating the ref_entry within the function.  This opens the way to\nhaving multiple kinds of ref_entries.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   14 +++++---------\n 1 files changed, 5 insertions(+), 9 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 163ce91..c76d8b5 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -74,13 +74,8 @@ static struct ref_entry *create_ref_entry(const char *refname,\n }\n \n /* Add a ref_entry to the end of the ref_array (unsorted). */\n-static void add_ref(const char *refname, const unsigned char *sha1,\n-\t\t    int flag, struct ref_array *refs,\n-\t\t    struct ref_entry **new_ref)\n+static void add_ref(struct ref_array *refs, struct ref_entry *ref)\n {\n-\tstruct ref_entry *ref = create_ref_entry(refname, sha1, flag);\n-\tif (new_ref)\n-\t\t*new_ref = ref;\n \tALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);\n \trefs->refs[refs->nr++] = ref;\n }\n@@ -265,7 +260,8 @@ static void read_packed_refs(FILE *f, struct ref_array *array)\n \n \t\trefname = parse_ref_line(refline, sha1);\n \t\tif (refname) {\n-\t\t\tadd_ref(refname, sha1, flag, array, &last);\n+\t\t\tlast = create_ref_entry(refname, sha1, flag);\n+\t\t\tadd_ref(array, last);\n \t\t\tcontinue;\n \t\t}\n \t\tif (last &&\n@@ -280,7 +276,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)\n \n void add_extra_ref(const char *refname, const unsigned char *sha1, int flag)\n {\n-\tadd_ref(refname, sha1, flag, &extra_refs, NULL);\n+\tadd_ref(&extra_refs, create_ref_entry(refname, sha1, flag));\n }\n \n void clear_extra_refs(void)\n@@ -367,7 +363,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,\n \t\t\t\t\thashclr(sha1);\n \t\t\t\t\tflag |= REF_ISBROKEN;\n \t\t\t\t}\n-\t\t\tadd_ref(refname, sha1, flag, array, NULL);\n+\t\t\tadd_ref(array, create_ref_entry(refname, sha1, flag));\n \t\t}\n \t\tfree(refname);\n \t\tclosedir(dir);\n-- \n1.7.7\n"},{"id":"178424","messageId":"1319801284-15625-7-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 06/12] do_for_each_ref(): correctly terminate while processesing extra_refs","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:58Z","receivedAt":"2011-10-28T11:27:58Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nIf the user-supplied function returns a nonzero value while processing\nextra_refs, terminate without processing the rest of the list.\n\nThis probably has no practical importance, but makes the handling of\nextra_refs a little bit more consistent with the handling of other\nrefs.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |    5 ++++-\n 1 files changed, 4 insertions(+), 1 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex c76d8b5..8043436 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -710,8 +710,11 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn\n \n \tstruct ref_array *extra = &extra_refs;\n \n-\tfor (i = 0; i < extra->nr; i++)\n+\tfor (i = 0; i < extra->nr; i++) {\n \t\tretval = do_one_ref(base, fn, trim, flags, cb_data, extra->refs[i]);\n+\t\tif (retval)\n+\t\t\tgoto end_each;\n+\t}\n \n \twhile (p < packed->nr && l < loose->nr) {\n \t\tstruct ref_entry *entry;\n-- \n1.7.7\n"},{"id":"178423","messageId":"1319801284-15625-8-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 07/12] do_for_each_ref_in_array(): new function","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:27:59Z","receivedAt":"2011-10-28T11:27:59Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nExtract function do_for_each_ref_in_array() from do_for_each_ref().\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   39 +++++++++++++++++++++++----------------\n 1 files changed, 23 insertions(+), 16 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 8043436..24a7a4d 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -700,21 +700,31 @@ fallback:\n \treturn -1;\n }\n \n+static int do_for_each_ref_in_array(struct ref_array *array, int offset,\n+\t\t\t\t    const char *base,\n+\t\t\t\t    each_ref_fn fn, int trim, int flags, void *cb_data)\n+{\n+\tint i;\n+\tfor (i = offset; i < array->nr; i++) {\n+\t\tint retval = do_one_ref(base, fn, trim, flags, cb_data, array->refs[i]);\n+\t\tif (retval)\n+\t\t\treturn retval;\n+\t}\n+\treturn 0;\n+}\n+\n static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,\n \t\t\t   int trim, int flags, void *cb_data)\n {\n-\tint retval = 0, i, p = 0, l = 0;\n+\tint retval = 0, p = 0, l = 0;\n \tstruct ref_cache *refs = get_ref_cache(submodule);\n \tstruct ref_array *packed = get_packed_refs(refs);\n \tstruct ref_array *loose = get_loose_refs(refs);\n \n-\tstruct ref_array *extra = &extra_refs;\n-\n-\tfor (i = 0; i < extra->nr; i++) {\n-\t\tretval = do_one_ref(base, fn, trim, flags, cb_data, extra->refs[i]);\n-\t\tif (retval)\n-\t\t\tgoto end_each;\n-\t}\n+\tretval = do_for_each_ref_in_array(&extra_refs, 0,\n+\t\t\t\t\t  base, fn, trim, flags, cb_data);\n+\tif (retval)\n+\t\tgoto end_each;\n \n \twhile (p < packed->nr && l < loose->nr) {\n \t\tstruct ref_entry *entry;\n@@ -734,14 +744,11 @@ static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn\n \t}\n \n \tif (l < loose->nr) {\n-\t\tp = l;\n-\t\tpacked = loose;\n-\t}\n-\n-\tfor (; p < packed->nr; p++) {\n-\t\tretval = do_one_ref(base, fn, trim, flags, cb_data, packed->refs[p]);\n-\t\tif (retval)\n-\t\t\tgoto end_each;\n+\t\tretval = do_for_each_ref_in_array(loose, l,\n+\t\t\t\t\t\t  base, fn, trim, flags, cb_data);\n+\t} else {\n+\t\tretval = do_for_each_ref_in_array(packed, p,\n+\t\t\t\t\t\t  base, fn, trim, flags, cb_data);\n \t}\n \n end_each:\n-- \n1.7.7\n"},{"id":"178419","messageId":"1319801284-15625-9-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 08/12] do_for_each_ref_in_arrays(): new function","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:28:00Z","receivedAt":"2011-10-28T11:28:00Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nExtract function do_for_each_ref_in_arrays() from do_for_each_ref().\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   71 +++++++++++++++++++++++++++++++++++++--------------------------\n 1 files changed, 42 insertions(+), 29 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 24a7a4d..ad7538a 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -713,45 +713,58 @@ static int do_for_each_ref_in_array(struct ref_array *array, int offset,\n \treturn 0;\n }\n \n-static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,\n-\t\t\t   int trim, int flags, void *cb_data)\n+static int do_for_each_ref_in_arrays(struct ref_array *array1,\n+\t\t\t\t     struct ref_array *array2,\n+\t\t\t\t     const char *base, each_ref_fn fn, int trim,\n+\t\t\t\t     int flags, void *cb_data)\n {\n-\tint retval = 0, p = 0, l = 0;\n-\tstruct ref_cache *refs = get_ref_cache(submodule);\n-\tstruct ref_array *packed = get_packed_refs(refs);\n-\tstruct ref_array *loose = get_loose_refs(refs);\n-\n-\tretval = do_for_each_ref_in_array(&extra_refs, 0,\n-\t\t\t\t\t  base, fn, trim, flags, cb_data);\n-\tif (retval)\n-\t\tgoto end_each;\n+\tint retval;\n+\tint i1 = 0, i2 = 0;\n \n-\twhile (p < packed->nr && l < loose->nr) {\n-\t\tstruct ref_entry *entry;\n-\t\tint cmp = strcmp(packed->refs[p]->name, loose->refs[l]->name);\n-\t\tif (!cmp) {\n-\t\t\tp++;\n+\twhile (1) {\n+\t\tstruct ref_entry *e1, *e2;\n+\t\tint cmp;\n+\t\tif (i1 == array1->nr) {\n+\t\t\treturn do_for_each_ref_in_array(array2, i2,\n+\t\t\t\t\t\t\tbase, fn, trim, flags, cb_data);\n+\t\t}\n+\t\tif (i2 == array2->nr) {\n+\t\t\treturn do_for_each_ref_in_array(array1, i1,\n+\t\t\t\t\t\t\tbase, fn, trim, flags, cb_data);\n+\t\t}\n+\t\te1 = array1->refs[i1];\n+\t\te2 = array2->refs[i2];\n+\t\tcmp = strcmp(e1->name, e2->name);\n+\t\tif (cmp == 0) {\n+\t\t\t/* Two refs with the same name; ignore the one from array1. */\n+\t\t\ti1++;\n \t\t\tcontinue;\n \t\t}\n-\t\tif (cmp > 0) {\n-\t\t\tentry = loose->refs[l++];\n+\t\tif (cmp < 0) {\n+\t\t\tretval = do_one_ref(base, fn, trim, flags, cb_data, e1);\n+\t\t\ti1++;\n \t\t} else {\n-\t\t\tentry = packed->refs[p++];\n+\t\t\tretval = do_one_ref(base, fn, trim, flags, cb_data, e2);\n+\t\t\ti2++;\n \t\t}\n-\t\tretval = do_one_ref(base, fn, trim, flags, cb_data, entry);\n \t\tif (retval)\n-\t\t\tgoto end_each;\n+\t\t\treturn retval;\n \t}\n+}\n \n-\tif (l < loose->nr) {\n-\t\tretval = do_for_each_ref_in_array(loose, l,\n-\t\t\t\t\t\t  base, fn, trim, flags, cb_data);\n-\t} else {\n-\t\tretval = do_for_each_ref_in_array(packed, p,\n-\t\t\t\t\t\t  base, fn, trim, flags, cb_data);\n-\t}\n+static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,\n+\t\t\t   int trim, int flags, void *cb_data)\n+{\n+\tint retval = 0;\n+\tstruct ref_cache *refs = get_ref_cache(submodule);\n+\n+\tretval = do_for_each_ref_in_array(&extra_refs, 0,\n+\t\t\t\t\t  base, fn, trim, flags, cb_data);\n+\tif (!retval)\n+\t\tretval = do_for_each_ref_in_arrays(get_packed_refs(refs),\n+\t\t\t\t\t\t   get_loose_refs(refs),\n+\t\t\t\t\t\t   base, fn, trim, flags, cb_data);\n \n-end_each:\n \tcurrent_ref = NULL;\n \treturn retval;\n }\n-- \n1.7.7\n"},{"id":"178425","messageId":"1319801284-15625-10-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 09/12] repack_without_ref(): reimplement using do_for_each_ref_in_array()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:28:01Z","receivedAt":"2011-10-28T11:28:01Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nIt costs a bit of boilerplate, but it means that the function can be\nignorant of how cached refs are stored.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   46 ++++++++++++++++++++++++++++------------------\n 1 files changed, 28 insertions(+), 18 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex ad7538a..d56f265 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1305,36 +1305,46 @@ struct ref_lock *lock_any_ref_for_update(const char *refname,\n \treturn lock_ref_sha1_basic(refname, old_sha1, flags, NULL);\n }\n \n+struct repack_without_ref_sb {\n+\tconst char *refname;\n+\tint fd;\n+};\n+\n+static int repack_without_ref_fn(const char *refname, const unsigned char *sha1,\n+\t\t\t\t int flags, void *cb_data)\n+{\n+\tstruct repack_without_ref_sb *data = cb_data;\n+\tchar line[PATH_MAX + 100];\n+\tint len;\n+\n+\tif (!strcmp(data->refname, refname))\n+\t\treturn 0;\n+\tlen = snprintf(line, sizeof(line), \"%s %s\\n\",\n+\t\t       sha1_to_hex(sha1), refname);\n+\t/* this should not happen but just being defensive */\n+\tif (len > sizeof(line))\n+\t\tdie(\"too long a refname '%s'\", refname);\n+\twrite_or_die(data->fd, line, len);\n+\treturn 0;\n+}\n+\n static struct lock_file packlock;\n \n static int repack_without_ref(const char *refname)\n {\n+\tstruct repack_without_ref_sb data;\n \tstruct ref_array *packed;\n-\tint fd, i;\n \n \tpacked = get_packed_refs(get_ref_cache(NULL));\n \tif (search_ref_array(packed, refname) == NULL)\n \t\treturn 0;\n-\tfd = hold_lock_file_for_update(&packlock, git_path(\"packed-refs\"), 0);\n-\tif (fd < 0) {\n+\tdata.refname = refname;\n+\tdata.fd = hold_lock_file_for_update(&packlock, git_path(\"packed-refs\"), 0);\n+\tif (data.fd < 0) {\n \t\tunable_to_lock_error(git_path(\"packed-refs\"), errno);\n \t\treturn error(\"cannot delete '%s' from packed refs\", refname);\n \t}\n-\n-\tfor (i = 0; i < packed->nr; i++) {\n-\t\tchar line[PATH_MAX + 100];\n-\t\tint len;\n-\t\tstruct ref_entry *ref = packed->refs[i];\n-\n-\t\tif (!strcmp(refname, ref->name))\n-\t\t\tcontinue;\n-\t\tlen = snprintf(line, sizeof(line), \"%s %s\\n\",\n-\t\t\t       sha1_to_hex(ref->sha1), ref->name);\n-\t\t/* this should not happen but just being defensive */\n-\t\tif (len > sizeof(line))\n-\t\t\tdie(\"too long a refname '%s'\", ref->name);\n-\t\twrite_or_die(fd, line, len);\n-\t}\n+\tdo_for_each_ref_in_array(packed, 0, \"\", repack_without_ref_fn, 0, 0, &data);\n \treturn commit_lock_file(&packlock);\n }\n \n-- \n1.7.7\n"},{"id":"178430","messageId":"1319801284-15625-11-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 10/12] names_conflict(): new function, extracted from is_refname_available()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:28:02Z","receivedAt":"2011-10-28T11:28:02Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nThis costs an extra strlen() in the loop, but even that small price\nwill be clawed back in the next patch.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   43 +++++++++++++++++++++++++++++++------------\n 1 files changed, 31 insertions(+), 12 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex d56f265..62e5fd3 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1092,6 +1092,30 @@ static int remove_empty_directories(const char *file)\n }\n \n /*\n+ * Return true iff refname1 and refname2 conflict with each other.\n+ * Two reference names conflict if one of them exactly matches the\n+ * leading components of the other; e.g., \"foo/bar\" conflicts with\n+ * both \"foo\" and with \"foo/bar/baz\" but not with \"foo/bar\" or\n+ * \"foo/barbados\".\n+ */\n+static int names_conflict(const char *refname1, const char *refname2)\n+{\n+\tint len1 = strlen(refname1);\n+\tint len2 = strlen(refname2);\n+\tint cmplen;\n+\tconst char *lead;\n+\n+\tif (len1 < len2) {\n+\t\tcmplen = len1;\n+\t\tlead = refname2;\n+\t} else {\n+\t\tcmplen = len2;\n+\t\tlead = refname1;\n+\t}\n+\treturn !strncmp(refname1, refname2, cmplen) && lead[cmplen] == '/';\n+}\n+\n+/*\n  * Return true iff a reference named refname could be created without\n  * conflicting with the name of an existing reference.  If oldrefname\n  * is non-NULL, ignore potential conflicts with oldrefname (e.g.,\n@@ -1101,20 +1125,15 @@ static int remove_empty_directories(const char *file)\n static int is_refname_available(const char *refname, const char *oldrefname,\n \t\t\t\tstruct ref_array *array)\n {\n-\tint i, namlen = strlen(refname); /* e.g. 'foo/bar' */\n+\tint i;\n \tfor (i = 0; i < array->nr; i++ ) {\n \t\tstruct ref_entry *entry = array->refs[i];\n-\t\t/* entry->name could be 'foo' or 'foo/bar/baz' */\n-\t\tif (!oldrefname || strcmp(oldrefname, entry->name)) {\n-\t\t\tint len = strlen(entry->name);\n-\t\t\tint cmplen = (namlen < len) ? namlen : len;\n-\t\t\tconst char *lead = (namlen < len) ? entry->name : refname;\n-\t\t\tif (!strncmp(refname, entry->name, cmplen) &&\n-\t\t\t    lead[cmplen] == '/') {\n-\t\t\t\terror(\"'%s' exists; cannot create '%s'\",\n-\t\t\t\t      entry->name, refname);\n-\t\t\t\treturn 0;\n-\t\t\t}\n+\t\tif (oldrefname && !strcmp(oldrefname, entry->name))\n+\t\t\tcontinue;\n+\t\tif (names_conflict(refname, entry->name)) {\n+\t\t\terror(\"'%s' exists; cannot create '%s'\",\n+\t\t\t      entry->name, refname);\n+\t\t\treturn 0;\n \t\t}\n \t}\n \treturn 1;\n-- \n1.7.7\n"},{"id":"178429","messageId":"1319801284-15625-12-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 11/12] names_conflict(): simplify implementation","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:28:03Z","receivedAt":"2011-10-28T11:28:03Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\n\nSave a bunch of lines of code and a couple of strlen() calls.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   17 ++++-------------\n 1 files changed, 4 insertions(+), 13 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 62e5fd3..2a5d8b2 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1100,19 +1100,10 @@ static int remove_empty_directories(const char *file)\n  */\n static int names_conflict(const char *refname1, const char *refname2)\n {\n-\tint len1 = strlen(refname1);\n-\tint len2 = strlen(refname2);\n-\tint cmplen;\n-\tconst char *lead;\n-\n-\tif (len1 < len2) {\n-\t\tcmplen = len1;\n-\t\tlead = refname2;\n-\t} else {\n-\t\tcmplen = len2;\n-\t\tlead = refname1;\n-\t}\n-\treturn !strncmp(refname1, refname2, cmplen) && lead[cmplen] == '/';\n+\tfor (; *refname1 && *refname1 == *refname2; refname1++, refname2++)\n+\t\t;\n+\treturn (*refname1 == '\\0' && *refname2 == '/')\n+\t\t|| (*refname1 == '/' && *refname2 == '\\0');\n }\n \n /*\n-- \n1.7.7\n"},{"id":"178431","messageId":"1319801284-15625-13-git-send-email-mhagger@alum.mit.edu","threadId":"28784","inReplyTo":"1319801284-15625-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH v2 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-28T11:28:04Z","receivedAt":"2011-10-28T11:28:04Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"From: Michael Haggerty <mhagger@alum.mit.edu>\n\nThis implementation will survive upcoming changes to the ref_array\ndata structure.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\n refs.c |   40 ++++++++++++++++++++++++++++++----------\n 1 files changed, 30 insertions(+), 10 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 2a5d8b2..96466f3 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1106,6 +1106,25 @@ static int names_conflict(const char *refname1, const char *refname2)\n \t\t|| (*refname1 == '/' && *refname2 == '\\0');\n }\n \n+struct name_conflict_cb {\n+\tconst char *refname;\n+\tconst char *oldrefname;\n+\tconst char *conflicting_refname;\n+};\n+\n+static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,\n+\t\t\t    int flags, void *cb_data)\n+{\n+\tstruct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;\n+\tif (data->oldrefname && !strcmp(data->oldrefname, existingrefname))\n+\t\treturn 0;\n+\tif (names_conflict(data->refname, existingrefname)) {\n+\t\tdata->conflicting_refname = existingrefname;\n+\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * Return true iff a reference named refname could be created without\n  * conflicting with the name of an existing reference.  If oldrefname\n@@ -1116,16 +1135,17 @@ static int names_conflict(const char *refname1, const char *refname2)\n static int is_refname_available(const char *refname, const char *oldrefname,\n \t\t\t\tstruct ref_array *array)\n {\n-\tint i;\n-\tfor (i = 0; i < array->nr; i++ ) {\n-\t\tstruct ref_entry *entry = array->refs[i];\n-\t\tif (oldrefname && !strcmp(oldrefname, entry->name))\n-\t\t\tcontinue;\n-\t\tif (names_conflict(refname, entry->name)) {\n-\t\t\terror(\"'%s' exists; cannot create '%s'\",\n-\t\t\t      entry->name, refname);\n-\t\t\treturn 0;\n-\t\t}\n+\tstruct name_conflict_cb data;\n+\tdata.refname = refname;\n+\tdata.oldrefname = oldrefname;\n+\tdata.conflicting_refname = NULL;\n+\n+\tif (do_for_each_ref_in_array(array, 0, \"\", name_conflict_fn,\n+\t\t\t\t     0, DO_FOR_EACH_INCLUDE_BROKEN,\n+\t\t\t\t     &data)) {\n+\t\terror(\"'%s' exists; cannot create '%s'\",\n+\t\t      data.conflicting_refname, refname);\n+\t\treturn 0;\n \t}\n \treturn 1;\n }\n-- \n1.7.7\n"}]}