diff options
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 153 |
1 files changed, 81 insertions, 72 deletions
diff --git a/read-cache.c b/read-cache.c index 89dbc0837a..38d67faf70 100644 --- a/read-cache.c +++ b/read-cache.c @@ -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" @@ -16,12 +17,8 @@ #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) @@ -164,7 +161,7 @@ static int ce_compare_data(const struct cache_entry *ce, struct stat *st) 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); @@ -627,7 +624,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 +656,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 +676,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 +690,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 +704,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 +742,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 +754,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 +1264,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 +1281,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); @@ -1438,7 +1451,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 +1546,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 +1671,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 +1689,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 +1876,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 +2065,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 +2149,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 +2173,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; @@ -2303,7 +2312,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; |