l10n: fr.po v2.11.0_rnd1
[gitweb.git] / sequencer.c
index 6d5fe9485a9496ca41ba6be95eb24499a8bac8a0..5fd75f30dd4455bf71a12fd628b488fc2b17e192 100644 (file)
@@ -15,6 +15,7 @@
 #include "merge-recursive.h"
 #include "refs.h"
 #include "argv-array.h"
+#include "quote.h"
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -33,6 +34,11 @@ static GIT_PATH_FUNC(git_path_head_file, "sequencer/head")
  * being rebased.
  */
 static GIT_PATH_FUNC(rebase_path_author_script, "rebase-merge/author-script")
+/*
+ * The following files are written by git-rebase just after parsing the
+ * command-line (and are only consumed, not modified, by the sequencer).
+ */
+static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 
 /* We will introduce the 'interactive rebase' mode later */
 static inline int is_rebase_i(const struct replay_opts *opts)
@@ -132,6 +138,16 @@ static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob,
        return 1;
 }
 
+static const char *gpg_sign_opt_quoted(struct replay_opts *opts)
+{
+       static struct strbuf buf = STRBUF_INIT;
+
+       strbuf_reset(&buf);
+       if (opts->gpg_sign)
+               sq_quotef(&buf, "-S%s", opts->gpg_sign);
+       return buf.buf;
+}
+
 int sequencer_remove_state(struct replay_opts *opts)
 {
        struct strbuf dir = STRBUF_INIT;
@@ -152,7 +168,7 @@ int sequencer_remove_state(struct replay_opts *opts)
 
 static const char *action_name(const struct replay_opts *opts)
 {
-       return opts->action == REPLAY_REVERT ? "revert" : "cherry-pick";
+       return opts->action == REPLAY_REVERT ? N_("revert") : N_("cherry-pick");
 }
 
 struct commit_message {
@@ -218,22 +234,64 @@ static void print_advice(int show_hint, struct replay_opts *opts)
        }
 }
 
-static int write_message(struct strbuf *msgbuf, const char *filename)
+static int write_message(const void *buf, size_t len, const char *filename,
+                        int append_eol)
 {
        static struct lock_file msg_file;
 
        int msg_fd = hold_lock_file_for_update(&msg_file, filename, 0);
        if (msg_fd < 0)
-               return error_errno(_("Could not lock '%s'"), filename);
-       if (write_in_full(msg_fd, msgbuf->buf, msgbuf->len) < 0)
-               return error_errno(_("Could not write to %s"), filename);
-       strbuf_release(msgbuf);
-       if (commit_lock_file(&msg_file) < 0)
-               return error(_("Error wrapping up %s."), filename);
+               return error_errno(_("could not lock '%s'"), filename);
+       if (write_in_full(msg_fd, buf, len) < 0) {
+               rollback_lock_file(&msg_file);
+               return error_errno(_("could not write to '%s'"), filename);
+       }
+       if (append_eol && write(msg_fd, "\n", 1) < 0) {
+               rollback_lock_file(&msg_file);
+               return error_errno(_("could not write eol to '%s"), filename);
+       }
+       if (commit_lock_file(&msg_file) < 0) {
+               rollback_lock_file(&msg_file);
+               return error(_("failed to finalize '%s'."), filename);
+       }
 
        return 0;
 }
 
