Skip to content

Commit

Permalink
Make 'unpack_trees()' have a separate source and destination index
Browse files Browse the repository at this point in the history
We will always unpack into our own internal index, but we will take the
source from wherever specified, and we will optionally write the result
to a specified index (optionally, because not everybody even _wants_ any
result: the index diffing really wants to just walk the tree and index
in parallel).

This ends up removing a fair number more lines than it adds, for the
simple reason that we can now skip all the crud that tried to be
oh-so-careful about maintaining our position in the index as we were
traversing and modifying it.  Since we don't actually modify the source
index any more, we can just update the 'o->pos' pointer without worrying
about whether an index entry got removed or replaced or added to.

Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
torvalds authored and gitster committed Mar 9, 2008
1 parent bc052d7 commit 34110cd
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 153 deletions.
9 changes: 6 additions & 3 deletions builtin-checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ static int reset_to_new(struct tree *tree, int quiet)
opts.merge = 1;
opts.fn = oneway_merge;
opts.verbose_update = !quiet;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = &the_index;
parse_tree(tree);
init_tree_desc(&tree_desc, tree->buffer, tree->size);
if (unpack_trees(1, &tree_desc, &opts))
Expand All @@ -180,7 +181,8 @@ static void reset_clean_to_new(struct tree *tree, int quiet)
opts.merge = 1;
opts.fn = oneway_merge;
opts.verbose_update = !quiet;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = &the_index;
parse_tree(tree);
init_tree_desc(&tree_desc, tree->buffer, tree->size);
if (unpack_trees(1, &tree_desc, &opts))
Expand Down Expand Up @@ -231,7 +233,8 @@ static int merge_working_tree(struct checkout_opts *opts,

memset(&topts, 0, sizeof(topts));
topts.head_idx = -1;
topts.index = &the_index;
topts.src_index = &the_index;
topts.dst_index = &the_index;

refresh_cache(REFRESH_QUIET);

Expand Down
3 changes: 2 additions & 1 deletion builtin-commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ static void create_base_index(void)
opts.head_idx = 1;
opts.index_only = 1;
opts.merge = 1;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = &the_index;

opts.fn = oneway_merge;
tree = parse_tree_indirect(head_sha1);
Expand Down
3 changes: 2 additions & 1 deletion builtin-merge-recursive.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ static int git_merge_trees(int index_only,
opts.merge = 1;
opts.head_idx = 2;
opts.fn = threeway_merge;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = &the_index;

init_tree_desc_from_tree(t+0, common);
init_tree_desc_from_tree(t+1, head);
Expand Down
24 changes: 2 additions & 22 deletions builtin-read-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)

memset(&opts, 0, sizeof(opts));
opts.head_idx = -1;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = &the_index;

git_config(git_default_config);

Expand Down Expand Up @@ -221,27 +222,6 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
if ((opts.dir && !opts.update))
die("--exclude-per-directory is meaningless unless -u");

if (opts.prefix) {
int pfxlen = strlen(opts.prefix);
int pos;
if (opts.prefix[pfxlen-1] != '/')
die("prefix must end with /");
if (stage != 2)
die("binding merge takes only one tree");
pos = cache_name_pos(opts.prefix, pfxlen);
if (0 <= pos)
die("corrupt index file");
pos = -pos-1;
if (pos < active_nr &&
!strncmp(active_cache[pos]->name, opts.prefix, pfxlen))
die("subdirectory '%s' already exists.", opts.prefix);
pos = cache_name_pos(opts.prefix, pfxlen-1);
if (0 <= pos)
die("file '%.*s' already exists.",
pfxlen-1, opts.prefix);
opts.pos = -1 - pos;
}

if (opts.merge) {
if (stage < 2)
die("just how do you expect me to merge %d trees?", stage-1);
Expand Down
49 changes: 8 additions & 41 deletions diff-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,7 @@ static void mark_merge_entries(void)
*/
static void do_oneway_diff(struct unpack_trees_options *o,
struct cache_entry *idx,
struct cache_entry *tree,
int idx_pos, int idx_nr)
struct cache_entry *tree)
{
struct rev_info *revs = o->unpack_data;
int match_missing, cached;
Expand Down Expand Up @@ -642,34 +641,6 @@ static void do_oneway_diff(struct unpack_trees_options *o,
show_modified(revs, tree, idx, 1, cached, match_missing);
}

/*
* Count how many index entries go with the first one
*/
static inline int count_skip(const struct cache_entry *src, int pos)
{
int skip = 1;

/* We can only have multiple entries if the first one is not stage-0 */
if (ce_stage(src)) {
struct cache_entry **p = active_cache + pos;
int namelen = ce_namelen(src);

for (;;) {
const struct cache_entry *ce;
pos++;
if (pos >= active_nr)
break;
ce = *++p;
if (ce_namelen(ce) != namelen)
break;
if (memcmp(ce->name, src->name, namelen))
break;
skip++;
}
}
return skip;
}

/*
* The unpack_trees() interface is designed for merging, so
* the different source entries are designed primarily for
Expand All @@ -685,18 +656,12 @@ static inline int count_skip(const struct cache_entry *src, int pos)
* the fairly complex unpack_trees() semantic requirements, including
* the skipping, the path matching, the type conflict cases etc.
*/
static int oneway_diff(struct cache_entry **src,
struct unpack_trees_options *o,
int index_pos)
static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
{
int skip = 0;
struct cache_entry *idx = src[0];
struct cache_entry *tree = src[1];
struct rev_info *revs = o->unpack_data;

if (index_pos >= 0)
skip = count_skip(idx, index_pos);

/*
* Unpack-trees generates a DF/conflict entry if
* there was a directory in the index and a tree
Expand All @@ -707,9 +672,9 @@ static int oneway_diff(struct cache_entry **src,
tree = NULL;

if (ce_path_match(idx ? idx : tree, revs->prune_data))
do_oneway_diff(o, idx, tree, index_pos, skip);
do_oneway_diff(o, idx, tree);

return skip;
return 0;
}

int run_diff_index(struct rev_info *revs, int cached)
Expand All @@ -734,7 +699,8 @@ int run_diff_index(struct rev_info *revs, int cached)
opts.merge = 1;
opts.fn = oneway_diff;
opts.unpack_data = revs;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = NULL;

init_tree_desc(&t, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts))
Expand Down Expand Up @@ -788,7 +754,8 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
opts.merge = 1;
opts.fn = oneway_diff;
opts.unpack_data = &revs;
opts.index = &the_index;
opts.src_index = &the_index;
opts.dst_index = &the_index;

init_tree_desc(&t, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts))
Expand Down
2 changes: 1 addition & 1 deletion t/t1005-read-tree-reset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test_expect_success 'setup' '
git commit -m two
'

test_expect_failure 'reset should work' '
test_expect_success 'reset should work' '
git read-tree -u --reset HEAD^ &&
git ls-files >actual &&
diff -u expect actual
Expand Down
Loading

0 comments on commit 34110cd

Please sign in to comment.