resolve_ref_unsafe(): ensure flags is always set
[gitweb.git] / refs / files-backend.c
index 9676ec2fd1054836a2695978430ae2977ae2dab8..067ce1c39e5f2fb12c12d2895f1584b90d2b5688 100644 (file)
@@ -1368,11 +1368,9 @@ static struct ref_entry *get_packed_ref(const char *refname)
 }
 
 /*
- * A loose ref file doesn't exist; check for a packed ref.  The
- * options are forwarded from resolve_safe_unsafe().
+ * A loose ref file doesn't exist; check for a packed ref.
  */
 static int resolve_missing_loose_ref(const char *refname,
-                                    int resolve_flags,
                                     unsigned char *sha1,
                                     int *flags)
 {
@@ -1385,18 +1383,11 @@ static int resolve_missing_loose_ref(const char *refname,
        entry = get_packed_ref(refname);
        if (entry) {
                hashcpy(sha1, entry->u.value.oid.hash);
-               if (flags)
-                       *flags |= REF_ISPACKED;
-               return 0;
-       }
-       /* The reference is not a packed reference, either. */
-       if (resolve_flags & RESOLVE_REF_READING) {
-               errno = ENOENT;
-               return -1;
-       } else {
-               hashclr(sha1);
+               *flags |= REF_ISPACKED;
                return 0;
        }
+       /* refname is not a packed reference. */
+       return -1;
 }
 
 /* This function needs to return a meaningful errno on failure */
@@ -1408,15 +1399,13 @@ static const char *resolve_ref_1(const char *refname,
                                 struct strbuf *sb_path,
                                 struct strbuf *sb_contents)
 {
-       int depth = MAXDEPTH;
        int bad_name = 0;
+       int symref_count;
 
-       if (flags)
-               *flags = 0;
+       *flags = 0;
 
        if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
-               if (flags)
-                       *flags |= REF_BAD_NAME;
+               *flags |= REF_BAD_NAME;
 
                if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
                    !refname_is_safe(refname)) {
@@ -1433,17 +1422,13 @@ static const char *resolve_ref_1(const char *refname,
                 */
                bad_name = 1;
        }
-       for (;;) {
+
+       for (symref_count = 0; symref_count < MAXDEPTH; symref_count++) {
                const char *path;
                struct stat st;
                char *buf;
                int fd;
 
-               if (--depth < 0) {
-                       errno = ELOOP;
-                       return NULL;
-               }
-
                strbuf_reset(sb_path);
                strbuf_git_path(sb_path, "%s", refname);
                path = sb_path->buf;
@@ -1461,13 +1446,16 @@ static const char *resolve_ref_1(const char *refname,
                if (lstat(path, &st) < 0) {
                        if (errno != ENOENT)
                                return NULL;
-                       if (resolve_missing_loose_ref(refname, resolve_flags,
-                                                     sha1, flags))
-                               return NULL;
+                       if (resolve_missing_loose_ref(refname, sha1, flags)) {
+                               if (resolve_flags & RESOLVE_REF_READING) {
+                                       errno = ENOENT;
+                                       return NULL;
+                               }
+                               hashclr(sha1);
+                       }
                        if (bad_name) {
                                hashclr(sha1);
-                               if (flags)
-                                       *flags |= REF_ISBROKEN;
+                               *flags |= REF_ISBROKEN;
                        }
                        return refname;
                }
@@ -1486,8 +1474,7 @@ static const char *resolve_ref_1(const char *refname,
                            !check_refname_format(sb_contents->buf, 0)) {
                                strbuf_swap(sb_refname, sb_contents);
                                refname = sb_refname->buf;
-                               if (flags)
-                                       *flags |= REF_ISSYMREF;
+                               *flags |= REF_ISSYMREF;
                                if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
                                        hashclr(sha1);
                                        return refname;
@@ -1534,20 +1521,17 @@ static const char *resolve_ref_1(const char *refname,
                         */
                        if (get_sha1_hex(sb_contents->buf, sha1) ||
                            (sb_contents->buf[40] != '\0' && !isspace(sb_contents->buf[40]))) {
-                               if (flags)
-                                       *flags |= REF_ISBROKEN;
+                               *flags |= REF_ISBROKEN;
                                errno = EINVAL;
                                return NULL;
                        }
                        if (bad_name) {
                                hashclr(sha1);
-                               if (flags)
-                                       *flags |= REF_ISBROKEN;
+                               *flags |= REF_ISBROKEN;
                        }
                        return refname;
                }
-               if (flags)
-                       *flags |= REF_ISSYMREF;
+               *flags |= REF_ISSYMREF;
                buf = sb_contents->buf + 4;
                while (isspace(*buf))
                        buf++;
@@ -1559,8 +1543,7 @@ static const char *resolve_ref_1(const char *refname,
                        return refname;
                }
                if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
-                       if (flags)
-                               *flags |= REF_ISBROKEN;
+                       *flags |= REF_ISBROKEN;
 
                        if (!(resolve_flags & RESOLVE_REF_ALLOW_BAD_NAME) ||
                            !refname_is_safe(buf)) {
@@ -1570,6 +1553,9 @@ static const char *resolve_ref_1(const char *refname,
                        bad_name = 1;
                }
        }
+
+       errno = ELOOP;
+       return NULL;
 }
 
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
@@ -1578,8 +1564,12 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
        static struct strbuf sb_refname = STRBUF_INIT;
        struct strbuf sb_contents = STRBUF_INIT;
        struct strbuf sb_path = STRBUF_INIT;
+       int unused_flags;
        const char *ret;
 
+       if (!flags)
+               flags = &unused_flags;
+
        ret = resolve_ref_1(refname, resolve_flags, sha1, flags,
                            &sb_refname, &sb_path, &sb_contents);
        strbuf_release(&sb_path);