Merge branch 'jc/add-u-A-default-to-top' into maint
[gitweb.git] / sha1_file.c
index f2e993e0b8b998c91b945771a87a099d882448f5..ca699d7beb067bff83ea15f0a0e724916f33549b 100644 (file)
@@ -377,15 +377,12 @@ void read_info_alternates(const char * relative_base, int depth)
        char *map;
        size_t mapsz;
        struct stat st;
-       const char alt_file_name[] = "info/alternates";
-       /* Given that relative_base is no longer than PATH_MAX,
-          ensure that "path" has enough space to append "/", the
-          file name, "info/alternates", and a trailing NUL.  */
-       char path[PATH_MAX + 1 + sizeof alt_file_name];
+       char *path;
        int fd;
 
-       sprintf(path, "%s/%s", relative_base, alt_file_name);
+       path = xstrfmt("%s/info/alternates", relative_base);
        fd = git_open_noatime(path);
+       free(path);
        if (fd < 0)
                return;
        if (fstat(fd, &st) || (st.st_size == 0)) {
@@ -404,13 +401,46 @@ void read_info_alternates(const char * relative_base, int depth)
 void add_to_alternates_file(const char *reference)
 {
        struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
-       int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), LOCK_DIE_ON_ERROR);
-       const char *alt = mkpath("%s\n", reference);
-       write_or_die(fd, alt, strlen(alt));
-       if (commit_lock_file(lock))
-               die("could not close alternates file");
-       if (alt_odb_tail)
-               link_alt_odb_entries(alt, strlen(alt), '\n', NULL, 0);
+       char *alts = git_pathdup("objects/info/alternates");
+       FILE *in, *out;
+
+       hold_lock_file_for_update(lock, alts, LOCK_DIE_ON_ERROR);
+       out = fdopen_lock_file(lock, "w");
+       if (!out)
+               die_errno("unable to fdopen alternates lockfile");
+
+       in = fopen(alts, "r");
+       if (in) {
+               struct strbuf line = STRBUF_INIT;
+               int found = 0;
+
+               while (strbuf_getline(&line, in, '\n') != EOF) {
+                       if (!strcmp(reference, line.buf)) {
+                               found = 1;
+                               break;
+                       }
+                       fprintf_or_die(out, "%s\n", line.buf);
+               }
+
+               strbuf_release(&line);
+               fclose(in);
+
+               if (found) {
+                       rollback_lock_file(lock);
+                       lock = NULL;
+               }
+       }
+       else if (errno != ENOENT)
+               die_errno("unable to read alternates file");
+
+       if (lock) {
+               fprintf_or_die(out, "%s\n", reference);
+               if (commit_lock_file(lock))
+                       die_errno("unable to move new alternates file into place");
+               if (alt_odb_tail)
+                       link_alt_odb_entries(reference, strlen(reference), '\n', NULL, 0);
+       }
+       free(alts);
 }
 
 int foreach_alt_odb(alt_odb_fn fn, void *cb)
@@ -756,6 +786,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.
@@ -823,12 +884,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;
 }
@@ -868,12 +925,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)
@@ -1007,11 +1059,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;
 }
 
@@ -1077,11 +1125,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)
@@ -2911,11 +2956,8 @@ static void write_sha1_file_prepare(const void *buf, unsigned long len,
 
 /*
  * Move the just written object into its final resting place.
- * NEEDSWORK: this should be renamed to finalize_temp_file() as
- * "moving" is only a part of what it does, when no patch between
- * master to pu changes the call sites of this function.
  */
-int move_temp_to_file(const char *tmpfile, const char *filename)
+int finalize_object_file(const char *tmpfile, const char *filename)
 {
        int ret = 0;
 
@@ -3088,7 +3130,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
                                tmp_file, strerror(errno));
        }
 
-       return move_temp_to_file(tmp_file, filename);
+       return finalize_object_file(tmp_file, filename);
 }
 
 static int freshen_loose_object(const unsigned char *sha1)