Commit bb0bd71ab4f404509aefa3be923916e886c9d25d

Edward Thomson 2016-06-15T15:47:28

checkout: use empty baseline when no index When no index file exists and a baseline is not explicitly provided, use an empty baseline instead of trying to load `HEAD`.

diff --git a/src/checkout.c b/src/checkout.c
index b3e95df..f39c341 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -2430,8 +2430,13 @@ static int checkout_data_init(
 
 	if (!data->opts.baseline && !data->opts.baseline_index) {
 		data->opts_free_baseline = true;
+		error = 0;
 
-		error = checkout_lookup_head_tree(&data->opts.baseline, repo);
+		/* if we don't have an index, this is an initial checkout and
+		 * should be against an empty baseline
+		 */
+		if (data->index->on_disk)
+			error = checkout_lookup_head_tree(&data->opts.baseline, repo);
 
 		if (error == GIT_EUNBORNBRANCH) {
 			error = 0;
diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c
index 5680b86..7df4d7e 100644
--- a/tests/checkout/tree.c
+++ b/tests/checkout/tree.c
@@ -1416,3 +1416,66 @@ void test_checkout_tree__safe_proceeds_if_no_index(void)
 	git_object_free(obj);
 }
 
+static int checkout_conflict_count_cb(
+	git_checkout_notify_t why,
+	const char *path,
+	const git_diff_file *b,
+	const git_diff_file *t,
+	const git_diff_file *w,
+	void *payload)
+{
+	size_t *n = payload;
+
+	GIT_UNUSED(why);
+	GIT_UNUSED(path);
+	GIT_UNUSED(b);
+	GIT_UNUSED(t);
+	GIT_UNUSED(w);
+
+	(*n)++;
+
+	return 0;
+}
+
+/* A repo that has a HEAD (even a properly born HEAD that peels to
+ * a commit) but no index should be treated as if it's an empty baseline
+ */
+void test_checkout_tree__baseline_is_empty_when_no_index(void)
+{
+	git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
+	git_reference *head;
+	git_object *obj;
+	git_status_list *status;
+	size_t conflicts = 0;
+
+	assert_on_branch(g_repo, "master");
+	cl_git_pass(git_repository_head(&head, g_repo));
+	cl_git_pass(git_reference_peel(&obj, head, GIT_OBJ_COMMIT));
+
+	cl_git_pass(git_reset(g_repo, obj, GIT_RESET_HARD, NULL));
+
+	cl_must_pass(p_unlink("testrepo/.git/index"));
+
+	/* for a safe checkout, we should have checkout conflicts with
+	 * the existing untracked files.
+	 */
+	opts.checkout_strategy &= ~GIT_CHECKOUT_FORCE;
+	opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
+	opts.notify_cb = checkout_conflict_count_cb;
+	opts.notify_payload = &conflicts;
+
+	cl_git_fail_with(GIT_ECONFLICT, git_checkout_tree(g_repo, obj, &opts));
+	cl_assert_equal_i(4, conflicts);
+
+	/* but force should succeed and update the index */
+	opts.checkout_strategy |= GIT_CHECKOUT_FORCE;
+	cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+
+	cl_git_pass(git_status_list_new(&status, g_repo, NULL));
+	cl_assert_equal_i(0, git_status_list_entrycount(status));
+	git_status_list_free(status);
+
+	git_object_free(obj);
+	git_reference_free(head);
+}
+