Commit 3f4437e714874ed10ce20fb32ca2dad3ca6f80ee

Vicent Martí 2013-01-11T10:59:31

Merge pull request #1227 from nulltoken/topic/emergeconflict Introduce EMERGECONFLICT

diff --git a/include/git2/errors.h b/include/git2/errors.h
index 9e0a1a9..917f069 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -31,6 +31,7 @@ enum {
 	GIT_EUNMERGED = -10,
 	GIT_ENONFASTFORWARD = -11,
 	GIT_EINVALIDSPEC = -12,
+	GIT_EMERGECONFLICT = -13,
 
 	GIT_PASSTHROUGH = -30,
 	GIT_ITEROVER = -31,
diff --git a/src/checkout.c b/src/checkout.c
index 4d6f994..cca66c3 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -616,7 +616,7 @@ static int checkout_get_actions(
 	{
 		giterr_set(GITERR_CHECKOUT, "%d conflicts prevent checkout",
 			(int)counts[CHECKOUT_ACTION__CONFLICT]);
-		error = -1;
+		error = GIT_EMERGECONFLICT;
 		goto fail;
 	}
 
diff --git a/src/indexer.c b/src/indexer.c
index 70b2ce0..603c206 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -273,7 +273,7 @@ static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start,
 		if (ptr == NULL)
 			return -1;
 
-		len = min(left, (size_t)size);
+		len = min(left, (unsigned int)size);
 		crc = crc32(crc, ptr, len);
 		size -= len;
 		start += len;
diff --git a/src/pack.c b/src/pack.c
index 6084508..3490c8b 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -621,7 +621,7 @@ ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t 
 		return GIT_EBUFS;
 
 	obj->zstream.next_out = buffer;
-	obj->zstream.avail_out = len;
+	obj->zstream.avail_out = (unsigned int)len;
 	obj->zstream.next_in = in;
 
 	st = inflate(&obj->zstream, Z_SYNC_FLUSH);
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index 1a471b7..808f6af 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -298,7 +298,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
 		return -1;
 
 	if (!WinHttpWriteData(request,
-		git_buf_cstr(&buf),	git_buf_len(&buf),
+		git_buf_cstr(&buf),	(DWORD)git_buf_len(&buf),
 		&bytes_written)) {
 		git_buf_free(&buf);
 		giterr_set(GITERR_OS, "Failed to write chunk header");
@@ -309,7 +309,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len)
 
 	/* Chunk body */
 	if (!WinHttpWriteData(request,
-		buffer, len,
+		buffer, (DWORD)len,
 		&bytes_written)) {
 		giterr_set(GITERR_OS, "Failed to write chunk");
 		return -1;
@@ -494,7 +494,7 @@ replay:
 
 	if (!WinHttpReadData(s->request,
 		(LPVOID)buffer,
-		buf_size,
+		(DWORD)buf_size,
 		&dw_bytes_read))
 	{
 		giterr_set(GITERR_OS, "Failed to read data");
@@ -580,7 +580,7 @@ static int put_uuid_string(LPWSTR buffer, DWORD buffer_len_cch)
 
 static int get_temp_file(LPWSTR buffer, DWORD buffer_len_cch)
 {
-	int len;
+	size_t len;
 
 	if (!GetTempPathW(buffer_len_cch, buffer)) {
 		giterr_set(GITERR_OS, "Failed to get temp path");
@@ -639,7 +639,7 @@ static int winhttp_stream_write_buffered(
 		}
 	}
 
-	if (!WriteFile(s->post_body, buffer, len, &bytes_written, NULL)) {
+	if (!WriteFile(s->post_body, buffer, (DWORD)len, &bytes_written, NULL)) {
 		giterr_set(GITERR_OS, "Failed to write to temporary file");
 		return -1;
 	}
@@ -697,7 +697,7 @@ static int winhttp_stream_write_chunked(
 	}
 	else {
 		/* Append as much to the buffer as we can */
-		int count = min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, len);
+		int count = min(CACHED_POST_BODY_BUF_SIZE - s->chunk_buffer_len, (int)len);
 
 		if (!s->chunk_buffer)
 			s->chunk_buffer = git__malloc(CACHED_POST_BODY_BUF_SIZE);
@@ -717,7 +717,7 @@ static int winhttp_stream_write_chunked(
 			/* Is there any remaining data from the source? */
 			if (len > 0) {
 				memcpy(s->chunk_buffer, buffer, len);
-				s->chunk_buffer_len = len;
+				s->chunk_buffer_len = (unsigned int)len;
 			}
 		}
 	}
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 013c79b..80e26a1 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -122,26 +122,26 @@ void test_checkout_tree__calls_progress_callback(void)
 
 void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void)
 {
-  git_oid master_oid;
-  git_oid chomped_oid;
-  git_commit* p_master_commit;
-  git_commit* p_chomped_commit;
-  git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
-
-  git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
-  git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d");
-  cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
-  cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
-
-  /* GIT_CHECKOUT_NONE should not add any file to the working tree from the
-   * index as it is supposed to be a dry run.
-   */
-  opts.checkout_strategy = GIT_CHECKOUT_NONE;
-  git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
-  cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
-
-  git_commit_free(p_master_commit);
-  git_commit_free(p_chomped_commit);
+	git_oid master_oid;
+	git_oid chomped_oid;
+	git_commit* p_master_commit;
+	git_commit* p_chomped_commit;
+	git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+	git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+	git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d");
+	cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
+	cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
+
+	/* GIT_CHECKOUT_NONE should not add any file to the working tree from the
+	 * index as it is supposed to be a dry run.
+	 */
+	opts.checkout_strategy = GIT_CHECKOUT_NONE;
+	git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
+	cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
+
+	git_commit_free(p_master_commit);
+	git_commit_free(p_chomped_commit);
 }
 
 void test_checkout_tree__can_switch_branches(void)
@@ -356,3 +356,89 @@ void test_checkout_tree__can_disable_pattern_match(void)
 
 	cl_assert(git_path_isfile("testrepo/branch_file.txt"));
 }
+
+void assert_conflict(
+	const char *entry_path,
+	const char *new_content,
+	const char *parent_sha,
+	const char *commit_sha)
+{
+	git_index *index;
+	git_object *hack_tree;
+	git_reference *branch, *head;
+	git_buf file_path = GIT_BUF_INIT; 
+	git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+	cl_git_pass(git_repository_index(&index, g_repo));
+
+	/* Create a branch pointing at the parent */
+	cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha));
+	cl_git_pass(git_branch_create(&branch, g_repo,
+		"potential_conflict", (git_commit *)g_object, 0));
+
+	/* Make HEAD point to this branch */
+	cl_git_pass(git_reference_symbolic_create(
+		&head, g_repo, "HEAD", git_reference_name(branch), 1));
+
+	/* Checkout the parent */
+	opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+	cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+	/* Hack-ishy workaound to ensure *all* the index entries
+	 * match the content of the tree
+	 */
+	cl_git_pass(git_object_peel(&hack_tree, g_object, GIT_OBJ_TREE));
+	cl_git_pass(git_index_read_tree(index, (git_tree *)hack_tree));
+	git_object_free(hack_tree);
+	git_object_free(g_object);
+	g_object = NULL;
+
+	/* Create a conflicting file */
+	cl_git_pass(git_buf_joinpath(&file_path, "./testrepo", entry_path));
+	cl_git_mkfile(git_buf_cstr(&file_path), new_content);
+	git_buf_free(&file_path);
+
+	/* Trying to checkout the original commit */
+	cl_git_pass(git_revparse_single(&g_object, g_repo, commit_sha));
+
+	opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+	cl_assert_equal_i(
+		GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts));
+
+	/* Stage the conflicting change */
+	cl_git_pass(git_index_add_from_workdir(index, entry_path));
+	cl_git_pass(git_index_write(index));
+
+	cl_assert_equal_i(
+		GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts));
+}
+
+void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT(void)
+{
+	/*
+	 * 099faba adds a symlink named 'link_to_new.txt'
+	 * a65fedf is the parent of 099faba
+	 */
+
+	assert_conflict("link_to_new.txt", "old.txt", "a65fedf", "099faba");
+}
+
+void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT_2(void)
+{
+	/*
+	 * cf80f8d adds a directory named 'a/'
+	 * a4a7dce is the parent of cf80f8d
+	 */
+
+	assert_conflict("a", "hello\n", "a4a7dce", "cf80f8d");
+}
+
+void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERGECONFLICT(void)
+{
+	/*
+	 * c47800c adds a symlink named 'branch_file.txt'
+	 * 5b5b025 is the parent of 763d71a
+	 */
+
+	assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c");
+}
diff --git a/tests-clar/clar/fs.h b/tests-clar/clar/fs.h
index 1cdc1ce..b7a1ff9 100644
--- a/tests-clar/clar/fs.h
+++ b/tests-clar/clar/fs.h
@@ -46,7 +46,7 @@ fs_rmdir_helper(WCHAR *_wsource)
 	WCHAR buffer[MAX_PATH];
 	HANDLE find_handle;
 	WIN32_FIND_DATAW find_data;
