Merge branch 'gr/rebase-i-drop-warn' into maint
[gitweb.git] / sha1_file.c
index f2e993e0b8b998c91b945771a87a099d882448f5..d295a3225a1e083708812f99746773d0ec8fdff4 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)
@@ -2911,11 +2941,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 +3115,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)