Skip to content

Commit 5ea721e

Browse files
committed
rebase -i: also expand/collapse the SHA-1s via the rebase--helper
This is crucial to improve performance on Windows, as the speed is now mostly dominated by the SHA-1 transformation (because it spawns a new rev-parse process for *every* line, and spawning processes is pretty slow from Git for Windows' MSYS2 Bash). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent d5a0115 commit 5ea721e

File tree

4 files changed

+68
-5
lines changed

4 files changed

+68
-5
lines changed

builtin/rebase--helper.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
1313
struct replay_opts opts = REPLAY_OPTS_INIT;
1414
int keep_empty = 0;
1515
enum {
16-
CONTINUE = 1, ABORT, MAKE_SCRIPT
16+
CONTINUE = 1, ABORT, MAKE_SCRIPT, SHORTEN_SHA1S, EXPAND_SHA1S
1717
} command = 0;
1818
struct option options[] = {
1919
OPT_BOOL(0, "ff", &opts.allow_ff, N_("allow fast-forward")),
@@ -24,6 +24,10 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
2424
ABORT),
2525
OPT_CMDMODE(0, "make-script", &command,
2626
N_("make rebase script"), MAKE_SCRIPT),
27+
OPT_CMDMODE(0, "shorten-sha1s", &command,
28+
N_("make rebase script"), SHORTEN_SHA1S),
29+
OPT_CMDMODE(0, "expand-sha1s", &command,
30+
N_("make rebase script"), EXPAND_SHA1S),
2731
OPT_END()
2832
};
2933

@@ -42,5 +46,9 @@ int cmd_rebase__helper(int argc, const char **argv, const char *prefix)
4246
return sequencer_remove_state(&opts);
4347
if (command == MAKE_SCRIPT && argc > 1)
4448
return sequencer_make_script(keep_empty, stdout, argc, argv);
49+
if (command == SHORTEN_SHA1S && argc == 1)
50+
return transform_todo_ids(1);
51+
if (command == EXPAND_SHA1S && argc == 1)
52+
return transform_todo_ids(0);
4553
usage_with_options(builtin_rebase_helper_usage, options);
4654
}

git-rebase--interactive.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,11 +743,11 @@ transform_todo_ids () {
743743
}
744744

745745
expand_todo_ids() {
746-
transform_todo_ids
746+
git rebase--helper --expand-sha1s
747747
}
748748

749749
collapse_todo_ids() {
750-
transform_todo_ids --short
750+
git rebase--helper --shorten-sha1s
751751
}
752752

753753
# Rearrange the todo list that has both "pick sha1 msg" and

sequencer.c

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ struct todo_item *append_todo(struct todo_list *todo_list)
11521152
}
11531153

11541154
static int parse_insn_line(struct todo_item *item,
1155-
const char *bol, char *eol, struct replay_opts *opts)
1155+
const char *bol, char *eol)
11561156
{
11571157
unsigned char commit_sha1[20];
11581158
char *end_of_object_name;
@@ -1226,7 +1226,7 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list,
12261226

12271227
item = append_todo(todo_list);
12281228
item->offset_in_buf = p - todo_list->buf.buf;
1229-
if (parse_insn_line(item, p, eol, opts))
1229+
if (parse_insn_line(item, p, eol))
12301230
return error(_("Could not parse line %d."), i);
12311231
if (fixup_okay)
12321232
; /* do nothing */
@@ -2206,3 +2206,56 @@ int sequencer_make_script(int keep_empty, FILE *out,
22062206
strbuf_release(&buf);
22072207
return 0;
22082208
}
2209+
2210+
2211+
int transform_todo_ids(int shorten_sha1s)
2212+
{
2213+
const char *todo_file = git_path_rebase_todo();
2214+
struct todo_list todo_list = TODO_LIST_INIT;
2215+
struct replay_opts opts;
2216+
int fd, res, i;
2217+
FILE *out;
2218+
2219+
strbuf_reset(&todo_list.buf);
2220+
fd = open(todo_file, O_RDONLY);
2221+
if (fd < 0)
2222+
return error(_("Could not open %s (%s)"),
2223+
todo_file, strerror(errno));
2224+
if (strbuf_read(&todo_list.buf, fd, 0) < 0) {
2225+
close(fd);
2226+
return error(_("Could not read %s."), todo_file);
2227+
}
2228+
close(fd);
2229+
2230+
memset(&opts, 0, sizeof(opts));
2231+
opts.action = REPLAY_INTERACTIVE_REBASE;
2232+
res = parse_insn_buffer(todo_list.buf.buf, &todo_list, &opts);
2233+
if (res)
2234+
return error(_("Unusable instruction sheet: %s"), todo_file);
2235+
2236+
out = fopen(todo_file, "w");
2237+
if (!out)
2238+
return error(_("Unable to open '%s' for writing"), todo_file);
2239+
for (i = 0; i < todo_list.nr; i++) {
2240+
struct todo_item *item = todo_list.items + i;
2241+
int bol = item->offset_in_buf;
2242+
const char *p = todo_list.buf.buf + bol;
2243+
int eol = i + 1 < todo_list.nr ?
2244+
todo_list.items[i + 1].offset_in_buf :
2245+
todo_list.buf.len;
2246+
2247+
if (item->command >= TODO_EXEC && item->command != TODO_DROP)
2248+
fwrite(p, eol - bol, 1, out);
2249+
else {
2250+
int eoc = strcspn(todo_list.buf.buf + bol, " \t");
2251+
const char *sha1 = shorten_sha1s ?
2252+
short_commit_name(item->commit) :
2253+
oid_to_hex(&item->commit->object.oid);
2254+
2255+
fprintf(out, "%.*s %s %.*s\n",
2256+
eoc, p, sha1, item->arg_len, item->arg);
2257+
}
2258+
}
2259+
fclose(out);
2260+
return 0;
2261+
}

sequencer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ int sequencer_commit(const char *defmsg, struct replay_opts *opts,
4949
int sequencer_make_script(int keep_empty, FILE *out,
5050
int argc, const char **argv);
5151

52+
int transform_todo_ids(int shorten_sha1s);
53+
5254
extern const char sign_off_header[];
5355

5456
void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag);

0 commit comments

Comments
 (0)