+/*
+ * Reads a file that was presumably written by a shell script, i.e. with an
+ * end-of-line marker that needs to be stripped.
+ *
+ * Note that only the last end-of-line marker is stripped, consistent with the
+ * behavior of "$(cat path)" in a shell script.
+ *
+ * Returns 1 if the file was read, 0 if it could not be read or does not exist.
+ */
+static int read_oneliner(struct strbuf *buf,
+       const char *path, int skip_if_empty)
+{
+       int orig_len = buf->len;
+
+       if (!file_exists(path))
+               return 0;
+
+       if (strbuf_read_file(buf, path, 0) < 0) {
+               warning_errno(_("could not read '%s'"), path);
+               return 0;
+       }
+
+       if (buf->len > orig_len && buf->buf[buf->len - 1] == '\n') {
+               if (--buf->len > orig_len && buf->buf[buf->len - 1] == '\r')
+                       --buf->len;
+               buf->buf[buf->len] = '\0';
+       }
+
+       if (skip_if_empty && buf->len == orig_len)
+               return 0;
+
+       return 1;
+}
+
 static struct tree *empty_tree(void)
 {
        return lookup_tree(EMPTY_TREE_SHA1_BIN);
@@ -242,13 +300,13 @@ static struct tree *empty_tree(void)
 static int error_dirty_index(struct replay_opts *opts)
 {
        if (read_cache_unmerged())
-               return error_resolve_conflict(action_name(opts));
+               return error_resolve_conflict(_(action_name(opts)));
 
-       error(_("Your local changes would be overwritten by %s."),
-               action_name(opts));
+       error(_("your local changes would be overwritten by %s."),
+               _(action_name(opts)));
 
        if (advice_commit_before_merge)
-               advise(_("Commit your changes or stash them to proceed."));
+               advise(_("commit your changes or stash them to proceed."));
        return -1;
 }
 
@@ -263,7 +321,7 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from,
        if (checkout_fast_forward(from, to, 1))
                return -1; /* 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 ||
@@ -339,7 +397,7 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
            write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
                /* TRANSLATORS: %s will be "revert" or "cherry-pick" */
                return error(_("%s: Unable to write new index file"),
-                       action_name(opts));
+                       _(action_name(opts)));
        rollback_lock_file(&index_lock);
 
        if (opts->signoff)
@@ -357,7 +415,7 @@ static int is_index_unchanged(void)
        struct commit *head_commit;
 
        if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL))
-               return error(_("Could not resolve HEAD commit\n"));
+               return error(_("could not resolve HEAD commit\n"));
 
        head_commit = lookup_commit(head_sha1);
 
@@ -377,7 +435,7 @@ static int is_index_unchanged(void)
 
        if (!cache_tree_fully_valid(active_cache_tree))
                if (cache_tree_update(&the_index, 0))
-                       return error(_("Unable to update cache tree\n"));
+                       return error(_("unable to update cache tree\n"));
 
        return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.oid.hash);
 }
@@ -421,6 +479,20 @@ static char **read_author_script(void)
        return env;
 }
 
