소스 검색

feat(vcs): test upDevel and extract OS runner

jguer 4 년 전
부모
커밋
9ad2862b7d
4개의 변경된 파일190개의 추가작업 그리고 80개의 파일을 삭제
  1. 5 44
      exec.go
  2. 65 0
      pkg/settings/runtime.go
  3. 118 11
      upgrade_test.go
  4. 2 25
      vcs.go

+ 5 - 44
exec.go

@@ -121,56 +121,17 @@ func passToMakepkg(dir string, args ...string) *exec.Cmd {
 }
 
 func passToGit(dir string, _args ...string) *exec.Cmd {
-	gitflags := strings.Fields(config.GitFlags)
-	args := []string{"-C", dir}
-	args = append(args, gitflags...)
+	args := strings.Fields(config.GitFlags)
+	if dir != "" {
+		args = append(args, "-C", dir)
+	}
 	args = append(args, _args...)
 
 	cmd := exec.Command(config.GitBin, args...)
+	cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
 	return cmd
 }
 
 func isTty() bool {
 	return terminal.IsTerminal(int(os.Stdout.Fd()))
 }
-
-type Runner interface {
-	Capture(string, int64, ...string) (string, string, error)
-}
-
-type OSRunner struct{}
-
-func (r *OSRunner) Capture(command string, timeout int64, args ...string) (stdout, stderr string, err error) {
-	var outbuf, errbuf bytes.Buffer
-	var timer *time.Timer
-
-	cmd := exec.Command(command, args...)
-	cmd.Stdout = &outbuf
-	cmd.Stderr = &errbuf
-	err = cmd.Start()
-	if err != nil {
-		return "", "", err
-	}
-
-	if timeout != 0 {
-		timer = time.AfterFunc(time.Duration(timeout)*time.Second, func() {
-			err = cmd.Process.Kill()
-			if err != nil {
-				text.Errorln(err)
-			}
-		})
-	}
-
-	err = cmd.Wait()
-	if timeout != 0 {
-		timer.Stop()
-	}
-	if err != nil {
-		return "", "", err
-	}
-
-	stdout = strings.TrimSpace(outbuf.String())
-	stderr = strings.TrimSpace(errbuf.String())
-
-	return stdout, stderr, err
-}

+ 65 - 0
pkg/settings/runtime.go

@@ -1,12 +1,19 @@
 package settings
 
 import (
+	"bytes"
+	"fmt"
 	"os"
+	"os/exec"
 	"path/filepath"
+	"strings"
+	"time"
 
 	"github.com/Morganamilo/go-pacmanconf"
 	"github.com/leonelquinteros/gotext"
 	"github.com/pkg/errors"
+
+	"github.com/Jguer/yay/v10/pkg/text"
 )
 
 type TargetMode int
@@ -25,6 +32,62 @@ const (
 	ModeRepo
 )
 
