diff --git a/git/git.go b/git/git.go new file mode 100644 index 00000000..4d85deaf --- /dev/null +++ b/git/git.go @@ -0,0 +1,24 @@ +package git + +import ( + "fmt" + "os" + "os/exec" +) + +var execCommand = exec.Command + +// Clone clones a git repo into a destination directory +func Clone(repo, destination string) error { + cmd := execCommand("git", "clone", repo, destination) + cmd.Stdout = os.Stdout + err := cmd.Start() + if err != nil { + return fmt.Errorf("starting git clone command: %v", err) + } + err = cmd.Wait() + if err != nil { + return fmt.Errorf("cloning git repo: %v", err) + } + return nil +} diff --git a/git/git_test.go b/git/git_test.go new file mode 100644 index 00000000..f0daf2ac --- /dev/null +++ b/git/git_test.go @@ -0,0 +1,71 @@ +package git + +import ( + "os" + "os/exec" + "testing" +) + +type execFunc func(command string, args ...string) *exec.Cmd + +func getFakeExecCommand(validator func(string, ...string)) execFunc { + return func(command string, args ...string) *exec.Cmd { + validator(command, args...) + return fakeExecCommand(command, args...) + } +} + +func fakeExecCommand(command string, args ...string) *exec.Cmd { + cs := []string{"-test.run=TestHelperProcess", "--", command} + cs = append(cs, args...) + cmd := exec.Command(os.Args[0], cs...) + cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} + return cmd +} + +func TestCheckout(t *testing.T) { + wantRepo := "testrepo" + wantDest := "testdest" + execCommand = getFakeExecCommand(func(cmd string, args ...string) { + want := []string{ + "clone", wantRepo, wantDest, + } + if len(args) != len(want) { + t.Errorf("Incorrect args sent to git: %q, want %q", args, want) + } + for i, arg := range args { + if arg != want[i] { + t.Errorf("args[%d] = %q, want %q", i, arg, want[i]) + } + } + }) + + err := Clone(wantRepo, wantDest) + if err != nil { + t.Errorf("Unexpected error from git clone: %v", err) + } +} + +func TestHelperProcess(*testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + return + } + defer os.Exit(0) + + args := os.Args[:] + for i, val := range os.Args { // Should become something lke ["git", "clone"] + args = os.Args[i:] + if val == "--" { + args = args[1:] + break + } + } + + if len(args) > 1 { + switch args[1] { + case "clone": + return + } + } + os.Exit(255) +} diff --git a/launch.go b/launch.go index 57f877d3..8934bf3c 100644 --- a/launch.go +++ b/launch.go @@ -6,6 +6,7 @@ import ( "path" "regexp" + "github.com/screwdriver-cd/launcher/git" "github.com/screwdriver-cd/launcher/screwdriver" "github.com/urfave/cli" ) @@ -22,6 +23,7 @@ type scmPath struct { var mkdirAll = os.MkdirAll var stat = os.Stat +var gitClone = git.Clone func (s scmPath) String() string { return fmt.Sprintf("%s:%s/%s#%s", s.Host, s.Org, s.Repo, s.Branch) @@ -103,11 +105,15 @@ func launch(api screwdriver.API, buildID string) error { } scm, err := parseScmURL(p.ScmURL) - _, err = createWorkspace(scm.Org, scm.Repo) + workspace, err := createWorkspace(scm.Org, scm.Repo) if err != nil { return err } + err = gitClone(p.ScmURL, workspace.Src) + if err != nil { + return err + } return nil } diff --git a/launch_test.go b/launch_test.go index 04945aad..e1c06a4d 100644 --- a/launch_test.go +++ b/launch_test.go @@ -211,3 +211,20 @@ func TestCreateWorkspace(t *testing.T) { } } } + +func TestClone(t *testing.T) { + testBuildID := "BUILDID" + testJobID := "JOBID" + testSCMURL := "git@github.com:screwdriver-cd/launcher#master" + api := mockAPI(t, testBuildID, testJobID, "") + api.pipelineFromID = func(pipelineID string) (screwdriver.Pipeline, error) { + return screwdriver.Pipeline(FakePipeline{ScmURL: testSCMURL}), nil + } + gitClone = func(repo, dest string) error { + if repo != testSCMURL { + t.Errorf("Git clone was called with repo %q, want %q", repo, testSCMURL) + } + return nil + } + launch(screwdriver.API(api), testBuildID) +}