+static const char staged_changes_advice[] =
+N_("you have staged changes in your working tree\n"
+"If these changes are meant to be squashed into the previous commit, run:\n"
+"\n"
+"  git commit --amend %s\n"
+"\n"
+"If they are meant to go into a new commit, run:\n"
+"\n"
+"  git commit %s\n"
+"\n"
+"In both cases, once you're done, continue with:\n"
+"\n"
+"  git rebase --continue\n");
+
 /*
  * If we are cherry-pick, and if the merge did not result in
  * hand-editing, we will hit this commit and inherit the original
@@ -434,7 +506,8 @@ static char **read_author_script(void)
  * author metadata.
  */
 static int run_git_commit(const char *defmsg, struct replay_opts *opts,
-                         int allow_empty)
+                         int allow_empty, int edit, int amend,
+                         int cleanup_commit_message)
 {
        char **env = NULL;
        struct argv_array array;
@@ -443,32 +516,32 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
 
        if (is_rebase_i(opts)) {
                env = read_author_script();
-               if (!env)
-                       return error("You have staged changes in your working "
-                               "tree. If these changes are meant to be\n"
-                               "squashed into the previous commit, run:\n\n"
-                               "  git commit --amend $gpg_sign_opt_quoted\n\n"
-                               "If they are meant to go into a new commit, "
-                               "run:\n\n"
-                               "  git commit $gpg_sign_opt_quoted\n\n"
-                               "In both cases, once you're done, continue "
-                               "with:\n\n"
-                               "  git rebase --continue\n");
+               if (!env) {
+                       const char *gpg_opt = gpg_sign_opt_quoted(opts);
+
+                       return error(_(staged_changes_advice),
+                                    gpg_opt, gpg_opt);
+               }
        }
 
        argv_array_init(&array);
        argv_array_push(&array, "commit");
        argv_array_push(&array, "-n");
 
+       if (amend)
+               argv_array_push(&array, "--amend");
        if (opts->gpg_sign)
                argv_array_pushf(&array, "-S%s", opts->gpg_sign);
        if (opts->signoff)
                argv_array_push(&array, "-s");
        if (defmsg)
                argv_array_pushl(&array, "-F", defmsg, NULL);
-       if (opts->edit)
+       if (cleanup_commit_message)
+               argv_array_push(&array, "--cleanup=strip");
+       if (edit)
                argv_array_push(&array, "-e");
-       else if (!opts->signoff && !opts->record_origin &&
+       else if (!cleanup_commit_message &&
+                !opts->signoff && !opts->record_origin &&
                 git_config_get_value("commit.cleanup", &value))
                argv_array_push(&array, "--cleanup=verbatim");
 
@@ -491,12 +564,12 @@ static int is_original_commit_empty(struct commit *commit)
        const unsigned char *ptree_sha1;
 
        if (parse_commit(commit))
-               return error(_("Could not parse commit %s\n"),
+               return error(_("could not parse commit %s\n"),
                             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"),
+                       return error(_("could not parse parent commit %s\n"),
                                oid_to_hex(&parent->object.oid));
                ptree_sha1 = parent->tree->object.oid.hash;
        } else {
@@ -580,12 +653,12 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                 * to work on.
                 */
                if (write_cache_as_tree(head, 0, NULL))
-                       return error(_("Your index file is unmerged."));
+                       return error(_("your index file is unmerged."));
        } else {
                unborn = get_sha1("HEAD", head);
                if (unborn)
                        hashcpy(head, EMPTY_TREE_SHA1_BIN);
-               if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0))
+               if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0, 0))
                        return error_dirty_index(opts);
        }
        discard_cache();
@@ -599,7 +672,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                struct commit_list *p;
 
                if (!opts->mainline)
