push_refs_with_export: convert to struct object_id
[gitweb.git] / sha1_file.c
index 2be1afdde0b1bde19583ad8fa183fb7f2546cc13..27ce7b705e12ca0343a4a232788494e5dee518d5 100644 (file)
@@ -208,44 +208,25 @@ const char *sha1_file_name(const unsigned char *sha1)
  * provided by the caller.  which should be "pack" or "idx".
  */
 static char *sha1_get_pack_name(const unsigned char *sha1,
-                               char **name, char **base, const char *which)
+                               struct strbuf *buf,
+                               const char *which)
 {
-       static const char hex[] = "0123456789abcdef";
-       char *buf;
-       int i;
-
-       if (!*base) {
-               const char *sha1_file_directory = get_object_directory();
-               int len = strlen(sha1_file_directory);
-               *base = xmalloc(len + 60);
-               sprintf(*base, "%s/pack/pack-1234567890123456789012345678901234567890.%s",
-                       sha1_file_directory, which);
-               *name = *base + len + 11;
-       }
-
-       buf = *name;
-
-       for (i = 0; i < 20; i++) {
-               unsigned int val = *sha1++;
-               *buf++ = hex[val >> 4];
-               *buf++ = hex[val & 0xf];
-       }
-
-       return *base;
+       strbuf_reset(buf);
+       strbuf_addf(buf, "%s/pack/pack-%s.%s", get_object_directory(),
+                   sha1_to_hex(sha1), which);
+       return buf->buf;
 }
 
 char *sha1_pack_name(const unsigned char *sha1)
 {
-       static char *name, *base;
-
-       return sha1_get_pack_name(sha1, &name, &base, "pack");
+       static struct strbuf buf = STRBUF_INIT;
+       return sha1_get_pack_name(sha1, &buf, "pack");
 }
 
 char *sha1_pack_index_name(const unsigned char *sha1)
 {
-       static char *name, *base;
-
-       return sha1_get_pack_name(sha1, &name, &base, "idx");
+       static struct strbuf buf = STRBUF_INIT;
+       return sha1_get_pack_name(sha1, &buf, "idx");
 }
 
 struct alternate_object_database *alt_odb_list;
@@ -788,6 +769,37 @@ void close_pack_windows(struct packed_git *p)
        }
 }
 
+static int close_pack_fd(struct packed_git *p)
+{
+       if (p->pack_fd < 0)
+               return 0;
+
+       close(p->pack_fd);
+       pack_open_fds--;
+       p->pack_fd = -1;
+
+       return 1;
+}
+
+static void close_pack(struct packed_git *p)
+{
+       close_pack_windows(p);
+       close_pack_fd(p);
+       close_pack_index(p);
+}
+
+void close_all_packs(void)
+{
+       struct packed_git *p;
+
+       for (p = packed_git; p; p = p->next)
+               if (p->do_not_close)
+                       die("BUG! Want to close pack marked 'do-not-close'");
+               else
+                       close_pack(p);
+}
+
+
 /*
  * The LRU pack is the one with the oldest MRU window, preferring packs
  * with no used windows, or the oldest mtime if it has no windows allocated.
@@ -855,12 +867,8 @@ static int close_one_pack(void)
                find_lru_pack(p, &lru_p, &mru_w, &accept_windows_inuse);
        }
 
-       if (lru_p) {
-               close(lru_p->pack_fd);
-               pack_open_fds--;
-               lru_p->pack_fd = -1;
-               return 1;
-       }
+       if (lru_p)
+               return close_pack_fd(lru_p);
 
        return 0;
 }
@@ -900,12 +908,7 @@ void free_pack_by_name(const char *pack_name)
                p = *pp;
                if (strcmp(pack_name, p->pack_name) == 0) {
                        clear_delta_base_cache();
-                       close_pack_windows(p);
-                       if (p->pack_fd != -1) {
-                               close(p->pack_fd);
-                               pack_open_fds--;
-                       }
-                       close_pack_index(p);
+                       close_pack(p);
                        free(p->bad_object_sha1);
                        *pp = p->next;
                        if (last_found_pack == p)
@@ -1039,11 +1042,7 @@ static int open_packed_git(struct packed_git *p)
 {
        if (!open_packed_git_1(p))
                return 0;
-       if (p->pack_fd != -1) {
-               close(p->pack_fd);
-               pack_open_fds--;
-               p->pack_fd = -1;
-       }
+       close_pack_fd(p);
        return -1;
 }
 
@@ -1109,11 +1108,8 @@ unsigned char *use_pack(struct packed_git *p,
                                        p->pack_name,
                                        strerror(errno));
                        if (!win->offset && win->len == p->pack_size
-                               && !p->do_not_close) {
-                               close(p->pack_fd);
-                               pack_open_fds--;
-                               p->pack_fd = -1;
-                       }
+                               && !p->do_not_close)
+                               close_pack_fd(p);
                        pack_mmap_calls++;
                        pack_open_windows++;
                        if (pack_mapped > peak_pack_mapped)
@@ -1199,9 +1195,10 @@ struct packed_git *add_packed_git(const char *path, size_t path_len, int local)
 struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
 {
        const char *path = sha1_pack_name(sha1);
-       struct packed_git *p = alloc_packed_git(strlen(path) + 1);
+       int alloc = strlen(path) + 1;
+       struct packed_git *p = alloc_packed_git(alloc);
 
-       strcpy(p->pack_name, path);
+       memcpy(p->pack_name, path, alloc); /* includes NUL */
        hashcpy(p->sha1, sha1);
        if (check_packed_git_idx(idx_path, p)) {
                free(p);
@@ -1220,27 +1217,16 @@ void install_packed_git(struct packed_git *pack)
        packed_git = pack;
 }
 
