git-rebase--interactive: auto amend only edited commit
[gitweb.git] / read-cache.c
index 0382804e7694e9a0e87cc2dc8340187ddeea2d64..35fec468b1951cc17606fca8edc47f809471f652 100644 (file)
@@ -38,6 +38,22 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
        istate->cache_changed = 1;
 }
 
+void rename_index_entry_at(struct index_state *istate, int nr, const char *new_name)
+{
+       struct cache_entry *old = istate->cache[nr], *new;
+       int namelen = strlen(new_name);
+
+       new = xmalloc(cache_entry_size(namelen));
+       copy_cache_entry(new, old);
+       new->ce_flags &= ~(CE_STATE_MASK | CE_NAMEMASK);
+       new->ce_flags |= (namelen >= CE_NAMEMASK ? CE_NAMEMASK : namelen);
+       memcpy(new->name, new_name, namelen + 1);
+
+       cache_tree_invalidate_path(istate->cache_tree, old->name);
+       remove_index_entry_at(istate, nr);
+       add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
+}
+
 /*
  * This only updates the "non-critical" parts of the directory
  * cache, ie the parts that aren't tracked by GIT, and only used
@@ -131,13 +147,23 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
                break;
        case S_IFDIR:
                if (S_ISGITLINK(ce->ce_mode))
-                       return 0;
+                       return ce_compare_gitlink(ce) ? DATA_CHANGED : 0;
        default:
                return TYPE_CHANGED;
        }
        return 0;
 }
 
+static int is_empty_blob_sha1(const unsigned char *sha1)
+{
+       static const unsigned char empty_blob_sha1[20] = {
+               0xe6,0x9d,0xe2,0x9b,0xb2,0xd1,0xd6,0x43,0x4b,0x8b,
+               0x29,0xae,0x77,0x5a,0xd8,0xc2,0xe4,0x8c,0x53,0x91
+       };
+
+       return !hashcmp(sha1, empty_blob_sha1);
+}
+
 static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 {
        unsigned int changed = 0;
@@ -161,6 +187,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
                        changed |= TYPE_CHANGED;
                break;
        case S_IFGITLINK:
+               /* We ignore most of the st_xxx fields for gitlinks */
                if (!S_ISDIR(st->st_mode))
                        changed |= TYPE_CHANGED;
                else if (ce_compare_gitlink(ce))
@@ -171,7 +198,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
        }
        if (ce->ce_mtime != (unsigned int) st->st_mtime)
                changed |= MTIME_CHANGED;
-       if (ce->ce_ctime != (unsigned int) st->st_ctime)
+       if (trust_ctime && ce->ce_ctime != (unsigned int) st->st_ctime)
                changed |= CTIME_CHANGED;
 
        if (ce->ce_uid != (unsigned int) st->st_uid ||
@@ -193,6 +220,12 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
        if (ce->ce_size != (unsigned int) st->st_size)
                changed |= DATA_CHANGED;
 
+       /* Racily smudged entry? */
+       if (!ce->ce_size) {
+               if (!is_empty_blob_sha1(ce->sha1))
+                       changed |= DATA_CHANGED;
+       }
+
        return changed;
 }
 
@@ -261,11 +294,22 @@ int ie_modified(const struct index_state *istate,
        if (changed & (MODE_CHANGED | TYPE_CHANGED))
                return changed;
 
-       /* Immediately after read-tree or update-index --cacheinfo,
-        * the length field is zero.  For other cases the ce_size
-        * should match the SHA1 recorded in the index entry.
+       /*
+        * Immediately after read-tree or update-index --cacheinfo,
+        * the length field is zero, as we have never even read the
+        * lstat(2) information once, and we cannot trust DATA_CHANGED
+        * returned by ie_match_stat() which in turn was returned by
+        * ce_match_stat_basic() to signal that the filesize of the
+        * blob changed.  We have to actually go to the filesystem to
+        * see if the contents match, and if so, should answer "unchanged".
+        *
+        * The logic does not apply to gitlinks, as ce_match_stat_basic()
+        * already has checked the actual HEAD from the filesystem in the
+        * subproject.  If ie_match_stat() already said it is different,
+        * then we know it is.
         */
-       if ((changed & DATA_CHANGED) && ce->ce_size != 0)
+       if ((changed & DATA_CHANGED) &&
+           (S_ISGITLINK(ce->ce_mode) || ce->ce_size != 0))
                return changed;
 
        changed_fs = ce_modified_check_fs(ce, st);
@@ -462,15 +506,17 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_
        return new;
 }
 
-int add_to_index(struct index_state *istate, const char *path, struct stat *st, int verbose)
+int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
 {
-       int size, namelen;
+       int size, namelen, was_same;
        mode_t st_mode = st->st_mode;
        struct cache_entry *ce, *alias;
        unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;
+       int verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);
+       int pretend = flags & ADD_CACHE_PRETEND;
 
        if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
-               die("%s: can only add regular files, symbolic links or git-directories", path);
+               return error("%s: can only add regular files, symbolic links or git-directories", path);
 
        namelen = strlen(path);
        if (S_ISDIR(st_mode)) {
@@ -505,23 +551,32 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                return 0;
        }
        if (index_path(ce->sha1, path, st, 1))
