summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2013-05-01 09:50:40 -0500
committerEdward Thomson <ethomson@edwardthomson.com>2013-05-01 09:50:40 -0500
commit0cc7d8df19c82a13fd9d7c48563f40580d366cd3 (patch)
treeae1e58d57f0ea80b025673147c67a5df76841c7e
parente1807113c43b7c5008e2d5c8c449ae56c8dceeb4 (diff)
downloadlibgit2-0cc7d8df19c82a13fd9d7c48563f40580d366cd3.tar.gz
allow empty dirs to exist when doing checkout
-rw-r--r--src/checkout.c8
-rw-r--r--tests-clar/checkout/tree.c25
2 files changed, 31 insertions, 2 deletions
diff --git a/src/checkout.c b/src/checkout.c
index defc21d2d..21f32d89a 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -467,6 +467,7 @@ static int checkout_action(
int cmp = -1, act;
int (*strcomp)(const char *, const char *) = data->diff->strcomp;
int (*pfxcomp)(const char *str, const char *pfx) = data->diff->pfxcomp;
+ int error;
/* move workdir iterator to follow along with deltas */
@@ -490,8 +491,11 @@ static int checkout_action(
if (cmp == 0) {
if (wd->mode == GIT_FILEMODE_TREE) {
/* case 2 - entry prefixed by workdir tree */
- if (git_iterator_advance_into(&wd, workdir) < 0)
- goto fail;
+ if ((error = git_iterator_advance_into(&wd, workdir)) < 0) {
+ if (error != GIT_ENOTFOUND ||
+ git_iterator_advance(&wd, workdir) < 0)
+ goto fail;
+ }
*wditem_ptr = wd;
continue;
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 0748b22e0..eb129f34e 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -501,3 +501,28 @@ void test_checkout_tree__issue_1397(void)
git_object_free(tree);
}
+
+void test_checkout_tree__can_write_to_empty_dirs(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_oid oid;
+ git_object *obj = NULL;
+
+ assert_on_branch(g_repo, "master");
+
+ cl_git_pass(p_mkdir("testrepo/a", 0777));
+
+ /* do first checkout with FORCE because we don't know if testrepo
+ * base data is clean for a checkout or not
+ */
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+
+ cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir"));
+ cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
+
+ cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+
+ cl_assert(git_path_isfile("testrepo/a/b.txt"));
+
+ git_object_free(obj);
+}