Skip to content

Commit

Permalink
reset: use "unpack_trees()" directly instead of "git read-tree"
Browse files Browse the repository at this point in the history
This patch makes "reset_index_file()" call "unpack_trees()" directly
instead of forking and execing "git read-tree". So the code is more
efficient.

And it's also easier to see which unpack_tree() options will be used,
as we don't need to follow "git read-tree"'s command line parsing
which is quite complex.

As Daniel Barkalow found, there is a difference between this new
version and the old one. The old version gives an error for
"git reset --merge" with unmerged entries, and the new version does
not when we reset the entries to some states that differ from HEAD.
Instead, it resets the index entry and succeeds, while leaving the
conflict markers in the corresponding file in the work tree (which
will be corrected by the next patch).

The code comes from the sequencer GSoC project:

git://repo.or.cz/git/sbeyer.git

(at commit 5a78908b70ceb5a4ea9fd4b82f07ceba1f019079)

Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Stephan Beyer authored and Junio C Hamano committed Jan 3, 2010
1 parent c939669 commit d0f379c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Documentation/git-reset.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ entries:
X U A B --soft (disallowed)
--mixed X B B
--hard B B B
--merge (disallowed)
--merge X B B

working index HEAD target working index HEAD
----------------------------------------------------
Expand Down
41 changes: 30 additions & 11 deletions builtin-reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "tree.h"
#include "branch.h"
#include "parse-options.h"
#include "unpack-trees.h"
#include "cache-tree.h"

static const char * const git_reset_usage[] = {
"git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]",
Expand Down Expand Up @@ -54,27 +56,44 @@ static inline int is_merge(void)

static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)
{
int i = 0;
const char *args[6];
int nr = 1;
int newfd;
struct tree_desc desc[2];
struct unpack_trees_options opts;
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));

args[i++] = "read-tree";
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.src_index = &the_index;
opts.dst_index = &the_index;
opts.fn = oneway_merge;
opts.merge = 1;
if (!quiet)
args[i++] = "-v";
opts.verbose_update = 1;
switch (reset_type) {
case MERGE:
args[i++] = "-u";
args[i++] = "-m";
opts.update = 1;
break;
case HARD:
args[i++] = "-u";
opts.update = 1;
/* fallthrough */
default:
args[i++] = "--reset";
opts.reset = 1;
}
args[i++] = sha1_to_hex(sha1);
args[i] = NULL;

return run_command_v_opt(args, RUN_GIT_CMD);
newfd = hold_locked_index(lock, 1);

read_cache_unmerged();

if (!fill_tree_descriptor(desc + nr - 1, sha1))
return error("Failed to find tree of %s.", sha1_to_hex(sha1));
if (unpack_trees(nr, desc, &opts))
return -1;
if (write_cache(newfd, active_cache, active_nr) ||
commit_locked_index(lock))
return error("Could not write new index file.");

return 0;
}

static void print_new_head_line(struct commit *commit)
Expand Down
12 changes: 7 additions & 5 deletions t/t7110-reset-merge.sh
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,14 @@ test_expect_success 'setup 2 different branches' '
#
# working index HEAD target working index HEAD
# ----------------------------------------------------
# file1: X U B C --merge (disallowed)
test_expect_success '"reset --merge HEAD^" fails with pending merge' '
# file1: X U B C --merge X C C
test_expect_success '"reset --merge HEAD^" is ok with pending merge' '
test_must_fail git merge branch1 &&
test_must_fail git reset --merge HEAD^ &&
test "$(git rev-parse HEAD)" = "$(git rev-parse third)" &&
test -n "$(git diff --cached)"
cat file1 >orig_file1 &&
git reset --merge HEAD^ &&
test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
test -z "$(git diff --cached)" &&
test_cmp file1 orig_file1
'

# The next test will test the following:
Expand Down

0 comments on commit d0f379c

Please sign in to comment.