gitweb: unify boolean feature subroutines
[gitweb.git] / sha1_file.c
index 0fa65baa59de4db058ca6a41bba29ac78eab2643..0e021c5eca8ea1a85d7863c427e054fd24fcd95a 100644 (file)
@@ -672,6 +672,37 @@ void unuse_pack(struct pack_window **w_cursor)
        }
 }
 
+/*
+ * This is used by git-repack in case a newly created pack happens to
+ * contain the same set of objects as an existing one.  In that case
+ * the resulting file might be different even if its name would be the
+ * same.  It is best to close any reference to the old pack before it is
+ * replaced on disk.  Of course no index pointers nor windows for given pack
+ * must subsist at this point.  If ever objects from this pack are requested
+ * again, the new version of the pack will be reinitialized through
+ * reprepare_packed_git().
+ */
+void free_pack_by_name(const char *pack_name)
+{
+       struct packed_git *p, **pp = &packed_git;
+
+       while (*pp) {
+               p = *pp;
+               if (strcmp(pack_name, p->pack_name) == 0) {
+                       close_pack_windows(p);
+                       if (p->pack_fd != -1)
+                               close(p->pack_fd);
+                       if (p->index_data)
+                               munmap((void *)p->index_data, p->index_size);
+                       free(p->bad_object_sha1);
+                       *pp = p->next;
+                       free(p);
+                       return;
+               }
+               pp = &p->next;
+       }
+}
+
 /*
  * Do not call this directly as this leaks p->pack_fd on error return;
  * call open_packed_git() instead.
@@ -1749,6 +1780,7 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                        error("bad packed object CRC for %s",
                              sha1_to_hex(sha1));
                        mark_bad_packed_object(p, sha1);
+                       unuse_pack(&w_curs);
                        return NULL;
                }
        }
@@ -2055,9 +2087,7 @@ static struct cached_object {
 static int cached_object_nr, cached_object_alloc;
 
 static struct cached_object empty_tree = {
-       /* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */
-       "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60"
-       "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04",
+       EMPTY_TREE_SHA1_BIN,
        OBJ_TREE,
        "",
        0
@@ -2290,7 +2320,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
        memcpy(buffer, filename, dirlen);
        strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
        fd = mkstemp(buffer);
-       if (fd < 0 && dirlen) {
+       if (fd < 0 && dirlen && errno == ENOENT) {
                /* Make sure the directory exists */
                memcpy(buffer, filename, dirlen);
                buffer[dirlen-1] = 0;
@@ -2316,7 +2346,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
        filename = sha1_file_name(sha1);
        fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
        if (fd < 0) {
-               if (errno == EPERM)
+               if (errno == EACCES)
                        return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
                else
                        return error("unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno));