From 5ce8412b1cf2324aeabbbbb1bd68ec8a05c3312a Mon Sep 17 00:00:00 2001 From: Andy Meneely Date: Fri, 31 Mar 2023 23:59:12 -0400 Subject: [PATCH 1/4] Add --filter to Git.clone for partial clones Signed-off-by: Andy Meneely --- lib/git/lib.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/git/lib.rb b/lib/git/lib.rb index 78e4fafb..40c23a94 100644 --- a/lib/git/lib.rb +++ b/lib/git/lib.rb @@ -84,6 +84,7 @@ def init(opts={}) # :bare:: no working directory # :branch:: name of branch to track (rather than 'master') # :depth:: the number of commits back to pull + # :filter:: specify partial clone # :origin:: name of remote (same as remote) # :path:: directory where the repo will be cloned # :remote:: name of remote (rather than 'origin') @@ -101,6 +102,7 @@ def clone(repository_url, directory, opts = {}) arr_opts << '--bare' if opts[:bare] arr_opts << '--branch' << opts[:branch] if opts[:branch] arr_opts << '--depth' << opts[:depth].to_i if opts[:depth] && opts[:depth].to_i > 0 + arr_opts << "--filter=#{opts[:filter]}" if opts[:filter] Array(opts[:config]).each { |c| arr_opts << '--config' << c } arr_opts << '--origin' << opts[:remote] || opts[:origin] if opts[:remote] || opts[:origin] arr_opts << '--recursive' if opts[:recursive] From 0007559b9b76c47fdfb0002f53f75d173c94d67c Mon Sep 17 00:00:00 2001 From: James Couball Date: Sat, 1 Apr 2023 13:14:35 -0700 Subject: [PATCH 2/4] Prefer separate args '--filter tree:0' instead of '--filter=tree:0' --- lib/git/lib.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/git/lib.rb b/lib/git/lib.rb index 40c23a94..27934aa3 100644 --- a/lib/git/lib.rb +++ b/lib/git/lib.rb @@ -102,7 +102,7 @@ def clone(repository_url, directory, opts = {}) arr_opts << '--bare' if opts[:bare] arr_opts << '--branch' << opts[:branch] if opts[:branch] arr_opts << '--depth' << opts[:depth].to_i if opts[:depth] && opts[:depth].to_i > 0 - arr_opts << "--filter=#{opts[:filter]}" if opts[:filter] + arr_opts << '--filter' << opts[:filter] if opts[:filter] Array(opts[:config]).each { |c| arr_opts << '--config' << c } arr_opts << '--origin' << opts[:remote] || opts[:origin] if opts[:remote] || opts[:origin] arr_opts << '--recursive' if opts[:recursive] From fa178a2d409b401b023d739c5971e725b039328d Mon Sep 17 00:00:00 2001 From: James Couball Date: Sat, 1 Apr 2023 13:15:21 -0700 Subject: [PATCH 3/4] Add a test for the --filter option of git clone --- tests/units/test_git_clone.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/units/test_git_clone.rb b/tests/units/test_git_clone.rb index 0ef25bf9..9f208b61 100644 --- a/tests/units/test_git_clone.rb +++ b/tests/units/test_git_clone.rb @@ -83,4 +83,29 @@ def test_git_clone_with_no_name assert_equal(expected_command_line, actual_command_line) end + test 'clone with a filter' do + repository_url = 'https://github.com/ruby-git/ruby-git.git' + destination = 'ruby-git' + + actual_command_line = nil + + in_temp_dir do |path| + git = Git.init('.') + + # Mock the Git::Lib#command method to capture the actual command line args + git.lib.define_singleton_method(:command) do |cmd, *opts, &block| + actual_command_line = [cmd, *opts.flatten] + end + + git.lib.clone(repository_url, destination, filter: 'tree:0') + end + + expected_command_line = [ + 'clone', + '--filter', 'tree:0', + '--', repository_url, destination + ] + + assert_equal(expected_command_line, actual_command_line) + end end From d85ec3eba6ef95c0acd34127a76b8d6d3cd2e006 Mon Sep 17 00:00:00 2001 From: James Couball Date: Sat, 1 Apr 2023 13:16:25 -0700 Subject: [PATCH 4/4] Document new --filter option in README.md and in the public interface Git.clone --- README.md | 3 +++ lib/git.rb | 3 +++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index ec97d4cd..7d3d61ef 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,9 @@ g.dir #=> /tmp/clone/ruby-git-clean g.config('user.name', 'Scott Chacon') g.config('user.email', 'email@email.com') +# Clone can take a filter to tell the serve to send a partial clone +g = Git.clone(git_url, name, :path => path, :filter => 'tree:0') + # Clone can take an optional logger logger = Logger.new g = Git.clone(git_url, NAME, :log => logger) diff --git a/lib/git.rb b/lib/git.rb index 1f81bbca..63e1f3b1 100644 --- a/lib/git.rb +++ b/lib/git.rb @@ -139,6 +139,9 @@ def self.bare(git_dir, options = {}) # @option options [Integer] :depth Create a shallow clone with a history # truncated to the specified number of commits. # + # @option options [String] :filter Request that the server send a partial + # clone according to the given filter + # # @option options [Logger] :log A logger to use for Git operations. Git # commands are logged at the `:info` level. Additional logging is done # at the `:debug` level.