Added CloneOptions and passing context object around

This commit is contained in:
Shreyas Goenka 2023-06-29 17:48:06 +02:00
parent 5f9ec5dd29
commit ac6cf0fec4
No known key found for this signature in database
GPG Key ID: 92A07DF49CCB0622
3 changed files with 102 additions and 59 deletions

View File

@ -1,6 +1,8 @@
package internal
import (
"context"
"os"
"path/filepath"
"testing"
@ -8,14 +10,51 @@ import (
"github.com/stretchr/testify/assert"
)
func TestAccGitClonePrivateRepository(t *testing.T) {
// TODO: add assertion that the git tool is not called, maybe by voiding PATH
// TODO: add assertion for error if git CLI is not found
func TestGitClonePublicRepository(t *testing.T) {
// t.Log(GetEnvOrSkipTest(t, "CLOUD_ENV"))
tmpDir := t.TempDir()
ctx := context.Background()
var err error
// We unset PATH to ensure that git.Clone cannot rely on the git CLI
t.Setenv("PATH", "")
err = git.Clone(ctx, git.CloneOptions{
Provider: "github",
Organization: "databricks",
RepositoryName: "cli",
Reference: "main",
TargetDir: tmpDir,
})
assert.NoError(t, err)
assert.DirExists(t, filepath.Join(tmpDir, "cli-main"))
b, err := os.ReadFile(filepath.Join(tmpDir, "cli-main/NOTICE"))
assert.NoError(t, err)
assert.Contains(t, string(b), "Copyright (2023) Databricks, Inc.")
}
func TestAccGitClonePrivateRepository(t *testing.T) {
// t.Log(GetEnvOrSkipTest(t, "CLOUD_ENV"))
tmpDir := t.TempDir()
ctx := context.Background()
// This is a private repository only accessible to databricks employees
err := git.Clone("databricks", "bundle-samples-internal", tmpDir)
err := git.Clone(ctx, git.CloneOptions{
Provider: "github",
Organization: "databricks",
RepositoryName: "bundle-samples-internal",
Reference: "main",
TargetDir: tmpDir,
})
assert.NoError(t, err)
// assert examples from the private repository
assert.DirExists(t, filepath.Join(tmpDir, "shark_sightings"))
assert.DirExists(t, filepath.Join(tmpDir, "wikipedia_clickstream"))
assert.DirExists(t, filepath.Join(tmpDir, "bundle-samples-internal-main", "shark_sightings"))
assert.DirExists(t, filepath.Join(tmpDir, "bundle-samples-internal-main", "wikipedia_clickstream"))
}

View File

@ -1,6 +1,7 @@
package git
import (
"context"
"errors"
"fmt"
"io"
@ -14,14 +15,6 @@ import (
var errNotFound = errors.New("not found")
func githubZipUrl(org string, name string, ref string) string {
return fmt.Sprintf(`%s/archive/%s.zip`, githubUrl(org, name), ref)
}
func githubUrl(org string, name string) string {
return fmt.Sprintf(`https://github.com/%s/%s`, org, name)
}
type RepositoryNotFoundError struct {
url string
}
@ -34,9 +27,42 @@ func (err RepositoryNotFoundError) Is(other error) bool {
return other == errNotFound
}
// TODO: pass context to these the get requests
func download(url string, dest string) error {
resp, err := http.Get(url)
type CloneOptions struct {
// Name of the organization or profile with the repository
Organization string
RepositoryName string
// Git service provider. Eg: github, gitlab
Provider string
// Branch or tag name to clone
Reference string
// Path to clone into. The repository is cloned as ${RepositoryName}-${Reference}
// in this target directory.
TargetDir string
}
func (opts CloneOptions) repoUrl() string {
return fmt.Sprintf(`https://github.com/%s/%s`, opts.Organization, opts.RepositoryName)
}
func (opts CloneOptions) zipUrl() string {
return fmt.Sprintf(`%s/archive/%s.zip`, opts.repoUrl(), opts.Reference)
}
// TODO: test this holds true for alternate branches and tags
func (opts CloneOptions) destination() string {
return filepath.Join(opts.TargetDir, opts.RepositoryName+"-"+opts.Reference)
}
func download(ctx context.Context, url string, dest string) error {
// Get request to download the ZIP archive
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(request)
if err != nil {
return err
}
@ -59,45 +85,45 @@ func download(url string, dest string) error {
return err
}
func clonePrivate(org string, repoName string, targetDir string) error {
zipUrl := githubUrl(org, repoName)
// We append repoName-main to targetDir to be symmetric to clonePublic
targetDir = filepath.Join(targetDir, repoName+"-main")
// TODO: pass context to the command execution
cmd := exec.Command("git", "clone", zipUrl, targetDir, "--branch", "main")
// TODO: check stdin / stdout works properly with git clone and requesting an ID/password
func clonePrivate(ctx context.Context, opts CloneOptions) error {
// TODO: test that the branch --branch flag works with tags
cmd := exec.CommandContext(ctx, "git", "clone", opts.repoUrl(), opts.destination(), "--branch", opts.Reference)
return cmd.Run()
}
func clonePublic(org string, repoName string, targetDir string) error {
zipDst := filepath.Join(targetDir, repoName+".zip")
zipUrl := githubZipUrl(org, repoName, "main")
func clonePublic(ctx context.Context, opts CloneOptions) error {
zipDst := filepath.Join(opts.TargetDir, opts.RepositoryName+".zip")
// Download public repository from github as a ZIP file
err := download(zipUrl, zipDst)
err := download(ctx, opts.zipUrl(), zipDst)
if err != nil {
return err
}
// Decompress the ZIP file
err = zip.Extract(zipDst, targetDir)
err = zip.Extract(zipDst, opts.TargetDir)
if err != nil {
return err
}
// Remove the ZIP file
// Remove the ZIP file post extraction
return os.Remove(zipDst)
}
func Clone(org, repoName string, targetDir string) error {
// First we try to clone the repository as a public URL, as that does not
// require the git CLI
err := clonePublic(org, repoName, targetDir)
if err != nil && !errors.Is(err, errNotFound) {
return err
func Clone(ctx context.Context, opts CloneOptions) error {
if opts.Provider != "github" {
return fmt.Errorf("git provider not supported: %s", opts.Provider)
}
// Since a public repository was not found, we defer to the git CLI
return clonePrivate(org, repoName, targetDir)
// First we try to clone the repository as a public URL, as that does not
// require the git CLI
err := clonePublic(ctx, opts)
// If a public repository was not found, we defer to the git CLI
if errors.Is(err, errNotFound) {
return clonePrivate(ctx, opts)
}
return err
}

View File

@ -1,22 +0,0 @@
package git
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGitClonePublicRepository(t *testing.T) {
tmpDir := t.TempDir()
var err error
err = clonePublic("databricks", "cli", tmpDir)
assert.NoError(t, err)
assert.DirExists(t, filepath.Join(tmpDir, "cli-main"))
b, err := os.ReadFile(filepath.Join(tmpDir, "cli-main/NOTICE"))
assert.NoError(t, err)
assert.Contains(t, string(b), "Copyright (2023) Databricks, Inc.")
}