t7061: status --ignored should search untracked dirs
[gitweb.git] / read-cache.c
index 89dbc0837a4155f9e70b56c7d61c8742482f3659..9054369dd0c6ddfd35794fc63f0e0296ec0c9c91 100644 (file)
@@ -5,6 +5,7 @@
  */
 #define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
+#include "tempfile.h"
 #include "lockfile.h"
 #include "cache-tree.h"
 #include "refs.h"
 #include "strbuf.h"
 #include "varint.h"
 #include "split-index.h"
-#include "sigchain.h"
 #include "utf8.h"
 
-static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
-                                              unsigned int options);
-
 /* Mask for the name length in ce_flags in the on-disk index */
 
 #define CE_NAMEMASK  (0x0fff)
@@ -159,12 +156,12 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
 static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
 {
        int match = -1;
-       int fd = open(ce->name, O_RDONLY);
+       int fd = git_open_cloexec(ce->name, O_RDONLY);
 
        if (fd >= 0) {
                unsigned char sha1[20];
                if (!index_fd(sha1, fd, st, OBJ_BLOB, ce->name, 0))
-                       match = hashcmp(sha1, ce->sha1);
+                       match = hashcmp(sha1, ce->oid.hash);
                /* index_fd() closed the file descriptor already */
        }
        return match;
@@ -181,7 +178,7 @@ static int ce_compare_link(const struct cache_entry *ce, size_t expected_size)
        if (strbuf_readlink(&sb, ce->name, expected_size))
                return -1;
 
-       buffer = read_sha1_file(ce->sha1, &type, &size);
+       buffer = read_sha1_file(ce->oid.hash, &type, &size);
        if (buffer) {
                if (size == sb.len)
                        match = memcmp(buffer, sb.buf, size);
@@ -205,7 +202,7 @@ static int ce_compare_gitlink(const struct cache_entry *ce)
         */
        if (resolve_gitlink_ref(ce->name, "HEAD", sha1) < 0)
                return 0;
-       return hashcmp(sha1, ce->sha1);
+       return hashcmp(sha1, ce->oid.hash);
 }
 
 static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
@@ -265,7 +262,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
 
        /* Racily smudged entry? */
        if (!ce->ce_stat_data.sd_size) {
-               if (!is_empty_blob_sha1(ce->sha1))
+               if (!is_empty_blob_sha1(ce->oid.hash))
                        changed |= DATA_CHANGED;
        }
 
@@ -327,7 +324,7 @@ int ie_match_stat(const struct index_state *istate,
         * by definition never matches what is in the work tree until it
         * actually gets added.
         */
-       if (ce->ce_flags & CE_INTENT_TO_ADD)
+       if (ce_intent_to_add(ce))
                return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED;
 
        changed = ce_match_stat_basic(ce, st);
@@ -506,7 +503,6 @@ int index_name_pos(const struct index_state *istate, const char *name, int namel
        return index_name_stage_pos(istate, name, namelen, 0);
 }
 
-/* Remove entry, return true if there are more entries to go.. */
 int remove_index_entry_at(struct index_state *istate, int pos)
 {
        struct cache_entry *ce = istate->cache[pos];
@@ -627,7 +623,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
        unsigned char sha1[20];
        if (write_sha1_file("", 0, blob_type, sha1))
                die("cannot create an empty blob in the object database");
-       hashcpy(ce->sha1, sha1);
+       hashcpy(ce->oid.hash, sha1);
 }
 
 int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
@@ -659,9 +655,10 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        else
                ce->ce_flags |= CE_INTENT_TO_ADD;
 
-       if (trust_executable_bit && has_symlinks)
+
+       if (trust_executable_bit && has_symlinks) {
                ce->ce_mode = create_ce_mode(st_mode);
-       else {
+       else {
                /* If there is an existing entry, pick the mode bits and type
                 * from it, otherwise assume unexecutable regular file.
                 */
@@ -678,21 +675,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
         * 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_dir_exists(istate, ce->name, ptr - ce->name - 1);
-                               if (foundce) {
-                                       memcpy((void *)startPtr, foundce->name + (startPtr - ce->name), ptr - startPtr);
-                                       startPtr = ptr;
-                               }
-                       }
-               }
+               adjust_dirname_case(istate, ce->name);
        }
 
        alias = index_file_exists(istate, ce->name, ce_namelen(ce), ignore_case);
@@ -706,7 +689,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                return 0;
        }
        if (!intent_only) {
-               if (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT)) {
+               if (index_path(ce->oid.hash, path, st, HASH_WRITE_OBJECT)) {
                        free(ce);
                        return error("unable to index file %s", path);
                }
@@ -720,7 +703,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        /* 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) &&
+                   !oidcmp(&alias->oid, &ce->oid) &&
                    ce->ce_mode == alias->ce_mode);
 
        if (pretend)
@@ -758,7 +741,7 @@ struct cache_entry *make_cache_entry(unsigned int mode,
        size = cache_entry_size(len);
        ce = xcalloc(1, size);
 
-       hashcpy(ce->sha1, sha1);
+       hashcpy(ce->oid.hash, sha1);
        memcpy(ce->name, path, len);
        ce->ce_flags = create_ce_flags(stage);
        ce->ce_namelen = len;
@@ -770,6 +753,35 @@ struct cache_entry *make_cache_entry(unsigned int mode,
        return ret;
 }
 
+/*
+ * Chmod an index entry with either +x or -x.
+ *
+ * Returns -1 if the chmod for the particular cache entry failed (if it's
+ * not a regular file), -2 if an invalid flip argument is passed in, 0
+ * otherwise.
+ */
+int chmod_index_entry(struct index_state *istate, struct cache_entry *ce,
+                     char flip)
+{
+       if (!S_ISREG(ce->ce_mode))
+               return -1;
+       switch (flip) {
+       case '+':
+               ce->ce_mode |= 0111;
+               break;
+       case '-':
+               ce->ce_mode &= ~0111;
+               break;
+       default:
+               return -2;
+       }
+       cache_tree_invalidate_path(istate, ce->name);
+       ce->ce_flags |= CE_UPDATE_IN_BASE;
+       istate->cache_changed |= CE_ENTRY_CHANGED;
+
+       return 0;
+}
+
 int ce_same_name(const struct cache_entry *a, const struct cache_entry *b)
 {
        int len = ce_namelen(a);
@@ -1251,7 +1263,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
 
                        if (cache_errno == ENOENT)
                                fmt = deleted_fmt;
-                       else if (ce->ce_flags & CE_INTENT_TO_ADD)
+                       else if (ce_intent_to_add(ce))
                                fmt = added_fmt; /* must be before other checks */
                        else if (changed & TYPE_CHANGED)
                                fmt = typechange_fmt;
@@ -1268,7 +1280,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
        return has_errors;
 }
 
-static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
+struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
                                               unsigned int options)
 {
        return refresh_cache_ent(&the_index, ce, options, NULL, NULL);
@@ -1405,12 +1417,9 @@ static int read_index_extension(struct index_state *istate,
        return 0;
 }
 
-int hold_locked_index(struct lock_file *lk, int die_on_error)
+int hold_locked_index(struct lock_file *lk, int lock_flags)
 {
-       return hold_lock_file_for_update(lk, get_index_file(),
-                                        die_on_error
-                                        ? LOCK_DIE_ON_ERROR
-                                        : 0);
+       return hold_lock_file_for_update(lk, get_index_file(), lock_flags);
 }
 
 int read_index(struct index_state *istate)
@@ -1438,7 +1447,7 @@ static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *on
        ce->ce_flags = flags & ~CE_NAMEMASK;
        ce->ce_namelen = len;
        ce->index = 0;
-       hashcpy(ce->sha1, ondisk->sha1);
+       hashcpy(ce->oid.hash, ondisk->sha1);
        memcpy(ce->name, name, len);
        ce->name[len] = '\0';
        return ce;
@@ -1533,6 +1542,28 @@ static void check_ce_order(struct index_state *istate)
        }
 }
 