-void (*report_garbage)(const char *desc, const char *path);
+void (*report_garbage)(unsigned seen_bits, const char *path);
 
 static void report_helper(const struct string_list *list,
                          int seen_bits, int first, int last)
 {
-       const char *msg;
-       switch (seen_bits) {
-       case 0:
-               msg = "no corresponding .idx or .pack";
-               break;
-       case 1:
-               msg = "no corresponding .idx";
-               break;
-       case 2:
-               msg = "no corresponding .pack";
-               break;
-       default:
+       if (seen_bits == (PACKDIR_FILE_PACK|PACKDIR_FILE_IDX))
                return;
-       }
+
        for (; first < last; first++)
-               report_garbage(msg, list->items[first].string);
+               report_garbage(seen_bits, list->items[first].string);
 }
 
 static void report_pack_garbage(struct string_list *list)
@@ -1263,7 +1249,7 @@ static void report_pack_garbage(struct string_list *list)
                if (baselen == -1) {
                        const char *dot = strrchr(path, '.');
                        if (!dot) {
-                               report_garbage("garbage found", path);
+                               report_garbage(PACKDIR_FILE_GARBAGE, path);
                                continue;
                        }
                        baselen = dot - path + 1;
@@ -1335,7 +1321,7 @@ static void prepare_packed_git_one(char *objdir, int local)
                    ends_with(de->d_name, ".keep"))
                        string_list_append(&garbage, path.buf);
                else
-                       report_garbage("garbage found", path.buf);
+                       report_garbage(PACKDIR_FILE_GARBAGE, path.buf);
        }
        closedir(dir);
        report_pack_garbage(&garbage);
@@ -2129,7 +2115,7 @@ static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset)
 {
        unsigned long hash;
 
-       hash = (unsigned long)p + (unsigned long)base_offset;
+       hash = (unsigned long)(intptr_t)p + (unsigned long)base_offset;
        hash += (hash >> 8) + (hash >> 16);
        return hash % MAX_DELTA_CACHE;
 }
@@ -3030,29 +3016,31 @@ static inline int directory_size(const char *filename)
  * We want to avoid cross-directory filename renames, because those
  * can have problems on various filesystems (FAT, NFS, Coda).
  */
-static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
+static int create_tmpfile(struct strbuf *tmp, const char *filename)
 {
        int fd, dirlen = directory_size(filename);
 
-       if (dirlen + 20 > bufsiz) {
-               errno = ENAMETOOLONG;
-               return -1;
-       }
-       memcpy(buffer, filename, dirlen);
-       strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
-       fd = git_mkstemp_mode(buffer, 0444);
+       strbuf_reset(tmp);
+       strbuf_add(tmp, filename, dirlen);
+       strbuf_addstr(tmp, "tmp_obj_XXXXXX");
+       fd = git_mkstemp_mode(tmp->buf, 0444);
        if (fd < 0 && dirlen && errno == ENOENT) {
-               /* Make sure the directory exists */
-               memcpy(buffer, filename, dirlen);
-               buffer[dirlen-1] = 0;
-               if (mkdir(buffer, 0777) && errno != EEXIST)
+               /*
+                * Make sure the directory exists; note that the contents
+                * of the buffer are undefined after mkstemp returns an
+                * error, so we have to rewrite the whole buffer from
+                * scratch.
+                */
+               strbuf_reset(tmp);
+               strbuf_add(tmp, filename, dirlen - 1);
+               if (mkdir(tmp->buf, 0777) && errno != EEXIST)
                        return -1;
-               if (adjust_shared_perm(buffer))
+               if (adjust_shared_perm(tmp->buf))
                        return -1;
 
                /* Try again */
-               strcpy(buffer + dirlen - 1, "/tmp_obj_XXXXXX");
-               fd = git_mkstemp_mode(buffer, 0444);
+               strbuf_addstr(tmp, "/tmp_obj_XXXXXX");
+               fd = git_mkstemp_mode(tmp->buf, 0444);
        }
        return fd;
 }
@@ -3065,10 +3053,10 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
        git_zstream stream;
        git_SHA_CTX c;
        unsigned char parano_sha1[20];
-       static char tmp_file[PATH_MAX];
+       static struct strbuf tmp_file = STRBUF_INIT;
        const char *filename = sha1_file_name(sha1);
 
-       fd = create_tmpfile(tmp_file, sizeof(tmp_file), filename);
+       fd = create_tmpfile(&tmp_file, filename);
        if (fd < 0) {
                if (errno == EACCES)
                        return error("insufficient permission for adding an object to repository database %s", get_object_directory());
@@ -3117,12 +3105,12 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
                struct utimbuf utb;
                utb.actime = mtime;
                utb.modtime = mtime;
-               if (utime(tmp_file, &utb) < 0)
+               if (utime(tmp_file.buf, &utb) < 0)
                        warning("failed utime() on %s: %s",
-                               tmp_file, strerror(errno));
+                               tmp_file.buf, strerror(errno));
        }
 
-       return finalize_object_file(tmp_file, filename);
+       return finalize_object_file(tmp_file.buf, filename);
 }
 
 static int freshen_loose_object(const unsigned char *sha1)
@@ -3228,6 +3216,11 @@ int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
        return find_pack_entry(sha1, &e);
 }
 
+int has_object_file(const struct object_id *oid)
+{
+       return has_sha1_file(oid->hash);
+}
+
 static void check_tree(const void *buf, size_t size)
 {
        struct tree_desc desc;