builtin/branch: strip refs/heads/ using skip_prefix
[gitweb.git] / read-cache.c
index 0724ea8c9b807eed87b571e3837a9be254c3b71b..2eb81a66b941325dc339d61a0ab804a60cbb8be2 100644 (file)
@@ -196,7 +196,7 @@ static int ce_compare_link(const struct cache_entry *ce, size_t expected_size)
 
 static int ce_compare_gitlink(const struct cache_entry *ce)
 {
-       unsigned char sha1[20];
+       struct object_id oid;
 
        /*
         * We don't actually require that the .git directory
@@ -206,9 +206,9 @@ static int ce_compare_gitlink(const struct cache_entry *ce)
         *
         * If so, we consider it always to match.
         */
-       if (resolve_gitlink_ref(ce->name, "HEAD", sha1) < 0)
+       if (resolve_gitlink_ref(ce->name, "HEAD", &oid) < 0)
                return 0;
-       return hashcmp(sha1, ce->oid.hash);
+       return oidcmp(&oid, &ce->oid);
 }
 
 static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
@@ -225,6 +225,7 @@ static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
        case S_IFDIR:
                if (S_ISGITLINK(ce->ce_mode))
                        return ce_compare_gitlink(ce) ? DATA_CHANGED : 0;
+               /* else fallthrough */
        default:
                return TYPE_CHANGED;
        }
@@ -640,13 +641,17 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 {
        int size, namelen, was_same;
        mode_t st_mode = st->st_mode;
-       struct cache_entry *ce, *alias;
+       struct cache_entry *ce, *alias = NULL;
        unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE|CE_MATCH_RACY_IS_DIRTY;
        int verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);
        int pretend = flags & ADD_CACHE_PRETEND;
        int intent_only = flags & ADD_CACHE_INTENT;
        int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
                          (intent_only ? ADD_CACHE_NEW_ONLY : 0));
+       int newflags = HASH_WRITE_OBJECT;
+
+       if (flags & HASH_RENORMALIZE)
+               newflags |= HASH_RENORMALIZE;
 
        if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))
                return error("%s: can only add regular files, symbolic links or git-directories", path);
@@ -687,19 +692,23 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
        if (ignore_case) {
                adjust_dirname_case(istate, ce->name);
        }
