summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c153
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;