Skip to content

Commit 2a1d97e

Browse files
authored
Merge pull request libgit2#5378 from libgit2/ethomson/checkout_pathspecs
Honor GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH for all checkout types
2 parents 02d27f6 + 63de212 commit 2a1d97e

File tree

2 files changed

+79
-9
lines changed

2 files changed

+79
-9
lines changed

src/checkout.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2544,6 +2544,17 @@ static int checkout_data_init(
25442544
#define CHECKOUT_INDEX_DONT_WRITE_MASK \
25452545
(GIT_CHECKOUT_DONT_UPDATE_INDEX | GIT_CHECKOUT_DONT_WRITE_INDEX)
25462546

2547+
GIT_INLINE(void) setup_pathspecs(
2548+
git_iterator_options *iter_opts,
2549+
const git_checkout_options *checkout_opts)
2550+
{
2551+
if (checkout_opts &&
2552+
(checkout_opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) {
2553+
iter_opts->pathlist.count = checkout_opts->paths.count;
2554+
iter_opts->pathlist.strings = checkout_opts->paths.strings;
2555+
}
2556+
}
2557+
25472558
int git_checkout_iterator(
25482559
git_iterator *target,
25492560
git_index *index,
@@ -2586,6 +2597,8 @@ int git_checkout_iterator(
25862597
workdir_opts.start = data.pfx;
25872598
workdir_opts.end = data.pfx;
25882599

2600+
setup_pathspecs(&workdir_opts, opts);
2601+
25892602
if ((error = git_iterator_reset_range(target, data.pfx, data.pfx)) < 0 ||
25902603
(error = git_iterator_for_workdir_ext(
25912604
&workdir, data.repo, data.opts.target_directory, index, NULL,
@@ -2596,10 +2609,8 @@ int git_checkout_iterator(
25962609
GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE;
25972610
baseline_opts.start = data.pfx;
25982611
baseline_opts.end = data.pfx;
2599-
if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) {
2600-
baseline_opts.pathlist.count = opts->paths.count;
2601-
baseline_opts.pathlist.strings = opts->paths.strings;
2602-
}
2612+
2613+
setup_pathspecs(&baseline_opts, opts);
26032614

26042615
if (data.opts.baseline_index) {
26052616
if ((error = git_iterator_for_index(
@@ -2689,6 +2700,7 @@ int git_checkout_index(
26892700
git_index *index,
26902701
const git_checkout_options *opts)
26912702
{
2703+
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
26922704
int error, owned = 0;
26932705
git_iterator *index_i;
26942706

@@ -2716,7 +2728,9 @@ int git_checkout_index(
27162728
return error;
27172729
GIT_REFCOUNT_INC(index);
27182730

2719-
if (!(error = git_iterator_for_index(&index_i, repo, index, NULL)))
2731+
setup_pathspecs(&iter_opts, opts);
2732+
2733+
if (!(error = git_iterator_for_index(&index_i, repo, index, &iter_opts)))
27202734
error = git_checkout_iterator(index_i, index, opts);
27212735

27222736
if (owned)
@@ -2773,10 +2787,7 @@ int git_checkout_tree(
27732787
if ((error = git_repository_index(&index, repo)) < 0)
27742788
return error;
27752789

2776-
if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) {
2777-
iter_opts.pathlist.count = opts->paths.count;
2778-
iter_opts.pathlist.strings = opts->paths.strings;
2779-
}
2790+
setup_pathspecs(&iter_opts, opts);
27802791

27812792
if (!(error = git_iterator_for_tree(&tree_i, tree, &iter_opts)))
27822793
error = git_checkout_iterator(tree_i, index, opts);

tests/checkout/index.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,65 @@ void test_checkout_index__can_remove_untracked_files(void)
8989
cl_assert_equal_i(false, git_path_isdir("./testrepo/dir"));
9090
}
9191

92+
void test_checkout_index__can_disable_pathspec_match(void)
93+
{
94+
static git_index *index;
95+
git_oid commit_id;
96+
git_checkout_options g_opts = GIT_CHECKOUT_OPTIONS_INIT;
97+
git_object *g_object;
98+
99+
char *files_to_checkout[] = { "test10.txt", "test11.txt"};
100+
size_t files_to_checkout_size = 2;
101+
102+
/* reset to beginning of history (i.e. just a README file) */
103+
g_opts.checkout_strategy =
104+
GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
105+
106+
cl_git_pass(git_revparse_single(&g_object, g_repo, "8496071c1b46c854b31185ea97743be6a8774479"));
107+
cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
108+
cl_git_pass(
109+
git_repository_set_head_detached(g_repo, git_object_id(g_object)));
110+
git_object_free(g_object);
111+
g_object = NULL;
112+
113+
cl_git_pass(git_repository_index(&index, g_repo));
114+
115+
/* We create 4 files and commit them */
116+
cl_git_mkfile("testrepo/test9.txt", "original\n");
117+
cl_git_mkfile("testrepo/test10.txt", "original\n");
118+
cl_git_mkfile("testrepo/test11.txt", "original\n");
119+
cl_git_mkfile("testrepo/test12.txt", "original\n");
120+
121+
cl_git_pass(git_index_add_bypath(index, "test9.txt"));
122+
cl_git_pass(git_index_add_bypath(index, "test10.txt"));
123+
cl_git_pass(git_index_add_bypath(index, "test11.txt"));
124+
cl_git_pass(git_index_add_bypath(index, "test12.txt"));
125+
cl_git_pass(git_index_write(index));
126+
127+
cl_repo_commit_from_index(&commit_id, g_repo, NULL, 0, "commit our test files");
128+
129+
/* We modify the content of all 4 of our files */
130+
cl_git_rewritefile("testrepo/test9.txt", "modified\n");
131+
cl_git_rewritefile("testrepo/test10.txt", "modified\n");
132+
cl_git_rewritefile("testrepo/test11.txt", "modified\n");
133+
cl_git_rewritefile("testrepo/test12.txt", "modified\n");
134+
135+
/* We checkout only test10.txt and test11.txt */
136+
g_opts.checkout_strategy =
137+
GIT_CHECKOUT_FORCE |
138+
GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH;
139+
g_opts.paths.strings = files_to_checkout;
140+
g_opts.paths.count = files_to_checkout_size;
141+
cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
142+
143+
/* The only files that have been reverted to their original content
144+
should be test10.txt and test11.txt */
145+
check_file_contents("testrepo/test9.txt", "modified\n");
146+
check_file_contents("testrepo/test10.txt", "original\n");
147+
check_file_contents("testrepo/test11.txt", "original\n");
148+
check_file_contents("testrepo/test12.txt", "modified\n");
149+
}
150+
92151
void test_checkout_index__honor_the_specified_pathspecs(void)
93152
{
94153
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;

0 commit comments

Comments
 (0)