+static void tweak_untracked_cache(struct index_state *istate)
+{
+       switch (git_config_get_untracked_cache()) {
+       case -1: /* keep: do nothing */
+               break;
+       case 0: /* false */
+               remove_untracked_cache(istate);
+               break;
+       case 1: /* true */
+               add_untracked_cache(istate);
+               break;
+       default: /* unknown value: do nothing */
+               break;
+       }
+}
+
+static void post_read_index_from(struct index_state *istate)
+{
+       check_ce_order(istate);
+       tweak_untracked_cache(istate);
+}
+
 /* remember to discard_cache() before reading a different cache! */
 int do_read_index(struct index_state *istate, const char *path, int must_exist)
 {
@@ -1636,9 +1667,10 @@ int read_index_from(struct index_state *istate, const char *path)
                return istate->cache_nr;
 
        ret = do_read_index(istate, path, 0);
+
        split_index = istate->split_index;
        if (!split_index || is_null_sha1(split_index->base_sha1)) {
-               check_ce_order(istate);
+               post_read_index_from(istate);
                return ret;
        }
 
@@ -1653,10 +1685,10 @@ int read_index_from(struct index_state *istate, const char *path)
                die("broken index, expect %s in %s, got %s",
                    sha1_to_hex(split_index->base_sha1),
                    git_path("sharedindex.%s",
-                                    sha1_to_hex(split_index->base_sha1)),
+                            sha1_to_hex(split_index->base_sha1)),
                    sha1_to_hex(split_index->base->sha1));
        merge_base_index(istate);