+type Runner interface {
+	Capture(cmd *exec.Cmd, timeout int64) (stdout string, stderr string, err error)
+	Show(cmd *exec.Cmd) error
+}
+
+type OSRunner struct {
+}
+
+func (r *OSRunner) Show(cmd *exec.Cmd) error {
+	cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+	err := cmd.Run()
+	if err != nil {
+		return fmt.Errorf("")
+	}
+	return nil
+}
+
+func (r *OSRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
+	var outbuf, errbuf bytes.Buffer
+	var timer *time.Timer
+	timedOut := false
+
+	cmd.Stdout = &outbuf
+	cmd.Stderr = &errbuf
+	err = cmd.Start()
+	if err != nil {
+		return "", "", err
+	}
+
+	if timeout != 0 {
+		timer = time.AfterFunc(time.Duration(timeout)*time.Second, func() {
+			err = cmd.Process.Kill()
+			if err != nil {
+				text.Errorln(err)
+			}
+			timedOut = true
+		})
+	}
+
+	err = cmd.Wait()
+	if timeout != 0 {
+		timer.Stop()
+	}
+	if err != nil {
+		return "", "", err
+	}
+
+	stdout = strings.TrimSpace(outbuf.String())
+	stderr = strings.TrimSpace(errbuf.String())
+	if timedOut {
+		err = fmt.Errorf("command timed out")
+	}
+
+	return stdout, stderr, err
+}
+
 type Runtime struct {
 	Mode           TargetMode
 	SaveConfig     bool
@@ -32,6 +95,7 @@ type Runtime struct {
 	ConfigPath     string
 	VCSPath        string
 	PacmanConf     *pacmanconf.Config
+	CmdRunner      Runner
 }
 
 func MakeRuntime() (*Runtime, error) {
@@ -42,6 +106,7 @@ func MakeRuntime() (*Runtime, error) {
 		Mode:           ModeAny,
 		SaveConfig:     false,
 		CompletionPath: "",
+		CmdRunner:      &OSRunner{},
 	}
 
 	if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {

+ 118 - 11
upgrade_test.go

@@ -1,17 +1,22 @@
 package main
 
 import (
+	"fmt"
 	"io/ioutil"
 	"os"
+	"os/exec"
+	"strconv"
 	"testing"
 	"time"
 
-	"github.com/Jguer/yay/v10/pkg/db"
-	"github.com/Jguer/yay/v10/pkg/db/mock"
-	"github.com/Jguer/yay/v10/pkg/upgrade"
 	"github.com/bradleyjkemp/cupaloy"
 	rpc "github.com/mikkeloscar/aur"
 	"github.com/stretchr/testify/assert"
+
+	"github.com/Jguer/yay/v10/pkg/db"
+	"github.com/Jguer/yay/v10/pkg/db/mock"
+	"github.com/Jguer/yay/v10/pkg/settings"
+	"github.com/Jguer/yay/v10/pkg/upgrade"
 )
 
 func Test_upAUR(t *testing.T) {
@@ -68,16 +73,51 @@ func Test_upAUR(t *testing.T) {
 	}
 }
 
+type MockRunner struct {
+	Returned []string
+	Index    int
+	t        *testing.T
+}
+
+func (r *MockRunner) Show(cmd *exec.Cmd) error {
+	return nil
+}
+
+func (r *MockRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
+	i, _ := strconv.Atoi(cmd.Args[len(cmd.Args)-1])
+	if i >= len(r.Returned) {
+		fmt.Println(r.Returned)
+		fmt.Println(cmd.Args)
+		fmt.Println(i)
+	}
+	stdout = r.Returned[i]
+	assert.Contains(r.t, cmd.Args, "ls-remote")
+	return stdout, stderr, err
+}
+
 func Test_upDevel(t *testing.T) {
+	config = settings.MakeConfig()
+	config.Runtime, _ = settings.MakeRuntime()
+	config.Runtime.CmdRunner = &MockRunner{
+		Returned: []string{
+			"7f4c277ce7149665d1c79b76ca8fbb832a65a03b	HEAD",
+			"7f4c277ce7149665d1c79b76ca8fbb832a65a03b	HEAD",
+			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa	HEAD",
+			"cccccccccccccccccccccccccccccccccccccccc	HEAD",
+			"991c5b4146fd27f4aacf4e3111258a848934aaa1	HEAD",
+		},
+	}
+
 	type args struct {
 		remote  []db.RepoPackage
 		aurdata map[string]*rpc.Pkg
 		cached  vcsInfo
 	}
 	tests := []struct {
-		name string
-		args args
-		want upgrade.UpSlice
+		name     string
+		args     args
+		want     upgrade.UpSlice
+		finalLen int
 	}{
 		{name: "No Updates",
 			args: args{
@@ -92,22 +132,89 @@ func Test_upDevel(t *testing.T) {
 			},
 			want: upgrade.UpSlice{}},
 		{name: "Simple Update",
+			finalLen: 3,
 			args: args{
 				cached: vcsInfo{
 					"hello": shaInfos{
-						"github.com/Jguer/yay.git": shaInfo{
+						"github.com/Jguer/z.git": shaInfo{
+							Protocols: []string{"https"},
+							Branch:    "0",
+							SHA:       "991c5b4146fd27f4aacf4e3111258a848934aaa1"}},
+					"hello-non-existant": shaInfos{
+						"github.com/Jguer/y.git": shaInfo{
+							Protocols: []string{"https"},
+							Branch:    "0",
+							SHA:       "991c5b4146fd27f4aacf4e3111258a848934aaa1"}},
+					"hello2": shaInfos{
+						"github.com/Jguer/a.git": shaInfo{
 							Protocols: []string{"https"},
-							Branch:    "main",
+							Branch:    "1",
+							SHA:       "7f4c277ce7149665d1c79b76ca8fbb832a65a03b"}},
+					"hello4": shaInfos{
+						"github.com/Jguer/b.git": shaInfo{
+							Protocols: []string{"https"},
+							Branch:    "2",
+							SHA:       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
+						"github.com/Jguer/c.git": shaInfo{
+							Protocols: []string{"https"},
+							Branch:    "3",
+							SHA:       "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"},
+					},
+				},
+				remote: []db.RepoPackage{
+					&mock.Package{PName: "hello", PVersion: "2.0.0"},
+					&mock.Package{PName: "hello2", PVersion: "3.0.0"},
+					&mock.Package{PName: "hello4", PVersion: "4.0.0"}},
+				aurdata: map[string]*rpc.Pkg{
+					"hello":  {Version: "2.0.0", Name: "hello"},
+					"hello2": {Version: "2.0.0", Name: "hello2"},
+					"hello4": {Version: "2.0.0", Name: "hello4"},
+				},
+			},
+			want: upgrade.UpSlice{upgrade.Upgrade{
+				Name:          "hello",
+				Repository:    "devel",
+				LocalVersion:  "2.0.0",
+				RemoteVersion: "latest-commit"},
+				upgrade.Upgrade{
+					Name:          "hello4",
+					Repository:    "devel",
+					LocalVersion:  "4.0.0",
+					RemoteVersion: "latest-commit"},
+			}},
+		{name: "No update returned",
+			finalLen: 1,
+			args: args{
+				cached: vcsInfo{
+					"hello": shaInfos{
+						"github.com/Jguer/d.git": shaInfo{
+							Protocols: []string{"https"},
+							Branch:    "4",
 							SHA:       "991c5b4146fd27f4aacf4e3111258a848934aaa1"}}},
 				remote:  []db.RepoPackage{&mock.Package{PName: "hello", PVersion: "2.0.0"}},
-				aurdata: map[string]*rpc.Pkg{"hello": {Version: "2.1.0", Name: "hello"}},
+				aurdata: map[string]*rpc.Pkg{"hello": {Version: "2.0.0", Name: "hello"}},
 			},
-			want: upgrade.UpSlice{upgrade.Upgrade{Name: "hello", Repository: "aur", LocalVersion: "2.0.0", RemoteVersion: "2.1.0"}}},
+			want: upgrade.UpSlice{}},
+		{name: "No update returned - ignored",
+			finalLen: 1,
+			args: args{
+				cached: vcsInfo{
+					"hello": shaInfos{
+						"github.com/Jguer/e.git": shaInfo{
+							Protocols: []string{"https"},
+							Branch:    "3",
+							SHA:       "991c5b4146fd27f4aacf4e3111258a848934aaa1"}}},
+				remote:  []db.RepoPackage{&mock.Package{PName: "hello", PVersion: "2.0.0", PShouldIgnore: true}},
+				aurdata: map[string]*rpc.Pkg{"hello": {Version: "2.0.0", Name: "hello"}},
+			},
+			want: upgrade.UpSlice{}},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			config.Runtime.CmdRunner.(*MockRunner).t = t
 			got := upDevel(tt.args.remote, tt.args.aurdata, tt.args.cached)
-			assert.EqualValues(t, tt.want, got)
+			assert.ElementsMatch(t, tt.want, got)
+			assert.Equal(t, tt.finalLen, len(tt.args.cached))
 		})
 	}
 }

+ 2 - 25
vcs.go

@@ -1,13 +1,11 @@
 package main
 
 import (
-	"bytes"
 	"encoding/json"
 	"fmt"
 	"os"
 	"strings"
 	"sync"
-	"time"
 
 	gosrc "github.com/Morganamilo/go-srcinfo"
 	"github.com/leonelquinteros/gotext"
@@ -165,35 +163,14 @@ func updateVCSData(vcsFilePath, pkgName string, sources []gosrc.ArchString, mux
 func getCommit(url, branch string, protocols []string) string {
 	if len(protocols) > 0 {
 		protocol := protocols[len(protocols)-1]
-		var outbuf bytes.Buffer
 
 		cmd := passToGit("", "ls-remote", protocol+"://"+url, branch)
-		cmd.Stdout = &outbuf
-		cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
-
-		err := cmd.Start()
-		if err != nil {
-			return ""
-		}
-
-		// for some reason
-		// git://bitbucket.org/volumesoffun/polyvox.git` hangs on my
-		// machine but using http:// instead of git does not hang.
-		// Introduce a time out so this can not hang
-		timer := time.AfterFunc(5*time.Second, func() {
-			err = cmd.Process.Kill()
-			if err != nil {
-				text.Errorln(err)
-			}
-		})
-
-		err = cmd.Wait()
-		timer.Stop()
+		stdout, _, err := config.Runtime.CmdRunner.Capture(cmd, 5)
 		if err != nil {
+			text.Warnln(err)
 			return ""
 		}
 
-		stdout := outbuf.String()
 		split := strings.Fields(stdout)
 
 		if len(split) < 2 {