@matheusbsbs / matheus-bagliano / commits / 1102952b45
Fork 0

Make git-add behave more sensibly in a case-insensitive environment

This expands on the previous patch, and allows "git add" to sanely handle a filename that has changed case, keeping the case in the index constant, and avoiding aliases. In particular, if you have an index entry called "File", but the checked-out tree is case-corrupted and has an entry called "file" instead, doing a git add . (or naming "file" explicitly) will automatically notice that we have an alias, and will replace the name "file" with the existing index capitalization (ie "File"). However, if we actually have *both* a file called "File" and one called "file", and they don't have the same lstat() information (ie we're on a case-sensitive filesystem but have the "core.ignorecase" flag set), we will error out if we try to add them both. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Linus Torvalds committed Mar 22, 2008 at 14:22 UTC 1102952b45dde09d73445aa2284bcb592362fa23
2 files changed +37 -1
cache.h
+1
@@ -133,6 +133,7 @@ struct cache_entry {
133 #define CE_UPDATE (0x10000)
134 #define CE_REMOVE (0x20000)
135 #define CE_UPTODATE (0x40000)
136 +#define CE_ADDED (0x80000)
137
138 #define CE_HASHED (0x100000)
139 #define CE_UNHASHED (0x200000)
read-cache.c
+36 -1
@@ -429,6 +429,38 @@ static int index_name_pos_also_unmerged(struct index_state *istate,
429 return pos;
430 }
431
432 +static int different_name(struct cache_entry *ce, struct cache_entry *alias)
433 +{
434 + int len = ce_namelen(ce);
435 + return ce_namelen(alias) != len || memcmp(ce->name, alias->name, len);
436 +}
437 +
438 +/*
439 + * If we add a filename that aliases in the cache, we will use the
440 + * name that we already have - but we don't want to update the same
441 + * alias twice, because that implies that there were actually two
442 + * different files with aliasing names!
443 + *
444 + * So we use the CE_ADDED flag to verify that the alias was an old
445 + * one before we accept it as
446 + */
447 +static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_entry *alias)
448 +{
449 + int len;
450 + struct cache_entry *new;
451 +
452 + if (alias->ce_flags & CE_ADDED)
453 + die("Will not add file alias '%s' ('%s' already exists in index)", ce->name, alias->name);
454 +
455 + /* Ok, create the new entry using the name of the existing alias */
456 + len = ce_namelen(alias);
457 + new = xcalloc(1, cache_entry_size(len));
458 + memcpy(new->name, alias->name, len);
459 + copy_cache_entry(new, ce);
460 + free(ce);
461 + return new;
462 +}
463 +
464 int add_file_to_index(struct index_state *istate, const char *path, int verbose)
465 {
466 int size, namelen;
@@ -471,11 +503,14 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
503 /* Nothing changed, really */
504 free(ce);
505 ce_mark_uptodate(alias);
506 + alias->ce_flags |= CE_ADDED;
507 return 0;
508 }
476 -
509 if (index_path(ce->sha1, path, &st, 1))
510 die("unable to index file %s", path);
511 + if (ignore_case && alias && different_name(ce, alias))
512 + ce = create_alias_ce(ce, alias);
513 + ce->ce_flags |= CE_ADDED;
514 if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
515 die("unable to add %s to index",path);
516 if (verbose)