parseopt: prevent KEEP_UNKNOWN and STOP_AT_NON_OPTION from being used together
[gitweb.git] / sha1_name.c
index 9d544a26332d14998bdcae0474bb66f1f542a4b4..2f75179f4c6c1d05bdd7594b23dcf77007c26751 100644 (file)
@@ -268,16 +268,19 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
                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, NULL);
+               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) &&
+                          (len != 4 || strcmp(str, "HEAD")))
+                       warning("ignoring dangling symref %s.", fullref);
        }
        free(last_branch);
        return refs_found;
@@ -334,7 +337,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 
        /* basic@{time or number or -number} format to query ref-log */
        reflog_len = at = 0;
-       if (str[len-1] == '}') {
+       if (len && str[len-1] == '}') {
                for (at = len-2; at >= 0; at--) {
                        if (str[at] == '@' && str[at+1] == '{') {
                                reflog_len = (len-1) - (at+2);
@@ -723,17 +726,13 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
 
        if (!prefixcmp(message, "checkout: moving from ")) {
                match = message + strlen("checkout: moving from ");
-               if ((target = strstr(match, " to ")) != NULL)
-                       target += 4;
+               target = strstr(match, " to ");
        }
 
-       if (!match)
-               return 0;
-
-       len = target - match - 4;
-       if (target[len] == '\n' && !strncmp(match, target, len))
+       if (!match || !target)
                return 0;
 
+       len = target - match;
        nth = cb->cnt++ % cb->alloc;
        strbuf_reset(&cb->buf[nth]);
        strbuf_add(&cb->buf[nth], match, len);
@@ -754,7 +753,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
 int interpret_nth_last_branch(const char *name, struct strbuf *buf)
 {
        long nth;
-       int i;
+       int i, retval;
        struct grab_nth_branch_switch_cbdata cb;
        const char *brace;
        char *num_end;
@@ -774,17 +773,27 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
        for (i = 0; i < nth; i++)
                strbuf_init(&cb.buf[i], 20);
        cb.cnt = 0;
-       for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
+       retval = 0;
+       for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
+       if (cb.cnt < nth) {
+               cb.cnt = 0;
+               for (i = 0; i < nth; i++)
+                       strbuf_release(&cb.buf[i]);
+               for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
+       }
        if (cb.cnt < nth)
-               return 0;
+               goto release_return;
        i = cb.cnt % nth;
        strbuf_reset(buf);
        strbuf_add(buf, cb.buf[i].buf, cb.buf[i].len);
+       retval = brace-name+1;
+
+release_return:
        for (i = 0; i < nth; i++)
                strbuf_release(&cb.buf[i]);
        free(cb.buf);
 
-       return brace-name+1;
+       return retval;
 }
 
 /*