feat(vcs): test upDevel and extract OS runner

This commit is contained in:
jguer 2020-08-18 01:19:51 +02:00
parent 4a761c287b
commit 9ad2862b7d
No known key found for this signature in database
GPG key ID: 6D6CC9BEA8556B35
4 changed files with 190 additions and 80 deletions

49
exec.go
View file

@ -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
}

View file

@ -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 != "" {

View file

@ -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: "main",
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: "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))
})
}
}

27
vcs.go
View file

@ -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()
stdout, _, err := config.Runtime.CmdRunner.Capture(cmd, 5)
if err != nil {
text.Warnln(err)
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()
if err != nil {
return ""
}
stdout := outbuf.String()
split := strings.Fields(stdout)
if len(split) < 2 {