Skip to content

Commit edfac5e

Browse files
chriscoolgitster
authored andcommitted
builtin/am: use apply API in run_apply()
This replaces run_apply() implementation with a new one that uses the apply API that has been previously prepared in apply.c and apply.h. This shoud improve performance a lot in certain cases. As the previous implementation was creating a new `git apply` process to apply each patch, it could be slow on systems like Windows where it is costly to create new processes. Also the new `git apply` process had to read the index from disk, and when the process was done the calling process discarded its own index and read back from disk the new index that had been created by the `git apply` process. This could be very inefficient with big repositories that have big index files, especially when the system decided that it was a good idea to run the `git apply` processes on a different processor core. Also eliminating index reads enables further performance improvements by using: `git update-index --split-index` For example here is a benchmark of a multi hundred commit rebase on the Linux kernel on a Debian laptop with SSD: command: git rebase --onto 1993b17 52bef0c 29dde7c Vanilla "next" without split index: 1m54.953s Vanilla "next" with split index: 1m22.476s This series on top of "next" without split index: 1m12.034s This series on top of "next" with split index: 0m15.678s (using branch "next" from mid April 2016.) Benchmarked-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5b0b57f commit edfac5e

File tree

1 file changed

+43
-22
lines changed

1 file changed

+43
-22
lines changed

builtin/am.c

+43-22
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "rerere.h"
2929
#include "prompt.h"
3030
#include "mailinfo.h"
31+
#include "apply.h"
3132

3233
/**
3334
* Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -1522,39 +1523,59 @@ static int parse_mail_rebase(struct am_state *state, const char *mail)
15221523
*/
15231524
static int run_apply(const struct am_state *state, const char *index_file)
15241525
{
1525-
struct child_process cp = CHILD_PROCESS_INIT;
1526-
1527-
cp.git_cmd = 1;
1528-
1529-
if (index_file)
1530-
argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", index_file);
1526+
struct argv_array apply_paths = ARGV_ARRAY_INIT;
1527+
struct argv_array apply_opts = ARGV_ARRAY_INIT;
1528+
struct apply_state apply_state;
1529+
int res, opts_left;
1530+
static struct lock_file lock_file;
1531+
int force_apply = 0;
1532+
int options = 0;
1533+
1534+
if (init_apply_state(&apply_state, NULL, &lock_file))
1535+
die("BUG: init_apply_state() failed");
1536+
1537+
argv_array_push(&apply_opts, "apply");
1538+
argv_array_pushv(&apply_opts, state->git_apply_opts.argv);
1539+
1540+
opts_left = apply_parse_options(apply_opts.argc, apply_opts.argv,
1541+
&apply_state, &force_apply, &options,
1542+
NULL);
1543+
1544+
if (opts_left != 0)
1545+
die("unknown option passed through to git apply");
1546+
1547+
if (index_file) {
1548+
apply_state.index_file = index_file;
1549+
apply_state.cached = 1;
1550+
} else
1551+
apply_state.check_index = 1;
15311552

15321553
/*
15331554
* If we are allowed to fall back on 3-way merge, don't give false
15341555
* errors during the initial attempt.
15351556
*/
1536-
if (state->threeway && !index_file) {
1537-
cp.no_stdout = 1;
1538-
cp.no_stderr = 1;
1539-
}
1557+
if (state->threeway && !index_file)
1558+
apply_state.apply_verbosity = verbosity_silent;
15401559

1541-
argv_array_push(&cp.args, "apply");
1560+
if (check_apply_state(&apply_state, force_apply))
1561+
die("BUG: check_apply_state() failed");
15421562

1543-
argv_array_pushv(&cp.args, state->git_apply_opts.argv);
1563+
argv_array_push(&apply_paths, am_path(state, "patch"));
15441564

1545-
if (index_file)
1546-
argv_array_push(&cp.args, "--cached");
1547-
else
1548-
argv_array_push(&cp.args, "--index");
1565+
res = apply_all_patches(&apply_state, apply_paths.argc, apply_paths.argv, options);
15491566

1550-
argv_array_push(&cp.args, am_path(state, "patch"));
1567+
argv_array_clear(&apply_paths);
1568+
argv_array_clear(&apply_opts);
1569+
clear_apply_state(&apply_state);
15511570

1552-
if (run_command(&cp))
1553-
return -1;
1571+
if (res)
1572+
return res;
15541573

1555-
/* Reload index as git-apply will have modified it. */
1556-
discard_cache();
1557-
read_cache_from(index_file ? index_file : get_index_file());
1574+
if (index_file) {
1575+
/* Reload index as apply_all_patches() will have modified it. */
1576+
discard_cache();
1577+
read_cache_from(index_file);
1578+
}
15581579

15591580
return 0;
15601581
}

0 commit comments

Comments
 (0)