Skip to content

Commit

Permalink
Merge pull request #942 from saschagrunert/git-tests
Browse files Browse the repository at this point in the history
Add git package unit tests
  • Loading branch information
k8s-ci-robot authored Nov 27, 2019
2 parents 2dae2ec + 5a4c06f commit 43e73cc
Show file tree
Hide file tree
Showing 5 changed files with 414 additions and 64 deletions.
57 changes: 49 additions & 8 deletions pkg/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,30 @@ type Status struct {
output string
}

// New creates a new command from provided string, which contains a whitespace
// sepearated shell command
// New creates a new command from the provided arguments.
func New(cmd ...string) *Command {
return NewWithWorkDir("", cmd...)
}

// New creates a new command from the provided workDir and the command
// arguments.
func NewWithWorkDir(workDir string, cmd ...string) *Command {
args := strings.Fields(strings.Join(cmd, " "))
if len(args) == 0 {
return &Command{exec.Command(cmd[0])}
} else if len(args) > 1 {
return &Command{exec.Command(args[0], args[1:]...)}

command := func() *Command {
if len(args) == 0 {
return &Command{exec.Command(cmd[0])}
} else if len(args) > 1 {
return &Command{exec.Command(args[0], args[1:]...)}
}
return &Command{exec.Command(args[0])}
}()

if workDir != "" {
command.cmd.Dir = workDir
}
return &Command{exec.Command(args[0])}

return command
}

// Run starts the command and waits for it to finish. It returns an error if
Expand All @@ -59,13 +73,40 @@ func (c *Command) Run() (res *Status, err error) {
return c.run(true)
}

// Run starts the command and waits for it to finish. It returns an error if
// the command execution was not successful.
func (c *Command) RunSuccess() (err error) {
res, err := c.run(true)
if err != nil {
return err
}
if !res.Success() {
return errors.Errorf("command %v did not succeed", c.cmd)
}
return nil
}

// Run starts the command and waits for it to finish. It returns an error if
// the command execution was not possible at all, otherwise the Status.
// This method does not print the output of the command during its execution.
func (c *Command) RunSilent() (res *Status, err error) {
return c.run(false)
}

// Run starts the command and waits for it to finish. It returns an error if
// the command execution was not successful.
// This method does not print the output of the command during its execution.
func (c *Command) RunSilentSuccess() (err error) {
res, err := c.run(false)
if err != nil {
return err
}
if !res.Success() {
return errors.Errorf("command %v did not succeed", c.cmd)
}
return nil
}

// run is the internal run method
func (c *Command) run(print bool) (res *Status, err error) {
log.Printf("Running command: %v", c.cmd)
Expand Down Expand Up @@ -140,7 +181,7 @@ func (s *Status) Output() string {
return s.output
}

// Execute is a convinience function which creates a new Command, excutes it
// Execute is a convenience function which creates a new Command, executes it
// and evaluates its status.
func Execute(cmd ...string) error {
status, err := New(cmd...).Run()
Expand Down
28 changes: 28 additions & 0 deletions pkg/command/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ func TestSuccess(t *testing.T) {
require.Zero(t, res.ExitCode())
}

func TestSuccessWithWorkingDir(t *testing.T) {
res, err := NewWithWorkDir("/", "ls -1").Run()
require.Nil(t, err)
require.True(t, res.Success())
require.Zero(t, res.ExitCode())
}

func TestFailureWithWrongWorkingDir(t *testing.T) {
_, err := NewWithWorkDir("/should/not/exist", "ls -1").Run()
require.NotNil(t, err)
}

func TestSuccessSilent(t *testing.T) {
res, err := New("echo hi").RunSilent()
require.Nil(t, err)
Expand Down Expand Up @@ -86,3 +98,19 @@ func TestAvailableFailure(t *testing.T) {
res := Available("echo", "this-command-should-not-exist")
require.False(t, res)
}

func TestSuccessRunSuccess(t *testing.T) {
require.Nil(t, New("echo hi").RunSuccess())
}

func TestFailureRunSuccess(t *testing.T) {
require.NotNil(t, New("cat /not/available").RunSuccess())
}

func TestSuccessRunSilentSuccess(t *testing.T) {
require.Nil(t, New("echo hi").RunSilentSuccess())
}

func TestFailureRunSuccessSilent(t *testing.T) {
require.NotNil(t, New("cat /not/available").RunSilentSuccess())
}
15 changes: 14 additions & 1 deletion pkg/git/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "go_default_library",
Expand Down Expand Up @@ -31,3 +31,16 @@ filegroup(
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

go_test(
name = "go_default_test",
srcs = ["git_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/command:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
"@in_gopkg_src_d_go_git_v4//:go_default_library",
"@in_gopkg_src_d_go_git_v4//config:go_default_library",
"@in_gopkg_src_d_go_git_v4//plumbing/object:go_default_library",
],
)
67 changes: 12 additions & 55 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ func (r *Repo) RevParse(rev string) (string, error) {
return ref.String(), nil
}

// RevParseShort parses a git revision and returns a SHA1 on success, otherwise
// an error.
// RevParseShort parses a git revision and returns a SHA1 trimmed to the length
// 10 on success, otherwise an error.
func (r *Repo) RevParseShort(rev string) (string, error) {
fullRev, err := r.RevParse(rev)
if err != nil {
Expand Down Expand Up @@ -319,7 +319,7 @@ func (r *Repo) CheckoutBranch(name string) error {
func IsReleaseBranch(branch string) bool {
re := regexp.MustCompile(branchRE)
if !re.MatchString(branch) {
log.Fatalf("%s is not a release branch\n", branch)
log.Printf("%s is not a release branch", branch)
return false
}

Expand Down Expand Up @@ -373,86 +373,43 @@ func Remotify(name string) string {
return fmt.Sprintf("%s/%s", DefaultRemote, name)
}

// switchToRepoDir changes into the repo dir and returning the old one for
// restoring it
func (r *Repo) switchToRepoDir() (string, error) {
oldWd, err := os.Getwd()
if err != nil {
return "", err
}
if err := os.Chdir(r.dir); err != nil {
return "", err
}
return oldWd, nil
}

// DescribeTag can be used to retrieve the latest tag for a provided revision
func (r *Repo) DescribeTag(rev string) (string, error) {
oldWd, err := r.switchToRepoDir()
if err != nil {
return "", err
}

// go git seems to have no implementation for `git describe`
// which means that we fallback to a shell command for sake of
// simplicity
status, err := command.New("git describe --abbrev=0 --tags", rev).RunSilent()
status, err := command.NewWithWorkDir(
r.Dir(), "git describe --abbrev=0 --tags", rev,
).RunSilent()
if err != nil {
return "", err
}
if !status.Success() {
return "", errors.New("git describe command failed")
}

// Restore working directory
if err := os.Chdir(oldWd); err != nil {
return "", err
}

return strings.TrimSpace(status.Output()), nil
}

// Merge does a git merge into the current branch from the provided one
func (r *Repo) Merge(from string) error {
oldWd, err := r.switchToRepoDir()
if err != nil {
return err
}

status, err := command.New("git merge -X ours", from).Run()
if err != nil {
return err
}
if !status.Success() {
return errors.New("git merge command failed")
}

return os.Chdir(oldWd)
return command.NewWithWorkDir(
r.Dir(), "git merge -X ours", from,
).RunSuccess()
}

// Push does push the specified branch to the default remote, but only if the
// repository is not in dry run mode
func (r *Repo) Push(remoteBranch string) error {
oldWd, err := r.switchToRepoDir()
if err != nil {
return err
}

dryRunFlag := ""
if r.dryRun {
log.Println("Won't push due to dry run repository")
dryRunFlag = "--dry-run"
}

status, err := command.New("git push", dryRunFlag, DefaultRemote, remoteBranch).Run()
if err != nil {
return err
}
if !status.Success() {
return errors.New("git push command failed")
}

return os.Chdir(oldWd)
return command.NewWithWorkDir(
r.Dir(), "git push", dryRunFlag, DefaultRemote, remoteBranch,
).RunSuccess()
}

// Head retrieves the current repository HEAD as a string
Expand Down
Loading

0 comments on commit 43e73cc

Please sign in to comment.