builtin/cat-file: convert struct expand_data to use struct object_id
[gitweb.git] / sequencer.c
index a0600aebcadb81e67921d953e8ed626d08529a9b..3804fa931d819f035ad6b3159cb8efa1745693d0 100644 (file)
@@ -112,7 +112,7 @@ static void remove_sequencer_state(void)
 {
        struct strbuf seq_dir = STRBUF_INIT;
 
-       strbuf_addf(&seq_dir, "%s", git_path(SEQ_DIR));
+       strbuf_addstr(&seq_dir, git_path(SEQ_DIR));
        remove_dir_recursively(&seq_dir, 0);
        strbuf_release(&seq_dir);
 }
@@ -124,42 +124,33 @@ static const char *action_name(const struct replay_opts *opts)
 
 struct commit_message {
        char *parent_label;
-       const char *label;
-       const char *subject;
+       char *label;
+       char *subject;
        const char *message;
 };
 
 static int get_message(struct commit *commit, struct commit_message *out)
 {
        const char *abbrev, *subject;
-       int abbrev_len, subject_len;
-       char *q;
-
-       if (!git_commit_encoding)
-               git_commit_encoding = "UTF-8";
+       int subject_len;
 
-       out->message = logmsg_reencode(commit, NULL, git_commit_encoding);
-       abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
-       abbrev_len = strlen(abbrev);
+       out->message = logmsg_reencode(commit, NULL, get_commit_output_encoding());
+       abbrev = find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV);
 
        subject_len = find_commit_subject(out->message, &subject);
 
-       out->parent_label = xmalloc(strlen("parent of ") + abbrev_len +
-                             strlen("... ") + subject_len + 1);
-       q = out->parent_label;
-       q = mempcpy(q, "parent of ", strlen("parent of "));
-       out->label = q;
-       q = mempcpy(q, abbrev, abbrev_len);
-       q = mempcpy(q, "... ", strlen("... "));
-       out->subject = q;
-       q = mempcpy(q, subject, subject_len);
-       *q = '\0';
+       out->subject = xmemdupz(subject, subject_len);
+       out->label = xstrfmt("%s... %s", abbrev, out->subject);
+       out->parent_label = xstrfmt("parent of %s", out->label);
+
        return 0;
 }
 
 static void free_message(struct commit *commit, struct commit_message *msg)
 {
        free(msg->parent_label);
+       free(msg->label);
+       free(msg->subject);
        unuse_commit_buffer(commit, msg->message);
 }
 
@@ -199,7 +190,7 @@ static void write_message(struct strbuf *msgbuf, const char *filename)
                die_errno(_("Could not write to %s"), filename);
        strbuf_release(msgbuf);
        if (commit_lock_file(&msg_file) < 0)
-               die(_("Error wrapping up %s"), filename);
+               die(_("Error wrapping up %s."), filename);
 }
 
 static struct tree *empty_tree(void)
@@ -234,7 +225,7 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from,
        if (checkout_fast_forward(from, to, 1))
                exit(128); /* the callee should have complained already */
 
-       strbuf_addf(&sb, "%s: fast-forward", action_name(opts));
+       strbuf_addf(&sb, _("%s: fast-forward"), action_name(opts));
 
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
@@ -302,6 +293,9 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
        clean = merge_trees(&o,
                            head_tree,
                            next_tree, base_tree, &result);
+       strbuf_release(&o.obuf);
+       if (clean < 0)
+               return clean;
 
        if (active_cache_changed &&
            write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
@@ -346,7 +340,7 @@ static int is_index_unchanged(void)
                if (cache_tree_update(&the_index, 0))
                        return error(_("Unable to update cache tree\n"));
 
-       return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.sha1);
+       return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.oid.hash);
 }
 
 /*
@@ -397,18 +391,18 @@ static int is_original_commit_empty(struct commit *commit)
 
        if (parse_commit(commit))
                return error(_("Could not parse commit %s\n"),
-                            sha1_to_hex(commit->object.sha1));
+                            oid_to_hex(&commit->object.oid));
        if (commit->parents) {
                struct commit *parent = commit->parents->item;
                if (parse_commit(parent))
                        return error(_("Could not parse parent commit %s\n"),
-                               sha1_to_hex(parent->object.sha1));
-               ptree_sha1 = parent->tree->object.sha1;
+                               oid_to_hex(&parent->object.oid));
+               ptree_sha1 = parent->tree->object.oid.hash;
        } else {
                ptree_sha1 = EMPTY_TREE_SHA1_BIN; /* commit is root */
        }
 
