summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-03-22 09:35:59 -0700
committerJunio C Hamano <gitster@pobox.com>2008-04-09 01:22:25 -0700
commit32260ad5dbc3100ebb5e05432198888bfbe600f8 (patch)
treedba543f212ca43a1ab90e6a532de72098609c3f8 /unpack-trees.c
parent0a9b88b7dee70bd36d35b7857640a18ee3adeef1 (diff)
downloadgit-32260ad5dbc3100ebb5e05432198888bfbe600f8.tar.gz
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 <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index bf7d8f6c5c..95d3413ae5 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -521,6 +521,22 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
}
/*
+ * 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