feat(config): refactor config to allow running without config
This commit is contained in:
19 files changed
+441
-605
No files matched your search
@@ -16,27 +16,6 @@ import (
|
||||
"github.com/Jguer/yay/v10/pkg/text"
|
||||
)
|
||||
|
||||
// GetPkgbuild gets the pkgbuild of the package 'pkg' trying the ABS first and then the AUR trying the ABS first and then the AUR.
|
||||
|
||||
// RemovePackage removes package from VCS information
|
||||
func removeVCSPackage(pkgs []string, localCache vcsInfo) {
|
||||
updated := false
|
||||
|
||||
for _, pkgName := range pkgs {
|
||||
if _, ok := localCache[pkgName]; ok {
|
||||
delete(localCache, pkgName)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
|
||||
if updated {
|
||||
err := saveVCSInfo(config.Runtime.VCSPath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CleanDependencies removes all dangling dependencies in system
|
||||
func cleanDependencies(cmdArgs *settings.Arguments, dbExecutor db.Executor, removeOptional bool) error {
|
||||
hanging := hangingPackages(removeOptional, dbExecutor)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/Jguer/yay/v10/pkg/query"
|
||||
"github.com/Jguer/yay/v10/pkg/settings"
|
||||
"github.com/Jguer/yay/v10/pkg/text"
|
||||
"github.com/Jguer/yay/v10/pkg/vcs"
|
||||
)
|
||||
|
||||
func usage() {
|
||||
@@ -199,8 +200,7 @@ func handleVersion() {
|
||||
func handlePrint(cmdArgs *settings.Arguments, dbExecutor db.Executor) (err error) {
|
||||
switch {
|
||||
case cmdArgs.ExistsArg("d", "defaultconfig"):
|
||||
tmpConfig := settings.MakeConfig()
|
||||
tmpConfig.ExpandEnv()
|
||||
tmpConfig := settings.DefaultConfig()
|
||||
fmt.Printf("%v", tmpConfig)
|
||||
case cmdArgs.ExistsArg("g", "currentconfig"):
|
||||
fmt.Printf("%v", config)
|
||||
@@ -224,7 +224,7 @@ func handlePrint(cmdArgs *settings.Arguments, dbExecutor db.Executor) (err error
|
||||
|
||||
func handleYay(cmdArgs *settings.Arguments, dbExecutor db.Executor) error {
|
||||
if cmdArgs.ExistsArg("gendb") {
|
||||
return createDevelDB(config.Runtime.VCSPath, dbExecutor)
|
||||
return createDevelDB(config, dbExecutor)
|
||||
}
|
||||
if cmdArgs.ExistsDouble("c") {
|
||||
return cleanDependencies(cmdArgs, dbExecutor, true)
|
||||
@@ -285,10 +285,10 @@ func handleSync(cmdArgs *settings.Arguments, dbExecutor db.Executor) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRemove(cmdArgs *settings.Arguments, localCache vcsInfo) error {
|
||||
func handleRemove(cmdArgs *settings.Arguments, localCache vcs.InfoStore) error {
|
||||
err := config.Runtime.CmdRunner.Show(passToPacman(cmdArgs))
|
||||
if err == nil {
|
||||
removeVCSPackage(cmdArgs.Targets, localCache)
|
||||
localCache.RemovePackage(cmdArgs.Targets)
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/Jguer/yay/v10/pkg/settings"
|
||||
"github.com/Jguer/yay/v10/pkg/text"
|
||||
"github.com/Jguer/yay/v10/pkg/vcs"
|
||||
)
|
||||
|
||||
// Verbosity settings for search
|
||||
@@ -25,7 +26,7 @@ var yayVersion = "10.0.0"
|
||||
var localePath = "/usr/share/locale"
|
||||
|
||||
// savedInfo holds the current vcs info
|
||||
var savedInfo vcsInfo
|
||||
var savedInfo vcs.InfoStore
|
||||
|
||||
// YayConf holds the current config values for yay.
|
||||
var config *settings.Configuration
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
github.com/Jguer/go-alpm v0.0.0-20200405152916-a3feea4322e9 h1:lLQSUe6iRdtFrP0zkDV7n8I8XKSxRHQTEU1KRh4IOLg=
|
||||
github.com/Jguer/go-alpm v0.0.0-20200405152916-a3feea4322e9/go.mod h1:D5SUcIS9Yiz/L8cjRzq/992eERnx6ugYmGlc4e7xdus=
|
||||
github.com/Jguer/yay v8.1173.0+incompatible h1:1IO32DoPD6Ds4YeqER6ppNjUtQ75cbhuBoVzQI762yk=
|
||||
github.com/Morganamilo/go-pacmanconf v0.0.0-20180910220353-9c5265e1b14f h1:ptFKynTV1p8JCzqk81NcMj0DV0Xle+PdKxfHjPbdIOU=
|
||||
github.com/Morganamilo/go-pacmanconf v0.0.0-20180910220353-9c5265e1b14f/go.mod h1:Hk55m330jNiwxRodIlMCvw5iEyoRUCIY64W1p9D+tHc=
|
||||
github.com/Morganamilo/go-srcinfo v1.0.0 h1:Wh4nEF+HJWo+29hnxM18Q2hi+DUf0GejS13+Wg+dzmI=
|
||||
|
||||
+3
-4
@@ -977,9 +977,8 @@ func buildInstallPkgbuilds(
|
||||
return errShow
|
||||
}
|
||||
|
||||
err = saveVCSInfo(config.Runtime.VCSPath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
if errStore := config.Runtime.VCSStore.Save(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, errStore)
|
||||
}
|
||||
|
||||
if errDeps := asdeps(cmdArgs, deps); err != nil {
|
||||
@@ -1160,7 +1159,7 @@ func buildInstallPkgbuilds(
|
||||
var wg sync.WaitGroup
|
||||
for _, pkg := range base {
|
||||
wg.Add(1)
|
||||
go updateVCSData(config.Runtime.VCSPath, pkg.Name, srcinfo.Source, &mux, &wg)
|
||||
go config.Runtime.VCSStore.Update(pkg.Name, srcinfo.Source, &mux, &wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package main // import "github.com/Jguer/yay"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -24,57 +22,6 @@ func initGotext() {
|
||||
gotext.Configure(localePath, os.Getenv("LANG"), "yay")
|
||||
}
|
||||
|
||||
func initConfig(configPath string) error {
|
||||
cfile, err := os.Open(configPath)
|
||||
if !os.IsNotExist(err) && err != nil {
|
||||
return errors.New(gotext.Get("failed to open config file '%s': %s", configPath, err))
|
||||
}
|
||||
|
||||
defer cfile.Close()
|
||||
if !os.IsNotExist(err) {
|
||||
decoder := json.NewDecoder(cfile)
|
||||
if err = decoder.Decode(&config); err != nil {
|
||||
return errors.New(gotext.Get("failed to read config file '%s': %s", configPath, err))
|
||||
}
|
||||
}
|
||||
|
||||
aurdest := os.Getenv("AURDEST")
|
||||
if aurdest != "" {
|
||||
config.BuildDir = aurdest
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initVCS(vcsFilePath string) error {
|
||||
vfile, err := os.Open(vcsFilePath)
|
||||
if !os.IsNotExist(err) && err != nil {
|
||||
return errors.New(gotext.Get("failed to open vcs file '%s': %s", vcsFilePath, err))
|
||||
}
|
||||
|
||||
defer vfile.Close()
|
||||
if !os.IsNotExist(err) {
|
||||
decoder := json.NewDecoder(vfile)
|
||||
if err = decoder.Decode(&savedInfo); err != nil {
|
||||
return errors.New(gotext.Get("failed to read vcs file '%s': %s", vcsFilePath, err))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initBuildDir() error {
|
||||
if _, err := os.Stat(config.BuildDir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(config.BuildDir, 0o755); err != nil {
|
||||
return errors.New(gotext.Get("failed to create BuildDir directory '%s': %s", config.BuildDir, err))
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initAlpm(cmdArgs *settings.Arguments, pacmanConfigPath string) (*pacmanconf.Config, bool, error) {
|
||||
root := "/"
|
||||
if value, _, exists := cmdArgs.GetArg("root", "r"); exists {
|
||||
@@ -124,6 +71,7 @@ func initAlpm(cmdArgs *settings.Arguments, pacmanConfigPath string) (*pacmanconf
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
ret := 0
|
||||
defer func() { os.Exit(ret) }()
|
||||
initGotext()
|
||||
@@ -131,28 +79,16 @@ func main() {
|
||||
text.Warnln(gotext.Get("Avoid running yay as root/sudo."))
|
||||
}
|
||||
|
||||
config, err = settings.NewConfig()
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
fmt.Fprintln(os.Stderr, str)
|
||||
}
|
||||
ret = 1
|
||||
return
|
||||
}
|
||||
|
||||
cmdArgs := settings.MakeArguments()
|
||||
runtime, err := settings.MakeRuntime()
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
fmt.Fprintln(os.Stderr, str)
|
||||
}
|
||||
ret = 1
|
||||
return
|
||||
}
|
||||
|
||||
config = settings.MakeConfig()
|
||||
config.Runtime = runtime
|
||||
|
||||
err = initConfig(runtime.ConfigPath)
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
fmt.Fprintln(os.Stderr, str)
|
||||
}
|
||||
ret = 1
|
||||
return
|
||||
}
|
||||
|
||||
err = cmdArgs.ParseCommandLine(config)
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
@@ -163,30 +99,12 @@ func main() {
|
||||
}
|
||||
|
||||
if config.Runtime.SaveConfig {
|
||||
errS := config.SaveConfig(runtime.ConfigPath)
|
||||
errS := config.Save(config.Runtime.ConfigPath)
|
||||
if errS != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
|
||||
config.ExpandEnv()
|
||||
err = initBuildDir()
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
fmt.Fprintln(os.Stderr, str)
|
||||
}
|
||||
ret = 1
|
||||
return
|
||||
}
|
||||
|
||||
err = initVCS(runtime.VCSPath)
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
fmt.Fprintln(os.Stderr, str)
|
||||
}
|
||||
ret = 1
|
||||
return
|
||||
}
|
||||
var useColor bool
|
||||
config.Runtime.PacmanConf, useColor, err = initAlpm(cmdArgs, config.PacmanConf)
|
||||
if err != nil {
|
||||
@@ -199,7 +117,7 @@ func main() {
|
||||
|
||||
text.UseColor = useColor
|
||||
|
||||
dbExecutor, err := ialpm.NewExecutor(runtime.PacmanConf)
|
||||
dbExecutor, err := ialpm.NewExecutor(config.Runtime.PacmanConf)
|
||||
if err != nil {
|
||||
if str := err.Error(); str != "" {
|
||||
fmt.Fprintln(os.Stderr, str)
|
||||
|
||||
+5
-3
@@ -10,7 +10,8 @@ import (
|
||||
)
|
||||
|
||||
func TestPacmanConf(t *testing.T) {
|
||||
expectedPacmanConf := &pacmanconf.Config{RootDir: "/",
|
||||
expectedPacmanConf := &pacmanconf.Config{
|
||||
RootDir: "/",
|
||||
DBPath: "//var/lib/pacman/",
|
||||
CacheDir: []string{"/cachedir/", "/another/"},
|
||||
HookDir: []string{"/hookdir/"},
|
||||
@@ -36,12 +37,13 @@ func TestPacmanConf(t *testing.T) {
|
||||
DisableDownloadTimeout: false,
|
||||
Repos: []pacmanconf.Repository{
|
||||
{Name: "repo1", Servers: []string{"repo1"}, SigLevel: []string(nil), Usage: []string{"All"}},
|
||||
{Name: "repo2", Servers: []string{"repo2"}, SigLevel: []string(nil), Usage: []string{"All"}}}}
|
||||
{Name: "repo2", Servers: []string{"repo2"}, SigLevel: []string(nil), Usage: []string{"All"}},
|
||||
},
|
||||
}
|
||||
|
||||
pacmanConf, color, err := initAlpm(settings.MakeArguments(), "testdata/pacman.conf")
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, pacmanConf)
|
||||
assert.Equal(t, color, false)
|
||||
assert.EqualValues(t, expectedPacmanConf, pacmanConf)
|
||||
|
||||
}
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
)
|
||||
|
||||
func TestAlpmExecutor(t *testing.T) {
|
||||
pacmanConf := &pacmanconf.Config{RootDir: "/",
|
||||
pacmanConf := &pacmanconf.Config{
|
||||
RootDir: "/",
|
||||
DBPath: "/var/lib/pacman/",
|
||||
CacheDir: []string{"/cachedir/", "/another/"},
|
||||
HookDir: []string{"/hookdir/"},
|
||||
@@ -34,7 +35,9 @@ func TestAlpmExecutor(t *testing.T) {
|
||||
DisableDownloadTimeout: false,
|
||||
Repos: []pacmanconf.Repository{
|
||||
{Name: "repo1", Servers: []string{"repo1"}, SigLevel: []string(nil), Usage: []string{"All"}},
|
||||
{Name: "repo2", Servers: []string{"repo2"}, SigLevel: []string(nil), Usage: []string{"All"}}}}
|
||||
{Name: "repo2", Servers: []string{"repo2"}, SigLevel: []string(nil), Usage: []string{"All"}},
|
||||
},
|
||||
}
|
||||
|
||||
aExec, err := NewExecutor(pacmanConf)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -22,30 +22,39 @@ type Package struct {
|
||||
func (p *Package) Base() string {
|
||||
return p.PBase
|
||||
}
|
||||
|
||||
func (p *Package) BuildDate() time.Time {
|
||||
return p.PBuildDate
|
||||
}
|
||||
|
||||
func (p *Package) DB() *alpm.DB {
|
||||
return p.PDB
|
||||
}
|
||||
|
||||
func (p *Package) Description() string {
|
||||
return p.PDescription
|
||||
}
|
||||
|
||||
func (p *Package) ISize() int64 {
|
||||
return p.PISize
|
||||
}
|
||||
|
||||
func (p *Package) Name() string {
|
||||
return p.PName
|
||||
}
|
||||
|
||||
func (p *Package) ShouldIgnore() bool {
|
||||
return p.PShouldIgnore
|
||||
}
|
||||
|
||||
func (p *Package) Size() int64 {
|
||||
return p.PSize
|
||||
}
|
||||
|
||||
func (p *Package) Version() string {
|
||||
return p.PVersion
|
||||
}
|
||||
|
||||
func (p *Package) Reason() alpm.PkgReason {
|
||||
return p.PReason
|
||||
}
|
||||
+93
-37
@@ -5,6 +5,12 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/Jguer/yay/v10/pkg/settings/exe"
|
||||
"github.com/Jguer/yay/v10/pkg/vcs"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -67,11 +73,12 @@ type Configuration struct {
|
||||
}
|
||||
|
||||
// SaveConfig writes yay config to file.
|
||||
func (config *Configuration) SaveConfig(configPath string) error {
|
||||
marshalledinfo, err := json.MarshalIndent(config, "", "\t")
|
||||
func (c *Configuration) Save(configPath string) error {
|
||||
marshalledinfo, err := json.MarshalIndent(c, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// https://github.com/Jguer/yay/issues/1325
|
||||
marshalledinfo = append(marshalledinfo, '\n')
|
||||
in, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
@@ -85,49 +92,49 @@ func (config *Configuration) SaveConfig(configPath string) error {
|
||||
return in.Sync()
|
||||
}
|
||||
|
||||
func (config *Configuration) ExpandEnv() {
|
||||
config.AURURL = os.ExpandEnv(config.AURURL)
|
||||
config.ABSDir = os.ExpandEnv(config.ABSDir)
|
||||
config.BuildDir = os.ExpandEnv(config.BuildDir)
|
||||
config.Editor = os.ExpandEnv(config.Editor)
|
||||
config.EditorFlags = os.ExpandEnv(config.EditorFlags)
|
||||
config.MakepkgBin = os.ExpandEnv(config.MakepkgBin)
|
||||
config.MakepkgConf = os.ExpandEnv(config.MakepkgConf)
|
||||
config.PacmanBin = os.ExpandEnv(config.PacmanBin)
|
||||
config.PacmanConf = os.ExpandEnv(config.PacmanConf)
|
||||
config.GpgFlags = os.ExpandEnv(config.GpgFlags)
|
||||
config.MFlags = os.ExpandEnv(config.MFlags)
|
||||
config.GitFlags = os.ExpandEnv(config.GitFlags)
|
||||
config.SortBy = os.ExpandEnv(config.SortBy)
|
||||
config.SearchBy = os.ExpandEnv(config.SearchBy)
|
||||
config.GitBin = os.ExpandEnv(config.GitBin)
|
||||
config.GpgBin = os.ExpandEnv(config.GpgBin)
|
||||
config.SudoBin = os.ExpandEnv(config.SudoBin)
|
||||
config.SudoFlags = os.ExpandEnv(config.SudoFlags)
|
||||
config.ReDownload = os.ExpandEnv(config.ReDownload)
|
||||
config.ReBuild = os.ExpandEnv(config.ReBuild)
|
||||
config.AnswerClean = os.ExpandEnv(config.AnswerClean)
|
||||
config.AnswerDiff = os.ExpandEnv(config.AnswerDiff)
|
||||
config.AnswerEdit = os.ExpandEnv(config.AnswerEdit)
|
||||
config.AnswerUpgrade = os.ExpandEnv(config.AnswerUpgrade)
|
||||
config.RemoveMake = os.ExpandEnv(config.RemoveMake)
|
||||
func (c *Configuration) expandEnv() {
|
||||
c.AURURL = os.ExpandEnv(c.AURURL)
|
||||
c.ABSDir = os.ExpandEnv(c.ABSDir)
|
||||
c.BuildDir = os.ExpandEnv(c.BuildDir)
|
||||
c.Editor = os.ExpandEnv(c.Editor)
|
||||
c.EditorFlags = os.ExpandEnv(c.EditorFlags)
|
||||
c.MakepkgBin = os.ExpandEnv(c.MakepkgBin)
|
||||
c.MakepkgConf = os.ExpandEnv(c.MakepkgConf)
|
||||
c.PacmanBin = os.ExpandEnv(c.PacmanBin)
|
||||
c.PacmanConf = os.ExpandEnv(c.PacmanConf)
|
||||
c.GpgFlags = os.ExpandEnv(c.GpgFlags)
|
||||
c.MFlags = os.ExpandEnv(c.MFlags)
|
||||
c.GitFlags = os.ExpandEnv(c.GitFlags)
|
||||
c.SortBy = os.ExpandEnv(c.SortBy)
|
||||
c.SearchBy = os.ExpandEnv(c.SearchBy)
|
||||
c.GitBin = os.ExpandEnv(c.GitBin)
|
||||
c.GpgBin = os.ExpandEnv(c.GpgBin)
|
||||
c.SudoBin = os.ExpandEnv(c.SudoBin)
|
||||
c.SudoFlags = os.ExpandEnv(c.SudoFlags)
|
||||
c.ReDownload = os.ExpandEnv(c.ReDownload)
|
||||
c.ReBuild = os.ExpandEnv(c.ReBuild)
|
||||
c.AnswerClean = os.ExpandEnv(c.AnswerClean)
|
||||
c.AnswerDiff = os.ExpandEnv(c.AnswerDiff)
|
||||
c.AnswerEdit = os.ExpandEnv(c.AnswerEdit)
|
||||
c.AnswerUpgrade = os.ExpandEnv(c.AnswerUpgrade)
|
||||
c.RemoveMake = os.ExpandEnv(c.RemoveMake)
|
||||
}
|
||||
|
||||
func (config *Configuration) String() string {
|
||||
func (c *Configuration) String() string {
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
enc.SetIndent("", "\t")
|
||||
if err := enc.Encode(config); err != nil {
|
||||
if err := enc.Encode(c); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func MakeConfig() *Configuration {
|
||||
newConfig := &Configuration{
|
||||
func DefaultConfig() *Configuration {
|
||||
return &Configuration{
|
||||
AURURL: "https://aur.archlinux.org",
|
||||
BuildDir: "$HOME/.cache/yay",
|
||||
ABSDir: "$HOME/.cache/yay/abs",
|
||||
BuildDir: os.ExpandEnv("$HOME/.cache/yay"),
|
||||
ABSDir: os.ExpandEnv("$HOME/.cache/yay/abs"),
|
||||
CleanAfter: false,
|
||||
Editor: "",
|
||||
EditorFlags: "",
|
||||
@@ -167,10 +174,59 @@ func MakeConfig() *Configuration {
|
||||
UseAsk: false,
|
||||
CombinedUpgrade: false,
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("XDG_CACHE_HOME") != "" {
|
||||
newConfig.BuildDir = "$XDG_CACHE_HOME/yay"
|
||||
func NewConfig() (*Configuration, error) {
|
||||
newConfig := DefaultConfig()
|
||||
|
||||
cacheHome := getCacheHome()
|
||||
newConfig.BuildDir = cacheHome
|
||||
|
||||
configPath := getConfigPath()
|
||||
newConfig.load(configPath)
|
||||
|
||||
if aurdest := os.Getenv("AURDEST"); aurdest != "" {
|
||||
newConfig.BuildDir = aurdest
|
||||
}
|
||||
|
||||
return newConfig
|
||||
newConfig.expandEnv()
|
||||
|
||||
newConfig.Runtime = &Runtime{
|
||||
Mode: ModeAny,
|
||||
SaveConfig: false,
|
||||
CompletionPath: filepath.Join(cacheHome, completionFileName),
|
||||
CmdRunner: &exe.OSRunner{},
|
||||
CmdBuilder: exe.NewCmdBuilder(newConfig.GitBin, newConfig.GitFlags),
|
||||
PacmanConf: nil,
|
||||
VCSStore: nil,
|
||||
}
|
||||
|
||||
newConfig.Runtime.VCSStore = vcs.NewInfoStore(filepath.Join(cacheHome, vcsFileName),
|
||||
newConfig.Runtime.CmdRunner, newConfig.Runtime.CmdBuilder)
|
||||
|
||||
if err := initDir(newConfig.BuildDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err := newConfig.Runtime.VCSStore.Load()
|
||||
|
||||
return newConfig, err
|
||||
}
|
||||
|
||||
func (c *Configuration) load(configPath string) {
|
||||
cfile, err := os.Open(configPath)
|
||||
if !os.IsNotExist(err) && err != nil {
|
||||
fmt.Fprintln(os.Stderr,
|
||||
gotext.Get("failed to open config file '%s': %s", configPath, err))
|
||||
return
|
||||
}
|
||||
|
||||
defer cfile.Close()
|
||||
if !os.IsNotExist(err) {
|
||||
decoder := json.NewDecoder(cfile)
|
||||
if err = decoder.Decode(c); err != nil {
|
||||
fmt.Fprintln(os.Stderr,
|
||||
gotext.Get("failed to read config file '%s': %s", configPath, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// configFileName holds the name of the config file.
|
||||
const configFileName string = "config.json"
|
||||
|
||||
// vcsFileName holds the name of the vcs file.
|
||||
const vcsFileName string = "vcs.json"
|
||||
|
||||
const completionFileName string = "completion.cache"
|
||||
|
||||
func getConfigPath() string {
|
||||
if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
if err := initDir(configHome); err == nil {
|
||||
return filepath.Join(configHome, "yay", configFileName)
|
||||
}
|
||||
}
|
||||
|
||||
if configHome := os.Getenv("HOME"); configHome != "" {
|
||||
if err := initDir(configHome); err == nil {
|
||||
return filepath.Join(configHome, ".config", "yay", configFileName)
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func getCacheHome() string {
|
||||
if cacheHome := os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
|
||||
if err := initDir(cacheHome); err == nil {
|
||||
return filepath.Join(cacheHome, "yay")
|
||||
}
|
||||
}
|
||||
|
||||
if cacheHome := os.Getenv("HOME"); cacheHome != "" {
|
||||
if err := initDir(cacheHome); err == nil {
|
||||
return filepath.Join(cacheHome, ".cache", "yay")
|
||||
}
|
||||
}
|
||||
|
||||
return "/tmp"
|
||||
}
|
||||
|
||||
func initDir(dir string) error {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, 0o755); err != nil {
|
||||
return errors.New(gotext.Get("failed to create config directory '%s': %s", dir, err))
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package exe
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Jguer/yay/v10/pkg/text"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package exe
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CmdBuilder struct {
|
||||
GitBin string
|
||||
GitFlags []string
|
||||
}
|
||||
|
||||
func NewCmdBuilder(gitBin, gitFlags string) *CmdBuilder {
|
||||
c := &CmdBuilder{GitBin: gitBin, GitFlags: strings.Fields(gitFlags)}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CmdBuilder) BuildGitCmd(dir string, extraArgs ...string) *exec.Cmd {
|
||||
args := make([]string, 0, len(c.GitFlags))
|
||||
copy(args, c.GitFlags)
|
||||
|
||||
if dir != "" {
|
||||
args = append(args, "-C", dir)
|
||||
}
|
||||
|
||||
args = append(args, extraArgs...)
|
||||
|
||||
cmd := exec.Command(c.GitBin, args...)
|
||||
cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")
|
||||
return cmd
|
||||
}
|
||||
+5
-131
@@ -1,153 +1,27 @@
|
||||
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"
|
||||
"github.com/Jguer/yay/v10/pkg/settings/exe"
|
||||
"github.com/Jguer/yay/v10/pkg/vcs"
|
||||
)
|
||||
|
||||
type TargetMode int
|
||||
|
||||
// configFileName holds the name of the config file.
|
||||
const configFileName string = "config.json"
|
||||
|
||||
// vcsFileName holds the name of the vcs file.
|
||||
const vcsFileName string = "vcs.json"
|
||||
|
||||
const completionFileName string = "completion.cache"
|
||||
|
||||
const (
|
||||
ModeAny TargetMode = iota
|
||||
ModeAUR
|
||||
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
|
||||
CompletionPath string
|
||||
ConfigPath string
|
||||
VCSPath string
|
||||
PacmanConf *pacmanconf.Config
|
||||
CmdRunner Runner
|
||||
}
|
||||
|
||||
func MakeRuntime() (*Runtime, error) {
|
||||
cacheHome := ""
|
||||
configHome := ""
|
||||
|
||||
runtime := &Runtime{
|
||||
Mode: ModeAny,
|
||||
SaveConfig: false,
|
||||
CompletionPath: "",
|
||||
CmdRunner: &OSRunner{},
|
||||
}
|
||||
|
||||
if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
configHome = filepath.Join(configHome, "yay")
|
||||
} else if configHome = os.Getenv("HOME"); configHome != "" {
|
||||
configHome = filepath.Join(configHome, ".config", "yay")
|
||||
} else {
|
||||
return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CONFIG_HOME", "HOME"))
|
||||
}
|
||||
|
||||
if err := initDir(configHome); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
|
||||
cacheHome = filepath.Join(cacheHome, "yay")
|
||||
} else if cacheHome = os.Getenv("HOME"); cacheHome != "" {
|
||||
cacheHome = filepath.Join(cacheHome, ".cache", "yay")
|
||||
} else {
|
||||
return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CACHE_HOME", "HOME"))
|
||||
}
|
||||
|
||||
if err := initDir(cacheHome); err != nil {
|
||||
return runtime, err
|
||||
}
|
||||
|
||||
runtime.ConfigPath = filepath.Join(configHome, configFileName)
|
||||
runtime.VCSPath = filepath.Join(cacheHome, vcsFileName)
|
||||
runtime.CompletionPath = filepath.Join(cacheHome, completionFileName)
|
||||
|
||||
return runtime, nil
|
||||
}
|
||||
|
||||
func initDir(dir string) error {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, 0o755); err != nil {
|
||||
return errors.New(gotext.Get("failed to create config directory '%s': %s", dir, err))
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
VCSStore *vcs.InfoStore
|
||||
CmdBuilder *exe.CmdBuilder
|
||||
CmdRunner exe.Runner
|
||||
}
|
||||
+2
-1
@@ -46,7 +46,8 @@ func NewInfoStore(filePath string, runner exe.Runner, cmdBuilder *exe.CmdBuilder
|
||||
CmdBuilder: cmdBuilder,
|
||||
FilePath: filePath,
|
||||
OriginsByPackage: map[string]OriginInfoByURL{},
|
||||
Runner: runner}
|
||||
Runner: runner,
|
||||
}
|
||||
|
||||
return infoStore
|
||||
}
|
||||
|
||||
+13
-9
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/Jguer/yay/v10/pkg/settings"
|
||||
"github.com/Jguer/yay/v10/pkg/text"
|
||||
"github.com/Jguer/yay/v10/pkg/upgrade"
|
||||
"github.com/Jguer/yay/v10/pkg/vcs"
|
||||
|
||||
rpc "github.com/mikkeloscar/aur"
|
||||
|
||||
@@ -97,20 +98,23 @@ func upList(warnings *query.AURWarnings, dbExecutor db.Executor, enableDowngrade
|
||||
return aurUp, repoUp, errs.Return()
|
||||
}
|
||||
|
||||
func upDevel(remote []db.RepoPackage, aurdata map[string]*rpc.Pkg, localCache vcsInfo) upgrade.UpSlice {
|
||||
func upDevel(
|
||||
remote []db.RepoPackage,
|
||||
aurdata map[string]*rpc.Pkg,
|
||||
localCache vcs.InfoStore) upgrade.UpSlice {
|
||||
toUpdate := make([]db.RepoPackage, 0, len(aurdata))
|
||||
toRemove := make([]string, 0)
|
||||
|
||||
var mux1, mux2 sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
|
||||
checkUpdate := func(vcsName string, e shaInfos) {
|
||||
checkUpdate := func(pkgName string, e vcs.OriginInfoByURL) {
|
||||
defer wg.Done()
|
||||
|
||||
if e.needsUpdate() {
|
||||
if _, ok := aurdata[vcsName]; ok {
|
||||
if localCache.NeedsUpdate(e) {
|
||||
if _, ok := aurdata[pkgName]; ok {
|
||||
for _, pkg := range remote {
|
||||
if pkg.Name() == vcsName {
|
||||
if pkg.Name() == pkgName {
|
||||
mux1.Lock()
|
||||
toUpdate = append(toUpdate, pkg)
|
||||
mux1.Unlock()
|
||||
@@ -120,14 +124,14 @@ func upDevel(remote []db.RepoPackage, aurdata map[string]*rpc.Pkg, localCache vc
|
||||
}
|
||||
|
||||
mux2.Lock()
|
||||
toRemove = append(toRemove, vcsName)
|
||||
toRemove = append(toRemove, pkgName)
|
||||
mux2.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
for vcsName, e := range localCache {
|
||||
for pkgName, e := range localCache.OriginsByPackage {
|
||||
wg.Add(1)
|
||||
go checkUpdate(vcsName, e)
|
||||
go checkUpdate(pkgName, e)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@@ -147,7 +151,7 @@ func upDevel(remote []db.RepoPackage, aurdata map[string]*rpc.Pkg, localCache vc
|
||||
}
|
||||
}
|
||||
|
||||
removeVCSPackage(toRemove, localCache)
|
||||
localCache.RemovePackage(toRemove)
|
||||
return toUpgrade
|
||||
}
|
||||
|
||||
|
||||
+121
-67
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/Jguer/yay/v10/pkg/db/mock"
|
||||
"github.com/Jguer/yay/v10/pkg/settings"
|
||||
"github.com/Jguer/yay/v10/pkg/upgrade"
|
||||
"github.com/Jguer/yay/v10/pkg/vcs"
|
||||
)
|
||||
|
||||
func Test_upAUR(t *testing.T) {
|
||||
@@ -30,32 +31,40 @@ func Test_upAUR(t *testing.T) {
|
||||
args args
|
||||
want upgrade.UpSlice
|
||||
}{
|
||||
{name: "No Updates",
|
||||
{
|
||||
name: "No Updates",
|
||||
args: args{
|
||||
remote: []db.RepoPackage{
|
||||
&mock.Package{PName: "hello", PVersion: "2.0.0"},
|
||||
&mock.Package{PName: "local_pkg", PVersion: "1.1.0"},
|
||||
&mock.Package{PName: "ignored", PVersion: "1.0.0", PShouldIgnore: true}},
|
||||
&mock.Package{PName: "ignored", PVersion: "1.0.0", PShouldIgnore: true},
|
||||
},
|
||||
aurdata: map[string]*rpc.Pkg{
|
||||
"hello": {Version: "2.0.0", Name: "hello"},
|
||||
"ignored": {Version: "2.0.0", Name: "ignored"}},
|
||||
"ignored": {Version: "2.0.0", Name: "ignored"},
|
||||
},
|
||||
timeUpdate: false,
|
||||
},
|
||||
want: upgrade.UpSlice{}},
|
||||
{name: "Simple Update",
|
||||
want: upgrade.UpSlice{},
|
||||
},
|
||||
{
|
||||
name: "Simple Update",
|
||||
args: args{
|
||||
remote: []db.RepoPackage{&mock.Package{PName: "hello", PVersion: "2.0.0"}},
|
||||
aurdata: map[string]*rpc.Pkg{"hello": {Version: "2.1.0", Name: "hello"}},
|
||||
timeUpdate: false,
|
||||
},
|
||||
want: upgrade.UpSlice{upgrade.Upgrade{Name: "hello", Repository: "aur", LocalVersion: "2.0.0", RemoteVersion: "2.1.0"}}},
|
||||
{name: "Time Update",
|
||||
want: upgrade.UpSlice{upgrade.Upgrade{Name: "hello", Repository: "aur", LocalVersion: "2.0.0", RemoteVersion: "2.1.0"}},
|
||||
},
|
||||
{
|
||||
name: "Time Update",
|
||||
args: args{
|
||||
remote: []db.RepoPackage{&mock.Package{PName: "hello", PVersion: "2.0.0", PBuildDate: time.Now()}},
|
||||
aurdata: map[string]*rpc.Pkg{"hello": {Version: "2.0.0", Name: "hello", LastModified: int(time.Now().AddDate(0, 0, 2).Unix())}},
|
||||
timeUpdate: true,
|
||||
},
|
||||
want: upgrade.UpSlice{upgrade.Upgrade{Name: "hello", Repository: "aur", LocalVersion: "2.0.0", RemoteVersion: "2.0.0"}}},
|
||||
want: upgrade.UpSlice{upgrade.Upgrade{Name: "hello", Repository: "aur", LocalVersion: "2.0.0", RemoteVersion: "2.0.0"}},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -96,8 +105,10 @@ func (r *MockRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr strin
|
||||
}
|
||||
|
||||
func Test_upDevel(t *testing.T) {
|
||||
config = settings.MakeConfig()
|
||||
config.Runtime, _ = settings.MakeRuntime()
|
||||
var err error
|
||||
config, err = settings.NewConfig()
|
||||
assert.NoError(t, err)
|
||||
|
||||
config.Runtime.CmdRunner = &MockRunner{
|
||||
Returned: []string{
|
||||
"7f4c277ce7149665d1c79b76ca8fbb832a65a03b HEAD",
|
||||
@@ -111,7 +122,7 @@ func Test_upDevel(t *testing.T) {
|
||||
type args struct {
|
||||
remote []db.RepoPackage
|
||||
aurdata map[string]*rpc.Pkg
|
||||
cached vcsInfo
|
||||
cached vcs.InfoStore
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -119,102 +130,145 @@ func Test_upDevel(t *testing.T) {
|
||||
want upgrade.UpSlice
|
||||
finalLen int
|
||||
}{
|
||||
{name: "No Updates",
|
||||
{
|
||||
name: "No Updates",
|
||||
args: args{
|
||||
cached: vcsInfo{},
|
||||
cached: vcs.InfoStore{
|
||||
Runner: config.Runtime.CmdRunner,
|
||||
CmdBuilder: config.Runtime.CmdBuilder,
|
||||
},
|
||||
remote: []db.RepoPackage{
|
||||
&mock.Package{PName: "hello", PVersion: "2.0.0"},
|
||||
&mock.Package{PName: "local_pkg", PVersion: "1.1.0"},
|
||||
&mock.Package{PName: "ignored", PVersion: "1.0.0", PShouldIgnore: true}},
|
||||
&mock.Package{PName: "ignored", PVersion: "1.0.0", PShouldIgnore: true},
|
||||
},
|
||||
aurdata: map[string]*rpc.Pkg{
|
||||
"hello": {Version: "2.0.0", Name: "hello"},
|
||||
"ignored": {Version: "2.0.0", Name: "ignored"}},
|
||||
"ignored": {Version: "2.0.0", Name: "ignored"},
|
||||
},
|
||||
},
|
||||
want: upgrade.UpSlice{}},
|
||||
{name: "Simple Update",
|
||||
want: upgrade.UpSlice{},
|
||||
},
|
||||
{
|
||||
name: "Simple Update",
|
||||
finalLen: 3,
|
||||
args: args{
|
||||
cached: vcsInfo{
|
||||
"hello": shaInfos{
|
||||
"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: "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"},
|
||||
cached: vcs.InfoStore{
|
||||
Runner: config.Runtime.CmdRunner,
|
||||
CmdBuilder: config.Runtime.CmdBuilder,
|
||||
OriginsByPackage: map[string]vcs.OriginInfoByURL{
|
||||
"hello": {
|
||||
"github.com/Jguer/z.git": vcs.OriginInfo{
|
||||
Protocols: []string{"https"},
|
||||
Branch: "0",
|
||||
SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1",
|
||||
},
|
||||
},
|
||||
"hello-non-existant": {
|
||||
"github.com/Jguer/y.git": vcs.OriginInfo{
|
||||
Protocols: []string{"https"},
|
||||
Branch: "0",
|
||||
SHA: "991c5b4146fd27f4aacf4e3111258a848934aaa1",
|
||||
},
|
||||
},
|
||||
"hello2": {
|
||||
"github.com/Jguer/a.git": vcs.OriginInfo{
|
||||
Protocols: []string{"https"},
|
||||
Branch: "1",
|
||||
SHA: "7f4c277ce7149665d1c79b76ca8fbb832a65a03b",
|
||||
},
|
||||
},
|
||||
"hello4": {
|
||||
"github.com/Jguer/b.git": vcs.OriginInfo{
|
||||
Protocols: []string{"https"},
|
||||
Branch: "2",
|
||||
SHA: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
},
|
||||
"github.com/Jguer/c.git": vcs.OriginInfo{
|
||||
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"}},
|
||||
&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"},
|
||||
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",
|
||||
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"}}},
|
||||
cached: vcs.InfoStore{
|
||||
Runner: config.Runtime.CmdRunner,
|
||||
CmdBuilder: config.Runtime.CmdBuilder,
|
||||
OriginsByPackage: map[string]vcs.OriginInfoByURL{
|
||||
"hello": {
|
||||
"github.com/Jguer/d.git": vcs.OriginInfo{
|
||||
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.0.0", Name: "hello"}},
|
||||
},
|
||||
want: upgrade.UpSlice{}},
|
||||
{name: "No update returned - ignored",
|
||||
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"}}},
|
||||
cached: vcs.InfoStore{
|
||||
Runner: config.Runtime.CmdRunner,
|
||||
CmdBuilder: config.Runtime.CmdBuilder,
|
||||
OriginsByPackage: map[string]vcs.OriginInfoByURL{
|
||||
"hello": {
|
||||
"github.com/Jguer/e.git": vcs.OriginInfo{
|
||||
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{}},
|
||||
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.ElementsMatch(t, tt.want, got)
|
||||
assert.Equal(t, tt.finalLen, len(tt.args.cached))
|
||||
assert.Equal(t, tt.finalLen, len(tt.args.cached.OriginsByPackage))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
gosrc "github.com/Morganamilo/go-srcinfo"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/Jguer/yay/v10/pkg/db"
|
||||
"github.com/Jguer/yay/v10/pkg/dep"
|
||||
"github.com/Jguer/yay/v10/pkg/query"
|
||||
"github.com/Jguer/yay/v10/pkg/settings"
|
||||
"github.com/Jguer/yay/v10/pkg/stringset"
|
||||
"github.com/Jguer/yay/v10/pkg/text"
|
||||
)
|
||||
|
||||
// Info contains the last commit sha of a repo
|
||||
type (
|
||||
vcsInfo map[string]shaInfos
|
||||
shaInfos map[string]shaInfo
|
||||
shaInfo struct {
|
||||
Protocols []string `json:"protocols"`
|
||||
Branch string `json:"branch"`
|
||||
SHA string `json:"sha"`
|
||||
}
|
||||
)
|
||||
|
||||
// createDevelDB forces yay to create a DB of the existing development packages
|
||||
func createDevelDB(vcsFilePath string, dbExecutor db.Executor) error {
|
||||
func createDevelDB(config *settings.Configuration, dbExecutor db.Executor) error {
|
||||
var mux sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
|
||||
@@ -58,7 +43,7 @@ func createDevelDB(vcsFilePath string, dbExecutor db.Executor) error {
|
||||
for i := range srcinfos {
|
||||
for iP := range srcinfos[i].Packages {
|
||||
wg.Add(1)
|
||||
go updateVCSData(vcsFilePath, srcinfos[i].Packages[iP].Pkgname, srcinfos[i].Source, &mux, &wg)
|
||||
go savedInfo.Update(srcinfos[i].Packages[iP].Pkgname, srcinfos[i].Source, &mux, &wg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,173 +51,3 @@ func createDevelDB(vcsFilePath string, dbExecutor db.Executor) error {
|
||||
text.OperationInfoln(gotext.Get("GenDB finished. No packages were installed"))
|
||||
return err
|
||||
}
|
||||
|
||||
// parseSource returns the git url, default branch and protocols it supports
|
||||
func parseSource(source string) (url, branch string, protocols []string) {
|
||||
split := strings.Split(source, "::")
|
||||
source = split[len(split)-1]
|
||||
split = strings.SplitN(source, "://", 2)
|
||||
|
||||
if len(split) != 2 {
|
||||
return "", "", nil
|
||||
}
|
||||
protocols = strings.SplitN(split[0], "+", 2)
|
||||
|
||||
git := false
|
||||
for _, protocol := range protocols {
|
||||
if protocol == "git" {
|
||||
git = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
protocols = protocols[len(protocols)-1:]
|
||||
|
||||
if !git {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
split = strings.SplitN(split[1], "#", 2)
|
||||
if len(split) == 2 {
|
||||
secondSplit := strings.SplitN(split[1], "=", 2)
|
||||
if secondSplit[0] != "branch" {
|
||||
// source has #commit= or #tag= which makes them not vcs
|
||||
// packages because they reference a specific point
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
if len(secondSplit) == 2 {
|
||||
url = split[0]
|
||||
branch = secondSplit[1]
|
||||
}
|
||||
} else {
|
||||
url = split[0]
|
||||
branch = "HEAD"
|
||||
}
|
||||
|
||||
url = strings.Split(url, "?")[0]
|
||||
branch = strings.Split(branch, "?")[0]
|
||||
|
||||
return url, branch, protocols
|
||||
}
|
||||
|
||||
func updateVCSData(vcsFilePath, pkgName string, sources []gosrc.ArchString, mux sync.Locker, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if savedInfo == nil {
|
||||
mux.Lock()
|
||||
savedInfo = make(vcsInfo)
|
||||
mux.Unlock()
|
||||
}
|
||||
|
||||
info := make(shaInfos)
|
||||
checkSource := func(source gosrc.ArchString) {
|
||||
defer wg.Done()
|
||||
url, branch, protocols := parseSource(source.Value)
|
||||
if url == "" || branch == "" {
|
||||
return
|
||||
}
|
||||
|
||||
commit := getCommit(url, branch, protocols)
|
||||
if commit == "" {
|
||||
return
|
||||
}
|
||||
|
||||
mux.Lock()
|
||||
info[url] = shaInfo{
|
||||
protocols,
|
||||
branch,
|
||||
commit,
|
||||
}
|
||||
|
||||
savedInfo[pkgName] = info
|
||||
text.Warnln(gotext.Get("Found git repo: %s", text.Cyan(url)))
|
||||
err := saveVCSInfo(vcsFilePath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
mux.Unlock()
|
||||
}
|
||||
|
||||
for _, source := range sources {
|
||||
wg.Add(1)
|
||||
go checkSource(source)
|
||||
}
|
||||
}
|
||||
|
||||
func getCommit(url, branch string, protocols []string) string {
|
||||
if len(protocols) > 0 {
|
||||
protocol := protocols[len(protocols)-1]
|
||||
|
||||
cmd := passToGit("", "ls-remote", protocol+"://"+url, branch)
|
||||
stdout, _, err := config.Runtime.CmdRunner.Capture(cmd, 5)
|
||||
if err != nil {
|
||||
text.Warnln(err)
|
||||
return ""
|
||||
}
|
||||
|
||||
split := strings.Fields(stdout)
|
||||
|
||||
if len(split) < 2 {
|
||||
return ""
|
||||
}
|
||||
|
||||
commit := split[0]
|
||||
return commit
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (infos shaInfos) needsUpdate() bool {
|
||||
// used to signal we have gone through all sources and found nothing
|
||||
finished := make(chan struct{})
|
||||
alive := 0
|
||||
|
||||
// if we find an update we use this to exit early and return true
|
||||
hasUpdate := make(chan struct{})
|
||||
|
||||
checkHash := func(url string, info shaInfo) {
|
||||
hash := getCommit(url, info.Branch, info.Protocols)
|
||||
if hash != "" && hash != info.SHA {
|
||||
hasUpdate <- struct{}{}
|
||||
} else {
|
||||
finished <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for url, info := range infos {
|
||||
alive++
|
||||
go checkHash(url, info)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-hasUpdate:
|
||||
return true
|
||||
case <-finished:
|
||||
alive--
|
||||
if alive == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func saveVCSInfo(vcsFilePath string) error {
|
||||
marshalledinfo, err := json.MarshalIndent(savedInfo, "", "\t")
|
||||
if err != nil || string(marshalledinfo) == "null" {
|
||||
return err
|
||||
}
|
||||
in, err := os.OpenFile(vcsFilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
_, err = in.Write(marshalledinfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = in.Sync()
|
||||
return err
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParsing(t *testing.T) {
|
||||
type source struct {
|
||||
URL string
|
||||
Branch string
|
||||
Protocols []string
|
||||
}
|
||||
|
||||
urls := []string{
|
||||
"git+https://github.com/neovim/neovim.git",
|
||||
"git://github.com/jguer/yay.git#branch=master",
|
||||
"git://github.com/davidgiven/ack",
|
||||
"git://github.com/jguer/yay.git#tag=v3.440",
|
||||
"git://github.com/jguer/yay.git#commit=e5470c88c6e2f9e0f97deb4728659ffa70ef5d0c",
|
||||
"a+b+c+d+e+f://github.com/jguer/yay.git#branch=foo",
|
||||
}
|
||||
|
||||
sources := []source{
|
||||
{"github.com/neovim/neovim.git", "HEAD", []string{"https"}},
|
||||
{"github.com/jguer/yay.git", "master", []string{"git"}},
|
||||
{"github.com/davidgiven/ack", "HEAD", []string{"git"}},
|
||||
{"", "", nil},
|
||||
{"", "", nil},
|
||||
{"", "", nil},
|
||||
}
|
||||
|
||||
for n, url := range urls {
|
||||
url, branch, protocols := parseSource(url)
|
||||
compare := sources[n]
|
||||
|
||||
assert.Equal(t, compare.URL, url)
|
||||
assert.Equal(t, compare.Branch, branch)
|
||||
assert.Equal(t, compare.Protocols, protocols)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user