-               die("unable to index file %s", path);
+               return error("unable to index file %s", path);
        if (ignore_case && alias && different_name(ce, alias))
                ce = create_alias_ce(ce, alias);
        ce->ce_flags |= CE_ADDED;
-       if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
-               die("unable to add %s to index",path);
-       if (verbose)
+
+       /* It was suspected to be racily clean, but it turns out to be Ok */
+       was_same = (alias &&
+                   !ce_stage(alias) &&
+                   !hashcmp(alias->sha1, ce->sha1) &&
+                   ce->ce_mode == alias->ce_mode);
+
+       if (pretend)
+               ;
+       else if (add_index_entry(istate, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
+               return error("unable to add %s to index",path);
+       if (verbose && !was_same)
                printf("add '%s'\n", path);
        return 0;
 }
 
-int add_file_to_index(struct index_state *istate, const char *path, int verbose)
+int add_file_to_index(struct index_state *istate, const char *path, int flags)
 {
        struct stat st;
        if (lstat(path, &st))
                die("%s: unable to stat (%s)", path, strerror(errno));
-       return add_to_index(istate, path, &st, verbose);
+       return add_to_index(istate, path, &st, flags);
 }
 
 struct cache_entry *make_cache_entry(unsigned int mode,
@@ -882,6 +937,15 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
        if (ce_uptodate(ce))
                return ce;
 
+       /*
+        * CE_VALID means the user promised us that the change to
+        * the work tree does not matter and told us not to worry.
+        */
+       if (!ignore_valid && (ce->ce_flags & CE_VALID)) {
+               ce_mark_uptodate(ce);
+               return ce;
+       }
+
        if (lstat(ce->name, &st) < 0) {
                if (err)
                        *err = errno;
@@ -942,13 +1006,20 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
        int allow_unmerged = (flags & REFRESH_UNMERGED) != 0;
        int quiet = (flags & REFRESH_QUIET) != 0;
        int not_new = (flags & REFRESH_IGNORE_MISSING) != 0;
+       int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0;
        unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
+       const char *needs_update_message;
 
+       needs_update_message = ((flags & REFRESH_SAY_CHANGED)
+                               ? "locally modified" : "needs update");
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce, *new;
                int cache_errno = 0;
 
                ce = istate->cache[i];
+               if (ignore_submodules && S_ISGITLINK(ce->ce_mode))
+                       continue;
+
                if (ce_stage(ce)) {
                        while ((i < istate->cache_nr) &&
                               ! strcmp(istate->cache[i]->name, ce->name))
@@ -979,7 +1050,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
                        }
                        if (quiet)
                                continue;
-                       printf("%s: needs update\n", ce->name);
+                       printf("%s: %s\n", ce->name, needs_update_message);
                        has_errors = 1;
                        continue;
                }
@@ -1084,7 +1155,7 @@ int read_index_from(struct index_state *istate, const char *path)
        size_t mmap_size;
 
        errno = EBUSY;
-       if (istate->alloc)
+       if (istate->initialized)
                return istate->cache_nr;
 
        errno = ENOENT;
@@ -1124,6 +1195,7 @@ int read_index_from(struct index_state *istate, const char *path)
         * index size
         */
        istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
+       istate->initialized = 1;
 
        src_offset = sizeof(*hdr);
        dst_offset = 0;
@@ -1176,6 +1248,7 @@ int discard_index(struct index_state *istate)
        cache_tree_free(&(istate->cache_tree));
        free(istate->alloc);
        istate->alloc = NULL;
+       istate->initialized = 0;
 
        /* no need to throw away allocated active_cache */
        return 0;
@@ -1267,6 +1340,11 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
         * falsely clean entry due to touch-update-touch race, so we leave
         * everything else as they are.  We are called for entries whose
         * ce_mtime match the index file mtime.
+        *
+        * Note that this actually does not do much for gitlinks, for
+        * which ce_match_stat_basic() always goes to the actual
+        * contents.  The caller checks with is_racy_timestamp() which
+        * always says "no" for gitlinks, so we are not called for them ;-)
         */
        struct stat st;
 
@@ -1370,3 +1448,34 @@ int write_index(const struct index_state *istate, int newfd)
        }
        return ce_flush(&c, newfd);
 }
+
+/*
+ * Read the index file that is potentially unmerged into given
+ * index_state, dropping any unmerged entries.  Returns true is
+ * the index is unmerged.  Callers who want to refuse to work
+ * from an unmerged state can call this and check its return value,
+ * instead of calling read_cache().
+ */
+int read_index_unmerged(struct index_state *istate)
+{
+       int i;
+       struct cache_entry **dst;
+       struct cache_entry *last = NULL;
+
+       read_index(istate);
+       dst = istate->cache;
+       for (i = 0; i < istate->cache_nr; i++) {
+               struct cache_entry *ce = istate->cache[i];
+               if (ce_stage(ce)) {
+                       remove_name_hash(ce);
+                       if (last && !strcmp(ce->name, last->name))
+                               continue;
+                       cache_tree_invalidate_path(istate->cache_tree, ce->name);
+                       last = ce;
+                       continue;
+               }
+               *dst++ = ce;
+       }
+       istate->cache_nr = dst - istate->cache;
+       return !!last;
+}