Commit Diff


commit - a7c182ac81f43ee290d92ff16781ea0b908c33c3
commit + 1430b4e093e8dcc1a214e26991cd06d3992db829
blob - c7e43f24fcf6a959ee0878eb5068515bd4b4ffdd
blob + cd22378a777b353c7f39ca3b244c95414d187c8a
--- lib/worktree.c
+++ lib/worktree.c
@@ -714,7 +714,6 @@ merge_blob(struct got_worktree *worktree, struct got_f
 	FILE *f1 = NULL, *f2 = NULL;
 	char *blob1_path = NULL, *blob2_path = NULL;
 	char *merged_path = NULL, *base_path = NULL;
-	struct got_object_id id2;
 	char *id_str = NULL;
 	char *label1 = NULL;
 	int overlapcnt = 0, update_timestamps = 0;
@@ -753,16 +752,24 @@ merge_blob(struct got_worktree *worktree, struct got_f
 	}
 
 	err = got_opentemp_named(&blob2_path, &f2, base_path);
-	if (err)
-		goto done;
-
-	memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
-	err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
 	if (err)
 		goto done;
-	err = got_object_blob_dump_to_file(NULL, NULL, f2, blob2);
-	if (err)
-		goto done;
+	if (got_fileindex_entry_has_blob(ie)) {
+		struct got_object_id id2;
+		memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
+		err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
+		if (err)
+			goto done;
+		err = got_object_blob_dump_to_file(NULL, NULL, f2, blob2);
+		if (err)
+			goto done;
+	} else {
+		/*
+		 * If the file has no blob, this is an "add vs add" conflict,
+		 * and we simply use an empty ancestor file to make both files
+		 * appear in the merged result in their entirety.
+		 */
+	}
 
 	err = got_object_id_str(&id_str, worktree->base_commit_id);
 	if (err)
@@ -1081,14 +1088,16 @@ update_blob(struct got_worktree *worktree,
 	}
 
 	if (ie && status != GOT_STATUS_MISSING) {
-		if (memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
+		if (got_fileindex_entry_has_commit(ie) &&
+		    memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
 		    SHA1_DIGEST_LENGTH) == 0) {
 			(*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
 			    path);
 			goto done;
 		}
-		if (memcmp(ie->blob_sha1,
-		    te->id->sha1, SHA1_DIGEST_LENGTH) == 0)
+		if (got_fileindex_entry_has_blob(ie) &&
+		    memcmp(ie->blob_sha1, te->id->sha1,
+		    SHA1_DIGEST_LENGTH) == 0)
 			goto done;
 	}
 
@@ -1096,7 +1105,7 @@ update_blob(struct got_worktree *worktree,
 	if (err)
 		goto done;
 
-	if (status == GOT_STATUS_MODIFY)
+	if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD)
 		err = merge_blob(worktree, fileindex, ie, ondisk_path, path,
 		    te->mode, sb.st_mode, blob, repo, progress_cb,
 		    progress_arg);
blob - f9501623254c8d3ca0f2fc660ad0840dd9d06a5e
blob + 897edc348bc687fb78ec40cb8f22235edb39e7cb
--- regress/cmdline/update.sh
+++ regress/cmdline/update.sh
@@ -839,7 +839,56 @@ function test_update_restores_missing_file {
 	echo "alpha" > $testroot/content.expected
 
 	cat $testroot/wt/alpha > $testroot/content
+
+	cmp $testroot/content.expected $testroot/content
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/content.expected $testroot/content
+	fi
+	test_done "$testroot" "$ret"
+}
+
+function test_update_conflict_add_vs_add {
+	local testroot=`test_init update_conflict_add_vs_add`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "new" > $testroot/repo/gamma/new
+	(cd $testroot/repo && git add .)
+	git_commit $testroot/repo -m "adding a new file"
+
+	echo "also new" > $testroot/wt/gamma/new
+	(cd $testroot/wt && got add gamma/new >/dev/null)
+
+	(cd $testroot/wt && got update > $testroot/stdout)
 
+	echo "C  gamma/new" > $testroot/stdout.expected
+	echo -n "Updated to commit " >> $testroot/stdout.expected
+	git_show_head $testroot/repo >> $testroot/stdout.expected
+	echo >> $testroot/stdout.expected
+	cmp $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo -n "<<<<<<< commit " > $testroot/content.expected
+	git_show_head $testroot/repo >> $testroot/content.expected
+	echo >> $testroot/content.expected
+	echo "new" >> $testroot/content.expected
+	echo "=======" >> $testroot/content.expected
+	echo "also new" >> $testroot/content.expected
+	echo '>>>>>>> gamma/new' >> $testroot/content.expected
+
+	cat $testroot/wt/gamma/new > $testroot/content
+
 	cmp $testroot/content.expected $testroot/content
 	ret="$?"
 	if [ "$ret" != "0" ]; then
@@ -865,3 +914,4 @@ run_test test_update_merges_file_edits
 run_test test_update_keeps_xbit
 run_test test_update_clears_xbit
 run_test test_update_restores_missing_file
+run_test test_update_conflict_add_vs_add