Merge branch 'jc/broken-ref-dwim-fix'
authorJunio C Hamano <gitster@pobox.com>
Fri, 21 Oct 2011 23:04:36 +0000 (16:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Oct 2011 23:04:36 +0000 (16:04 -0700)
* jc/broken-ref-dwim-fix:
resolve_ref(): report breakage to the caller without warning
resolve_ref(): expose REF_ISBROKEN flag
refs.c: move dwim_ref()/dwim_log() from sha1_name.c

refs.c
refs.h
sha1_name.c
diff --git a/refs.c b/refs.c
index ee7e38182a5ded3aa13e513880be7edf52a5be2b..e69ba26b74e430388c63af21473438468678bb4b 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -4,9 +4,8 @@
 #include "tag.h"
 #include "dir.h"
 
-/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
-#define REF_KNOWS_PEELED 04
-#define REF_BROKEN 010
+/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
+#define REF_KNOWS_PEELED 0x10
 
 struct ref_entry {
        unsigned char flag; /* ISSYMREF? ISPACKED? */
@@ -332,12 +331,12 @@ static void get_ref_dir(const char *submodule, const char *base,
                                flag = 0;
                                if (resolve_gitlink_ref(submodule, ref, sha1) < 0) {
                                        hashclr(sha1);
-                                       flag |= REF_BROKEN;
+                                       flag |= REF_ISBROKEN;
                                }
                        } else
                                if (!resolve_ref(ref, sha1, 1, &flag)) {
                                        hashclr(sha1);
-                                       flag |= REF_BROKEN;
+                                       flag |= REF_ISBROKEN;
                                }
                        add_ref(ref, sha1, flag, array, NULL);
                }
@@ -504,7 +503,6 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
        ssize_t len;
        char buffer[256];
        static char ref_buffer[256];
-       char path[PATH_MAX];
 
        if (flag)
                *flag = 0;
@@ -513,6 +511,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
                return NULL;
 
        for (;;) {
+               char path[PATH_MAX];
                struct stat st;
                char *buf;
                int fd;
@@ -585,21 +584,22 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
                 */
                if (prefixcmp(buffer, "ref:"))
                        break;
+               if (flag)
+                       *flag |= REF_ISSYMREF;
                buf = buffer + 4;
                while (isspace(*buf))
                        buf++;
                if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
-                       warning("symbolic reference in %s is formatted incorrectly",
-                               path);
+                       if (flag)
+                               *flag |= REF_ISBROKEN;
                        return NULL;
                }
                ref = strcpy(ref_buffer, buf);
-               if (flag)
-                       *flag |= REF_ISSYMREF;
        }
        /* Please note that FETCH_HEAD has a second line containing other data. */
        if (get_sha1_hex(buffer, sha1) || (buffer[40] != '\0' && !isspace(buffer[40]))) {
-               warning("reference in %s is formatted incorrectly", path);
+               if (flag)
+                       *flag |= REF_ISBROKEN;
                return NULL;
        }
        return ref;
@@ -627,8 +627,8 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
                return 0;
 
        if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