-       return !hashcmp(ptree_sha1, commit->tree->object.sha1);
+       return !hashcmp(ptree_sha1, commit->tree->object.oid.hash);
 }
 
 /*
@@ -486,7 +480,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
 
                if (!opts->mainline)
                        return error(_("Commit %s is a merge but no -m option was given."),
-                               sha1_to_hex(commit->object.sha1));
+                               oid_to_hex(&commit->object.oid));
 
                for (cnt = 1, p = commit->parents;
                     cnt != opts->mainline && p;
@@ -494,28 +488,28 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
                        p = p->next;
                if (cnt != opts->mainline || !p)
                        return error(_("Commit %s does not have parent %d"),
-                               sha1_to_hex(commit->object.sha1), opts->mainline);
+                               oid_to_hex(&commit->object.oid), opts->mainline);
                parent = p->item;
        } else if (0 < opts->mainline)
                return error(_("Mainline was specified but commit %s is not a merge."),
-                       sha1_to_hex(commit->object.sha1));
+                       oid_to_hex(&commit->object.oid));
        else
                parent = commit->parents->item;
 
        if (opts->allow_ff &&
-           ((parent && !hashcmp(parent->object.sha1, head)) ||
+           ((parent && !hashcmp(parent->object.oid.hash, head)) ||
             (!parent && unborn)))
-               return fast_forward_to(commit->object.sha1, head, unborn, opts);
+               return fast_forward_to(commit->object.oid.hash, head, unborn, opts);
 
        if (parent && parse_commit(parent) < 0)
                /* TRANSLATORS: The first %s will be "revert" or
                   "cherry-pick", the second %s a SHA1 */
                return error(_("%s: cannot parse parent commit %s"),
-                       action_name(opts), sha1_to_hex(parent->object.sha1));
+                       action_name(opts), oid_to_hex(&parent->object.oid));
 
        if (get_message(commit, &msg) != 0)
                return error(_("Cannot get commit message for %s"),
-                       sha1_to_hex(commit->object.sha1));
+                       oid_to_hex(&commit->object.oid));
 
        /*
         * "commit" is an existing commit.  We would want to apply
@@ -532,11 +526,11 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
                strbuf_addstr(&msgbuf, "Revert \"");
                strbuf_addstr(&msgbuf, msg.subject);
                strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit ");
-               strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
+               strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
 
                if (commit->parents && commit->parents->next) {
                        strbuf_addstr(&msgbuf, ", reversing\nchanges made to ");
-                       strbuf_addstr(&msgbuf, sha1_to_hex(parent->object.sha1));
+                       strbuf_addstr(&msgbuf, oid_to_hex(&parent->object.oid));
                }
                strbuf_addstr(&msgbuf, ".\n");
        } else {
@@ -553,16 +547,14 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
                 * information followed by "\n\n".
                 */
                p = strstr(msg.message, "\n\n");
-               if (p) {
-                       p += 2;
-                       strbuf_addstr(&msgbuf, p);
-               }
+               if (p)
+                       strbuf_addstr(&msgbuf, skip_blank_lines(p + 2));
 
                if (opts->record_origin) {
                        if (!has_conforming_footer(&msgbuf, NULL, 0))
                                strbuf_addch(&msgbuf, '\n');
                        strbuf_addstr(&msgbuf, cherry_picked_prefix);
-                       strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
+                       strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
                        strbuf_addstr(&msgbuf, ")\n");
                }
        }