-       check_ce_order(istate);
+       post_read_index_from(istate);
        return ret;
 }
 
@@ -1840,7 +1872,7 @@ static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
        ondisk->uid  = htonl(ce->ce_stat_data.sd_uid);
        ondisk->gid  = htonl(ce->ce_stat_data.sd_gid);
        ondisk->size = htonl(ce->ce_stat_data.sd_size);
-       hashcpy(ondisk->sha1, ce->sha1);
+       hashcpy(ondisk->sha1, ce->oid.hash);
 
        flags = ce->ce_flags & ~CE_NAMEMASK;
        flags |= (ce_namelen(ce) >= CE_NAMEMASK ? CE_NAMEMASK : ce_namelen(ce));
@@ -2029,7 +2061,7 @@ static int do_write_index(struct index_state *istate, int newfd,
                        continue;
                if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
                        ce_smudge_racily_clean_entry(ce);
-               if (is_null_sha1(ce->sha1)) {
+               if (is_null_oid(&ce->oid)) {
                        static const char msg[] = "cache entry has null sha1: %s";
                        static int allow = -1;
 
@@ -2113,7 +2145,7 @@ static int commit_locked_index(struct lock_file *lk)
 static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
                                 unsigned flags)
 {
-       int ret = do_write_index(istate, lock->fd, 0);
+       int ret = do_write_index(istate, get_lock_file_fd(lock), 0);
        if (ret)
                return ret;
        assert((flags & (COMMIT_LOCK | CLOSE_LOCK)) !=
@@ -2137,54 +2169,27 @@ static int write_split_index(struct index_state *istate,
        return ret;
 }
 
-static char *temporary_sharedindex;
-
-static void remove_temporary_sharedindex(void)
-{
-       if (temporary_sharedindex) {
-               unlink_or_warn(temporary_sharedindex);
-               free(temporary_sharedindex);
-               temporary_sharedindex = NULL;
-       }
-}
-
-static void remove_temporary_sharedindex_on_signal(int signo)
-{
-       remove_temporary_sharedindex();
-       sigchain_pop(signo);
-       raise(signo);
-}
+static struct tempfile temporary_sharedindex;
 
 static int write_shared_index(struct index_state *istate,
                              struct lock_file *lock, unsigned flags)
 {
        struct split_index *si = istate->split_index;
-       static int installed_handler;
        int fd, ret;
 
-       temporary_sharedindex = git_pathdup("sharedindex_XXXXXX");
-       fd = mkstemp(temporary_sharedindex);
+       fd = mks_tempfile(&temporary_sharedindex, git_path("sharedindex_XXXXXX"));
        if (fd < 0) {
-               free(temporary_sharedindex);
-               temporary_sharedindex = NULL;
                hashclr(si->base_sha1);
                return do_write_locked_index(istate, lock, flags);
        }
-       if (!installed_handler) {
-               atexit(remove_temporary_sharedindex);
-               sigchain_push_common(remove_temporary_sharedindex_on_signal);
-       }
        move_cache_to_base_index(istate);
        ret = do_write_index(si->base, fd, 1);
-       close(fd);
        if (ret) {
-               remove_temporary_sharedindex();
+               delete_tempfile(&temporary_sharedindex);
                return ret;
        }
-       ret = rename(temporary_sharedindex,
-                    git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
-       free(temporary_sharedindex);
-       temporary_sharedindex = NULL;
+       ret = rename_tempfile(&temporary_sharedindex,
+                             git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
        if (!ret)
                hashcpy(si->base_sha1, si->base->sha1);
        return ret;
@@ -2279,7 +2284,8 @@ int index_name_is_other(const struct index_state *istate, const char *name,
        return 1;
 }
 
-void *read_blob_data_from_index(struct index_state *istate, const char *path, unsigned long *size)
+void *read_blob_data_from_index(const struct index_state *istate,
+                               const char *path, unsigned long *size)
 {
        int pos, len;
        unsigned long sz;
@@ -2303,7 +2309,7 @@ void *read_blob_data_from_index(struct index_state *istate, const char *path, un
        }
        if (pos < 0)
                return NULL;
-       data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
+       data = read_sha1_file(istate->cache[pos]->oid.hash, &type, &sz);
        if (!data || type != OBJ_BLOB) {
                free(data);
                return NULL;