From 32260ad5dbc3100ebb5e05432198888bfbe600f8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 22 Mar 2008 09:35:59 -0700 Subject: Make branch merging aware of underlying case-insensitive filsystems If we find an unexpected file, see if that filename perhaps exists in a case-insensitive way in the index, and whether the file matches that. If so, ignore it as a known pre-existing file of a different name. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- unpack-trees.c | 26 ++++++++++++++++++++++++++ unpack-trees.h | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/unpack-trees.c b/unpack-trees.c index bf7d8f6c5c..95d3413ae5 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -520,6 +520,22 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action, return cnt; } +/* + * This gets called when there was no index entry for the tree entry 'dst', + * but we found a file in the working tree that 'lstat()' said was fine, + * and we're on a case-insensitive filesystem. + * + * See if we can find a case-insensitive match in the index that also + * matches the stat information, and assume it's that other file! + */ +static int icase_exists(struct unpack_trees_options *o, struct cache_entry *dst, struct stat *st) +{ + struct cache_entry *src; + + src = index_name_exists(o->src_index, dst->name, ce_namelen(dst), 1); + return src && !ie_match_stat(o->src_index, src, st, CE_MATCH_IGNORE_VALID); +} + /* * We do not want to remove or overwrite a working tree file that * is not tracked, unless it is ignored. @@ -540,6 +556,16 @@ static int verify_absent(struct cache_entry *ce, const char *action, int dtype = ce_to_dtype(ce); struct cache_entry *result; + /* + * It may be that the 'lstat()' succeeded even though + * target 'ce' was absent, because there is an old + * entry that is different only in case.. + * + * Ignore that lstat() if it matches. + */ + if (ignore_case && icase_exists(o, ce, &st)) + return 0; + if (o->dir && excluded(o->dir, ce->name, &dtype)) /* * ce->name is explicitly excluded, so it is Ok to diff --git a/unpack-trees.h b/unpack-trees.h index ad8cc65d68..d436d6ced9 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -31,7 +31,7 @@ struct unpack_trees_options { void *unpack_data; struct index_state *dst_index; - const struct index_state *src_index; + struct index_state *src_index; struct index_state result; }; -- cgit v1.2.3