@@ -570,6 +562,8 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
        if (!opts->strategy || !strcmp(opts->strategy, "recursive") || opts->action == REPLAY_REVERT) {
                res = do_recursive_merge(base, next, base_label, next_label,
                                         head, &msgbuf, opts);
+               if (res < 0)
+                       return res;
                write_message(&msgbuf, git_path_merge_msg());
        } else {
                struct commit_list *common = NULL;
@@ -592,17 +586,17 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
         * write it at all.
         */
        if (opts->action == REPLAY_PICK && !opts->no_commit && (res == 0 || res == 1))
-               update_ref(NULL, "CHERRY_PICK_HEAD", commit->object.sha1, NULL,
+               update_ref(NULL, "CHERRY_PICK_HEAD", commit->object.oid.hash, NULL,
                           REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
        if (opts->action == REPLAY_REVERT && ((opts->no_commit && res == 0) || res == 1))
-               update_ref(NULL, "REVERT_HEAD", commit->object.sha1, NULL,
+               update_ref(NULL, "REVERT_HEAD", commit->object.oid.hash, NULL,
                           REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
 
        if (res) {
                error(opts->action == REPLAY_REVERT
                      ? _("could not revert %s... %s")
                      : _("could not apply %s... %s"),
-                     find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV),
+                     find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV),
                      msg.subject);
                print_advice(res == 1, opts);
                rerere(opts->allow_rerere_auto);
@@ -664,7 +658,7 @@ static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
 
        for (cur = todo_list; cur; cur = cur->next) {
                const char *commit_buffer = get_commit_buffer(cur->item, NULL);
-               sha1_abbrev = find_unique_abbrev(cur->item->object.sha1, DEFAULT_ABBREV);
+               sha1_abbrev = find_unique_abbrev(cur->item->object.oid.hash, DEFAULT_ABBREV);
                subject_len = find_commit_subject(commit_buffer, &subject);
                strbuf_addf(buf, "%s %s %.*s\n", action_str, sha1_abbrev,
                        subject_len, subject);
@@ -706,9 +700,14 @@ static struct commit *parse_insn_line(char *bol, char *eol, struct replay_opts *
         * opts; we don't support arbitrary instructions
         */
        if (action != opts->action) {
-               const char *action_str;
-               action_str = action == REPLAY_REVERT ? "revert" : "cherry-pick";
-               error(_("Cannot %s during a %s"), action_str, action_name(opts));
+               if (action == REPLAY_REVERT)
+                     error((opts->action == REPLAY_REVERT)
+                           ? _("Cannot revert during another revert.")
+                           : _("Cannot revert during a cherry-pick."));
+               else
+                     error((opts->action == REPLAY_REVERT)
+                           ? _("Cannot cherry-pick during a revert.")
+                           : _("Cannot cherry-pick during another cherry-pick."));
                return NULL;
        }
 
@@ -884,9 +883,8 @@ static int sequencer_rollback(struct replay_opts *opts)
                return rollback_single_pick();
        }
        if (!f)
-               return error(_("cannot open %s: %s"), git_path_head_file(),
-                                               strerror(errno));
-       if (strbuf_getline(&buf, f, '\n')) {
+               return error_errno(_("cannot open %s"), git_path_head_file());
+       if (strbuf_getline_lf(&buf, f)) {
                error(_("cannot read %s: %s"), git_path_head_file(),
                      ferror(f) ?  strerror(errno) : _("unexpected end of file"));
                fclose(f);
@@ -898,6 +896,10 @@ static int sequencer_rollback(struct replay_opts *opts)
                        git_path_head_file());
                goto fail;
        }
+       if (is_null_sha1(sha1)) {
+               error(_("cannot abort from a branch yet to be born"));
+               goto fail;
+       }
        if (reset_for_rollback(sha1))
                goto fail;
        remove_sequencer_state();
@@ -1096,11 +1098,8 @@ int sequencer_pick_revisions(struct replay_opts *opts)
        walk_revs_populate_todo(&todo_list, opts);
        if (create_seq_dir() < 0)
                return -1;
-       if (get_sha1("HEAD", sha1)) {
-               if (opts->action == REPLAY_REVERT)
-                       return error(_("Can't revert as initial commit"));
-               return error(_("Can't cherry-pick into empty head"));
-       }
+       if (get_sha1("HEAD", sha1) && (opts->action == REPLAY_REVERT))
+               return error(_("Can't revert as initial commit"));
        save_head(sha1_to_hex(sha1));
        save_opts(opts);
        return pick_commits(todo_list, opts);