Teach show-branch how to show ref-log data.
[gitweb.git] / read-cache.c
index 4d621ef4448b34ce8c46674989191513a950cd35..b8d83ccd9f7985d60f69b7cd44db698d4e932612 100644 (file)
 #define CACHE_EXT(s) ( (s[0]<<24)|(s[1]<<16)|(s[2]<<8)|(s[3]) )
 #define CACHE_EXT_TREE 0x54524545      /* "TREE" */
 
-struct cache_entry **active_cache = NULL;
+struct cache_entry **active_cache;
 static time_t index_file_timestamp;
-unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
+unsigned int active_nr, active_alloc, active_cache_changed;
 
-struct cache_tree *active_cache_tree = NULL;
+struct cache_tree *active_cache_tree;
 
-int cache_errno = 0;
+int cache_errno;
 
-static void *cache_mmap = NULL;
-static size_t cache_mmap_size = 0;
+static void *cache_mmap;
+static size_t cache_mmap_size;
 
 /*
  * This only updates the "non-critical" parts of the directory
@@ -60,7 +60,7 @@ static int ce_compare_data(struct cache_entry *ce, struct stat *st)
        if (fd >= 0) {
                unsigned char sha1[20];
                if (!index_fd(sha1, fd, st, 0, NULL))
-                       match = memcmp(sha1, ce->sha1, 20);
+                       match = hashcmp(sha1, ce->sha1);
                /* index_fd() closed the file descriptor already */
        }
        return match;
@@ -347,16 +347,18 @@ int add_file_to_index(const char *path, int verbose)
        ce->ce_mode = create_ce_mode(st.st_mode);
        if (!trust_executable_bit) {
                /* If there is an existing entry, pick the mode bits
-                * from it.
+                * from it, otherwise assume unexecutable.
                 */
                int pos = cache_name_pos(path, namelen);
                if (pos >= 0)
                        ce->ce_mode = active_cache[pos]->ce_mode;
+               else if (S_ISREG(st.st_mode))
+                       ce->ce_mode = create_ce_mode(S_IFREG | 0666);
        }
 
        if (index_path(ce->sha1, path, &st, 1))
                die("unable to index file %s", path);
-       if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD))
+       if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE))
                die("unable to add %s to index",path);
        if (verbose)
                printf("add '%s'\n", path);
@@ -515,7 +517,7 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
                pos = cache_name_pos(name, ntohs(create_ce_flags(len, stage)));
                if (pos >= 0) {
                        retval = -1;
-                       if (ok_to_replace)
+                       if (!ok_to_replace)
                                break;
                        remove_cache_entry_at(pos);
                        continue;
@@ -607,7 +609,7 @@ int add_cache_entry(struct cache_entry *ce, int option)
        if (!skip_df_check &&
            check_file_directory_conflict(ce, pos, ok_to_replace)) {
                if (!ok_to_replace)
-                       return -1;
+                       return error("'%s' appears as both a file and as a directory", ce->name);
                pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
                pos = -pos-1;
        }
@@ -744,7 +746,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
        SHA1_Init(&c);
        SHA1_Update(&c, hdr, size - 20);
        SHA1_Final(sha1, &c);
-       if (memcmp(sha1, (char *) hdr + size - 20, 20))
+       if (hashcmp(sha1, (unsigned char *)hdr + size - 20))
                return error("bad index file sha1 signature");
        return 0;
 }
@@ -842,6 +844,23 @@ int read_cache_from(const char *path)
        die("index file corrupt");
 }
 
+int discard_cache(void)
+{
+       int ret;
+
+       active_nr = active_cache_changed = 0;
+       index_file_timestamp = 0;
+       cache_tree_free(&active_cache_tree);
+       if (cache_mmap == NULL)
+               return 0;
+       ret = munmap(cache_mmap, cache_mmap_size);
+       cache_mmap = NULL;
+       cache_mmap_size = 0;
+
+       /* no need to throw away allocated active_cache */
+       return ret;
+}
+
 #define WRITE_BUFFER_SIZE 8192
 static unsigned char write_buffer[WRITE_BUFFER_SIZE];
 static unsigned long write_buffer_len;
@@ -959,9 +978,7 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
 {
        SHA_CTX c;
        struct cache_header hdr;
-       int i, removed, recent;
-       struct stat st;
-       time_t now;
+       int i, removed;
 
        for (i = removed = 0; i < entries; i++)
                if (!cache[i]->ce_mode)
@@ -999,54 +1016,5 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
                        return -1;
                }
        }
-
-       /*
-        * To prevent later ce_match_stat() from always falling into
-        * check_fs(), if we have too many entries that can trigger
-        * racily clean check, we are better off delaying the return.
-        * We arbitrarily say if more than 20 paths or 25% of total
-        * paths are very new, we delay the return until the index
-        * file gets a new timestamp.
-        *
-        * NOTE! NOTE! NOTE!
-        *
-        * This assumes that nobody is touching the working tree while
-        * we are updating the index.
-        */
-
-       /* Make sure that the new index file has st_mtime
-        * that is current enough -- ce_write() batches the data
-        * so it might not have written anything yet.
-        */
-       ce_write_flush(&c, newfd);
-
-       now = fstat(newfd, &st) ? 0 : st.st_mtime;
-       if (now) {
-               recent = 0;
-               for (i = 0; i < entries; i++) {
-                       struct cache_entry *ce = cache[i];
-                       time_t entry_time = (time_t) ntohl(ce->ce_mtime.sec);
-                       if (!ce->ce_mode)
-                               continue;
-                       if (now && now <= entry_time)
-                               recent++;
-               }
-               if (20 < recent && entries <= recent * 4) {
-#if 0
-                       fprintf(stderr, "entries    %d\n", entries);
-                       fprintf(stderr, "recent     %d\n", recent);
-                       fprintf(stderr, "now        %lu\n", now);
-#endif
-                       while (!fstat(newfd, &st) && st.st_mtime <= now) {
-                               off_t where = lseek(newfd, 0, SEEK_CUR);
-                               sleep(1);
-                               if ((where == (off_t) -1) ||
-                                   (write(newfd, "", 1) != 1) ||
-                                   (lseek(newfd, -1, SEEK_CUR) != where) ||
-                                   ftruncate(newfd, where))
-                                       break;
-                       }
-               }
-       }
        return ce_flush(&c, newfd);
 }