Sync with 2.6.4
[gitweb.git] / builtin / show-branch.c
index 9b0aba2accee0b1984aba859b22b423f0bab5dec..e17744bc0dad37b75865b5da8c8c3037bcc02167 100644 (file)
@@ -3,6 +3,7 @@
 #include "refs.h"
 #include "builtin.h"
 #include "color.h"
+#include "argv-array.h"
 #include "parse-options.h"
 
 static const char* show_branch_usage[] = {
@@ -16,9 +17,7 @@ static const char* show_branch_usage[] = {
 
 static int showbranch_use_color = -1;
 
-static int default_num;
-static int default_alloc;
-static const char **default_arg;
+static struct argv_array default_args = ARGV_ARRAY_INIT;
 
 #define UNINTERESTING  01
 
@@ -53,17 +52,6 @@ static struct commit *interesting(struct commit_list *list)
        return NULL;
 }
 
-static struct commit *pop_one_commit(struct commit_list **list_p)
-{
-       struct commit *commit;
-       struct commit_list *list;
-       list = *list_p;
-       commit = list->item;
-       *list_p = list->next;
-       free(list);
-       return commit;
-}
-
 struct commit_name {
        const char *head_name; /* which head's ancestor? */
        int generation; /* how many parents away from head_name */
@@ -213,7 +201,7 @@ static void join_revs(struct commit_list **list_p,
        while (*list_p) {
                struct commit_list *parents;
                int still_interesting = !!interesting(*list_p);
-               struct commit *commit = pop_one_commit(list_p);
+               struct commit *commit = pop_commit(list_p);
                int flags = commit->object.flags & all_mask;
 
                if (!still_interesting && extra <= 0)
@@ -369,10 +357,10 @@ static void sort_ref_range(int bottom, int top)
              compare_ref_name);
 }
 
-static int append_ref(const char *refname, const unsigned char *sha1,
+static int append_ref(const char *refname, const struct object_id *oid,
                      int allow_dups)
 {
-       struct commit *commit = lookup_commit_reference_gently(sha1, 1);
+       struct commit *commit = lookup_commit_reference_gently(oid->hash, 1);
        int i;
 
        if (!commit)
@@ -394,39 +382,42 @@ static int append_ref(const char *refname, const unsigned char *sha1,
        return 0;
 }
 
-static int append_head_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+static int append_head_ref(const char *refname, const struct object_id *oid,
+                          int flag, void *cb_data)
 {
-       unsigned char tmp[20];
+       struct object_id tmp;
        int ofs = 11;
        if (!starts_with(refname, "refs/heads/"))
                return 0;
        /* If both heads/foo and tags/foo exists, get_sha1 would
         * get confused.
         */
-       if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
+       if (get_sha1(refname + ofs, tmp.hash) || oidcmp(&tmp, oid))
                ofs = 5;
-       return append_ref(refname + ofs, sha1, 0);
+       return append_ref(refname + ofs, oid, 0);
 }
 
-static int append_remote_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+static int append_remote_ref(const char *refname, const struct object_id *oid,
+                            int flag, void *cb_data)
 {
-       unsigned char tmp[20];
+       struct object_id tmp;
        int ofs = 13;
        if (!starts_with(refname, "refs/remotes/"))
                return 0;
        /* If both heads/foo and tags/foo exists, get_sha1 would
         * get confused.
         */
-       if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
+       if (get_sha1(refname + ofs, tmp.hash) || oidcmp(&tmp, oid))
                ofs = 5;
-       return append_ref(refname + ofs, sha1, 0);
+       return append_ref(refname + ofs, oid, 0);
 }
 
-static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+static int append_tag_ref(const char *refname, const struct object_id *oid,
+                         int flag, void *cb_data)
 {
        if (!starts_with(refname, "refs/tags/"))
                return 0;
-       return append_ref(refname + 5, sha1, 0);
+       return append_ref(refname + 5, oid, 0);
 }
 
 static const char *match_ref_pattern = NULL;
@@ -440,7 +431,8 @@ static int count_slash(const char *s)
        return cnt;
 }
 
-static int append_matching_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+static int append_matching_ref(const char *refname, const struct object_id *oid,
+                              int flag, void *cb_data)
 {
        /* we want to allow pattern hold/<asterisk> to show all
         * branches under refs/heads/hold/, and v0.99.9? to show
@@ -456,21 +448,23 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
        if (wildmatch(match_ref_pattern, tail, 0, NULL))
                return 0;
        if (starts_with(refname, "refs/heads/"))
-               return append_head_ref(refname, sha1, flag, cb_data);
+               return append_head_ref(refname, oid, flag, cb_data);
        if (starts_with(refname, "refs/tags/"))
-               return append_tag_ref(refname, sha1, flag, cb_data);
-       return append_ref(refname, sha1, 0);
+               return append_tag_ref(refname, oid, flag, cb_data);
+       return append_ref(refname, oid, 0);
 }
 
 static void snarf_refs(int head, int remotes)
 {
        if (head) {
                int orig_cnt = ref_name_cnt;
+
                for_each_ref(append_head_ref, NULL);
                sort_ref_range(orig_cnt, ref_name_cnt);
        }
        if (remotes) {
                int orig_cnt = ref_name_cnt;
+
                for_each_ref(append_remote_ref, NULL);
                sort_ref_range(orig_cnt, ref_name_cnt);
        }
@@ -498,7 +492,7 @@ static int show_merge_base(struct commit_list *seen, int num_rev)
        int exit_status = 1;
 
        while (seen) {
-               struct commit *commit = pop_one_commit(&seen);
+               struct commit *commit = pop_commit(&seen);
                int flags = commit->object.flags & all_mask;
                if (!(flags & UNINTERESTING) &&
                    ((flags & all_revs) == all_revs)) {
@@ -530,14 +524,15 @@ static int show_independent(struct commit **rev,
 
 static void append_one_rev(const char *av)
 {
-       unsigned char revkey[20];
-       if (!get_sha1(av, revkey)) {
-               append_ref(av, revkey, 0);
+       struct object_id revkey;
+       if (!get_sha1(av, revkey.hash)) {
+               append_ref(av, &revkey, 0);
                return;
        }
        if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
                /* glob style match */
                int saved_matches = ref_name_cnt;
+
                match_ref_pattern = av;
                match_ref_slash = count_slash(av);
                for_each_ref(append_matching_ref, NULL);
@@ -560,16 +555,9 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
                 * default_arg is now passed to parse_options(), so we need to
                 * mimic the real argv a bit better.
                 */
-               if (!default_num) {
-                       default_alloc = 20;
-                       default_arg = xcalloc(default_alloc, sizeof(*default_arg));
-                       default_arg[default_num++] = "show-branch";
-               } else if (default_alloc <= default_num + 1) {
-                       default_alloc = default_alloc * 3 / 2 + 20;
-                       REALLOC_ARRAY(default_arg, default_alloc);
-               }
-               default_arg[default_num++] = xstrdup(value);
-               default_arg[default_num] = NULL;
+               if (!default_args.argc)
+                       argv_array_push(&default_args, "show-branch");
+               argv_array_push(&default_args, value);
                return 0;
        }
 
@@ -636,7 +624,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        char head[128];
        const char *head_p;
        int head_len;
-       unsigned char head_sha1[20];
+       struct object_id head_oid;
        int merge_base = 0;
        int independent = 0;
        int no_name = 0;
@@ -689,9 +677,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        git_config(git_show_branch_config, NULL);
 
        /* If nothing is specified, try the default first */
-       if (ac == 1 && default_num) {
-               ac = default_num;
-               av = default_arg;
+       if (ac == 1 && default_args.argc) {
+               ac = default_args.argc;
+               av = default_args.argv;
        }
 
        ac = parse_options(ac, av, prefix, builtin_show_branch_options,
@@ -718,11 +706,11 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        }
 
        /* If nothing is specified, show all branches by default */
-       if (ac + all_heads + all_remotes == 0)
+       if (ac <= topics && all_heads + all_remotes == 0)
                all_heads = 1;
 
        if (reflog) {
-               unsigned char sha1[20];
+               struct object_id oid;
                char *ref;
                int base = 0;
                unsigned int flags = 0;
@@ -732,10 +720,12 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 
                        fake_av[0] = resolve_refdup("HEAD",
                                                    RESOLVE_REF_READING,
-                                                   sha1, NULL);
+                                                   oid.hash, NULL);
                        fake_av[1] = NULL;
                        av = fake_av;
                        ac = 1;
+                       if (!*av)
+                               die("no branches given, and HEAD is not valid");
                }
                if (ac != 1)
                        die("--reflog option needs one branch name");
@@ -743,7 +733,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                if (MAX_REVS < reflog)
                        die("Only %d entries can be shown at one time.",
                            MAX_REVS);
-               if (!dwim_ref(*av, strlen(*av), sha1, &ref))
+               if (!dwim_ref(*av, strlen(*av), oid.hash, &ref))
                        die("No such ref %s", *av);
 
                /* Has the base been specified? */
@@ -754,7 +744,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                                /* Ah, that is a date spec... */
                                unsigned long at;
                                at = approxidate(reflog_base);
-                               read_ref_at(ref, flags, at, -1, sha1, NULL,
+                               read_ref_at(ref, flags, at, -1, oid.hash, NULL,
                                            NULL, NULL, &base);
                        }
                }
@@ -766,7 +756,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        unsigned long timestamp;
                        int tz;
 
-                       if (read_ref_at(ref, flags, 0, base+i, sha1, &logmsg,
+                       if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg,
                                        &timestamp, &tz, NULL)) {
                                reflog = i;
                                break;
@@ -777,27 +767,28 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        else
                                msg++;
                        reflog_msg[i] = xstrfmt("(%s) %s",
-                                               show_date(timestamp, tz, 1),
+                                               show_date(timestamp, tz,
+                                                         DATE_MODE(RELATIVE)),
                                                msg);
                        free(logmsg);
 
                        nth_desc = xstrfmt("%s@{%d}", *av, base+i);
-                       append_ref(nth_desc, sha1, 1);
+                       append_ref(nth_desc, &oid, 1);
                        free(nth_desc);
                }
                free(ref);
        }
-       else if (all_heads + all_remotes)
-               snarf_refs(all_heads, all_remotes);
        else {
                while (0 < ac) {
                        append_one_rev(*av);
                        ac--; av++;
                }
+               if (all_heads + all_remotes)
+                       snarf_refs(all_heads, all_remotes);
        }
 
        head_p = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
-                                   head_sha1, NULL);
+                                   head_oid.hash, NULL);
        if (head_p) {
                head_len = strlen(head_p);
                memcpy(head, head_p, head_len + 1);
@@ -816,7 +807,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        if (rev_is_head(head,
                                        head_len,
                                        ref_name[i],
-                                       head_sha1, NULL))
+                                       head_oid.hash, NULL))
                                has_head++;
                }
                if (!has_head) {
@@ -831,17 +822,17 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        }
 
        for (num_rev = 0; ref_name[num_rev]; num_rev++) {
-               unsigned char revkey[20];
+               struct object_id revkey;
                unsigned int flag = 1u << (num_rev + REV_SHIFT);
 
                if (MAX_REVS <= num_rev)
                        die("cannot handle more than %d revs.", MAX_REVS);
-               if (get_sha1(ref_name[num_rev], revkey))
+               if (get_sha1(ref_name[num_rev], revkey.hash))
                        die("'%s' is not a valid ref.", ref_name[num_rev]);
-               commit = lookup_commit_reference(revkey);
+               commit = lookup_commit_reference(revkey.hash);
                if (!commit)
                        die("cannot find commit %s (%s)",
-                           ref_name[num_rev], revkey);
+                           ref_name[num_rev], oid_to_hex(&revkey));
                parse_commit(commit);
                mark_seen(commit, &seen);
 
@@ -875,7 +866,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        int is_head = rev_is_head(head,
                                                  head_len,
                                                  ref_name[i],
-                                                 head_sha1,
+                                                 head_oid.hash,
                                                  rev[i]->object.sha1);
                        if (extra < 0)
                                printf("%c [%s] ",
@@ -919,7 +910,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
 
        while (seen) {
-               struct commit *commit = pop_one_commit(&seen);
+               struct commit *commit = pop_commit(&seen);
                int this_flag = commit->object.flags;
                int is_merge_point = ((this_flag & all_revs) == all_revs);