package builder
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"testing"
"time"
"github.com/openshift/origin/pkg/build/api"
"github.com/openshift/origin/pkg/generate/git"
)
func TestCheckRemoteGit(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
}))
defer server.Close()
gitRepo := git.NewRepositoryWithEnv([]string{"GIT_ASKPASS=true"})
var err error
err = checkRemoteGit(gitRepo, server.URL, 10*time.Second)
switch v := err.(type) {
case gitAuthError:
default:
t.Errorf("expected gitAuthError, got %q", v)
}
err = checkRemoteGit(gitRepo, "https://github.com/openshift/origin", 10*time.Second)
if err != nil {
t.Errorf("unexpected error %q", err)
}
}
type testGitRepo struct {
Name string
Path string
Files []string
Submodule *testGitRepo
}
func initializeTestGitRepo(name string) (*testGitRepo, error) {
repo := &testGitRepo{Name: name}
dir, err := ioutil.TempDir("", "test-"+repo.Name)
if err != nil {
return repo, err
}
repo.Path = dir
tmpfn := filepath.Join(dir, "initial-file")
if err := ioutil.WriteFile(tmpfn, []byte("test"), 0666); err != nil {
return repo, fmt.Errorf("unable to create temporary file")
}
repo.Files = append(repo.Files, tmpfn)
initCmd := exec.Command("git", "init")
initCmd.Dir = dir
if out, err := initCmd.CombinedOutput(); err != nil {
return repo, fmt.Errorf("unable to initialize repository: %q", out)
}
configEmailCmd := exec.Command("git", "config", "user.email", "me@example.com")
configEmailCmd.Dir = dir
if out, err := configEmailCmd.CombinedOutput(); err != nil {
return repo, fmt.Errorf("unable to set git email prefs: %q", out)
}
configNameCmd := exec.Command("git", "config", "user.name", "Me Myself")
configNameCmd.Dir = dir
if out, err := configNameCmd.CombinedOutput(); err != nil {
return repo, fmt.Errorf("unable to set git name prefs: %q", out)
}
return repo, nil
}
func (r *testGitRepo) addSubmodule() error {
subRepo, err := initializeTestGitRepo("submodule")
if err != nil {
return err
}
if err := subRepo.addCommit(); err != nil {
return err
}
subCmd := exec.Command("git", "submodule", "add", "file://"+subRepo.Path, "sub")
subCmd.Dir = r.Path
if out, err := subCmd.CombinedOutput(); err != nil {
return fmt.Errorf("unable to add submodule: %q", out)
}
r.Submodule = subRepo
return nil
}
// getRef returns the sha256 of the commit specified by the negative offset.
// The '0' is the current HEAD.
func (r *testGitRepo) getRef(offset int) (string, error) {
q := ""
for i := offset; i != 0; i++ {
q += "^"
}
refCmd := exec.Command("git", "rev-parse", "HEAD"+q)
refCmd.Dir = r.Path
if out, err := refCmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("unable to checkout %d offset: %q", offset, out)
} else {
return strings.TrimSpace(string(out)), nil
}
}
func (r *testGitRepo) createBranch(name string) error {
refCmd := exec.Command("git", "checkout", "-b", name)
refCmd.Dir = r.Path
if out, err := refCmd.CombinedOutput(); err != nil {
return fmt.Errorf("unable to checkout new branch: %q", out)
}
return nil
}
func (r *testGitRepo) switchBranch(name string) error {
refCmd := exec.Command("git", "checkout", name)
refCmd.Dir = r.Path
if out, err := refCmd.CombinedOutput(); err != nil {
return fmt.Errorf("unable to checkout branch: %q", out)
}
return nil
}
func (r *testGitRepo) cleanup() {
os.RemoveAll(r.Path)
if r.Submodule != nil {
os.RemoveAll(r.Submodule.Path)
}
}
func (r *testGitRepo) addCommit() error {
f, err := ioutil.TempFile(r.Path, "")
if err != nil {
return err
}
if err := ioutil.WriteFile(f.Name(), []byte("test"), 0666); err != nil {
return fmt.Errorf("unable to create temporary file %q", f.Name())
}
addCmd := exec.Command("git", "add", ".")
addCmd.Dir = r.Path
if out, err := addCmd.CombinedOutput(); err != nil {
return fmt.Errorf("unable to add files to repo: %q", out)
}
commitCmd := exec.Command("git", "commit", "-a", "-m", "test commit")
commitCmd.Dir = r.Path
out, err := commitCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("unable to commit: %q", out)
}
r.Files = append(r.Files, f.Name())
return nil
}
func TestUnqualifiedClone(t *testing.T) {
repo, err := initializeTestGitRepo("unqualified")
defer repo.cleanup()
if err != nil {
t.Errorf("%v", err)
}
if err := repo.addSubmodule(); err != nil {
t.Errorf("%v", err)
}
// add two commits to check that shallow clone take account
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
destDir, err := ioutil.TempDir("", "clone-dest-")
defer os.RemoveAll(destDir)
client := git.NewRepositoryWithEnv([]string{})
source := &api.GitBuildSource{URI: "file://" + repo.Path}
revision := api.SourceRevision{Git: &api.GitSourceRevision{}}
if _, err = extractGitSource(client, source, &revision, destDir, 10*time.Second); err != nil {
t.Errorf("%v", err)
}
for _, f := range repo.Files {
if _, err := os.Stat(filepath.Join(destDir, path.Base(f))); os.IsNotExist(err) {
t.Errorf("unable to find repository file %q", path.Base(f))
}
}
if _, err := os.Stat(filepath.Join(destDir, "sub")); os.IsNotExist(err) {
t.Errorf("unable to find submodule dir")
}
for _, f := range repo.Submodule.Files {
if _, err := os.Stat(filepath.Join(destDir, "sub/"+path.Base(f))); os.IsNotExist(err) {
t.Errorf("unable to find submodule repository file %q", path.Base(f))
}
}
}
func TestCloneFromRef(t *testing.T) {
repo, err := initializeTestGitRepo("commit")
defer repo.cleanup()
if err != nil {
t.Errorf("%v", err)
}
if err := repo.addSubmodule(); err != nil {
t.Errorf("%v", err)
}
// add two commits to check that shallow clone take account
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
destDir, err := ioutil.TempDir("", "commit-dest-")
defer os.RemoveAll(destDir)
client := git.NewRepositoryWithEnv([]string{})
firstCommitRef, err := repo.getRef(-1)
if err != nil {
t.Errorf("%v", err)
}
source := &api.GitBuildSource{
URI: "file://" + repo.Path,
Ref: firstCommitRef,
}
revision := api.SourceRevision{Git: &api.GitSourceRevision{}}
if _, err = extractGitSource(client, source, &revision, destDir, 10*time.Second); err != nil {
t.Errorf("%v", err)
}
for _, f := range repo.Files[:len(repo.Files)-1] {
if _, err := os.Stat(filepath.Join(destDir, path.Base(f))); os.IsNotExist(err) {
t.Errorf("unable to find repository file %q", path.Base(f))
}
}
if _, err := os.Stat(filepath.Join(destDir, path.Base(repo.Files[len(repo.Files)-1]))); !os.IsNotExist(err) {
t.Errorf("last file should not exists in this checkout")
}
if _, err := os.Stat(filepath.Join(destDir, "sub")); os.IsNotExist(err) {
t.Errorf("unable to find submodule dir")
}
for _, f := range repo.Submodule.Files {
if _, err := os.Stat(filepath.Join(destDir, "sub/"+path.Base(f))); os.IsNotExist(err) {
t.Errorf("unable to find submodule repository file %q", path.Base(f))
}
}
}
func TestCloneFromBranch(t *testing.T) {
repo, err := initializeTestGitRepo("branch")
defer repo.cleanup()
if err != nil {
t.Errorf("%v", err)
}
if err := repo.addSubmodule(); err != nil {
t.Errorf("%v", err)
}
// add two commits to check that shallow clone take account
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
if err := repo.createBranch("test"); err != nil {
t.Errorf("%v", err)
}
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
if err := repo.switchBranch("master"); err != nil {
t.Errorf("%v", err)
}
if err := repo.addCommit(); err != nil {
t.Errorf("unable to add commit: %v", err)
}
destDir, err := ioutil.TempDir("", "branch-dest-")
defer os.RemoveAll(destDir)
client := git.NewRepositoryWithEnv([]string{})
source := &api.GitBuildSource{
URI: "file://" + repo.Path,
Ref: "test",
}
revision := api.SourceRevision{Git: &api.GitSourceRevision{}}
if _, err = extractGitSource(client, source, &revision, destDir, 10*time.Second); err != nil {
t.Errorf("%v", err)
}
for _, f := range repo.Files[:len(repo.Files)-1] {
if _, err := os.Stat(filepath.Join(destDir, path.Base(f))); os.IsNotExist(err) {
t.Errorf("file %q should not exists in the test branch", f)
}
}
if _, err := os.Stat(filepath.Join(destDir, path.Base(repo.Files[len(repo.Files)-1]))); !os.IsNotExist(err) {
t.Errorf("last file should not exists in the test branch")
}
if _, err := os.Stat(filepath.Join(destDir, "sub")); os.IsNotExist(err) {
t.Errorf("unable to find submodule dir")
}
for _, f := range repo.Submodule.Files {
if _, err := os.Stat(filepath.Join(destDir, "sub/"+path.Base(f))); os.IsNotExist(err) {
t.Errorf("unable to find submodule repository file %q", path.Base(f))
}
}
}