1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-10-31 14:27:54 +01:00

Merge branch 'pt/am-builtin-abort-fix'

"git am" that was recently reimplemented in C had a performance
regression in "git am --abort" that goes back to the version before
an attempted (and failed) patch application.

* pt/am-builtin-abort-fix:
  am --skip/--abort: merge HEAD/ORIG_HEAD tree into index
This commit is contained in:
Junio C Hamano 2015-08-26 15:45:32 -07:00
commit b7d2a15b9f
2 changed files with 60 additions and 13 deletions

View file

@ -1962,16 +1962,49 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
return 0;
}
/**
* Merges a tree into the index. The index's stat info will take precedence
* over the merged tree's. Returns 0 on success, -1 on failure.
*/
static int merge_tree(struct tree *tree)
{
struct lock_file *lock_file;
struct unpack_trees_options opts;
struct tree_desc t[1];
if (parse_tree(tree))
return -1;
lock_file = xcalloc(1, sizeof(struct lock_file));
hold_locked_index(lock_file, 1);
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.src_index = &the_index;
opts.dst_index = &the_index;
opts.merge = 1;
opts.fn = oneway_merge;
init_tree_desc(&t[0], tree->buffer, tree->size);
if (unpack_trees(1, t, &opts)) {
rollback_lock_file(lock_file);
return -1;
}
if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
}
/**
* Clean the index without touching entries that are not modified between
* `head` and `remote`.
*/
static int clean_index(const unsigned char *head, const unsigned char *remote)
{
struct lock_file *lock_file;
struct tree *head_tree, *remote_tree, *index_tree;
unsigned char index[GIT_SHA1_RAWSZ];
struct pathspec pathspec;
head_tree = parse_tree_indirect(head);
if (!head_tree)
@ -1996,18 +2029,8 @@ static int clean_index(const unsigned char *head, const unsigned char *remote)
if (fast_forward_to(index_tree, remote_tree, 0))
return -1;
memset(&pathspec, 0, sizeof(pathspec));
lock_file = xcalloc(1, sizeof(struct lock_file));
hold_locked_index(lock_file, 1);
if (read_tree(remote_tree, 0, &pathspec)) {
rollback_lock_file(lock_file);
if (merge_tree(remote_tree))
return -1;
}
if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
remove_branch_state();

View file

@ -168,4 +168,28 @@ test_expect_success 'am --abort on unborn branch will keep local commits intact'
test_cmp expect actual
'
test_expect_success 'am --skip leaves index stat info alone' '
git checkout -f --orphan skip-stat-info &&
git reset &&
test_commit skip-should-be-untouched &&
test-chmtime =0 skip-should-be-untouched.t &&
git update-index --refresh &&
git diff-files --exit-code --quiet &&
test_must_fail git am 0001-*.patch &&
git am --skip &&
git diff-files --exit-code --quiet
'
test_expect_success 'am --abort leaves index stat info alone' '
git checkout -f --orphan abort-stat-info &&
git reset &&
test_commit abort-should-be-untouched &&
test-chmtime =0 abort-should-be-untouched.t &&
git update-index --refresh &&
git diff-files --exit-code --quiet &&
test_must_fail git am 0001-*.patch &&
git am --abort &&
git diff-files --exit-code --quiet
'
test_done