t3001: test ls-files -o ignored/dir
[gitweb.git] / sha1_name.c
index 9d544a26332d14998bdcae0474bb66f1f542a4b4..44bb62d270739a232e87c90c05ce89fcc86bc15b 100644 (file)
@@ -242,10 +242,10 @@ static int ambiguous_path(const char *path, int len)
  * *string and *len will only be substituted, and *string returned (for
  * later free()ing) if the string passed in is of the form @{-<n>}.
  */
-static char *substitute_nth_last_branch(const char **string, int *len)
+static char *substitute_branch_name(const char **string, int *len)
 {
        struct strbuf buf = STRBUF_INIT;
-       int ret = interpret_nth_last_branch(*string, &buf);
+       int ret = interpret_branch_name(*string, &buf);
 
        if (ret == *len) {
                size_t size;
@@ -259,7 +259,7 @@ static char *substitute_nth_last_branch(const char **string, int *len)
 
 int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 {
-       char *last_branch = substitute_nth_last_branch(&str, &len);
+       char *last_branch = substitute_branch_name(&str, &len);
        const char **p, *r;
        int refs_found = 0;
 
@@ -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;
@@ -285,7 +288,7 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 
 int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
 {
-       char *last_branch = substitute_nth_last_branch(&str, &len);
+       char *last_branch = substitute_branch_name(&str, &len);
        const char **p;
        int logs_found = 0;
 
@@ -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);
@@ -352,7 +355,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
                struct strbuf buf = STRBUF_INIT;
                int ret;
                /* try the @{-N} syntax for n-th checkout */
-               ret = interpret_nth_last_branch(str+at, &buf);
+               ret = interpret_branch_name(str+at, &buf);
                if (ret > 0) {
                        /* substitute this branch name and restart */
                        return get_sha1_1(buf.buf, buf.len, sha1);
@@ -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);
@@ -751,10 +750,10 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
  * If the input was ok but there are not N branch switches in the
  * reflog, it returns 0.
  */
-int interpret_nth_last_branch(const char *name, struct strbuf *buf)
+int interpret_branch_name(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,25 @@ 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_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;
 }
 
 /*