real_path: do not assume '/' is the path seperator
[gitweb.git] / read-cache.c
index 1f42473e8070a05ada8c56b0d60537227a5223ec..0480d9455cec042cf128e4d92bbc44a9dcc3fe32 100644 (file)
@@ -608,6 +608,29 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                ce->ce_mode = ce_mode_from_stat(ent, st_mode);
        }
 
+       /* When core.ignorecase=true, determine if a directory of the same name but differing
+        * case already exists within the Git repository.  If it does, ensure the directory
+        * case of the file being added to the repository matches (is folded into) the existing
+        * entry's directory case.
+        */
+       if (ignore_case) {
+               const char *startPtr = ce->name;
+               const char *ptr = startPtr;
+               while (*ptr) {
+                       while (*ptr && *ptr != '/')
+                               ++ptr;
+                       if (*ptr == '/') {
+                               struct cache_entry *foundce;
+                               ++ptr;
+                               foundce = index_name_exists(&the_index, ce->name, ptr - ce->name, ignore_case);
+                               if (foundce) {
+                                       memcpy((void *)startPtr, foundce->name + (startPtr - ce->name), ptr - startPtr);
+                                       startPtr = ptr;
+                               }
+                       }
+               }
+       }
+
        alias = index_name_exists(istate, ce->name, ce_namelen(ce), ignore_case);
        if (alias && !ce_stage(alias) && !ie_match_stat(istate, alias, st, ce_option)) {
                /* Nothing changed, really */
@@ -1545,6 +1568,31 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
        return result;
 }
 
+static int has_racy_timestamp(struct index_state *istate)
+{
+       int entries = istate->cache_nr;
+       int i;
+
+       for (i = 0; i < entries; i++) {
+               struct cache_entry *ce = istate->cache[i];
+               if (is_racy_timestamp(istate, ce))
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * Opportunisticly update the index but do not complain if we can't
+ */
+void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
+{
+       if ((istate->cache_changed || has_racy_timestamp(istate)) &&
+           !write_index(istate, lockfile->fd))
+               commit_locked_index(lockfile);
+       else
+               rollback_lock_file(lockfile);
+}
+
 int write_index(struct index_state *istate, int newfd)
 {
        git_SHA_CTX c;