+       if (!(flags & HASH_RENORMALIZE)) {
+               alias = index_file_exists(istate, ce->name,
+                                         ce_namelen(ce), ignore_case);
+               if (alias &&
+                   !ce_stage(alias) &&
+                   !ie_match_stat(istate, alias, st, ce_option)) {
+                       /* Nothing changed, really */
+                       if (!S_ISGITLINK(alias->ce_mode))
+                               ce_mark_uptodate(alias);
+                       alias->ce_flags |= CE_ADDED;
 
-       alias = index_file_exists(istate, ce->name, ce_namelen(ce), ignore_case);
-       if (alias && !ce_stage(alias) && !ie_match_stat(istate, alias, st, ce_option)) {
-               /* Nothing changed, really */
-               if (!S_ISGITLINK(alias->ce_mode))
-                       ce_mark_uptodate(alias);
-               alias->ce_flags |= CE_ADDED;
-
-               free(ce);
-               return 0;
+                       free(ce);
+                       return 0;
+               }
        }
        if (!intent_only) {
-               if (index_path(&ce->oid, path, st, HASH_WRITE_OBJECT)) {
+               if (index_path(&ce->oid, path, st, newflags)) {
                        free(ce);
                        return error("unable to index file %s", path);
                }
@@ -1531,6 +1540,9 @@ struct ondisk_cache_entry_extended {
 /* Allow fsck to force verification of the index checksum. */
 int verify_index_checksum;
 
+/* Allow fsck to force verification of the cache entry order. */
+int verify_ce_order;
+
 static int verify_hdr(struct cache_header *hdr, unsigned long size)
 {
        git_SHA_CTX c;
@@ -1691,6 +1703,9 @@ static void check_ce_order(struct index_state *istate)
 {
        unsigned int i;
 
+       if (!verify_ce_order)
+               return;
+
        for (i = 1; i < istate->cache_nr; i++) {
                struct cache_entry *ce = istate->cache[i - 1];
                struct cache_entry *next_ce = istate->cache[i];
@@ -1947,7 +1962,7 @@ static int ce_write_flush(git_SHA_CTX *context, int fd)
        unsigned int buffered = write_buffer_len;
        if (buffered) {
                git_SHA1_Update(context, write_buffer, buffered);
-               if (write_in_full(fd, write_buffer, buffered) != buffered)
+               if (write_in_full(fd, write_buffer, buffered) < 0)
                        return -1;
                write_buffer_len = 0;
        }
@@ -1996,7 +2011,7 @@ static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1)
 
        /* Flush first if not enough space for SHA1 signature */
        if (left + 20 > WRITE_BUFFER_SIZE) {
-               if (write_in_full(fd, write_buffer, left) != left)
+               if (write_in_full(fd, write_buffer, left) < 0)
                        return -1;
                left = 0;
        }
@@ -2005,7 +2020,7 @@ static int ce_flush(git_SHA_CTX *context, int fd, unsigned char *sha1)
        git_SHA1_Final(write_buffer + left, context);
        hashcpy(sha1, write_buffer + left);
        left += 20;
-       return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0;
+       return (write_in_full(fd, write_buffer, left) < 0) ? -1 : 0;
 }
 
 static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
@@ -2128,7 +2143,9 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
                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 + 1);
+                       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);
@@ -2198,17 +2215,22 @@ static int has_racy_timestamp(struct index_state *istate)
        return 0;
 }
 
-/*
- * Opportunistically update the index but do not complain if we can't
- */
 void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
 {
        if ((istate->cache_changed || has_racy_timestamp(istate)) &&
-           verify_index(istate) &&
-           write_locked_index(istate, lockfile, COMMIT_LOCK))
+           verify_index(istate))
+               write_locked_index(istate, lockfile, COMMIT_LOCK);
+       else
                rollback_lock_file(lockfile);
 }
 
+/*
+ * On success, `tempfile` is closed. If it is the temporary file
+ * of a `struct lock_file`, we will therefore effectively perform
+ * a 'close_lock_file_gently()`. Since that is an implementation
+ * detail of lockfiles, callers of `do_write_index()` should not
+ * rely on it.
+ */
 static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
                          int strip_extensions)
 {
@@ -2344,8 +2366,10 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
 
        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);
+               return -1;
+       }
        if (stat(tempfile->filename.buf, &st))
                return -1;
        istate->timestamp.sec = (unsigned int)st.st_mtime;
@@ -2369,17 +2393,12 @@ 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->tempfile, 0);
+       int ret = do_write_index(istate, lock->tempfile, 0);
        if (ret)
                return ret;
-       assert((flags & (COMMIT_LOCK | CLOSE_LOCK)) !=
-              (COMMIT_LOCK | CLOSE_LOCK));
        if (flags & COMMIT_LOCK)
                return commit_locked_index(lock);
-       else if (flags & CLOSE_LOCK)
-               return close_lock_file(lock);
-       else
-               return ret;
+       return close_lock_file_gently(lock);
 }
 
 static int write_split_index(struct index_state *istate,
@@ -2452,34 +2471,33 @@ static int clean_shared_index_files(const char *current_hex)
        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);
@@ -2532,7 +2550,8 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
            (istate->cache_changed & ~EXTMASK)) {
                if (si)
                        hashclr(si->base_sha1);
-               return do_write_locked_index(istate, lock, flags);
+               ret = do_write_locked_index(istate, lock, flags);
+               goto out;
        }
 
        if (getenv("GIT_TEST_SPLIT_INDEX")) {
@@ -2548,7 +2567,7 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
        if (new_shared_index) {
                ret = write_shared_index(istate, lock, flags);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        ret = write_split_index(istate, lock, flags);
@@ -2557,6 +2576,9 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
        if (!ret && !new_shared_index)
                freshen_shared_index(sha1_to_hex(si->base_sha1), 1);
 
+out:
+       if (flags & COMMIT_LOCK)
+               rollback_lock_file(lock);
        return ret;
 }