summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2013-01-10 15:18:49 -0800
committerVicent Martí <vicent@github.com>2013-01-10 15:18:49 -0800
commit3a5e8faee7f4e5ede2f938d8975261cc84e27383 (patch)
treee27a4fea5b34bae98b558526297232c58eebd0e4
parent404880b1bac746f15ca73bb57a5c034df6c6b630 (diff)
parent40342bd2b654bed4a49fe84de36e19ba0fefb8b6 (diff)
downloadlibgit2-3a5e8faee7f4e5ede2f938d8975261cc84e27383.tar.gz
Merge pull request #1221 from arrbee/checkout-without-pathspec-match
Add GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH
-rw-r--r--include/git2/checkout.h6
-rw-r--r--src/checkout.c6
-rw-r--r--tests-clar/checkout/tree.c83
3 files changed, 93 insertions, 2 deletions
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index dfc7e0580..d3e971b43 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -131,6 +131,9 @@ typedef enum {
/** Don't refresh index/config/etc before doing checkout */
GIT_CHECKOUT_NO_REFRESH = (1u << 9),
+ /** Treat pathspec as simple list of exact match file paths */
+ GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = (1u << 13),
+
/**
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
*/
@@ -222,7 +225,8 @@ typedef struct git_checkout_opts {
void *progress_payload;
/** When not zeroed out, array of fnmatch patterns specifying which
- * paths should be taken into account, otherwise all files.
+ * paths should be taken into account, otherwise all files. Use
+ * GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH to treat as simple list.
*/
git_strarray paths;
diff --git a/src/checkout.c b/src/checkout.c
index da22df680..4d6f99463 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -222,7 +222,9 @@ static int checkout_action_wd_only(
git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE;
if (!git_pathspec_match_path(
- pathspec, wd->path, false, workdir->ignore_case))
+ pathspec, wd->path,
+ (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0,
+ workdir->ignore_case))
return 0;
/* check if item is tracked in the index but not in the checkout diff */
@@ -1209,6 +1211,8 @@ int git_checkout_iterator(
GIT_DIFF_INCLUDE_TYPECHANGE |
GIT_DIFF_INCLUDE_TYPECHANGE_TREES |
GIT_DIFF_SKIP_BINARY_CHECK;
+ if (data.opts.checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)
+ diff_opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
if (data.opts.paths.count > 0)
diff_opts.pathspec = data.opts.paths;
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 30887588f..013c79b57 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -273,3 +273,86 @@ void test_checkout_tree__can_update_only(void)
git_object_free(obj);
}
+
+void test_checkout_tree__can_checkout_with_pattern(void)
+{
+ char *entries[] = { "[l-z]*.txt" };
+
+ /* reset to beginning of history (i.e. just a README file) */
+
+ g_opts.checkout_strategy =
+ GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+
+ cl_git_pass(git_revparse_single(&g_object, g_repo,
+ "8496071c1b46c854b31185ea97743be6a8774479"));
+
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+ cl_git_pass(
+ git_repository_set_head_detached(g_repo, git_object_id(g_object)));
+
+ git_object_free(g_object);
+ g_object = NULL;
+
+ cl_assert(git_path_exists("testrepo/README"));
+ cl_assert(!git_path_exists("testrepo/branch_file.txt"));
+ cl_assert(!git_path_exists("testrepo/link_to_new.txt"));
+ cl_assert(!git_path_exists("testrepo/new.txt"));
+
+ /* now to a narrow patterned checkout */
+
+ g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ g_opts.paths.strings = entries;
+ g_opts.paths.count = 1;
+
+ cl_git_pass(git_revparse_single(&g_object, g_repo, "refs/heads/master"));
+
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+ cl_assert(git_path_exists("testrepo/README"));
+ cl_assert(!git_path_exists("testrepo/branch_file.txt"));
+ cl_assert(git_path_exists("testrepo/link_to_new.txt"));
+ cl_assert(git_path_exists("testrepo/new.txt"));
+}
+
+void test_checkout_tree__can_disable_pattern_match(void)
+{
+ char *entries[] = { "b*.txt" };
+
+ /* reset to beginning of history (i.e. just a README file) */
+
+ g_opts.checkout_strategy =
+ GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+
+ cl_git_pass(git_revparse_single(&g_object, g_repo,
+ "8496071c1b46c854b31185ea97743be6a8774479"));
+
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+ cl_git_pass(
+ git_repository_set_head_detached(g_repo, git_object_id(g_object)));
+
+ git_object_free(g_object);
+ g_object = NULL;
+
+ cl_assert(!git_path_isfile("testrepo/branch_file.txt"));
+
+ /* now to a narrow patterned checkout, but disable pattern */
+
+ g_opts.checkout_strategy =
+ GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH;
+ g_opts.paths.strings = entries;
+ g_opts.paths.count = 1;
+
+ cl_git_pass(git_revparse_single(&g_object, g_repo, "refs/heads/master"));
+
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+ cl_assert(!git_path_isfile("testrepo/branch_file.txt"));
+
+ /* let's try that again, but allow the pattern match */
+
+ g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+ cl_assert(git_path_isfile("testrepo/branch_file.txt"));
+}