Merge branch 'mh/iterate-refs'
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2011 22:56:18 +0000 (15:56 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Oct 2011 22:56:18 +0000 (15:56 -0700)
* mh/iterate-refs:
refs.c: make create_cached_refs() static
Retain caches of submodule refs
Store the submodule name in struct cached_refs
Allocate cached_refs objects dynamically
Change the signature of read_packed_refs()
Access reference caches only through new function get_cached_refs()
Extract a function clear_cached_refs()

1  2 
refs.c
diff --combined refs.c
index a615043b34cd6d0507d8a30f7bd69445ec9f2456,2cb93e2f7b4dbf86d832751852bb7337f3578efe..6e9588bf161a895f4f9adc750ba9f7ac53b84b2b
--- 1/refs.c
--- 2/refs.c
+++ b/refs.c
@@@ -153,11 -153,15 +153,15 @@@ static struct ref_list *sort_ref_list(s
   * when doing a full libification.
   */
  static struct cached_refs {
+       struct cached_refs *next;
        char did_loose;
        char did_packed;
        struct ref_list *loose;
        struct ref_list *packed;
- } cached_refs, submodule_refs;
+       /* The submodule name, or "" for the main repo. */
+       char name[FLEX_ARRAY];
+ } *cached_refs;
  static struct ref_list *current_ref;
  
  static struct ref_list *extra_refs;
@@@ -171,10 -175,8 +175,8 @@@ static void free_ref_list(struct ref_li
        }
  }
  
- static void invalidate_cached_refs(void)
+ static void clear_cached_refs(struct cached_refs *ca)
  {
-       struct cached_refs *ca = &cached_refs;
        if (ca->did_loose && ca->loose)
                free_ref_list(ca->loose);
        if (ca->did_packed && ca->packed)
        ca->did_loose = ca->did_packed = 0;
  }
  
- static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
+ static struct cached_refs *create_cached_refs(const char *submodule)
+ {
+       int len;
+       struct cached_refs *refs;
+       if (!submodule)
+               submodule = "";
+       len = strlen(submodule) + 1;
+       refs = xmalloc(sizeof(struct cached_refs) + len);
+       refs->next = NULL;
+       refs->did_loose = refs->did_packed = 0;
+       refs->loose = refs->packed = NULL;
+       memcpy(refs->name, submodule, len);
+       return refs;
+ }
+ /*
+  * Return a pointer to a cached_refs for the specified submodule. For
+  * the main repository, use submodule==NULL. The returned structure
+  * will be allocated and initialized but not necessarily populated; it
+  * should not be freed.
+  */
+ static struct cached_refs *get_cached_refs(const char *submodule)
+ {
+       struct cached_refs *refs = cached_refs;
+       if (!submodule)
+               submodule = "";
+       while (refs) {
+               if (!strcmp(submodule, refs->name))
+                       return refs;
+               refs = refs->next;
+       }
+       refs = create_cached_refs(submodule);
+       refs->next = cached_refs;
+       cached_refs = refs;
+       return refs;
+ }
+ static void invalidate_cached_refs(void)
+ {
+       struct cached_refs *refs = cached_refs;
+       while (refs) {
+               clear_cached_refs(refs);
+               refs = refs->next;
+       }
+ }
+ static struct ref_list *read_packed_refs(FILE *f)
  {
        struct ref_list *list = NULL;
        struct ref_list *last = NULL;
                    !get_sha1_hex(refline + 1, sha1))
                        hashcpy(last->peeled, sha1);
        }
-       cached_refs->packed = sort_ref_list(list);
+       return sort_ref_list(list);
  }
  
  void add_extra_ref(const char *name, const unsigned char *sha1, int flag)
