Check for an existing match before appending a path to the alternates file. Beyond making git look smart to anyone checking the alternates file, this removes the last use of hold_lock_file_for_append. Signed-off-by: Jim Hill <gjthill@xxxxxxxxx> --- sha1_file.c | 29 +++++++++++++++++++++++++---- t/t5700-clone-reference.sh | 4 ++-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index 47f56f2..43d9530 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -403,14 +403,35 @@ 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); + static struct lock_file lock = {0}; char *alt = mkpath("%s\n", reference); + char *alts = git_path("objects/info/alternates"); + int fd = hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR); + struct strbuf altdata = STRBUF_INIT; + struct string_list lines = STRING_LIST_INIT_NODUP; + + if (strbuf_read_file(&altdata, alts, 0) < 0) + if (errno != ENOENT) + die("alternates file unreadable"); + strbuf_complete_line(&altdata); + write_or_die(fd, altdata.buf, altdata.len); + + string_list_split_in_place(&lines, altdata.buf, '\n', -1); + lines.cmp = strcmp_icase; + if (unsorted_string_list_has_string(&lines, reference)) { + rollback_lock_file(&lock); + goto cleanup; + } + write_or_die(fd, alt, strlen(alt)); - if (commit_lock_file(lock)) - die("could not close alternates file"); + if (commit_lock_file(&lock)) + die("could not update alternates file"); if (alt_odb_tail) link_alt_odb_entries(alt, strlen(alt), '\n', NULL, 0); + +cleanup: + strbuf_reset(&altdata); + string_list_clear(&lines,0); } int foreach_alt_odb(alt_odb_fn fn, void *cb) diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh index 3e783fc..cd9fa34 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -29,11 +29,11 @@ git prune' cd "$base_dir" test_expect_success 'cloning with reference (-l -s)' \ -'git clone -l -s --reference B A C' +'git clone -l -s --reference B --reference A --reference B A C' cd "$base_dir" -test_expect_success 'existence of info/alternates' \ +test_expect_success 'existence of info/alternates, no duplicates' \ 'test_line_count = 2 C/.git/objects/info/alternates' cd "$base_dir" -- 2.4.1.4.gfc728c2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html