git-p4: check free space during streaming
[gitweb.git] / revision.c
index 6399a0412cc9005875e282a139200a4f918743f5..af2a18ed7485ea83170409ce55f81473ee606221 100644 (file)
 #include "commit-slab.h"
 #include "dir.h"
 #include "cache-tree.h"
+#include "bisect.h"
 
 volatile show_early_output_fn_t show_early_output;
 
+static const char *term_bad;
+static const char *term_good;
+
 char *path_name(const struct name_path *path, const char *name)
 {
        const struct name_path *p;
@@ -345,14 +349,24 @@ static struct commit *handle_commit(struct rev_info *revs,
        die("%s is unknown object", name);
 }
 
-static int everybody_uninteresting(struct commit_list *orig)
+static int everybody_uninteresting(struct commit_list *orig,
+                                  struct commit **interesting_cache)
 {
        struct commit_list *list = orig;
+
+       if (*interesting_cache) {
+               struct commit *commit = *interesting_cache;
+               if (!(commit->object.flags & UNINTERESTING))
+                       return 0;
+       }
+
        while (list) {
                struct commit *commit = list->item;
                list = list->next;
                if (commit->object.flags & UNINTERESTING)
                        continue;
+
+               *interesting_cache = commit;
                return 0;
        }
        return 1;
@@ -807,7 +821,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
                        parent = parent->next;
                        if (p)
                                p->object.flags |= UNINTERESTING;
-                       if (parse_commit(p) < 0)
+                       if (parse_commit_gently(p, 1) < 0)
                                continue;
                        if (p->parents)
                                mark_parents_uninteresting(p);
@@ -834,7 +848,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
        for (parent = commit->parents; parent; parent = parent->next) {
                struct commit *p = parent->item;
 
-               if (parse_commit(p) < 0)
+               if (parse_commit_gently(p, revs->ignore_missing_links) < 0)
                        return -1;
                if (revs->show_source && !p->util)
                        p->util = commit->util;
@@ -940,7 +954,8 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
 /* How many extra uninteresting commits we want to see.. */
 #define SLOP 5
 
-static int still_interesting(struct commit_list *src, unsigned long date, int slop)
+static int still_interesting(struct commit_list *src, unsigned long date, int slop,
+                            struct commit **interesting_cache)
 {
        /*
         * No source list at all? We're definitely done..
@@ -959,7 +974,7 @@ static int still_interesting(struct commit_list *src, unsigned long date, int sl
         * Does the source list still have interesting commits in
         * it? Definitely not done..
         */
-       if (!everybody_uninteresting(src))
+       if (!everybody_uninteresting(src, interesting_cache))
                return SLOP;
 
        /* Ok, we're closing in.. */
@@ -1078,6 +1093,7 @@ static int limit_list(struct rev_info *revs)
        struct commit_list *newlist = NULL;
        struct commit_list **p = &newlist;
        struct commit_list *bottom = NULL;
+       struct commit *interesting_cache = NULL;
 
        if (revs->ancestry_path) {
                bottom = collect_bottom_commits(list);
@@ -1094,6 +1110,9 @@ static int limit_list(struct rev_info *revs)
                list = list->next;
                free(entry);
 
+               if (commit == interesting_cache)
+                       interesting_cache = NULL;
+
                if (revs->max_age != -1 && (commit->date < revs->max_age))
                        obj->flags |= UNINTERESTING;
                if (add_parents_to_list(revs, commit, &list, NULL) < 0)
@@ -1102,7 +1121,7 @@ static int limit_list(struct rev_info *revs)
                        mark_parents_uninteresting(commit);
                        if (revs->show_all)
                                p = &commit_list_insert(commit, p)->next;
-                       slop = still_interesting(list, date, slop);
+                       slop = still_interesting(list, date, slop, &interesting_cache);
                        if (slop)
                                continue;
                        /* If showing all, add the whole pending list to the end */
@@ -1203,7 +1222,8 @@ int ref_excluded(struct string_list *ref_excludes, const char *path)
        return 0;
 }
 
-static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static int handle_one_ref(const char *path, const struct object_id *oid,
+                         int flag, void *cb_data)
 {
        struct all_refs_cb *cb = cb_data;
        struct object *object;
@@ -1211,9 +1231,9 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, int flag,
        if (ref_excluded(cb->all_revs->ref_excludes, path))
            return 0;
 
-       object = get_reference(cb->all_revs, path, sha1, cb->all_flags);
+       object = get_reference(cb->all_revs, path, oid->hash, cb->all_flags);
        add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
-       add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags);
+       add_pending_sha1(cb->all_revs, path, oid->hash, cb->all_flags);
        return 0;
 }
 
@@ -1277,7 +1297,8 @@ static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
        return 0;
 }
 
-static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data)
+static int handle_one_reflog(const char *path, const struct object_id *oid,
+                            int flag, void *cb_data)
 {
        struct all_refs_cb *cb = cb_data;
        cb->warned_bad_reflog = 0;
@@ -1289,6 +1310,7 @@ static int handle_one_reflog(const char *path, const unsigned char *sha1, int fl
 void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
 {
        struct all_refs_cb cb;
+
        cb.all_revs = revs;
        cb.all_flags = flags;
        for_each_reflog(handle_one_reflog, &cb);
@@ -1978,10 +2000,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--full-history")) {
                revs->simplify_history = 0;
        } else if (!strcmp(arg, "--relative-date")) {
-               revs->date_mode = DATE_RELATIVE;
+               revs->date_mode.type = DATE_RELATIVE;
                revs->date_mode_explicit = 1;
        } else if ((argcount = parse_long_opt("date", argv, &optarg))) {
-               revs->date_mode = parse_date_format(optarg);
+               parse_date_format(optarg, &revs->date_mode);
                revs->date_mode_explicit = 1;
                return argcount;
        } else if (!strcmp(arg, "--log-size")) {
@@ -2058,14 +2080,23 @@ void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
        ctx->argc -= n;
 }
 
+static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
+       struct strbuf bisect_refs = STRBUF_INIT;
+       int status;
+       strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
+       status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
+       strbuf_release(&bisect_refs);
+       return status;
+}
+
 static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-       return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data);
+       return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
 }
 
 static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-       return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
+       return for_each_bisect_ref(submodule, fn, cb_data, term_good);
 }
 
 static int handle_revision_pseudo_opt(const char *submodule,
@@ -2094,6 +2125,7 @@ static int handle_revision_pseudo_opt(const char *submodule,
                handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--bisect")) {
+               read_bisect_terms(&term_bad, &term_good);
                handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
                handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
                revs->bisect = 1;
@@ -2155,6 +2187,21 @@ static int handle_revision_pseudo_opt(const char *submodule,
        return 1;
 }
 
+static void NORETURN diagnose_missing_default(const char *def)
+{
+       unsigned char sha1[20];
+       int flags;
+       const char *refname;
+
+       refname = resolve_ref_unsafe(def, 0, sha1, &flags);
+       if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
+               die(_("your current branch appears to be broken"));
+
+       skip_prefix(refname, "refs/heads/", &refname);
+       die(_("your current branch '%s' does not have any commits yet"),
+           refname);
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -2284,7 +2331,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                struct object *object;
                struct object_context oc;
                if (get_sha1_with_context(revs->def, 0, sha1, &oc))
-                       die("bad default revision '%s'", revs->def);
+                       diagnose_missing_default(revs->def);
                object = get_reference(revs, revs->def, sha1, 0);
                add_pending_object_with_mode(revs, object, revs->def, oc.mode);
        }