summaryrefslogtreecommitdiff
path: root/sha1_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'sha1_file.c')
-rw-r--r--sha1_file.c68
1 files changed, 49 insertions, 19 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 1cee438422..d295a3225a 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -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)
@@ -1461,7 +1491,10 @@ int git_open_noatime(const char *name)
static int sha1_file_open_flag = O_NOATIME;
for (;;) {
- int fd = open(name, O_RDONLY | sha1_file_open_flag);
+ int fd;
+
+ errno = 0;
+ fd = open(name, O_RDONLY | sha1_file_open_flag);
if (fd >= 0)
return fd;
@@ -2908,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;
@@ -3085,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)