-                       return error(_("Commit %s is a merge but no -m option was given."),
+                       return error(_("commit %s is a merge but no -m option was given."),
                                oid_to_hex(&commit->object.oid));
 
                for (cnt = 1, p = commit->parents;
@@ -607,11 +680,11 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                     cnt++)
                        p = p->next;
                if (cnt != opts->mainline || !p)
-                       return error(_("Commit %s does not have parent %d"),
+                       return error(_("commit %s does not have parent %d"),
                                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."),
+               return error(_("mainline was specified but commit %s is not a merge."),
                        oid_to_hex(&commit->object.oid));
        else
                parent = commit->parents->item;
@@ -629,7 +702,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                        oid_to_hex(&parent->object.oid));
 
        if (get_message(commit, &msg) != 0)
-               return error(_("Cannot get commit message for %s"),
+               return error(_("cannot get commit message for %s"),
                        oid_to_hex(&commit->object.oid));
 
        /*
@@ -685,12 +758,14 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                                         head, &msgbuf, opts);
                if (res < 0)
                        return res;
-               res |= write_message(&msgbuf, git_path_merge_msg());
+               res |= write_message(msgbuf.buf, msgbuf.len,
+                                    git_path_merge_msg(), 0);
        } else {
                struct commit_list *common = NULL;
                struct commit_list *remotes = NULL;
 
-               res = write_message(&msgbuf, git_path_merge_msg());
+               res = write_message(msgbuf.buf, msgbuf.len,
+                                   git_path_merge_msg(), 0);
 
                commit_list_insert(base, &common);
                commit_list_insert(next, &remotes);
@@ -700,6 +775,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
                free_commit_list(common);
                free_commit_list(remotes);
        }
+       strbuf_release(&msgbuf);
 
        /*
         * If the merge was clean or if it failed due to conflict, we write
@@ -733,7 +809,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
        }
        if (!opts->no_commit)
                res = run_git_commit(opts->edit ? NULL : git_path_merge_msg(),
-                                    opts, allow);
+                                    opts, allow, opts->edit, 0, 0);
 
 leave:
        free_message(commit, &msg);
@@ -765,14 +841,14 @@ static int read_and_refresh_cache(struct replay_opts *opts)
        if (read_index_preload(&the_index, NULL) < 0) {
                rollback_lock_file(&index_lock);
                return error(_("git %s: failed to read the index"),
-                       action_name(opts));
+                       _(action_name(opts)));
        }
        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL, NULL);
        if (the_index.cache_changed && index_fd >= 0) {
                if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) {
                        rollback_lock_file(&index_lock);
                        return error(_("git %s: failed to refresh the index"),
-                               action_name(opts));
+                               _(action_name(opts)));
                }
        }
        rollback_lock_file(&index_lock);
@@ -815,6 +891,9 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
        char *end_of_object_name;
        int i, saved, status, padding;
 
+       /* left-trim */
+       bol += strspn(bol, " \t");
+
        for (i = 0; i < ARRAY_SIZE(todo_command_strings); i++)
                if (skip_prefix(bol, todo_command_strings[i], &bol)) {
                        item->command = i;
@@ -862,13 +941,13 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list)
                item = append_new_todo(todo_list);
                item->offset_in_buf = p - todo_list->buf.buf;
                if (parse_insn_line(item, p, eol)) {
-                       res = error(_("Invalid line %d: %.*s"),
+                       res = error(_("invalid line %d: %.*s"),
                                i, (int)(eol - p), p);
                        item->command = -1;
                }
        }
        if (!todo_list->nr)
-               return error(_("No commits parsed."));
+               return error(_("no commits parsed."));
        return res;
 }
 
@@ -881,15 +960,18 @@ static int read_populate_todo(struct todo_list *todo_list,
        strbuf_reset(&todo_list->buf);
        fd = open(todo_file, O_RDONLY);
        if (fd < 0)
-               return error_errno(_("Could not open %s"), todo_file);
+               return error_errno(_("could not open '%s'"), todo_file);
        if (strbuf_read(&todo_list->buf, fd, 0) < 0) {
                close(fd);
-               return error(_("Could not read %s."), todo_file);
+               return error(_("could not read '%s'."), todo_file);
        }
        close(fd);
 
        res = parse_insn_buffer(todo_list->buf.buf, todo_list);
-       if (!res) {
+       if (res)
+               return error(_("unusable instruction sheet: '%s'"), todo_file);
+
+       if (!is_rebase_i(opts)) {
                enum todo_command valid =
                        opts->action == REPLAY_PICK ? TODO_PICK : TODO_REVERT;
                int i;
@@ -898,13 +980,11 @@ static int read_populate_todo(struct todo_list *todo_list,
                        if (valid == todo_list->items[i].command)
                                continue;
                        else if (valid == TODO_PICK)
-                               return error(_("Cannot cherry-pick during a revert."));
+                               return error(_("cannot cherry-pick during a revert."));
                        else
-                               return error(_("Cannot revert during a cherry-pick."));
+                               return error(_("cannot revert during a cherry-pick."));
        }
 
-       if (res)
-               return error(_("Unusable instruction sheet: %s"), todo_file);
        return 0;
 }
 
@@ -945,18 +1025,31 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
                ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
                opts->xopts[opts->xopts_nr++] = xstrdup(value);
        } else
-               return error(_("Invalid key: %s"), key);
+               return error(_("invalid key: %s"), key);
 
        if (!error_flag)
-               return error(_("Invalid value for %s: %s"), key, value);
+               return error(_("invalid value for %s: %s"), key, value);
 
        return 0;
 }
 
 static int read_populate_opts(struct replay_opts *opts)
 {
-       if (is_rebase_i(opts))
+       if (is_rebase_i(opts)) {
+               struct strbuf buf = STRBUF_INIT;
+
+               if (read_oneliner(&buf, rebase_path_gpg_sign_opt(), 1)) {
+                       if (!starts_with(buf.buf, "-S"))
+                               strbuf_reset(&buf);
+                       else {
+                               free(opts->gpg_sign);
+                               opts->gpg_sign = xstrdup(buf.buf + 2);
+                       }
+               }
+               strbuf_release(&buf);
+
                return 0;
+       }
 
        if (!file_exists(git_path_opts_file()))
                return 0;
@@ -967,7 +1060,7 @@ static int read_populate_opts(struct replay_opts *opts)
         * are pretty certain that it is syntactically correct.
         */
        if (git_config_from_file(populate_opts_cb, git_path_opts_file(), opts) < 0)
-               return error(_("Malformed options sheet: %s"),
+               return error(_("malformed options sheet: '%s'"),
                        git_path_opts_file());
        return 0;
 }
@@ -1010,7 +1103,7 @@ static int create_seq_dir(void)
                return -1;
        }
        else if (mkdir(git_path_seq_dir(), 0777) < 0)
-               return error_errno(_("Could not create sequencer directory %s"),
+               return error_errno(_("could not create sequencer directory '%s'"),
                                   git_path_seq_dir());
        return 0;
 }
@@ -1024,17 +1117,17 @@ static int save_head(const char *head)
        fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
        if (fd < 0) {
                rollback_lock_file(&head_lock);
-               return error_errno(_("Could not lock HEAD"));
+               return error_errno(_("could not lock HEAD"));
        }
        strbuf_addf(&buf, "%s\n", head);
        if (write_in_full(fd, buf.buf, buf.len) < 0) {
                rollback_lock_file(&head_lock);
-               return error_errno(_("Could not write to %s"),
+               return error_errno(_("could not write to '%s'"),
                                   git_path_head_file());
        }
        if (commit_lock_file(&head_lock) < 0) {
                rollback_lock_file(&head_lock);
-               return error(_("Error wrapping up %s."), git_path_head_file());
+               return error(_("failed to finalize '%s'."), git_path_head_file());
        }
        return 0;
 }
@@ -1079,9 +1172,9 @@ int sequencer_rollback(struct replay_opts *opts)
                return rollback_single_pick();
        }
        if (!f)
-               return error_errno(_("cannot open %s"), git_path_head_file());
+               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(),
+               error(_("cannot read '%s': %s"), git_path_head_file(),
                      ferror(f) ?  strerror(errno) : _("unexpected end of file"));
                fclose(f);
                goto fail;
@@ -1113,14 +1206,14 @@ static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
 
        fd = hold_lock_file_for_update(&todo_lock, todo_path, 0);
        if (fd < 0)
-               return error_errno(_("Could not lock '%s'"), todo_path);
+               return error_errno(_("could not lock '%s'"), todo_path);
        offset = next < todo_list->nr ?
                todo_list->items[next].offset_in_buf : todo_list->buf.len;
        if (write_in_full(fd, todo_list->buf.buf + offset,
                        todo_list->buf.len - offset) < 0)
-               return error_errno(_("Could not write to '%s'"), todo_path);
+               return error_errno(_("could not write to '%s'"), todo_path);
        if (commit_lock_file(&todo_lock) < 0)
-               return error(_("Error wrapping up %s."), todo_path);
+               return error(_("failed to finalize '%s'."), todo_path);
        return 0;
 }
 
@@ -1219,7 +1312,7 @@ int sequencer_continue(struct replay_opts *opts)
                if (res)
                        goto release_todo_list;
        }
-       if (index_differs_from("HEAD", 0)) {
+       if (index_differs_from("HEAD", 0, 0)) {
                res = error_dirty_index(opts);
                goto release_todo_list;
        }
@@ -1295,7 +1388,7 @@ int sequencer_pick_revisions(struct replay_opts *opts)
                        create_seq_dir() < 0)
                return -1;
        if (get_sha1("HEAD", sha1) && (opts->action == REPLAY_REVERT))
-               return error(_("Can't revert as initial commit"));
+               return error(_("can't revert as initial commit"));
        if (save_head(sha1_to_hex(sha1)))
                return -1;
        if (save_opts(opts))