@@@ -231,23 -280,20 +280,20 @@@ void clear_extra_refs(void
  
  static struct ref_list *get_packed_refs(const char *submodule)
  {
-       const char *packed_refs_file;
-       struct cached_refs *refs;
+       struct cached_refs *refs = get_cached_refs(submodule);
  
-       if (submodule) {
-               packed_refs_file = git_path_submodule(submodule, "packed-refs");
-               refs = &submodule_refs;
-               free_ref_list(refs->packed);
-       } else {
-               packed_refs_file = git_path("packed-refs");
-               refs = &cached_refs;
-       }
+       if (!refs->did_packed) {
+               const char *packed_refs_file;
+               FILE *f;
  
-       if (!refs->did_packed || submodule) {
-               FILE *f = fopen(packed_refs_file, "r");
+               if (submodule)
+                       packed_refs_file = git_path_submodule(submodule, "packed-refs");
+               else
+                       packed_refs_file = git_path("packed-refs");
+               f = fopen(packed_refs_file, "r");
                refs->packed = NULL;
                if (f) {
-                       read_packed_refs(f, refs);
+                       refs->packed = read_packed_refs(f);
                        fclose(f);
                }
                refs->did_packed = 1;
@@@ -358,17 -404,13 +404,13 @@@ void warn_dangling_symref(FILE *fp, con
  
  static struct ref_list *get_loose_refs(const char *submodule)
  {
-       if (submodule) {
-               free_ref_list(submodule_refs.loose);
-               submodule_refs.loose = get_ref_dir(submodule, "refs", NULL);
-               return submodule_refs.loose;
-       }
+       struct cached_refs *refs = get_cached_refs(submodule);
  
-       if (!cached_refs.did_loose) {
-               cached_refs.loose = get_ref_dir(NULL, "refs", NULL);
-               cached_refs.did_loose = 1;
+       if (!refs->did_loose) {
+               refs->loose = get_ref_dir(submodule, "refs", NULL);
+               refs->did_loose = 1;
        }
-       return cached_refs.loose;
+       return refs->loose;
  }
  
  /* We allow "recursive" symbolic refs. Only within reason, though */
  static int resolve_gitlink_packed_ref(char *name, int pathlen, const char *refname, unsigned char *result)
  {
        FILE *f;
-       struct cached_refs refs;
+       struct ref_list *packed_refs;
        struct ref_list *ref;
        int retval;
  
        f = fopen(name, "r");
        if (!f)
                return -1;
-       read_packed_refs(f, &refs);
+       packed_refs = read_packed_refs(f);
        fclose(f);
-       ref = refs.packed;
+       ref = packed_refs;
        retval = -1;
        while (ref) {
                if (!strcmp(ref->name, refname)) {
                }
                ref = ref->next;
        }
-       free_ref_list(refs.packed);
+       free_ref_list(packed_refs);
        return retval;
  }
  
@@@ -451,7 -493,7 +493,7 @@@ int resolve_gitlink_ref(const char *pat
        memcpy(gitdir + len, "/.git", 6);
        len += 5;
  
 -      tmp = read_gitfile_gently(gitdir);
 +      tmp = read_gitfile(gitdir);
        if (tmp) {
                free(gitdir);
                len = strlen(tmp);
@@@ -584,7 -626,7 +626,7 @@@ int read_ref(const char *ref, unsigned 
  static int do_one_ref(const char *base, each_ref_fn fn, int trim,
                      int flags, void *cb_data, struct ref_list *entry)
  {
 -      if (strncmp(base, entry->name, trim))
 +      if (prefixcmp(entry->name, base))
                return 0;
  
        if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
@@@ -728,12 -770,12 +770,12 @@@ int head_ref_submodule(const char *subm
  
  int for_each_ref(each_ref_fn fn, void *cb_data)
  {
 -      return do_for_each_ref(NULL, "refs/", fn, 0, 0, cb_data);
 +      return do_for_each_ref(NULL, "", fn, 0, 0, cb_data);
  }
  
  int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
  {
 -      return do_for_each_ref(submodule, "refs/", fn, 0, 0, cb_data);
 +      return do_for_each_ref(submodule, "", fn, 0, 0, cb_data);
  }
  
  int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
@@@ -782,31 -824,6 +824,31 @@@ int for_each_replace_ref(each_ref_fn fn
        return do_for_each_ref(NULL, "refs/replace/", fn, 13, 0, cb_data);
  }
  
 +int head_ref_namespaced(each_ref_fn fn, void *cb_data)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +      int ret = 0;
 +      unsigned char sha1[20];
 +      int flag;
 +
 +      strbuf_addf(&buf, "%sHEAD", get_git_namespace());
 +      if (resolve_ref(buf.buf, sha1, 1, &flag))
 +              ret = fn(buf.buf, sha1, flag, cb_data);
 +      strbuf_release(&buf);
 +
 +      return ret;
 +}
 +
 +int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +      int ret;
 +      strbuf_addf(&buf, "%srefs/", get_git_namespace());
 +      ret = do_for_each_ref(NULL, buf.buf, fn, 0, 0, cb_data);
 +      strbuf_release(&buf);
 +      return ret;
 +}
 +
  int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
        const char *prefix, void *cb_data)
  {
@@@ -844,7 -861,7 +886,7 @@@ int for_each_glob_ref(each_ref_fn fn, c
  
  int for_each_rawref(each_ref_fn fn, void *cb_data)
  {
 -      return do_for_each_ref(NULL, "refs/", fn, 0,
 +      return do_for_each_ref(NULL, "", fn, 0,
                               DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
  }
  
  
  static inline int bad_ref_char(int ch)
  {
 -      if (((unsigned) ch) <= ' ' ||
 +      if (((unsigned) ch) <= ' ' || ch == 0x7f ||
            ch == '~' || ch == '^' || ch == ':' || ch == '\\')
                return 1;
        /* 2.13 Pattern Matching Notation */