-	int buffer_prefix_len;
+	size_t buffer_prefix_len;
 
 	/* Set up the buffer and capture the length */
 	wcscpy_s(buffer, MAX_PATH, _wsource);
@@ -153,7 +153,7 @@ fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
 	WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH];
 	HANDLE find_handle;
 	WIN32_FIND_DATAW find_data;
-	int buf_source_prefix_len, buf_dest_prefix_len;
+	size_t buf_source_prefix_len, buf_dest_prefix_len;
 
 	wcscpy_s(buf_source, MAX_PATH, _wsource);
 	wcscat_s(buf_source, MAX_PATH, L"\\");
diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c
index 9d22b73..f241abf 100644
--- a/tests-clar/clone/nonetwork.c
+++ b/tests-clar/clone/nonetwork.c
@@ -143,7 +143,7 @@ void test_clone_nonetwork__custom_autotag(void)
 	cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options));
 
 	cl_git_pass(git_tag_list(&tags, g_repo));
-	cl_assert_equal_i(0, tags.count);
+	cl_assert_equal_sz(0, tags.count);
 
 	git_strarray_free(&tags);
 }
diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c
index 293a585..e2617ab 100644
--- a/tests-clar/revwalk/mergebase.c
+++ b/tests-clar/revwalk/mergebase.c
@@ -33,12 +33,12 @@ void test_revwalk_mergebase__single1(void)
 	cl_assert(git_oid_cmp(&result, &expected) == 0);
 
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two));
-	cl_assert_equal_i(ahead, 2);
-	cl_assert_equal_i(behind, 1);
+	cl_assert_equal_sz(ahead, 2);
+	cl_assert_equal_sz(behind, 1);
 
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one));
-	cl_assert_equal_i(ahead,  1);
-	cl_assert_equal_i(behind,  2);
+	cl_assert_equal_sz(ahead,  1);
+	cl_assert_equal_sz(behind,  2);
 }
 
 void test_revwalk_mergebase__single2(void)
