Merge branch 'jt/avoid-ls-refs-with-http'
[gitweb.git] / revision.c
index eb8e51bc6302b65dfc5a921d59b2bcacd6cc19d9..51690e480d5b626224e919f04dbfb8d1c3426f3e 100644 (file)
@@ -436,7 +436,9 @@ static struct commit *handle_commit(struct rev_info *revs,
                        die("unable to parse commit %s", name);
                if (flags & UNINTERESTING) {
                        mark_parents_uninteresting(commit);
-                       revs->limited = 1;
+
+                       if (!revs->topo_order || !generation_numbers_enabled(the_repository))
+                               revs->limited = 1;
                }
                if (revs->sources) {
                        char **slot = revision_sources_at(revs->sources, commit);
@@ -911,26 +913,11 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                commit->object.flags |= TREESAME;
 }
 
-static void commit_list_insert_by_date_cached(struct commit *p, struct commit_list **head,
-                   struct commit_list *cached_base, struct commit_list **cache)
-{
-       struct commit_list *new_entry;
-
-       if (cached_base && p->date < cached_base->item->date)
-               new_entry = commit_list_insert_by_date(p, &cached_base->next);
-       else
-               new_entry = commit_list_insert_by_date(p, head);
-
-       if (cache && (!*cache || p->date < (*cache)->item->date))
-               *cache = new_entry;
-}
-
 static int process_parents(struct rev_info *revs, struct commit *commit,
-                          struct commit_list **list, struct commit_list **cache_ptr)
+                          struct commit_list **list, struct prio_queue *queue)
 {
        struct commit_list *parent = commit->parents;
        unsigned left_flag;
-       struct commit_list *cached_base = cache_ptr ? *cache_ptr : NULL;
 
        if (commit->object.flags & ADDED)
                return 0;
@@ -966,7 +953,9 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
                                continue;
                        p->object.flags |= SEEN;
                        if (list)
-                               commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
+                               commit_list_insert_by_date(p, list);
+                       if (queue)
+                               prio_queue_put(queue, p);
                }
                return 0;
        }
@@ -1006,7 +995,9 @@ static int process_parents(struct rev_info *revs, struct commit *commit,
                if (!(p->object.flags & SEEN)) {
                        p->object.flags |= SEEN;
                        if (list)
-                               commit_list_insert_by_date_cached(p, list, cached_base, cache_ptr);
+                               commit_list_insert_by_date(p, list);
+                       if (queue)
+                               prio_queue_put(queue, p);
                }
                if (revs->first_parent_only)
                        break;
@@ -1563,6 +1554,32 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
        free_worktrees(worktrees);
 }
 
+struct add_alternate_refs_data {
+       struct rev_info *revs;
+       unsigned int flags;
+};
+
+static void add_one_alternate_ref(const struct object_id *oid,
+                                 void *vdata)
+{
+       const char *name = ".alternate";
+       struct add_alternate_refs_data *data = vdata;
+       struct object *obj;
+
+       obj = get_reference(data->revs, name, oid, data->flags);
+       add_rev_cmdline(data->revs, obj, name, REV_CMD_REV, data->flags);
+       add_pending_object(data->revs, obj, name);
+}
+
+static void add_alternate_refs_to_pending(struct rev_info *revs,
+                                         unsigned int flags)
+{
+       struct add_alternate_refs_data data;
+       data.revs = revs;
+       data.flags = flags;
+       for_each_alternate_ref(add_one_alternate_ref, &data);
+}
+
 static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
                            int exclude_parent)
 {
@@ -1894,7 +1911,7 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
        return 0;
 }
 