-               if (entry->flag & REF_BROKEN)
-                       return 0; /* ignore dangling symref */
+               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;
@@ -1078,6 +1078,94 @@ static int is_refname_available(const char *ref, const char *oldref,
        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.
+ */
+static char *substitute_branch_name(const char **string, int *len)
+{
+       struct strbuf buf = STRBUF_INIT;
+       int ret = interpret_branch_name(*string, &buf);
+
+       if (ret == *len) {
+               size_t size;
+               *string = strbuf_detach(&buf, &size);
+               *len = size;
+               return (char *)*string;
+       }
+
+       return NULL;
+}
+
+int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
+{
+       char *last_branch = substitute_branch_name(&str, &len);
+       const char **p, *r;
+       int refs_found = 0;
+
+       *ref = NULL;
+       for (p = ref_rev_parse_rules; *p; p++) {
+               char fullref[PATH_MAX];
+               unsigned char sha1_from_ref[20];
+               unsigned char *this_result;
+               int flag;
+
+               this_result = refs_found ? sha1_from_ref : sha1;
+               mksnpath(fullref, sizeof(fullref), *p, len, str);
+               r = resolve_ref(fullref, this_result, 1, &flag);
+               if (r) {
+                       if (!refs_found++)
+                               *ref = xstrdup(r);
+                       if (!warn_ambiguous_refs)
+                               break;
+               } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) {
+                       warning("ignoring dangling symref %s.", fullref);
+               } else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) {
+                       warning("ignoring broken ref %s.", fullref);
+               }
+       }
+       free(last_branch);
+       return refs_found;
+}
+
+int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
+{
+       char *last_branch = substitute_branch_name(&str, &len);
+       const char **p;
+       int logs_found = 0;
+
+       *log = NULL;
+       for (p = ref_rev_parse_rules; *p; p++) {
+               struct stat st;
+               unsigned char hash[20];
+               char path[PATH_MAX];
+               const char *ref, *it;
+
+               mksnpath(path, sizeof(path), *p, len, str);
+               ref = resolve_ref(path, hash, 1, NULL);
+               if (!ref)
+                       continue;
+               if (!stat(git_path("logs/%s", path), &st) &&
+                   S_ISREG(st.st_mode))
+                       it = path;
+               else if (strcmp(ref, path) &&
+                        !stat(git_path("logs/%s", ref), &st) &&
+                        S_ISREG(st.st_mode))
+                       it = ref;
+               else
+                       continue;
+               if (!logs_found++) {
+                       *log = xstrdup(it);
+                       hashcpy(sha1, hash);
+               }
+               if (!warn_ambiguous_refs)
+                       break;
+       }
+       free(last_branch);
+       return logs_found;
+}
+
 static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int flags, int *type_p)
 {
        char *ref_file;
diff --git a/refs.h b/refs.h
index f439c54eb23f11e084ad9f8299d17e2ad888424b..3fd55369f90829706c3f4b11329fadc38380da32 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -10,8 +10,9 @@ struct ref_lock {
        int force_write;
 };
 
-#define REF_ISSYMREF 01
-#define REF_ISPACKED 02
+#define REF_ISSYMREF 0x01
+#define REF_ISPACKED 0x02
+#define REF_ISBROKEN 0x04
 
 /*
  * Calls the specified function for each ref file until it returns nonzero,
index ba976b48398d4be0635746bcabb5b1c881e77ae8..03ffc2caaa6524a3361bc47a89e101ced2f0e987 100644 (file)
@@ -241,91 +241,6 @@ static int ambiguous_path(const char *path, int len)
        return slash;
 }
 
-/*
- * *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.
- */
-static char *substitute_branch_name(const char **string, int *len)
-{
-       struct strbuf buf = STRBUF_INIT;
-       int ret = interpret_branch_name(*string, &buf);
-
-       if (ret == *len) {
-               size_t size;
-               *string = strbuf_detach(&buf, &size);
-               *len = size;
-               return (char *)*string;
-       }
-
-       return NULL;
-}
-
-int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
-{
-       char *last_branch = substitute_branch_name(&str, &len);
-       const char **p, *r;
-       int refs_found = 0;
-
-       *ref = NULL;
-       for (p = ref_rev_parse_rules; *p; p++) {
-               char fullref[PATH_MAX];
-               unsigned char sha1_from_ref[20];
-               unsigned char *this_result;
-               int flag;
-
-               this_result = refs_found ? sha1_from_ref : sha1;
-               mksnpath(fullref, sizeof(fullref), *p, len, str);
-               r = resolve_ref(fullref, this_result, 1, &flag);
-               if (r) {
-                       if (!refs_found++)
-                               *ref = xstrdup(r);
-                       if (!warn_ambiguous_refs)
-                               break;
-               } else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD"))
-                       warning("ignoring dangling symref %s.", fullref);
-       }
-       free(last_branch);
-       return refs_found;
-}
-
-int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
-{
-       char *last_branch = substitute_branch_name(&str, &len);
-       const char **p;
-       int logs_found = 0;
-
-       *log = NULL;
-       for (p = ref_rev_parse_rules; *p; p++) {
-               struct stat st;
-               unsigned char hash[20];
-               char path[PATH_MAX];
-               const char *ref, *it;
-
-               mksnpath(path, sizeof(path), *p, len, str);
-               ref = resolve_ref(path, hash, 1, NULL);
-               if (!ref)
-                       continue;
-               if (!stat(git_path("logs/%s", path), &st) &&
-                   S_ISREG(st.st_mode))
-                       it = path;
-               else if (strcmp(ref, path) &&
-                        !stat(git_path("logs/%s", ref), &st) &&
-                        S_ISREG(st.st_mode))
-                       it = ref;
-               else
-                       continue;
-               if (!logs_found++) {
-                       *log = xstrdup(it);
-                       hashcpy(sha1, hash);
-               }
-               if (!warn_ambiguous_refs)
-                       break;
-       }
-       free(last_branch);
-       return logs_found;
-}
-
 static inline int upstream_mark(const char *string, int len)
 {
        const char *suffix[] = { "@{upstream}", "@{u}" };