@@ -54,12 +54,12 @@ void test_revwalk_mergebase__single2(void)
 	cl_assert(git_oid_cmp(&result, &expected) == 0);
 
 	cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two));
-	cl_assert_equal_i(ahead,  4);
-	cl_assert_equal_i(behind,  1);
+	cl_assert_equal_sz(ahead,  4);
+	cl_assert_equal_sz(behind,  1);
 
 	cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &two, &one));
-	cl_assert_equal_i(ahead,  1);
-	cl_assert_equal_i(behind,  4);
+	cl_assert_equal_sz(ahead,  1);
+	cl_assert_equal_sz(behind,  4);
 }
 
 void test_revwalk_mergebase__merged_branch(void)
@@ -78,12 +78,12 @@ void test_revwalk_mergebase__merged_branch(void)
 	cl_assert(git_oid_cmp(&result, &expected) == 0);
 
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two));
-	cl_assert_equal_i(ahead,  0);
-	cl_assert_equal_i(behind,  3);
+	cl_assert_equal_sz(ahead,  0);
+	cl_assert_equal_sz(behind,  3);
 
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one));
-	cl_assert_equal_i(ahead,  3);
-	cl_assert_equal_i(behind,  0);
+	cl_assert_equal_sz(ahead,  3);
+	cl_assert_equal_sz(behind,  0);
 }
 
 void test_revwalk_mergebase__two_way_merge(void)
@@ -95,13 +95,13 @@ void test_revwalk_mergebase__two_way_merge(void)
 	cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417"));
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &one, &two));
 
-	cl_assert_equal_i(ahead,  2);
-	cl_assert_equal_i(behind,  8);
+	cl_assert_equal_sz(ahead,  2);
+	cl_assert_equal_sz(behind,  8);
 
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &two, &one));
 
-	cl_assert_equal_i(ahead,  8);
-	cl_assert_equal_i(behind,  2);
+	cl_assert_equal_sz(ahead,  8);
+	cl_assert_equal_sz(behind,  2);
 }
 
 void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void)
@@ -119,8 +119,8 @@ void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void)
 	cl_assert_equal_i(GIT_ENOTFOUND, error);
 
 	cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two));
-	cl_assert_equal_i(2, ahead);
-	cl_assert_equal_i(4, behind);
+	cl_assert_equal_sz(2, ahead);
+	cl_assert_equal_sz(4, behind);
 }
 
 void test_revwalk_mergebase__no_off_by_one_missing(void)