Browse Source

Merge branch 'pw/rebase-i-author-script-fix'

Recent "git rebase -i" update started to write bogusly formatted
author-script, with a matching broken reading code.  These are
fixed.

* pw/rebase-i-author-script-fix:
  sequencer: fix quoting in write_author_script
  sequencer: handle errors from read_author_ident()
maint
Junio C Hamano 6 years ago
parent
commit
064e0b2d4c
  1. 47
      sequencer.c
  2. 18
      t/t3404-rebase-interactive.sh

47
sequencer.c

@ -639,7 +639,7 @@ missing_author: @@ -639,7 +639,7 @@ missing_author:
else if (*message != '\'')
strbuf_addch(&buf, *(message++));
else
strbuf_addf(&buf, "'\\\\%c'", *(message++));
strbuf_addf(&buf, "'\\%c'", *(message++));
strbuf_addstr(&buf, "'\nGIT_AUTHOR_EMAIL='");
while (*message && *message != '\n' && *message != '\r')
if (skip_prefix(message, "> ", &message))
@ -647,19 +647,37 @@ missing_author: @@ -647,19 +647,37 @@ missing_author:
else if (*message != '\'')
strbuf_addch(&buf, *(message++));
else
strbuf_addf(&buf, "'\\\\%c'", *(message++));
strbuf_addf(&buf, "'\\%c'", *(message++));
strbuf_addstr(&buf, "'\nGIT_AUTHOR_DATE='@");
while (*message && *message != '\n' && *message != '\r')
if (*message != '\'')
strbuf_addch(&buf, *(message++));
else
strbuf_addf(&buf, "'\\\\%c'", *(message++));
strbuf_addf(&buf, "'\\%c'", *(message++));
strbuf_addch(&buf, '\'');
res = write_message(buf.buf, buf.len, rebase_path_author_script(), 1);
strbuf_release(&buf);
return res;
}


/*
* write_author_script() used to fail to terminate the last line with a "'" and
* also escaped "'" incorrectly as "'\\\\''" rather than "'\\''". We check for
* the terminating "'" on the last line to see how "'" has been escaped in case
* git was upgraded while rebase was stopped.
*/
static int quoting_is_broken(const char *s, size_t n)
{
/* Skip any empty lines in case the file was hand edited */
while (n > 0 && s[--n] == '\n')
; /* empty */
if (n > 0 && s[n] != '\'')
return 1;

return 0;
}

/*
* Read a list of environment variable assignments (such as the author-script
* file) into an environment block. Returns -1 on error, 0 otherwise.
@ -667,14 +685,18 @@ missing_author: @@ -667,14 +685,18 @@ missing_author:
static int read_env_script(struct argv_array *env)
{
struct strbuf script = STRBUF_INIT;
int i, count = 0;
char *p, *p2;
int i, count = 0, sq_bug;
const char *p2;
char *p;

if (strbuf_read_file(&script, rebase_path_author_script(), 256) <= 0)
return -1;

/* write_author_script() used to quote incorrectly */
sq_bug = quoting_is_broken(script.buf, script.len);
for (p = script.buf; *p; p++)
if (skip_prefix(p, "'\\\\''", (const char **)&p2))
if (sq_bug && skip_prefix(p, "'\\\\''", &p2))
strbuf_splice(&script, p - script.buf, p2 - p, "'", 1);
else if (skip_prefix(p, "'\\''", &p2))
strbuf_splice(&script, p - script.buf, p2 - p, "'", 1);
else if (*p == '\'')
strbuf_splice(&script, p-- - script.buf, 1, "", 0);
@ -798,11 +820,18 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts, @@ -798,11 +820,18 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,

if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {
struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;
const char *author = is_rebase_i(opts) ?
read_author_ident(&script) : NULL;
const char *author = NULL;
struct object_id root_commit, *cache_tree_oid;
int res = 0;

if (is_rebase_i(opts)) {
author = read_author_ident(&script);
if (!author) {
strbuf_release(&script);
return -1;
}
}

if (!defmsg)
BUG("root commit without message");


18
t/t3404-rebase-interactive.sh

@ -1426,9 +1426,21 @@ test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' @@ -1426,9 +1426,21 @@ test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' '
test_expect_success 'valid author header after --root swap' '
rebase_setup_and_clean author-header no-conflict-branch &&
set_fake_editor &&
FAKE_LINES="2 1" git rebase -i --root &&
git cat-file commit HEAD^ >out &&
grep "^author ..*> [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$" out
git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit &&
git cat-file commit HEAD | grep ^author >expected &&
FAKE_LINES="5 1" git rebase -i --root &&
git cat-file commit HEAD^ | grep ^author >actual &&
test_cmp expected actual
'

test_expect_success 'valid author header when author contains single quote' '
rebase_setup_and_clean author-header no-conflict-branch &&
set_fake_editor &&
git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit &&
git cat-file commit HEAD | grep ^author >expected &&
FAKE_LINES="2" git rebase -i HEAD~2 &&
git cat-file commit HEAD | grep ^author >actual &&
test_cmp expected actual
'

test_done

Loading…
Cancel
Save