Skip to content

Commit

Permalink
Fall back to full Git clone if shallow clone is not supported (#775)
Browse files Browse the repository at this point in the history
## 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.
  • Loading branch information
shreyas-goenka authored Sep 15, 2023
1 parent 327ab0e commit 2c58deb
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 18 deletions.
50 changes: 34 additions & 16 deletions libs/git/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,23 @@ type cloneOptions struct {

// Local path to clone repository at
TargetPath string

// If true, the repository is shallow cloned
Shallow bool
}

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 != "" {
args = append(args, "--branch", opts.Reference)
}
if opts.Shallow {
args = append(args, "--depth=1")
}
return args
}

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,
}

func (opts cloneOptions) clone(ctx context.Context) error {
cmd := exec.CommandContext(ctx, "git", opts.args()...)
var cmdErr bytes.Buffer
cmd.Stderr = &cmdErr
Expand All @@ -70,3 +62,29 @@ func Clone(ctx context.Context, url, reference, targetPath string) error {
}
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
}
14 changes: 12 additions & 2 deletions libs/git/clone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,27 @@ import (

func TestGitCloneArgs(t *testing.T) {
// 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: "",
RepositoryUrl: "abc",
TargetPath: "/def",
Shallow: true,
}.args())

// 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",
RepositoryUrl: "abc",
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())
}

Expand Down

0 comments on commit 2c58deb

Please sign in to comment.