Consistent message encoding while reusing log from an existing commit.
[gitweb.git] / revision.c
index bda9d4dfa58a9b4af33e117314aa48ce74dcbdb9..f2ddd95e29e5eaef2cb4beb28c34921396d94fdf 100644 (file)
@@ -466,6 +466,7 @@ static void limit_list(struct rev_info *revs)
 
 struct all_refs_cb {
        int all_flags;
+       int warned_bad_reflog;
        struct rev_info *all_revs;
        const char *name_for_errormsg;
 };
@@ -487,25 +488,36 @@ static void handle_all(struct rev_info *revs, unsigned flags)
        for_each_ref(handle_one_ref, &cb);
 }
 
-static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1, char *detail, void *cb_data)
+static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
 {
        struct all_refs_cb *cb = cb_data;
-       struct object *object;
-
-       if (!is_null_sha1(osha1)) {
-               object = get_reference(cb->all_revs, cb->name_for_errormsg,
-                                      osha1, cb->all_flags);
-               add_pending_object(cb->all_revs, object, "");
+       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;
+               }
        }
-       object = get_reference(cb->all_revs, cb->name_for_errormsg,
-                              nsha1, cb->all_flags);
-       add_pending_object(cb->all_revs, object, "");
+}
+
+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;
@@ -564,6 +576,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;
@@ -800,6 +813,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 -<digit>, like traditional "head" */
                        if ((*arg == '-') && isdigit(arg[1])) {
                                revs->max_count = atoi(arg + 1);
@@ -1024,6 +1041,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) {
@@ -1096,21 +1121,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;
@@ -1171,23 +1198,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;
@@ -1254,3 +1269,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);
+}