Skip to content

Commit b140632

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 <[email protected]>
1 parent 5620e55 commit b140632

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-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
@@ -744,11 +744,11 @@ transform_todo_ids () {
744744
}
745745

746746
expand_todo_ids() {
747-
transform_todo_ids
747+
git rebase--helper --expand-sha1s
748748
}
749749

750750
collapse_todo_ids() {
751-
transform_todo_ids --short
751+
git rebase--helper --shorten-sha1s
752752
}
753753

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

sequencer.c

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

11531153
static int parse_insn_line(struct todo_item *item,
1154-
const char *bol, char *eol, struct replay_opts *opts)
1154+
const char *bol, char *eol)
11551155
{
11561156
unsigned char commit_sha1[20];
11571157
char *end_of_object_name;
@@ -1225,7 +1225,7 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list,
12251225

12261226
item = append_todo(todo_list);
12271227
item->offset_in_buf = p - todo_list->buf.buf;
1228-
if (parse_insn_line(item, p, eol, opts))
1228+
if (parse_insn_line(item, p, eol))
12291229
return error(_("Could not parse line %d."), i);
12301230
if (fixup_okay)
12311231
; /* do nothing */
@@ -2226,3 +2226,61 @@ int sequencer_make_script(int keep_empty, FILE *out,
22262226
strbuf_release(&buf);
22272227
return 0;
22282228
}
2229+
2230+
2231+
int transform_todo_ids(int shorten_sha1s)
2232+
{
2233+
const char *todo_file = git_path_rebase_todo();
2234+
struct todo_list todo_list = TODO_LIST_INIT;
2235+
struct replay_opts opts;
2236+
int fd, res, i;
2237+
FILE *out;
2238+
2239+
strbuf_reset(&todo_list.buf);
2240+
fd = open(todo_file, O_RDONLY);
2241+
if (fd < 0)
2242+
return error(_("Could not open %s (%s)"),
2243+
todo_file, strerror(errno));
2244+
if (strbuf_read(&todo_list.buf, fd, 0) < 0) {
2245+
close(fd);
2246+
return error(_("Could not read %s."), todo_file);
2247+
}
2248+
close(fd);
2249+
2250+
memset(&opts, 0, sizeof(opts));
2251+
opts.action = REPLAY_INTERACTIVE_REBASE;
2252+
res = parse_insn_buffer(todo_list.buf.buf, &todo_list, &opts);
2253+
if (res)
2254+
return error(_("Unusable instruction sheet: %s"), todo_file);
2255+
2256+
out = fopen(todo_file, "w");
2257+
if (!out)
2258+
return error(_("Unable to open '%s' for writing"), todo_file);
2259+
for (i = 0; i < todo_list.nr; i++) {
2260+
struct todo_item *item = todo_list.items + i;
2261+
int bol = item->offset_in_buf;
2262+
const char *p = todo_list.buf.buf + bol;
2263+
int eol = i + 1 < todo_list.nr ?
2264+
todo_list.items[i + 1].offset_in_buf :
2265+
todo_list.buf.len;
2266+
2267+
if (item->command >= TODO_EXEC && item->command != TODO_DROP)
2268+
fwrite(p, eol - bol, 1, out);
2269+
else {
2270+
int eoc = strcspn(p, " \t");
2271+
const char *sha1 = shorten_sha1s ?
2272+
short_commit_name(item->commit) :
2273+
oid_to_hex(&item->commit->object.oid);
2274+
2275+
if (!eoc) {
2276+
p += strspn(p, " \t");
2277+
eoc = strcspn(p, " \t");
2278+
}
2279+
2280+
fprintf(out, "%.*s %s %.*s\n",
2281+
eoc, p, sha1, item->arg_len, item->arg);
2282+
}
2283+
}
2284+
fclose(out);
2285+
return 0;
2286+
}

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)