{"thread":{"id":"28724","subject":"[PATCH 00/12] Use refs API more consistently","startedAt":"2011-10-19T21:44:40Z","lastAt":"2011-10-24T11:58:46Z","messageCount":18,"participants":["mhagger@alum.mit.edu","Junio C Hamano","Michael Haggerty"],"isPatch":true,"patchVersion":1,"patchTotal":12},"messages":[{"id":"178034","messageId":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":null,"subject":"[PATCH 00/12] Use refs API more consistently","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:40Z","receivedAt":"2011-10-19T21:44:40Z","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 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 becomes 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\nThis series applies on top of mh/ref-api-2.  It conflicts with the\n\"Checking full vs. partial refnames\" series that I just submitted but\nnot in any fundamental way.  I'll be happy to reconcile them for you\nin a later round when it is clear if and when each series is accepted.\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 |  259 ++++++++++++++++++++++++++++++++++++++++------------------------\n 1 files changed, 162 insertions(+), 97 deletions(-)\n\n-- \n1.7.7\n"},{"id":"178036","messageId":"1319060692-27216-2-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 01/12] Rename another local variable name -> refname","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:41Z","receivedAt":"2011-10-19T21:44:41Z","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\nI missed this one earlier.  (There are probably others too.  I hope\nyou don't feel that I'm morally obliged to find every single analogous\nexample...)\n\n refs.c |   22 +++++++++++-----------\n 1 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 7e6cea5..f6752a4 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -317,11 +317,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@@ -337,31 +337,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_BROKEN;\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_BROKEN;\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":"178035","messageId":"1319060692-27216-3-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 02/12] repack_without_ref(): remove temporary","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:42Z","receivedAt":"2011-10-19T21:44:42Z","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\nTrivial and boring.\n\n refs.c |    7 ++-----\n 1 files changed, 2 insertions(+), 5 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex f6752a4..431d3c6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1190,12 +1190,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@@ -1206,8 +1204,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":"178037","messageId":"1319060692-27216-4-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 03/12] parse_ref_line(): add a check that the refname is properly formatted","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:43Z","receivedAt":"2011-10-19T21:44:43Z","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 431d3c6..752938c 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -51,6 +51,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":"178042","messageId":"1319060692-27216-5-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 04/12] create_ref_entry(): extract function from add_ref()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:44Z","receivedAt":"2011-10-19T21:44:44Z","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 752938c..acb098c 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -57,27 +57,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":"178038","messageId":"1319060692-27216-6-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 05/12] add_ref(): take a (struct ref_entry *) parameter","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:45Z","receivedAt":"2011-10-19T21:44:45Z","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 acb098c..ae90993 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -75,13 +75,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@@ -266,7 +261,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@@ -281,7 +277,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@@ -368,7 +364,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_BROKEN;\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":"178041","messageId":"1319060692-27216-7-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 06/12] do_for_each_ref(): correctly terminate while processesing extra_refs","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:46Z","receivedAt":"2011-10-19T21:44:46Z","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\n refs.c |    5 ++++-\n 1 files changed, 4 insertions(+), 1 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex ae90993..7aef76c 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -706,8 +706,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":"178043","messageId":"1319060692-27216-8-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 07/12] do_for_each_ref_in_array(): new function","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:47Z","receivedAt":"2011-10-19T21:44:47Z","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 7aef76c..4e60edb 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -696,21 +696,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@@ -730,14 +740,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":"178039","messageId":"1319060692-27216-9-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 08/12] do_for_each_ref_in_arrays(): new function","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:48Z","receivedAt":"2011-10-19T21:44:48Z","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 4e60edb..cd3acf8 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -709,45 +709,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":"178040","messageId":"1319060692-27216-10-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 09/12] repack_without_ref(): reimplement using do_for_each_ref_in_array()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:49Z","receivedAt":"2011-10-19T21:44:49Z","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\n refs.c |   46 ++++++++++++++++++++++++++++------------------\n 1 files changed, 28 insertions(+), 18 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex cd3acf8..7c2bcab 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1213,36 +1213,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":"178048","messageId":"1319060692-27216-11-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 10/12] names_conflict(): new function, extracted from is_refname_available()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:50Z","receivedAt":"2011-10-19T21:44:50Z","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 7c2bcab..ada691b 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1088,6 +1088,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@@ -1097,20 +1121,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":"178047","messageId":"1319060692-27216-12-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 11/12] names_conflict(): simplify implementation","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:51Z","receivedAt":"2011-10-19T21:44:51Z","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 ada691b..4bc6041 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1096,19 +1096,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":"178046","messageId":"1319060692-27216-13-git-send-email-mhagger@alum.mit.edu","threadId":"28724","inReplyTo":"1319060692-27216-1-git-send-email-mhagger@alum.mit.edu","subject":"[PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()","fromName":"","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-19T21:44:52Z","receivedAt":"2011-10-19T21:44: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 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 |   44 ++++++++++++++++++++++++++++++++------------\n 1 files changed, 32 insertions(+), 12 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 4bc6041..c41d995 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1102,6 +1102,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+       const char *refname;\n+       const char *oldrefname;\n+       const 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+       struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;\n+       if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))\n+\t       return 0;\n+       if (names_conflict(data->refname, existingrefname)) {\n+\t       data->conflicting_refname = existingrefname;\n+\t       return 1;\n+       }\n+       return 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@@ -1112,18 +1131,19 @@ 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-\t}\n-\treturn 1;\n+       struct name_conflict_cb data;\n+       data.refname = refname;\n+       data.oldrefname = oldrefname;\n+       data.conflicting_refname = NULL;\n+\n+       if (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       error(\"'%s' exists; cannot create '%s'\",\n+\t\t     data.conflicting_refname, refname);\n+\t       return 0;\n+       }\n+       return 1;\n }\n \n static struct ref_lock *lock_ref_sha1_basic(const char *refname,\n-- \n1.7.7\n"},{"id":"178053","messageId":"7vfwiobo75.fsf@alter.siamese.dyndns.org","threadId":"28724","inReplyTo":"1319060692-27216-9-git-send-email-mhagger@alum.mit.edu","subject":"Re: [PATCH 08/12] do_for_each_ref_in_arrays(): new function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-19T22:39:58Z","receivedAt":"2011-10-19T22:39:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Is this necessary?  IOW, is the helper function usable in any context\nother than merge-iterate loose and packed refs?\n"},{"id":"178063","messageId":"7v4nz4bftk.fsf@alter.siamese.dyndns.org","threadId":"28724","inReplyTo":"1319060692-27216-13-git-send-email-mhagger@alum.mit.edu","subject":"Re: [PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-20T01:40:55Z","receivedAt":"2011-10-20T01:40:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Hmm, why is this patch and only this one in the series full of whitespace\nviolations? Did you use a different settings or something?\n"},{"id":"178077","messageId":"4E9FCDDE.4070107@alum.mit.edu","threadId":"28724","inReplyTo":"7vfwiobo75.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 08/12] do_for_each_ref_in_arrays(): new function","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-20T07:29:34Z","receivedAt":"2011-10-20T07:29:34Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/20/2011 12:39 AM, Junio C Hamano wrote:\n> Is this necessary?  IOW, is the helper function usable in any context\n> other than merge-iterate loose and packed refs?\n\nSoon the packed and cached refs will each be stored hierarchically, so\niteration through the combined caches will use a call to\ndo_for_each_ref_in_arrays() in each subdirectory, recursively.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"178078","messageId":"4E9FD1C3.3090302@alum.mit.edu","threadId":"28724","inReplyTo":"7v4nz4bftk.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-20T07:46:11Z","receivedAt":"2011-10-20T07:46:11Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/20/2011 03:40 AM, Junio C Hamano wrote:\n> Hmm, why is this patch and only this one in the series full of whitespace\n> violations? Did you use a different settings or something?\n\nThis happens rarely; I don't know why.  Maybe I copy-pasted snippets\nfrom a view in an application that expanded the tabs.  Maybe emacs's\neliza program has achieved self-awareness and is punishing me for never\nhaving properly learned elisp.\n\nThe incorrect lines are indented with 7, not 8, spaces so \"tabify\"\ndidn't help either.\n\nI'll fix in reroll after I've received any other feedback.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"178233","messageId":"4EA552F6.4010005@alum.mit.edu","threadId":"28724","inReplyTo":"4E9FD1C3.3090302@alum.mit.edu","subject":"Re: [PATCH 12/12] is_refname_available(): reimplement using do_for_each_ref_in_array()","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2011-10-24T11:58:46Z","receivedAt":"2011-10-24T11:58:46Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 10/20/2011 09:46 AM, Michael Haggerty wrote:\n> On 10/20/2011 03:40 AM, Junio C Hamano wrote:\n>> Hmm, why is this patch and only this one in the series full of whitespace\n>> violations? Did you use a different settings or something?\n> \n> This happens rarely; I don't know why.  Maybe I copy-pasted snippets\n> from a view in an application that expanded the tabs.  [...]\n\nNow I think I know how this happened.  When \"git diff\"'s output goes to\na TTY, it passes its output through the pager.  The default pager, less,\nseems to convert tabs into spaces.  I probably copy-pasted some output\nof diff into my editor then removed the first column of '+' characters.\n\nJust another reason why tabs are evil...\n\n:-)\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"}]}