summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorLibravatar Josh Steadmon <steadmon@google.com>2022-02-04 21:00:49 -0800
committerLibravatar Junio C Hamano <gitster@pobox.com>2022-02-09 15:38:36 -0800
commitf05da2b48b48a46db65fc768b3ffecaf996dd655 (patch)
tree11b0ef5fdb0e46d0cf82ca8be204775501dc9434 /t
parentMerge branch 'js/branch-track-inherit' (diff)
downloadtgif-f05da2b48b48a46db65fc768b3ffecaf996dd655.tar.xz
clone, submodule: pass partial clone filters to submodules
When cloning a repo with a --filter and with --recurse-submodules enabled, the partial clone filter only applies to the top-level repo. This can lead to unexpected bandwidth and disk usage for projects which include large submodules. For example, a user might wish to make a partial clone of Gerrit and would run: `git clone --recurse-submodules --filter=blob:5k https://gerrit.googlesource.com/gerrit`. However, only the superproject would be a partial clone; all the submodules would have all blobs downloaded regardless of their size. With this change, the same filter can also be applied to submodules, meaning the expected bandwidth and disk savings apply consistently. To avoid changing default behavior, add a new clone flag, `--also-filter-submodules`. When this is set along with `--filter` and `--recurse-submodules`, the filter spec is passed along to git-submodule and git-submodule--helper, such that submodule clones also have the filter applied. This applies the same filter to the superproject and all submodules. Users who need to customize the filter per-submodule would need to clone with `--no-recurse-submodules` and then manually initialize each submodule with the proper filter. Applying filters to submodules should be safe thanks to Jonathan Tan's recent work [1, 2, 3] eliminating the use of alternates as a method of accessing submodule objects, so any submodule object access now triggers a lazy fetch from the submodule's promisor remote if the accessed object is missing. This patch is a reworked version of [4], which was created prior to Jonathan Tan's work. [1]: 8721e2e (Merge branch 'jt/partial-clone-submodule-1', 2021-07-16) [2]: 11e5d0a (Merge branch 'jt/grep-wo-submodule-odb-as-alternate', 2021-09-20) [3]: 162a13b (Merge branch 'jt/no-abuse-alternate-odb-for-submodules', 2021-10-25) [4]: https://lore.kernel.org/git/52bf9d45b8e2b72ff32aa773f2415bf7b2b86da2.1563322192.git.steadmon@google.com/ Signed-off-by: Josh Steadmon <steadmon@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't')
-rwxr-xr-xt/t5617-clone-submodules-remote.sh41
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh41
2 files changed, 82 insertions, 0 deletions
diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh
index e2dbb4eaba..ca8f80083a 100755
--- a/t/t5617-clone-submodules-remote.sh
+++ b/t/t5617-clone-submodules-remote.sh
@@ -28,6 +28,13 @@ test_expect_success 'setup' '
)
'
+# bare clone giving "srv.bare" for use as our server.
+test_expect_success 'setup bare clone for server' '
+ git clone --bare "file://$(pwd)/." srv.bare &&
+ git -C srv.bare config --local uploadpack.allowfilter 1 &&
+ git -C srv.bare config --local uploadpack.allowanysha1inwant 1
+'
+
test_expect_success 'clone with --no-remote-submodules' '
test_when_finished "rm -rf super_clone" &&
git clone --recurse-submodules --no-remote-submodules "file://$pwd/." super_clone &&
@@ -65,4 +72,38 @@ test_expect_success 'clone with --single-branch' '
)
'
+# do basic partial clone from "srv.bare"
+# confirm partial clone was registered in the local config for super and sub.
+test_expect_success 'clone with --filter' '
+ git clone --recurse-submodules \
+ --filter blob:none --also-filter-submodules \
+ "file://$pwd/srv.bare" super_clone &&
+ test_cmp_config -C super_clone true remote.origin.promisor &&
+ test_cmp_config -C super_clone blob:none remote.origin.partialclonefilter &&
+ test_cmp_config -C super_clone/sub true remote.origin.promisor &&
+ test_cmp_config -C super_clone/sub blob:none remote.origin.partialclonefilter
+'
+
+# check that clone.filterSubmodules works (--also-filter-submodules can be
+# omitted)
+test_expect_success 'filters applied with clone.filterSubmodules' '
+ test_config_global clone.filterSubmodules true &&
+ git clone --recurse-submodules --filter blob:none \
+ "file://$pwd/srv.bare" super_clone2 &&
+ test_cmp_config -C super_clone2 true remote.origin.promisor &&
+ test_cmp_config -C super_clone2 blob:none remote.origin.partialclonefilter &&
+ test_cmp_config -C super_clone2/sub true remote.origin.promisor &&
+ test_cmp_config -C super_clone2/sub blob:none remote.origin.partialclonefilter
+'
+
+test_expect_success '--no-also-filter-submodules overrides clone.filterSubmodules=true' '
+ test_config_global clone.filterSubmodules true &&
+ git clone --recurse-submodules --filter blob:none \
+ --no-also-filter-submodules \
+ "file://$pwd/srv.bare" super_clone3 &&
+ test_cmp_config -C super_clone3 true remote.origin.promisor &&
+ test_cmp_config -C super_clone3 blob:none remote.origin.partialclonefilter &&
+ test_cmp_config -C super_clone3/sub false --default false remote.origin.promisor
+'
+
test_done
diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh
index 058e5d0c96..a4476dc492 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -544,4 +544,45 @@ test_expect_failure 'grep saves textconv cache in the appropriate repository' '
test_path_is_file "$sub_textconv_cache"
'
+test_expect_success 'grep partially-cloned submodule' '
+ # Set up clean superproject and submodule for partial cloning.
+ git init super &&
+ git init super/sub &&
+ (
+ cd super &&
+ test_commit --no-tag "Add file in superproject" \
+ super-file "Some content for super-file" &&
+ test_commit -C sub --no-tag "Add file in submodule" \
+ sub-file "Some content for sub-file" &&
+ git submodule add ./sub &&
+ git commit -m "Add other as submodule sub" &&
+ test_tick &&
+ test_commit -C sub --no-tag --append "Update file in submodule" \
+ sub-file "Some more content for sub-file" &&
+ git add sub &&
+ git commit -m "Update submodule" &&
+ test_tick &&
+ git config --local uploadpack.allowfilter 1 &&
+ git config --local uploadpack.allowanysha1inwant 1 &&
+ git -C sub config --local uploadpack.allowfilter 1 &&
+ git -C sub config --local uploadpack.allowanysha1inwant 1
+ ) &&
+ # Clone the superproject & submodule, then make sure we can lazy-fetch submodule objects.
+ git clone --filter=blob:none --also-filter-submodules \
+ --recurse-submodules "file://$(pwd)/super" partial &&
+ (
+ cd partial &&
+ cat >expect <<-\EOF &&
+ HEAD^:sub/sub-file:Some content for sub-file
+ HEAD^:super-file:Some content for super-file
+ EOF
+
+ GIT_TRACE2_EVENT="$(pwd)/trace2.log" git grep -e content \
+ --recurse-submodules HEAD^ >actual &&
+ test_cmp expect actual &&
+ # Verify that we actually fetched data from the promisor remote:
+ grep \"category\":\"promisor\",\"key\":\"fetch_count\",\"value\":\"1\" trace2.log
+ )
+'
+
test_done