зеркало из https://github.com/microsoft/git.git
sequencer: refactor rearrange_squash() to work on a todo_list
This refactors rearrange_squash() to work on a todo_list to avoid redundant reads and writes. The function is renamed todo_list_rearrange_squash(). The old version created a new buffer, which was directly written to the disk. This new version creates a new item list by just copying items from the old item list, without creating a new buffer. This eliminates the need to reparse the todo list, but this also means its buffer cannot be directly written to the disk. As rebase -p still need to check the todo list from the disk, a new function is introduced, rearrange_squash_in_todo_file(). complete_action() still uses rearrange_squash_in_todo_file() for now. This will be changed in a future commit. Signed-off-by: Alban Gruin <alban.gruin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
683153a438
Коммит
f2a04904be
|
@ -268,7 +268,7 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
|
|||
ret = check_todo_list_from_file(the_repository);
|
||||
break;
|
||||
case REARRANGE_SQUASH:
|
||||
ret = rearrange_squash(the_repository);
|
||||
ret = rearrange_squash_in_todo_file(the_repository);
|
||||
break;
|
||||
case ADD_EXEC:
|
||||
ret = sequencer_add_exec_commands(the_repository, &commands);
|
||||
|
|
92
sequencer.c
92
sequencer.c
|
@ -4840,7 +4840,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
|
|||
write_message("noop\n", 5, todo_file, 0))
|
||||
return -1;
|
||||
|
||||
if (autosquash && rearrange_squash(r))
|
||||
if (autosquash && rearrange_squash_in_todo_file(r))
|
||||
return -1;
|
||||
|
||||
if (commands->nr)
|
||||
|
@ -4946,21 +4946,13 @@ define_commit_slab(commit_todo_item, struct todo_item *);
|
|||
* message will have to be retrieved from the commit (as the oneline in the
|
||||
* script cannot be trusted) in order to normalize the autosquash arrangement.
|
||||
*/
|
||||
int rearrange_squash(struct repository *r)
|
||||
static int todo_list_rearrange_squash(struct todo_list *todo_list)
|
||||
{
|
||||
const char *todo_file = rebase_path_todo();
|
||||
struct todo_list todo_list = TODO_LIST_INIT;
|
||||
struct hashmap subject2item;
|
||||
int res = 0, rearranged = 0, *next, *tail, i;
|
||||
int rearranged = 0, *next, *tail, i, nr = 0, alloc = 0;
|
||||
char **subjects;
|
||||
struct commit_todo_item commit_todo;
|
||||
|
||||
if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
|
||||
return -1;
|
||||
if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list) < 0) {
|
||||
todo_list_release(&todo_list);
|
||||
return -1;
|
||||
}
|
||||
struct todo_item *items = NULL;
|
||||
|
||||
init_commit_todo_item(&commit_todo);
|
||||
/*
|
||||
|
@ -4973,13 +4965,13 @@ int rearrange_squash(struct repository *r)
|
|||
* be moved to appear after the i'th.
|
||||
*/
|
||||
hashmap_init(&subject2item, (hashmap_cmp_fn) subject2item_cmp,
|
||||
NULL, todo_list.nr);
|
||||
ALLOC_ARRAY(next, todo_list.nr);
|
||||
ALLOC_ARRAY(tail, todo_list.nr);
|
||||
ALLOC_ARRAY(subjects, todo_list.nr);
|
||||
for (i = 0; i < todo_list.nr; i++) {
|
||||
NULL, todo_list->nr);
|
||||
ALLOC_ARRAY(next, todo_list->nr);
|
||||
ALLOC_ARRAY(tail, todo_list->nr);
|
||||
ALLOC_ARRAY(subjects, todo_list->nr);
|
||||
for (i = 0; i < todo_list->nr; i++) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct todo_item *item = todo_list.items + i;
|
||||
struct todo_item *item = todo_list->items + i;
|
||||
const char *commit_buffer, *subject, *p;
|
||||
size_t subject_len;
|
||||
int i2 = -1;
|
||||
|
@ -4992,7 +4984,6 @@ int rearrange_squash(struct repository *r)
|
|||
}
|
||||
|
||||
if (is_fixup(item->command)) {
|
||||
todo_list_release(&todo_list);
|
||||
clear_commit_todo_item(&commit_todo);
|
||||
return error(_("the script was already rearranged."));
|
||||
}
|
||||
|
@ -5027,7 +5018,7 @@ int rearrange_squash(struct repository *r)
|
|||
*commit_todo_item_at(&commit_todo, commit2))
|
||||
/* found by commit name */
|
||||
i2 = *commit_todo_item_at(&commit_todo, commit2)
|
||||
- todo_list.items;
|
||||
- todo_list->items;
|
||||
else {
|
||||
/* copy can be a prefix of the commit subject */
|
||||
for (i2 = 0; i2 < i; i2++)
|
||||
|
@ -5040,7 +5031,7 @@ int rearrange_squash(struct repository *r)
|
|||
}
|
||||
if (i2 >= 0) {
|
||||
rearranged = 1;
|
||||
todo_list.items[i].command =
|
||||
todo_list->items[i].command =
|
||||
starts_with(subject, "fixup!") ?
|
||||
TODO_FIXUP : TODO_SQUASH;
|
||||
if (next[i2] < 0)
|
||||
|
@ -5058,10 +5049,8 @@ int rearrange_squash(struct repository *r)
|
|||
}
|
||||
|
||||
if (rearranged) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
for (i = 0; i < todo_list.nr; i++) {
|
||||
enum todo_command command = todo_list.items[i].command;
|
||||
for (i = 0; i < todo_list->nr; i++) {
|
||||
enum todo_command command = todo_list->items[i].command;
|
||||
int cur = i;
|
||||
|
||||
/*
|
||||
|
@ -5072,37 +5061,50 @@ int rearrange_squash(struct repository *r)
|
|||
continue;
|
||||
|
||||
while (cur >= 0) {
|
||||
const char *bol =
|
||||
get_item_line(&todo_list, cur);
|
||||
const char *eol =
|
||||
get_item_line(&todo_list, cur + 1);
|
||||
|
||||
/* replace 'pick', by 'fixup' or 'squash' */
|
||||
command = todo_list.items[cur].command;
|
||||
if (is_fixup(command)) {
|
||||
strbuf_addstr(&buf,
|
||||
todo_command_info[command].str);
|
||||
bol += strcspn(bol, " \t");
|
||||
}
|
||||
|
||||
strbuf_add(&buf, bol, eol - bol);
|
||||
|
||||
ALLOC_GROW(items, nr + 1, alloc);
|
||||
items[nr++] = todo_list->items[cur];
|
||||
cur = next[cur];
|
||||
}
|
||||
}
|
||||
|
||||
res = rewrite_file(todo_file, buf.buf, buf.len);
|
||||
strbuf_release(&buf);
|
||||
FREE_AND_NULL(todo_list->items);
|
||||
todo_list->items = items;
|
||||
todo_list->nr = nr;
|
||||
todo_list->alloc = alloc;
|
||||
}
|
||||
|
||||
free(next);
|
||||
free(tail);
|
||||
for (i = 0; i < todo_list.nr; i++)
|
||||
for (i = 0; i < todo_list->nr; i++)
|
||||
free(subjects[i]);
|
||||
free(subjects);
|
||||
hashmap_free(&subject2item, 1);
|
||||
todo_list_release(&todo_list);
|
||||
|
||||
clear_commit_todo_item(&commit_todo);
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rearrange_squash_in_todo_file(struct repository *r)
|
||||
{
|
||||
const char *todo_file = rebase_path_todo();
|
||||
struct todo_list todo_list = TODO_LIST_INIT;
|
||||
int res = 0;
|
||||
|
||||
if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
|
||||
return -1;
|
||||
if (todo_list_parse_insn_buffer(r, todo_list.buf.buf, &todo_list) < 0) {
|
||||
todo_list_release(&todo_list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = todo_list_rearrange_squash(&todo_list);
|
||||
if (!res)
|
||||
res = todo_list_write_to_file(r, &todo_list, todo_file, NULL, NULL, -1, 0);
|
||||
|
||||
todo_list_release(&todo_list);
|
||||
|
||||
if (res)
|
||||
return error_errno(_("could not write '%s'."), todo_file);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
|
|||
const char *shortrevisions, const char *onto_name,
|
||||
const char *onto, const char *orig_head, struct string_list *commands,
|
||||
unsigned autosquash);
|
||||
int rearrange_squash(struct repository *r);
|
||||
int rearrange_squash_in_todo_file(struct repository *r);
|
||||
|
||||
extern const char sign_off_header[];
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче