Merge pull request #14035 from hmarr/git-partial-clone-sparse-checkout
Support git partial clones with sparse checkouts (take 2)
This commit is contained in:
commit
b9411ef8a6
@ -51,7 +51,9 @@ module Cask
|
|||||||
target = target_hash[:target]
|
target = target_hash[:target]
|
||||||
@source_string = source.to_s
|
@source_string = source.to_s
|
||||||
@target_string = target.to_s
|
@target_string = target.to_s
|
||||||
source = cask.staged_path.join(source)
|
base_path = cask.staged_path
|
||||||
|
base_path = base_path.join(cask.url.only_path) if cask.url&.only_path.present?
|
||||||
|
source = base_path.join(source)
|
||||||
@source = source
|
@source = source
|
||||||
target ||= source.basename
|
target ||= source.basename
|
||||||
@target = resolve_target(target)
|
@target = resolve_target(target)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class URL < Delegator
|
|||||||
:verified, :using,
|
:verified, :using,
|
||||||
:tag, :branch, :revisions, :revision,
|
:tag, :branch, :revisions, :revision,
|
||||||
:trust_cert, :cookies, :referer, :header, :user_agent,
|
:trust_cert, :cookies, :referer, :header, :user_agent,
|
||||||
:data
|
:data, :only_path
|
||||||
|
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
def_delegators :uri, :path, :scheme, :to_s
|
def_delegators :uri, :path, :scheme, :to_s
|
||||||
@ -36,6 +36,7 @@ class URL < Delegator
|
|||||||
header: T.nilable(String),
|
header: T.nilable(String),
|
||||||
user_agent: T.nilable(T.any(Symbol, String)),
|
user_agent: T.nilable(T.any(Symbol, String)),
|
||||||
data: T.nilable(T::Hash[String, String]),
|
data: T.nilable(T::Hash[String, String]),
|
||||||
|
only_path: T.nilable(String),
|
||||||
).void
|
).void
|
||||||
}
|
}
|
||||||
def initialize(
|
def initialize(
|
||||||
@ -51,7 +52,8 @@ class URL < Delegator
|
|||||||
referer: nil,
|
referer: nil,
|
||||||
header: nil,
|
header: nil,
|
||||||
user_agent: nil,
|
user_agent: nil,
|
||||||
data: nil
|
data: nil,
|
||||||
|
only_path: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@uri = URI(uri)
|
@uri = URI(uri)
|
||||||
@ -69,6 +71,7 @@ class URL < Delegator
|
|||||||
specs[:header] = @header = header
|
specs[:header] = @header = header
|
||||||
specs[:user_agent] = @user_agent = user_agent || :default
|
specs[:user_agent] = @user_agent = user_agent || :default
|
||||||
specs[:data] = @data = data
|
specs[:data] = @data = data
|
||||||
|
specs[:only_path] = @only_path = only_path
|
||||||
|
|
||||||
@specs = specs.compact
|
@specs = specs.compact
|
||||||
end
|
end
|
||||||
@ -156,6 +159,7 @@ class URL < Delegator
|
|||||||
header: T.nilable(String),
|
header: T.nilable(String),
|
||||||
user_agent: T.nilable(T.any(Symbol, String)),
|
user_agent: T.nilable(T.any(Symbol, String)),
|
||||||
data: T.nilable(T::Hash[String, String]),
|
data: T.nilable(T::Hash[String, String]),
|
||||||
|
only_path: T.nilable(String),
|
||||||
caller_location: Thread::Backtrace::Location,
|
caller_location: Thread::Backtrace::Location,
|
||||||
dsl: T.nilable(Cask::DSL),
|
dsl: T.nilable(Cask::DSL),
|
||||||
block: T.nilable(T.proc.params(arg0: T.all(String, BlockDSL::PageWithURL)).returns(T.untyped)),
|
block: T.nilable(T.proc.params(arg0: T.all(String, BlockDSL::PageWithURL)).returns(T.untyped)),
|
||||||
@ -175,6 +179,7 @@ class URL < Delegator
|
|||||||
header: nil,
|
header: nil,
|
||||||
user_agent: nil,
|
user_agent: nil,
|
||||||
data: nil,
|
data: nil,
|
||||||
|
only_path: nil,
|
||||||
caller_location: T.must(caller_locations).fetch(0),
|
caller_location: T.must(caller_locations).fetch(0),
|
||||||
dsl: nil,
|
dsl: nil,
|
||||||
&block
|
&block
|
||||||
@ -202,6 +207,7 @@ class URL < Delegator
|
|||||||
header: header,
|
header: header,
|
||||||
user_agent: user_agent,
|
user_agent: user_agent,
|
||||||
data: data,
|
data: data,
|
||||||
|
only_path: only_path,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|||||||
@ -811,6 +811,10 @@ end
|
|||||||
# @api public
|
# @api public
|
||||||
class GitDownloadStrategy < VCSDownloadStrategy
|
class GitDownloadStrategy < VCSDownloadStrategy
|
||||||
def initialize(url, name, version, **meta)
|
def initialize(url, name, version, **meta)
|
||||||
|
# Needs to be before the call to `super`, as the VCSDownloadStrategy's
|
||||||
|
# constructor calls `cache_tag` and sets the cache path.
|
||||||
|
@only_path = meta[:only_path]
|
||||||
|
|
||||||
super
|
super
|
||||||
@ref_type ||= :branch
|
@ref_type ||= :branch
|
||||||
@ref ||= "master"
|
@ref ||= "master"
|
||||||
@ -836,8 +840,12 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def cache_tag
|
def cache_tag
|
||||||
|
if partial_clone_sparse_checkout?
|
||||||
|
"git-sparse"
|
||||||
|
else
|
||||||
"git"
|
"git"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(Integer) }
|
sig { returns(Integer) }
|
||||||
def cache_version
|
def cache_version
|
||||||
@ -880,6 +888,12 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
(cached_location/".gitmodules").exist?
|
(cached_location/".gitmodules").exist?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def partial_clone_sparse_checkout?
|
||||||
|
return false if @only_path.blank?
|
||||||
|
|
||||||
|
Utils::Git.supports_partial_clone_sparse_checkout?
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def clone_args
|
def clone_args
|
||||||
args = %w[clone]
|
args = %w[clone]
|
||||||
@ -889,6 +903,8 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
args << "--branch" << @ref
|
args << "--branch" << @ref
|
||||||
end
|
end
|
||||||
|
|
||||||
|
args << "--no-checkout" << "--filter=blob:none" if partial_clone_sparse_checkout?
|
||||||
|
|
||||||
args << "-c" << "advice.detachedHead=false" # silences detached head warning
|
args << "-c" << "advice.detachedHead=false" # silences detached head warning
|
||||||
args << @url << cached_location
|
args << @url << cached_location
|
||||||
end
|
end
|
||||||
@ -922,6 +938,13 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
command! "git",
|
command! "git",
|
||||||
args: ["config", "advice.detachedHead", "false"],
|
args: ["config", "advice.detachedHead", "false"],
|
||||||
chdir: cached_location
|
chdir: cached_location
|
||||||
|
|
||||||
|
return unless partial_clone_sparse_checkout?
|
||||||
|
|
||||||
|
command! "git",
|
||||||
|
args: ["config", "origin.partialclonefilter", "blob:none"],
|
||||||
|
chdir: cached_location
|
||||||
|
configure_sparse_checkout
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(timeout: T.nilable(Time)).void }
|
sig { params(timeout: T.nilable(Time)).void }
|
||||||
@ -950,6 +973,9 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
args: ["config", "homebrew.cacheversion", cache_version],
|
args: ["config", "homebrew.cacheversion", cache_version],
|
||||||
chdir: cached_location,
|
chdir: cached_location,
|
||||||
timeout: timeout&.remaining
|
timeout: timeout&.remaining
|
||||||
|
|
||||||
|
configure_sparse_checkout if partial_clone_sparse_checkout?
|
||||||
|
|
||||||
checkout(timeout: timeout)
|
checkout(timeout: timeout)
|
||||||
update_submodules(timeout: timeout) if submodules?
|
update_submodules(timeout: timeout) if submodules?
|
||||||
end
|
end
|
||||||
@ -1020,6 +1046,14 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
|||||||
dot_git.atomic_write("gitdir: #{relative_git_dir}\n")
|
dot_git.atomic_write("gitdir: #{relative_git_dir}\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def configure_sparse_checkout
|
||||||
|
command! "git",
|
||||||
|
args: ["config", "core.sparseCheckout", "true"],
|
||||||
|
chdir: cached_location
|
||||||
|
|
||||||
|
(git_dir/"info"/"sparse-checkout").atomic_write("#{@only_path}\n")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Strategy for downloading a Git repository from GitHub.
|
# Strategy for downloading a Git repository from GitHub.
|
||||||
|
|||||||
@ -141,5 +141,11 @@ module Utils
|
|||||||
raise ErrorDuringExecution.new(cmd, status: $CHILD_STATUS, output: [[:stdout, output]])
|
raise ErrorDuringExecution.new(cmd, status: $CHILD_STATUS, output: [[:stdout, output]])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def supports_partial_clone_sparse_checkout?
|
||||||
|
# There is some support for partial clones prior to 2.20, but we avoid using it
|
||||||
|
# due to performance issues
|
||||||
|
Version.create(version) >= Version.create("2.20.0")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1138,6 +1138,18 @@ In rare cases, a distribution may not be available over ordinary HTTP/S. Subvers
|
|||||||
| `revision:` | a string identifying the subversion revision to download
|
| `revision:` | a string identifying the subversion revision to download
|
||||||
| `trust_cert:` | set to `true` to automatically trust the certificate presented by the server (avoiding an interactive prompt)
|
| `trust_cert:` | set to `true` to automatically trust the certificate presented by the server (avoiding an interactive prompt)
|
||||||
|
|
||||||
|
#### Git URLs
|
||||||
|
|
||||||
|
Artifacts also may be distributed via git repositories. URLs that end in `.git` are automatically assumed to be git repositories, and the following key/value pairs may be appended to `url`:
|
||||||
|
|
||||||
|
| key | value |
|
||||||
|
| ------------------ | ----------- |
|
||||||
|
| `using:` | the symbol `:git` is the only legal value
|
||||||
|
| `tag:` | a string identifying the git tag to download
|
||||||
|
| `revision:` | a string identifying the git revision to download
|
||||||
|
| `branch:` | a string identifying the git branch to download
|
||||||
|
| `only_path:` | a path within the repository to limit the checkout to. If only a single directory of a large repository is required, using this option can signficantly speed up downloads. If provided, artifact paths are relative to this path.
|
||||||
|
|
||||||
#### SourceForge/OSDN URLs
|
#### SourceForge/OSDN URLs
|
||||||
|
|
||||||
SourceForge and OSDN (formerly `SourceForge.JP`) projects are common ways to distribute binaries, but they provide many different styles of URLs to get to the goods.
|
SourceForge and OSDN (formerly `SourceForge.JP`) projects are common ways to distribute binaries, but they provide many different styles of URLs to get to the goods.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user