[PATCH v3 0/9] The final building block for a faster rebase -i
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Apr 26, 2017, 11:59 UTC
- Message-ID
- <cover.1493207864.git.johannes.schindelin@gmx.de>
- In-Reply-To
- <cover.1493128210.git.johannes.schindelin@gmx.de>
This patch series reimplements the expensive pre- and post-processing of the todo script in C.
And it concludes the work I did to accelerate rebase -i.
Changes since v2:
- rearranged error_errno() calls to come before any subsequent free() and close()
- now call close(fd) in case of error to avoid resource leaks
- removed unused `format` variable holding the value of rebase.instructionFormat from rearrange_squash()
- modified rearrange_squash() to make it easier to reason about subjects[i] taking custody of a strbuf's buffer (this should enable Coverity to see that there is no resource leak here)
Johannes Schindelin (9): rebase -i: generate the script via rebase--helper rebase -i: remove useless indentation rebase -i: do not invent onelines when expanding/collapsing SHA-1s rebase -i: also expand/collapse the SHA-1s via the rebase--helper t3404: relax rebase.missingCommitsCheck tests rebase -i: check for missing commits in the rebase--helper rebase -i: skip unnecessary picks using the rebase--helper t3415: test fixup with wrapped oneline rebase -i: rearrange fixup/squash lines using the rebase--helper
Documentation/git-rebase.txt | 16 +- builtin/rebase--helper.c | 29 ++- git-rebase--interactive.sh | 362 ++++------------------------ sequencer.c | 531 ++++++++++++++++++++++++++++++++++++++++++ sequencer.h | 8 + t/t3404-rebase-interactive.sh | 22 +- t/t3415-rebase-autosquash.sh | 16 +- 7 files changed, 641 insertions(+), 343 deletions(-)
base-commit: e2cb6ab84c94f147f1259260961513b40c36108a Based-On: rebase--helper at https://github.com/dscho/git Fetch-Base-Via: git fetch https://github.com/dscho/git rebase--helper Published-As: https://github.com/dscho/git/releases/tag/rebase-i-extra-v3 Fetch-It-Via: git fetch https://github.com/dscho/git rebase-i-extra-v3
Interdiff vs v2:
diff --git a/sequencer.c b/sequencer.c
index 2b07fb9e0ce..7ac1792311e 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2393,7 +2393,7 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag)
int sequencer_make_script(int keep_empty, FILE *out,
int argc, const char **argv)
{
- char *format = "%s";
+ char *format = xstrdup("%s");
struct pretty_print_context pp = {0};
struct strbuf buf = STRBUF_INIT;
struct rev_info revs;
@@ -2412,6 +2412,7 @@ int sequencer_make_script(int keep_empty, FILE *out,
revs.pretty_given = 1;
git_config_get_string("rebase.instructionFormat", &format);
get_commit_format(format, &revs);
+ free(format);
pp.fmt = revs.commit_format;
pp.output_encoding = get_log_output_encoding();
@@ -2676,24 +2677,41 @@ int skip_unnecessary_picks(void)
const char *done_path = rebase_path_done();
fd = open(done_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
+ if (fd < 0) {
+ error_errno(_("could not open '%s' for writing"),
+ done_path);
+ todo_list_release(&todo_list);
+ return -1;
+ }
if (write_in_full(fd, todo_list.buf.buf, offset) < 0) {
+ error_errno(_("could not write to '%s'"), done_path);
todo_list_release(&todo_list);
- return error_errno(_("could not write to '%s'"),
- done_path);
+ close(fd);
+ return -1;
}
close(fd);
fd = open(rebase_path_todo(), O_WRONLY, 0666);
+ if (fd < 0) {
+ error_errno(_("could not open '%s' for writing"),
+ rebase_path_todo());
+ todo_list_release(&todo_list);
+ return -1;
+ }
if (write_in_full(fd, todo_list.buf.buf + offset,
todo_list.buf.len - offset) < 0) {
+ error_errno(_("could not write to '%s'"),
+ rebase_path_todo());
+ close(fd);
todo_list_release(&todo_list);
- return error_errno(_("could not write to '%s'"),
- rebase_path_todo());
+ return -1;
}
if (ftruncate(fd, todo_list.buf.len - offset) < 0) {
+ error_errno(_("could not truncate '%s'"),
+ rebase_path_todo());
todo_list_release(&todo_list);
- return error_errno(_("could not truncate '%s'"),
- rebase_path_todo());
+ close(fd);
+ return -1;
}
close(fd);
@@ -2768,6 +2786,7 @@ int rearrange_squash(void)
struct strbuf buf = STRBUF_INIT;
struct todo_item *item = todo_list.items + i;
const char *commit_buffer, *subject, *p;
+ size_t subject_len;
int i2 = -1;
struct subject2item_entry *entry;
@@ -2788,7 +2807,7 @@ int rearrange_squash(void)
commit_buffer = get_commit_buffer(item->commit, NULL);
find_commit_subject(commit_buffer, &subject);
format_subject(&buf, subject, " ");
- subject = subjects[i] = buf.buf;
+ subject = subjects[i] = strbuf_detach(&buf, &subject_len);
unuse_commit_buffer(item->commit, commit_buffer);
if ((skip_prefix(subject, "fixup! ", &p) ||
skip_prefix(subject, "squash! ", &p))) {
@@ -2835,19 +2854,16 @@ int rearrange_squash(void)
tail[i2] = i;
} else if (!hashmap_get_from_hash(&subject2item,
strhash(subject), subject)) {
- FLEX_ALLOC_MEM(entry, subject, buf.buf, buf.len);
+ FLEX_ALLOC_MEM(entry, subject, subject, subject_len);
entry->i = i;
hashmap_entry_init(entry, strhash(entry->subject));
hashmap_put(&subject2item, entry);
}
- strbuf_detach(&buf, NULL);
}
if (rearranged) {
struct strbuf buf = STRBUF_INIT;
- char *format = NULL;
- git_config_get_string("rebase.instructionFormat", &format);
for (i = 0; i < todo_list.nr; i++) {
enum todo_command command = todo_list.items[i].command;
int cur = i;-- 2.12.2.windows.2.406.gd14a8f8640f