Merge commit 'mingw/master' into devel

Conflicts:

	Makefile
	RelNotes
	compat/qsort.c
	help.c
	read-cache.c
This commit is contained in:
Steffen Prohaska
2008-02-24 15:48:45 +01:00
207 changed files with 4417 additions and 1581 deletions

View File

@@ -9,6 +9,7 @@
#include "revision.h"
#include "cache-tree.h"
#include "path-list.h"
#include "unpack-trees.h"
/*
* diff-files
@@ -37,7 +38,7 @@ static int get_mode(const char *path, int *mode)
if (!path || is_dev_null(path))
*mode = 0;
else if (!strcmp(path, "-"))
*mode = ntohl(create_ce_mode(0666));
*mode = create_ce_mode(0666);
else if (stat(path, &st))
return error("Could not access '%s'", path);
else
@@ -388,7 +389,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
continue;
}
else
dpath->mode = ntohl(ce_mode_from_stat(ce, st.st_mode));
dpath->mode = ce_mode_from_stat(ce, st.st_mode);
while (i < entries) {
struct cache_entry *nce = active_cache[i];
@@ -402,10 +403,10 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
*/
stage = ce_stage(nce);
if (2 <= stage) {
int mode = ntohl(nce->ce_mode);
int mode = nce->ce_mode;
num_compare_stages++;
hashcpy(dpath->parent[stage-2].sha1, nce->sha1);
dpath->parent[stage-2].mode = ntohl(ce_mode_from_stat(nce, mode));
dpath->parent[stage-2].mode = ce_mode_from_stat(nce, mode);
dpath->parent[stage-2].status =
DIFF_STATUS_MODIFIED;
}
@@ -439,6 +440,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
continue;
}
if (ce_uptodate(ce))
continue;
if (lstat(ce->name, &st) < 0) {
if (errno != ENOENT && errno != ENOTDIR) {
perror(ce->name);
@@ -446,15 +449,15 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
}
if (silent_on_removed)
continue;
diff_addremove(&revs->diffopt, '-', ntohl(ce->ce_mode),
diff_addremove(&revs->diffopt, '-', ce->ce_mode,
ce->sha1, ce->name, NULL);
continue;
}
changed = ce_match_stat(ce, &st, ce_option);
if (!changed && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
continue;
oldmode = ntohl(ce->ce_mode);
newmode = ntohl(ce_mode_from_stat(ce, st.st_mode));
oldmode = ce->ce_mode;
newmode = ce_mode_from_stat(ce, st.st_mode);
diff_change(&revs->diffopt, oldmode, newmode,
ce->sha1, (changed ? null_sha1 : ce->sha1),
ce->name, NULL);
@@ -475,7 +478,7 @@ static void diff_index_show_file(struct rev_info *revs,
struct cache_entry *ce,
unsigned char *sha1, unsigned int mode)
{
diff_addremove(&revs->diffopt, prefix[0], ntohl(mode),
diff_addremove(&revs->diffopt, prefix[0], mode,
sha1, ce->name, NULL);
}
@@ -554,14 +557,14 @@ static int show_modified(struct rev_info *revs,
p->len = pathlen;
memcpy(p->path, new->name, pathlen);
p->path[pathlen] = 0;
p->mode = ntohl(mode);
p->mode = mode;
hashclr(p->sha1);
memset(p->parent, 0, 2 * sizeof(struct combine_diff_parent));
p->parent[0].status = DIFF_STATUS_MODIFIED;
p->parent[0].mode = ntohl(new->ce_mode);
p->parent[0].mode = new->ce_mode;
hashcpy(p->parent[0].sha1, new->sha1);
p->parent[1].status = DIFF_STATUS_MODIFIED;
p->parent[1].mode = ntohl(old->ce_mode);
p->parent[1].mode = old->ce_mode;
hashcpy(p->parent[1].sha1, old->sha1);
show_combined_diff(p, 2, revs->dense_combined_merges, revs);
free(p);
@@ -573,89 +576,11 @@ static int show_modified(struct rev_info *revs,
!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
return 0;
mode = ntohl(mode);
oldmode = ntohl(oldmode);
diff_change(&revs->diffopt, oldmode, mode,
old->sha1, sha1, old->name, NULL);
return 0;
}
static int diff_cache(struct rev_info *revs,
struct cache_entry **ac, int entries,
const char **pathspec,
int cached, int match_missing)
{
while (entries) {
struct cache_entry *ce = *ac;
int same = (entries > 1) && ce_same_name(ce, ac[1]);
if (DIFF_OPT_TST(&revs->diffopt, QUIET) &&
DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
break;
if (!ce_path_match(ce, pathspec))
goto skip_entry;
switch (ce_stage(ce)) {
case 0:
/* No stage 1 entry? That means it's a new file */
if (!same) {
show_new_file(revs, ce, cached, match_missing);
break;
}
/* Show difference between old and new */
show_modified(revs, ac[1], ce, 1,
cached, match_missing);
break;
case 1:
/* No stage 3 (merge) entry?
* That means it's been deleted.
*/
if (!same) {
diff_index_show_file(revs, "-", ce,
ce->sha1, ce->ce_mode);
break;
}
/* We come here with ce pointing at stage 1
* (original tree) and ac[1] pointing at stage
* 3 (unmerged). show-modified with
* report-missing set to false does not say the
* file is deleted but reports true if work
* tree does not have it, in which case we
* fall through to report the unmerged state.
* Otherwise, we show the differences between
* the original tree and the work tree.
*/
if (!cached &&
!show_modified(revs, ce, ac[1], 0,
cached, match_missing))
break;
diff_unmerge(&revs->diffopt, ce->name,
ntohl(ce->ce_mode), ce->sha1);
break;
case 3:
diff_unmerge(&revs->diffopt, ce->name,
0, null_sha1);
break;
default:
die("impossible cache entry stage");
}
skip_entry:
/*
* Ignore all the different stages for this file,
* we've handled the relevant cases now.
*/
do {
ac++;
entries--;
} while (entries && ce_same_name(ce, ac[0]));
}
return 0;
}
/*
* This turns all merge entries into "stage 3". That guarantees that
* when we read in the new tree (into "stage 1"), we won't lose sight
@@ -668,24 +593,137 @@ static void mark_merge_entries(void)
struct cache_entry *ce = active_cache[i];
if (!ce_stage(ce))
continue;
ce->ce_flags |= htons(CE_STAGEMASK);
ce->ce_flags |= CE_STAGEMASK;
}
}
/*
* This gets a mix of an existing index and a tree, one pathname entry
* at a time. The index entry may be a single stage-0 one, but it could
* also be multiple unmerged entries (in which case idx_pos/idx_nr will
* give you the position and number of entries in the index).
*/
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 rev_info *revs = o->unpack_data;
int match_missing, cached;
/*
* Backward compatibility wart - "diff-index -m" does
* not mean "do not ignore merges", but "match_missing".
*
* But with the revision flag parsing, that's found in
* "!revs->ignore_merges".
*/
cached = o->index_only;
match_missing = !revs->ignore_merges;
if (cached && idx && ce_stage(idx)) {
if (tree)
diff_unmerge(&revs->diffopt, idx->name, idx->ce_mode, idx->sha1);
return;
}
/*
* Something added to the tree?
*/
if (!tree) {
show_new_file(revs, idx, cached, match_missing);
return;
}
/*
* Something removed from the tree?
*/
if (!idx) {
diff_index_show_file(revs, "-", tree, tree->sha1, tree->ce_mode);
return;
}
/* Show difference between old and new */
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
* the source trees, with the old index being really mainly
* used for being replaced by the result.
*
* For diffing, the index is more important, and we only have a
* single tree.
*
* We're supposed to return how many index entries we want to skip.
*
* This wrapper makes it all more readable, and takes care of all
* 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)
{
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
* in the tree. From a diff standpoint, that's a
* delete of the tree and a create of the file.
*/
if (tree == o->df_conflict_entry)
tree = NULL;
if (ce_path_match(idx ? idx : tree, revs->prune_data))
do_oneway_diff(o, idx, tree, index_pos, skip);
return skip;
}
int run_diff_index(struct rev_info *revs, int cached)
{
int ret;
struct object *ent;
struct tree *tree;
const char *tree_name;
int match_missing = 0;
/*
* Backward compatibility wart - "diff-index -m" does
* not mean "do not ignore merges", but totally different.
*/
if (!revs->ignore_merges)
match_missing = 1;
struct unpack_trees_options opts;
struct tree_desc t;
mark_merge_entries();
@@ -694,13 +732,20 @@ int run_diff_index(struct rev_info *revs, int cached)
tree = parse_tree_indirect(ent->sha1);
if (!tree)
return error("bad tree object %s", tree_name);
if (read_tree(tree, 1, revs->prune_data))
return error("unable to read tree object %s", tree_name);
ret = diff_cache(revs, active_cache, active_nr, revs->prune_data,
cached, match_missing);
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.index_only = cached;
opts.merge = 1;
opts.fn = oneway_diff;
opts.unpack_data = revs;
init_tree_desc(&t, tree->buffer, tree->size);
unpack_trees(1, &t, &opts);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return ret;
return 0;
}
int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
@@ -710,6 +755,8 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
int i;
struct cache_entry **dst;
struct cache_entry *last = NULL;
struct unpack_trees_options opts;
struct tree_desc t;
/*
* This is used by git-blame to run diff-cache internally;
@@ -726,8 +773,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
cache_tree_invalidate_path(active_cache_tree,
ce->name);
last = ce;
ce->ce_mode = 0;
ce->ce_flags &= ~htons(CE_STAGEMASK);
ce->ce_flags |= CE_REMOVE;
}
*dst++ = ce;
}
@@ -738,8 +784,15 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
tree = parse_tree_indirect(tree_sha1);
if (!tree)
die("bad tree object %s", sha1_to_hex(tree_sha1));
if (read_tree(tree, 1, opt->paths))
return error("unable to read tree %s", sha1_to_hex(tree_sha1));
return diff_cache(&revs, active_cache, active_nr, revs.prune_data,
1, 0);
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.index_only = 1;
opts.merge = 1;
opts.fn = oneway_diff;
opts.unpack_data = &revs;
init_tree_desc(&t, tree->buffer, tree->size);
unpack_trees(1, &t, &opts);
return 0;
}