mirror of https://github.com/databricks/cli.git
Fall back to full Git clone if shallow clone is not supported (#775)
## Changes Git repos hosted over HTTP do not support shallow cloning. This PR adds retry logic if we detect shallow cloning is not supported. Note I saw the match string `dumb http transport does not support shallow capabilities` being reported in for different hosts on the internet, so this should work accross a large class of git servers. Howerver, it's not strictly necessary to have the `--depth` flag so we can remove it if this issue is reported again. ## Tests Tested manually. `bundle init` successfully downloads the private HTTP repo reported during by internal user.
This commit is contained in:
parent
327ab0e598
commit
2c58deb2c5
|
@ -25,31 +25,23 @@ type cloneOptions struct {
|
||||||
|
|
||||||
// Local path to clone repository at
|
// Local path to clone repository at
|
||||||
TargetPath string
|
TargetPath string
|
||||||
|
|
||||||
|
// If true, the repository is shallow cloned
|
||||||
|
Shallow bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts cloneOptions) args() []string {
|
func (opts cloneOptions) args() []string {
|
||||||
args := []string{"clone", opts.RepositoryUrl, opts.TargetPath, "--depth=1", "--no-tags"}
|
args := []string{"clone", opts.RepositoryUrl, opts.TargetPath, "--no-tags"}
|
||||||
if opts.Reference != "" {
|
if opts.Reference != "" {
|
||||||
args = append(args, "--branch", opts.Reference)
|
args = append(args, "--branch", opts.Reference)
|
||||||
}
|
}
|
||||||
|
if opts.Shallow {
|
||||||
|
args = append(args, "--depth=1")
|
||||||
|
}
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
func Clone(ctx context.Context, url, reference, targetPath string) error {
|
func (opts cloneOptions) clone(ctx context.Context) error {
|
||||||
// We assume only the repository name has been if input does not contain any
|
|
||||||
// `/` characters and the url is only made up of alphanumeric characters and
|
|
||||||
// ".", "_" and "-". This repository is resolved again databricks github account.
|
|
||||||
fullUrl := url
|
|
||||||
if githubRepoRegex.MatchString(url) {
|
|
||||||
fullUrl = strings.Join([]string{githubUrl, databricksOrg, url}, "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := cloneOptions{
|
|
||||||
Reference: reference,
|
|
||||||
RepositoryUrl: fullUrl,
|
|
||||||
TargetPath: targetPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, "git", opts.args()...)
|
cmd := exec.CommandContext(ctx, "git", opts.args()...)
|
||||||
var cmdErr bytes.Buffer
|
var cmdErr bytes.Buffer
|
||||||
cmd.Stderr = &cmdErr
|
cmd.Stderr = &cmdErr
|
||||||
|
@ -70,3 +62,29 @@ func Clone(ctx context.Context, url, reference, targetPath string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Clone(ctx context.Context, url, reference, targetPath string) error {
|
||||||
|
// We assume only the repository name has been if input does not contain any
|
||||||
|
// `/` characters and the url is only made up of alphanumeric characters and
|
||||||
|
// ".", "_" and "-". This repository is resolved again databricks github account.
|
||||||
|
fullUrl := url
|
||||||
|
if githubRepoRegex.MatchString(url) {
|
||||||
|
fullUrl = strings.Join([]string{githubUrl, databricksOrg, url}, "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := cloneOptions{
|
||||||
|
Reference: reference,
|
||||||
|
RepositoryUrl: fullUrl,
|
||||||
|
TargetPath: targetPath,
|
||||||
|
Shallow: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := opts.clone(ctx)
|
||||||
|
// Git repos hosted via HTTP do not support shallow cloning. We try with
|
||||||
|
// a deep clone this time
|
||||||
|
if err != nil && strings.Contains(err.Error(), "dumb http transport does not support shallow capabilities") {
|
||||||
|
opts.Shallow = false
|
||||||
|
return opts.clone(ctx)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -10,17 +10,27 @@ import (
|
||||||
|
|
||||||
func TestGitCloneArgs(t *testing.T) {
|
func TestGitCloneArgs(t *testing.T) {
|
||||||
// case: No branch / tag specified. In this case git clones the default branch
|
// case: No branch / tag specified. In this case git clones the default branch
|
||||||
assert.Equal(t, []string{"clone", "abc", "/def", "--depth=1", "--no-tags"}, cloneOptions{
|
assert.Equal(t, []string{"clone", "abc", "/def", "--no-tags", "--depth=1"}, cloneOptions{
|
||||||
Reference: "",
|
Reference: "",
|
||||||
RepositoryUrl: "abc",
|
RepositoryUrl: "abc",
|
||||||
TargetPath: "/def",
|
TargetPath: "/def",
|
||||||
|
Shallow: true,
|
||||||
}.args())
|
}.args())
|
||||||
|
|
||||||
// case: A branch is specified.
|
// case: A branch is specified.
|
||||||
assert.Equal(t, []string{"clone", "abc", "/def", "--depth=1", "--no-tags", "--branch", "my-branch"}, cloneOptions{
|
assert.Equal(t, []string{"clone", "abc", "/def", "--no-tags", "--branch", "my-branch", "--depth=1"}, cloneOptions{
|
||||||
Reference: "my-branch",
|
Reference: "my-branch",
|
||||||
RepositoryUrl: "abc",
|
RepositoryUrl: "abc",
|
||||||
TargetPath: "/def",
|
TargetPath: "/def",
|
||||||
|
Shallow: true,
|
||||||
|
}.args())
|
||||||
|
|
||||||
|
// case: deep cloning
|
||||||
|
assert.Equal(t, []string{"clone", "abc", "/def", "--no-tags"}, cloneOptions{
|
||||||
|
Reference: "",
|
||||||
|
RepositoryUrl: "abc",
|
||||||
|
TargetPath: "/def",
|
||||||
|
Shallow: false,
|
||||||
}.args())
|
}.args())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue