diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2020-05-11 00:09:18 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-11 00:09:18 +0100 |
commit | 2a1d97e6e7ca0fee3fcc5e86e8bf61ab2f182d64 (patch) | |
tree | 58b4c52c547edd66ca84b0b400f1ab11f69c7e4b | |
parent | 02d27f61737b2f77967e6f5beeb3a2ace629d9c4 (diff) | |
parent | 63de21283f1c8d4ca415d19088fbdb46076e54d6 (diff) | |
download | libgit2-2a1d97e6e7ca0fee3fcc5e86e8bf61ab2f182d64.tar.gz |
Merge pull request #5378 from libgit2/ethomson/checkout_pathspecs
Honor GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH for all checkout types
-rw-r--r-- | src/checkout.c | 29 | ||||
-rw-r--r-- | tests/checkout/index.c | 59 |
2 files changed, 79 insertions, 9 deletions
diff --git a/src/checkout.c b/src/checkout.c index 5cfa7280b..f0dd736dc 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2544,6 +2544,17 @@ cleanup: #define CHECKOUT_INDEX_DONT_WRITE_MASK \ (GIT_CHECKOUT_DONT_UPDATE_INDEX | GIT_CHECKOUT_DONT_WRITE_INDEX) +GIT_INLINE(void) setup_pathspecs( + git_iterator_options *iter_opts, + const git_checkout_options *checkout_opts) +{ + if (checkout_opts && + (checkout_opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { + iter_opts->pathlist.count = checkout_opts->paths.count; + iter_opts->pathlist.strings = checkout_opts->paths.strings; + } +} + int git_checkout_iterator( git_iterator *target, git_index *index, @@ -2586,6 +2597,8 @@ int git_checkout_iterator( workdir_opts.start = data.pfx; workdir_opts.end = data.pfx; + setup_pathspecs(&workdir_opts, opts); + if ((error = git_iterator_reset_range(target, data.pfx, data.pfx)) < 0 || (error = git_iterator_for_workdir_ext( &workdir, data.repo, data.opts.target_directory, index, NULL, @@ -2596,10 +2609,8 @@ int git_checkout_iterator( GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE; baseline_opts.start = data.pfx; baseline_opts.end = data.pfx; - if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { - baseline_opts.pathlist.count = opts->paths.count; - baseline_opts.pathlist.strings = opts->paths.strings; - } + + setup_pathspecs(&baseline_opts, opts); if (data.opts.baseline_index) { if ((error = git_iterator_for_index( @@ -2689,6 +2700,7 @@ int git_checkout_index( git_index *index, const git_checkout_options *opts) { + git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT; int error, owned = 0; git_iterator *index_i; @@ -2716,7 +2728,9 @@ int git_checkout_index( return error; GIT_REFCOUNT_INC(index); - if (!(error = git_iterator_for_index(&index_i, repo, index, NULL))) + setup_pathspecs(&iter_opts, opts); + + if (!(error = git_iterator_for_index(&index_i, repo, index, &iter_opts))) error = git_checkout_iterator(index_i, index, opts); if (owned) @@ -2773,10 +2787,7 @@ int git_checkout_tree( if ((error = git_repository_index(&index, repo)) < 0) return error; - if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { - iter_opts.pathlist.count = opts->paths.count; - iter_opts.pathlist.strings = opts->paths.strings; - } + setup_pathspecs(&iter_opts, opts); if (!(error = git_iterator_for_tree(&tree_i, tree, &iter_opts))) error = git_checkout_iterator(tree_i, index, opts); diff --git a/tests/checkout/index.c b/tests/checkout/index.c index a76c471e8..813467324 100644 --- a/tests/checkout/index.c +++ b/tests/checkout/index.c @@ -89,6 +89,65 @@ void test_checkout_index__can_remove_untracked_files(void) cl_assert_equal_i(false, git_path_isdir("./testrepo/dir")); } +void test_checkout_index__can_disable_pathspec_match(void) +{ + static git_index *index; + git_oid commit_id; + git_checkout_options g_opts = GIT_CHECKOUT_OPTIONS_INIT; + git_object *g_object; + + char *files_to_checkout[] = { "test10.txt", "test11.txt"}; + size_t files_to_checkout_size = 2; + + /* 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_git_pass(git_repository_index(&index, g_repo)); + + /* We create 4 files and commit them */ + cl_git_mkfile("testrepo/test9.txt", "original\n"); + cl_git_mkfile("testrepo/test10.txt", "original\n"); + cl_git_mkfile("testrepo/test11.txt", "original\n"); + cl_git_mkfile("testrepo/test12.txt", "original\n"); + + cl_git_pass(git_index_add_bypath(index, "test9.txt")); + cl_git_pass(git_index_add_bypath(index, "test10.txt")); + cl_git_pass(git_index_add_bypath(index, "test11.txt")); + cl_git_pass(git_index_add_bypath(index, "test12.txt")); + cl_git_pass(git_index_write(index)); + + cl_repo_commit_from_index(&commit_id, g_repo, NULL, 0, "commit our test files"); + + /* We modify the content of all 4 of our files */ + cl_git_rewritefile("testrepo/test9.txt", "modified\n"); + cl_git_rewritefile("testrepo/test10.txt", "modified\n"); + cl_git_rewritefile("testrepo/test11.txt", "modified\n"); + cl_git_rewritefile("testrepo/test12.txt", "modified\n"); + + /* We checkout only test10.txt and test11.txt */ + g_opts.checkout_strategy = + GIT_CHECKOUT_FORCE | + GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH; + g_opts.paths.strings = files_to_checkout; + g_opts.paths.count = files_to_checkout_size; + cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts)); + + /* The only files that have been reverted to their original content + should be test10.txt and test11.txt */ + check_file_contents("testrepo/test9.txt", "modified\n"); + check_file_contents("testrepo/test10.txt", "original\n"); + check_file_contents("testrepo/test11.txt", "original\n"); + check_file_contents("testrepo/test12.txt", "modified\n"); +} + void test_checkout_index__honor_the_specified_pathspecs(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; |