-static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb,
+static void read_pathspec_from_stdin(struct strbuf *sb,
                                     struct argv_array *prune)
 {
        while (strbuf_getline(sb, stdin) != EOF)
@@ -1928,7 +1945,7 @@ static void read_revisions_from_stdin(struct rev_info *revs,
                        die("bad revision '%s'", sb.buf);
        }
        if (seen_dashdash)
-               read_pathspec_from_stdin(revs, &sb, prune);
+               read_pathspec_from_stdin(&sb, prune);
 
        strbuf_release(&sb);
        warn_on_object_refname_ambiguity = save_warning;
@@ -1965,6 +1982,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
            !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
            !strcmp(arg, "--bisect") || starts_with(arg, "--glob=") ||
            !strcmp(arg, "--indexed-objects") ||
+           !strcmp(arg, "--alternate-refs") ||
            starts_with(arg, "--exclude=") ||
            starts_with(arg, "--branches=") || starts_with(arg, "--tags=") ||
            starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk="))
@@ -2451,6 +2469,8 @@ static int handle_revision_pseudo_opt(const char *submodule,
                add_reflogs_to_pending(revs, *flags);
        } else if (!strcmp(arg, "--indexed-objects")) {
                add_index_objects_to_pending(revs, *flags);
+       } else if (!strcmp(arg, "--alternate-refs")) {
+               add_alternate_refs_to_pending(revs, *flags);
        } else if (!strcmp(arg, "--not")) {
                *flags ^= UNINTERESTING | BOTTOM;
        } else if (!strcmp(arg, "--no-walk")) {
@@ -2503,6 +2523,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
        int i, flags, left, seen_dashdash, got_rev_arg = 0, revarg_opt;
        struct argv_array prune_data = ARGV_ARRAY_INIT;
        const char *submodule = NULL;
+       int seen_end_of_options = 0;
 
        if (opt)
                submodule = opt->submodule;
@@ -2532,7 +2553,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                revarg_opt |= REVARG_CANNOT_BE_FILENAME;
        for (left = i = 1; i < argc; i++) {
                const char *arg = argv[i];
-               if (*arg == '-') {
+               if (!seen_end_of_options && *arg == '-') {
                        int opts;
 
                        opts = handle_revision_pseudo_opt(submodule,
@@ -2554,6 +2575,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                                continue;
                        }
 
+                       if (!strcmp(arg, "--end-of-options")) {
+                               seen_end_of_options = 1;
+                               continue;
+                       }
+
                        opts = handle_revision_opt(revs, argc - i, argv + i,
                                                   &left, argv, opt);
                        if (opts > 0) {
@@ -2689,6 +2715,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
        if (revs->first_parent_only && revs->bisect)
                die(_("--first-parent is incompatible with --bisect"));
 
+       if (revs->line_level_traverse &&
+           (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
+               die(_("-L does not yet support diff formats besides -p and -s"));
+
        if (revs->expand_tabs_in_log < 0)
                revs->expand_tabs_in_log = revs->expand_tabs_in_log_default;
 
@@ -2748,7 +2778,7 @@ static struct merge_simplify_state *locate_simplify_state(struct rev_info *revs,
        return st;
 }
 
-static int mark_redundant_parents(struct rev_info *revs, struct commit *commit)
+static int mark_redundant_parents(struct commit *commit)
 {
        struct commit_list *h = reduce_heads(commit->parents);
        int i = 0, marked = 0;
@@ -2784,7 +2814,7 @@ static int mark_redundant_parents(struct rev_info *revs, struct commit *commit)
        return marked;
 }
 
-static int mark_treesame_root_parents(struct rev_info *revs, struct commit *commit)
+static int mark_treesame_root_parents(struct commit *commit)
 {
        struct commit_list *p;
        int marked = 0;
@@ -2976,8 +3006,8 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
         * Detect and simplify both cases.
         */
        if (1 < cnt) {
-               int marked = mark_redundant_parents(revs, commit);
-               marked += mark_treesame_root_parents(revs, commit);
+               int marked = mark_redundant_parents(commit);
+               marked += mark_treesame_root_parents(commit);
                if (marked)
                        marked -= leave_one_treesame_to_parent(revs, commit);
                if (marked)
@@ -3270,6 +3300,9 @@ static void expand_topo_walk(struct rev_info *revs, struct commit *commit)
                struct commit *parent = p->item;
                int *pi;
 
+               if (parent->object.flags & UNINTERESTING)
+                       continue;
+
                if (parse_commit_gently(parent, 1) < 0)
                        continue;
 
@@ -3341,14 +3374,14 @@ int prepare_revision_walk(struct rev_info *revs)
        return 0;
 }
 
-static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
+static enum rewrite_result rewrite_one_1(struct rev_info *revs,
+                                        struct commit **pp,
+                                        struct prio_queue *queue)
 {
-       struct commit_list *cache = NULL;
-
        for (;;) {
                struct commit *p = *pp;
                if (!revs->limited)
-                       if (process_parents(revs, p, &revs->commits, &cache) < 0)
+                       if (process_parents(revs, p, NULL, queue) < 0)
                                return rewrite_one_error;
                if (p->object.flags & UNINTERESTING)
                        return rewrite_one_ok;
@@ -3362,6 +3395,31 @@ static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp
        }
 }
 
+static void merge_queue_into_list(struct prio_queue *q, struct commit_list **list)
+{
+       while (q->nr) {
+               struct commit *item = prio_queue_peek(q);
+               struct commit_list *p = *list;
+
+               if (p && p->item->date >= item->date)
+                       list = &p->next;
+               else {
+                       p = commit_list_insert(item, list);
+                       list = &p->next; /* skip newly added item */
+                       prio_queue_get(q); /* pop item */
+               }
+       }
+}
+
+static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
+{
+       struct prio_queue queue = { compare_commits_by_commit_date };
+       enum rewrite_result ret = rewrite_one_1(revs, pp, &queue);
+       merge_queue_into_list(&queue, &revs->commits);
+       clear_prio_queue(&queue);
+       return ret;
+}
+
 int rewrite_parents(struct rev_info *revs, struct commit *commit,
        rewrite_parent_fn_t rewrite_parent)
 {