Commit 395509ffcd5007d8fa9ecccdf2090c5ed24c00e6

Edward Thomson 2013-02-27T14:47:39

don't dereference at the end of the workdir iterator

diff --git a/src/checkout.c b/src/checkout.c
index 59cd218..eda3e0b 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -456,7 +456,7 @@ static int checkout_action(
 	while (1) {
 		if (!wd)
 			return checkout_action_no_wd(data, delta);
-
+		
 		cmp = strcomp(wd->path, delta->old_file.path);
 
 		/* 1. wd before delta ("a/a" before "a/b")
@@ -475,6 +475,8 @@ static int checkout_action(
 					/* case 2 - entry prefixed by workdir tree */
 					if (git_iterator_advance_into_directory(workdir, &wd) < 0)
 						goto fail;
+					
+					*wditem_ptr = wd;
 					continue;
 				}
 
@@ -608,7 +610,7 @@ static int checkout_get_actions(
 		if (act & CHECKOUT_ACTION__CONFLICT)
 			counts[CHECKOUT_ACTION__CONFLICT]++;
 	}
-
+	
 	error = checkout_remaining_wd_items(data, workdir, wditem, &pathspec);
 	if (error < 0)
 		goto fail;
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 821cbfe..348be51 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -444,3 +444,41 @@ void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERG
 
 	assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c");
 }
+
+void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
+{
+	git_index *index = NULL;
+	git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+	git_oid tree_id, commit_id;
+	git_tree *tree = NULL;
+	git_commit *commit = NULL;
+	
+	git_repository_index(&index, g_repo);
+	
+	opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+	
+	cl_git_pass(git_reference_name_to_id(&commit_id, g_repo, "refs/heads/master"));
+	cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id));
+	
+	cl_git_pass(git_checkout_tree(g_repo, (git_object *)commit, &opts));
+	cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
+	
+	
+	cl_git_pass(p_mkdir("./testrepo/this-is-dir", 0777));
+	cl_git_mkfile("./testrepo/this-is-dir/contained_file", "content\n");
+	
+	cl_git_pass(git_index_add_bypath(index, "this-is-dir/contained_file"));
+	git_index_write_tree(&tree_id, index);
+	cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id));
+	
+	cl_git_pass(p_unlink("./testrepo/this-is-dir/contained_file"));
+	
+	opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+	
+	opts.checkout_strategy = 1;
+	git_checkout_tree(g_repo, (git_object *)tree, &opts);
+	
+	git_tree_free(tree);
+	git_commit_free(commit);
+	git_index_free(index);
+}