X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=revision.c;h=76499dcf38bb9c92bd52d251549725bceb6a9ba1;hb=refs%2Ftags%2Fv1.5.0.7;hp=f1e0caaae3d2a96de6cf9bad12e8641c19d788dd;hpb=01fe679a341ed3b1a816404faf76bf454712aa2f;p=git.git diff --git a/revision.c b/revision.c index f1e0caaae..76499dcf3 100644 --- a/revision.c +++ b/revision.c @@ -6,8 +6,8 @@ #include "diff.h" #include "refs.h" #include "revision.h" -#include #include "grep.h" +#include "reflog-walk.h" static char *path_name(struct name_path *path, const char *name) { @@ -116,7 +116,12 @@ void mark_parents_uninteresting(struct commit *commit) void add_pending_object(struct rev_info *revs, struct object *obj, const char *name) { + if (revs->no_walk && (obj->flags & UNINTERESTING)) + die("object ranges do not make sense when not walking revisions"); add_object_array(obj, name, &revs->pending); + if (revs->reflog_info && obj->type == OBJ_COMMIT) + add_reflog_for_walk(revs->reflog_info, + (struct commit *)obj, name); } static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags) @@ -344,6 +349,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list) { struct commit_list *parent = commit->parents; + unsigned left_flag; if (commit->object.flags & ADDED) return; @@ -388,6 +394,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st if (revs->no_walk) return; + left_flag = (commit->object.flags & SYMMETRIC_LEFT); parent = commit->parents; while (parent) { struct commit *p = parent->item; @@ -395,6 +402,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st parent = parent->next; parse_commit(p); + p->object.flags |= left_flag; if (p->object.flags & SEEN) continue; p->object.flags |= SEEN; @@ -418,9 +426,6 @@ static void limit_list(struct rev_info *revs) if (revs->max_age != -1 && (commit->date < revs->max_age)) obj->flags |= UNINTERESTING; - if (revs->unpacked && - has_sha1_pack(obj->sha1, revs->ignore_packed)) - obj->flags |= UNINTERESTING; add_parents_to_list(revs, commit, &list); if (obj->flags & UNINTERESTING) { mark_parents_uninteresting(commit); @@ -465,21 +470,71 @@ static void limit_list(struct rev_info *revs) revs->commits = newlist; } -static int all_flags; -static struct rev_info *all_revs; +struct all_refs_cb { + int all_flags; + int warned_bad_reflog; + struct rev_info *all_revs; + const char *name_for_errormsg; +}; -static int handle_one_ref(const char *path, const unsigned char *sha1) +static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { - struct object *object = get_reference(all_revs, path, sha1, all_flags); - add_pending_object(all_revs, object, ""); + struct all_refs_cb *cb = cb_data; + struct object *object = get_reference(cb->all_revs, path, sha1, + cb->all_flags); + add_pending_object(cb->all_revs, object, ""); return 0; } static void handle_all(struct rev_info *revs, unsigned flags) { - all_revs = revs; - all_flags = flags; - for_each_ref(handle_one_ref); + struct all_refs_cb cb; + cb.all_revs = revs; + cb.all_flags = flags; + for_each_ref(handle_one_ref, &cb); +} + +static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data) +{ + struct all_refs_cb *cb = cb_data; + if (!is_null_sha1(sha1)) { + struct object *o = parse_object(sha1); + if (o) { + o->flags |= cb->all_flags; + add_pending_object(cb->all_revs, o, ""); + } + else if (!cb->warned_bad_reflog) { + warn("reflog of '%s' references pruned commits", + cb->name_for_errormsg); + cb->warned_bad_reflog = 1; + } + } +} + +static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1, + const char *email, unsigned long timestamp, int tz, + const char *message, void *cb_data) +{ + handle_one_reflog_commit(osha1, cb_data); + handle_one_reflog_commit(nsha1, cb_data); + return 0; +} + +static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data) +{ + struct all_refs_cb *cb = cb_data; + cb->warned_bad_reflog = 0; + cb->name_for_errormsg = path; + for_each_reflog_ent(path, handle_one_reflog_ent, cb_data); + return 0; +} + +static void handle_reflog(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); } static int add_parents_only(struct rev_info *revs, const char *arg, int flags) @@ -527,6 +582,7 @@ void init_revisions(struct rev_info *revs, const char *prefix) revs->prefix = prefix; revs->max_age = -1; revs->min_age = -1; + revs->skip_count = -1; revs->max_count = -1; revs->prune_fn = NULL; @@ -643,7 +699,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, add_pending_commit_list(revs, exclude, flags_exclude); free_commit_list(exclude); - a->object.flags |= flags; + a->object.flags |= flags | SYMMETRIC_LEFT; } else a->object.flags |= flags_exclude; b->object.flags |= flags; @@ -660,6 +716,13 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, return 0; *dotdot = '^'; } + dotdot = strstr(arg, "^!"); + if (dotdot && !dotdot[2]) { + *dotdot = 0; + if (!add_parents_only(revs, arg, flags ^ UNINTERESTING)) + *dotdot = '^'; + } + local_flags = 0; if (*arg == '^') { local_flags = UNINTERESTING; @@ -756,6 +819,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->max_count = atoi(arg + 12); continue; } + if (!strncmp(arg, "--skip=", 7)) { + revs->skip_count = atoi(arg + 7); + continue; + } /* accept -, like traditional "head" */ if ((*arg == '-') && isdigit(arg[1])) { revs->max_count = atoi(arg + 1); @@ -799,6 +866,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch handle_all(revs, flags); continue; } + if (!strcmp(arg, "--reflog")) { + handle_reflog(revs, flags); + continue; + } + if (!strcmp(arg, "-g") || + !strcmp(arg, "--walk-reflogs")) { + init_reflog_walk(&revs->reflog_info); + continue; + } if (!strcmp(arg, "--not")) { flags ^= UNINTERESTING; continue; @@ -846,6 +922,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->boundary = 1; continue; } + if (!strcmp(arg, "--left-right")) { + revs->left_right = 1; + continue; + } if (!strcmp(arg, "--objects")) { revs->tag_objects = 1; revs->tree_objects = 1; @@ -972,6 +1052,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch all_match = 1; continue; } + if (!strncmp(arg, "--encoding=", 11)) { + arg += 11; + if (strcmp(arg, "none")) + git_log_output_encoding = strdup(arg); + else + git_log_output_encoding = ""; + continue; + } opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); if (opts > 0) { @@ -1015,7 +1103,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch add_pending_object(revs, object, def); } - if (revs->topo_order || revs->unpacked) + if (revs->topo_order) revs->limited = 1; if (revs->prune_data) { @@ -1044,21 +1132,23 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch void prepare_revision_walk(struct rev_info *revs) { int nr = revs->pending.nr; - struct object_array_entry *list = revs->pending.objects; + struct object_array_entry *e, *list; + e = list = revs->pending.objects; revs->pending.nr = 0; revs->pending.alloc = 0; revs->pending.objects = NULL; while (--nr >= 0) { - struct commit *commit = handle_commit(revs, list->item, list->name); + struct commit *commit = handle_commit(revs, e->item, e->name); if (commit) { if (!(commit->object.flags & SEEN)) { commit->object.flags |= SEEN; insert_by_date(commit, &revs->commits); } } - list++; + e++; } + free(list); if (revs->no_walk) return; @@ -1119,23 +1209,11 @@ static int commit_match(struct commit *commit, struct rev_info *opt) commit->buffer, strlen(commit->buffer)); } -struct commit *get_revision(struct rev_info *revs) +static struct commit *get_revision_1(struct rev_info *revs) { - struct commit_list *list = revs->commits; - - if (!list) + if (!revs->commits) return NULL; - /* Check the max_count ... */ - switch (revs->max_count) { - case -1: - break; - case 0: - return NULL; - default: - revs->max_count--; - } - do { struct commit_list *entry = revs->commits; struct commit *commit = entry->item; @@ -1143,23 +1221,27 @@ struct commit *get_revision(struct rev_info *revs) revs->commits = entry->next; free(entry); + if (revs->reflog_info) + fake_reflog_parent(revs->reflog_info, commit); + /* * If we haven't done the list limiting, we need to look at * the parents here. We also need to do the date-based limiting * that we'd otherwise have done in limit_list(). */ if (!revs->limited) { - if ((revs->unpacked && - has_sha1_pack(commit->object.sha1, - revs->ignore_packed)) || - (revs->max_age != -1 && - (commit->date < revs->max_age))) + if (revs->max_age != -1 && + (commit->date < revs->max_age)) continue; add_parents_to_list(revs, commit, &revs->commits); } if (commit->object.flags & SHOWN) continue; + if (revs->unpacked && has_sha1_pack(commit->object.sha1, + revs->ignore_packed)) + continue; + /* We want to show boundary commits only when their * children are shown. When path-limiter is in effect, * rewrite_parents() drops some commits from getting shown, @@ -1201,3 +1283,28 @@ struct commit *get_revision(struct rev_info *revs) } while (revs->commits); return NULL; } + +struct commit *get_revision(struct rev_info *revs) +{ + struct commit *c = NULL; + + if (0 < revs->skip_count) { + while ((c = get_revision_1(revs)) != NULL) { + if (revs->skip_count-- <= 0) + break; + } + } + + /* Check the max_count ... */ + switch (revs->max_count) { + case -1: + break; + case 0: + return NULL; + default: + revs->max_count--; + } + if (c) + return c; + return get_revision_1(revs); +}