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->oid.hash);
+ struct object_id oid;
+ if (!index_fd(&oid, fd, st, OBJ_BLOB, ce->name, 0))
+ match = oidcmp(&oid, &ce->oid);
/* index_fd() closed the file descriptor already */
}
return match;
case S_IFDIR:
if (S_ISGITLINK(ce->ce_mode))
return ce_compare_gitlink(ce) ? DATA_CHANGED : 0;
+ /* else fallthrough */
default:
return TYPE_CHANGED;
}
return 0;
}
if (!intent_only) {
- if (index_path(ce->oid.hash, path, st, HASH_WRITE_OBJECT)) {
+ if (index_path(&ce->oid, path, st, HASH_WRITE_OBJECT)) {
free(ce);
return error("unable to index file %s", path);
}
};
/* These are only used for v3 or lower */
+#define align_padding_size(size, len) ((size + (len) + 8) & ~7) - (size + len)
#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
#define ondisk_cache_entry_size(len) align_flex_name(ondisk_cache_entry,len)
#define ondisk_cache_entry_extended_size(len) align_flex_name(ondisk_cache_entry_extended,len)
int read_index(struct index_state *istate)
{
- return read_index_from(istate, get_index_file());
+ return read_index_from(istate, get_index_file(), get_git_dir());
}
static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
* This way, shared index can be removed if they have not been used
* for some time.
*/
-static void freshen_shared_index(char *base_sha1_hex, int warn)
+static void freshen_shared_index(const char *shared_index, int warn)
{
- char *shared_index = git_pathdup("sharedindex.%s", base_sha1_hex);
if (!check_and_freshen_file(shared_index, 1) && warn)
warning("could not freshen shared index '%s'", shared_index);
- free(shared_index);
}
-int read_index_from(struct index_state *istate, const char *path)
+int read_index_from(struct index_state *istate, const char *path,
+ const char *gitdir)
{
struct split_index *split_index;
int ret;
char *base_sha1_hex;
- const char *base_path;
+ char *base_path;
/* istate->initialized covers both .git/index and .git/sharedindex.xxx */
if (istate->initialized)
split_index->base = xcalloc(1, sizeof(*split_index->base));
base_sha1_hex = sha1_to_hex(split_index->base_sha1);
- base_path = git_path("sharedindex.%s", base_sha1_hex);
+ base_path = xstrfmt("%s/sharedindex.%s", gitdir, base_sha1_hex);
ret = do_read_index(split_index->base, base_path, 1);
if (hashcmp(split_index->base_sha1, split_index->base->sha1))
die("broken index, expect %s in %s, got %s",
base_sha1_hex, base_path,
sha1_to_hex(split_index->base->sha1));
- freshen_shared_index(base_sha1_hex, 0);
+ freshen_shared_index(base_path, 0);
merge_base_index(istate);
post_read_index_from(istate);
+ free(base_path);
return ret;
}
}
/* Copy miscellaneous fields but not the name */
-static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
+static void copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
struct cache_entry *ce)
{
short flags;
struct ondisk_cache_entry_extended *ondisk2;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
- return ondisk2->name;
- }
- else {
- return ondisk->name;
}
}
static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
- struct strbuf *previous_name)
+ struct strbuf *previous_name, struct ondisk_cache_entry *ondisk)
{
int size;
- struct ondisk_cache_entry *ondisk;
int saved_namelen = saved_namelen; /* compiler workaround */
- char *name;
int result;
+ static unsigned char padding[8] = { 0x00 };
if (ce->ce_flags & CE_STRIP_NAME) {
saved_namelen = ce_namelen(ce);
ce->ce_namelen = 0;
}
+ if (ce->ce_flags & CE_EXTENDED)
+ size = offsetof(struct ondisk_cache_entry_extended, name);
+ else
+ size = offsetof(struct ondisk_cache_entry, name);
+
if (!previous_name) {
- size = ondisk_ce_size(ce);
- ondisk = xcalloc(1, size);
- name = copy_cache_entry_to_ondisk(ondisk, ce);
- memcpy(name, ce->name, ce_namelen(ce));
+ int len = ce_namelen(ce);
+ copy_cache_entry_to_ondisk(ondisk, ce);
+ result = ce_write(c, fd, ondisk, size);
+ if (!result)
+ result = ce_write(c, fd, ce->name, len);
+ if (!result)
+ result = ce_write(c, fd, padding, align_padding_size(size, len));
} else {
int common, to_remove, prefix_size;
unsigned char to_remove_vi[16];
to_remove = previous_name->len - common;
prefix_size = encode_varint(to_remove, to_remove_vi);
- if (ce->ce_flags & CE_EXTENDED)
- size = offsetof(struct ondisk_cache_entry_extended, name);
- else
- size = offsetof(struct ondisk_cache_entry, name);
- size += prefix_size + (ce_namelen(ce) - common + 1);
-
- ondisk = xcalloc(1, size);
- name = copy_cache_entry_to_ondisk(ondisk, ce);
- memcpy(name, to_remove_vi, prefix_size);
- memcpy(name + prefix_size, ce->name + common, ce_namelen(ce) - common);
+ copy_cache_entry_to_ondisk(ondisk, ce);
+ result = ce_write(c, fd, ondisk, size);
+ if (!result)
+ result = ce_write(c, fd, to_remove_vi, prefix_size);
+ if (!result)
+ result = ce_write(c, fd, ce->name + common, ce_namelen(ce) - common);
+ if (!result)
+ result = ce_write(c, fd, padding, 1);
strbuf_splice(previous_name, common, to_remove,
ce->name + common, ce_namelen(ce) - common);
ce->ce_flags &= ~CE_STRIP_NAME;
}
- result = ce_write(c, fd, ondisk, size);
- free(ondisk);
return result;
}
int newfd = tempfile->fd;
git_SHA_CTX c;
struct cache_header hdr;
- int i, err, removed, extended, hdr_version;
+ int i, err = 0, removed, extended, hdr_version;
struct cache_entry **cache = istate->cache;
int entries = istate->cache_nr;
struct stat st;
+ struct ondisk_cache_entry_extended ondisk;
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
- int drop_cache_tree = 0;
+ int drop_cache_tree = istate->drop_cache_tree;
for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
return -1;
previous_name = (hdr_version == 4) ? &previous_name_buf : NULL;
+
for (i = 0; i < entries; i++) {
struct cache_entry *ce = cache[i];
if (ce->ce_flags & CE_REMOVE)
if (allow)
warning(msg, ce->name);
else
- return error(msg, ce->name);
+ err = error(msg, ce->name);
drop_cache_tree = 1;
}
- if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
- return -1;
+ if (ce_write_entry(&c, newfd, ce, previous_name, (struct ondisk_cache_entry *)&ondisk) < 0)
+ err = -1;
+
+ if (err)
+ break;
}
strbuf_release(&previous_name_buf);
+ if (err)
+ return err;
+
/* Write extension data here */
if (!strip_extensions && istate->split_index) {
struct strbuf sb = STRBUF_INIT;
if (ce_flush(&c, newfd, istate->sha1))
return -1;
- if (close_tempfile(tempfile))
- return error(_("could not close '%s'"), tempfile->filename.buf);
+ if (close_tempfile_gently(tempfile)) {
+ error(_("could not close '%s'"), tempfile->filename.buf);
+ delete_tempfile(&tempfile);
+ return -1;
+ }
if (stat(tempfile->filename.buf, &st))
return -1;
istate->timestamp.sec = (unsigned int)st.st_mtime;
static int do_write_locked_index(struct index_state *istate, struct lock_file *lock,
unsigned flags)
{
- int ret = do_write_index(istate, &lock->tempfile, 0);
+ int ret = do_write_index(istate, lock->tempfile, 0);
if (ret)
return ret;
assert((flags & (COMMIT_LOCK | CLOSE_LOCK)) !=
if (flags & COMMIT_LOCK)
return commit_locked_index(lock);
else if (flags & CLOSE_LOCK)
- return close_lock_file(lock);
+ return close_lock_file_gently(lock);
else
return ret;
}
return 0;
}
-static struct tempfile temporary_sharedindex;
-
static int write_shared_index(struct index_state *istate,
struct lock_file *lock, unsigned flags)
{
+ struct tempfile *temp;
struct split_index *si = istate->split_index;
- int fd, ret;
+ int ret;
- fd = mks_tempfile(&temporary_sharedindex, git_path("sharedindex_XXXXXX"));
- if (fd < 0) {
+ temp = mks_tempfile(git_path("sharedindex_XXXXXX"));
+ if (!temp) {
hashclr(si->base_sha1);
return do_write_locked_index(istate, lock, flags);
}
move_cache_to_base_index(istate);
- ret = do_write_index(si->base, &temporary_sharedindex, 1);
+ ret = do_write_index(si->base, temp, 1);
if (ret) {
- delete_tempfile(&temporary_sharedindex);
+ delete_tempfile(&temp);
return ret;
}
- ret = adjust_shared_perm(get_tempfile_path(&temporary_sharedindex));
+ ret = adjust_shared_perm(get_tempfile_path(temp));
if (ret) {
int save_errno = errno;
- error("cannot fix permission bits on %s", get_tempfile_path(&temporary_sharedindex));
- delete_tempfile(&temporary_sharedindex);
+ error("cannot fix permission bits on %s", get_tempfile_path(temp));
+ delete_tempfile(&temp);
errno = save_errno;
return ret;
}
- ret = rename_tempfile(&temporary_sharedindex,
+ ret = rename_tempfile(&temp,
git_path("sharedindex.%s", sha1_to_hex(si->base->sha1)));
if (!ret) {
hashcpy(si->base_sha1, si->base->sha1);
ret = write_split_index(istate, lock, flags);
/* Freshen the shared index only if the split-index was written */
- if (!ret && !new_shared_index)
- freshen_shared_index(sha1_to_hex(si->base_sha1), 1);
+ if (!ret && !new_shared_index) {
+ const char *shared_index = git_path("sharedindex.%s",
+ sha1_to_hex(si->base_sha1));
+ freshen_shared_index(shared_index, 1);
+ }
return ret;
}