posh/example/.posh/command/gomod.go
Kevin Franklin Kim e2ad376b6c initial commit
2023-01-03 15:37:15 +01:00

198 lines
4.5 KiB
Go

package command
import (
"context"
"io/fs"
"path"
"github.com/charlievieth/fastwalk"
"github.com/foomo/posh/pkg/cache"
"github.com/foomo/posh/pkg/command/tree"
"github.com/foomo/posh/pkg/log"
"github.com/foomo/posh/pkg/prompt"
"github.com/foomo/posh/pkg/readline"
"github.com/foomo/posh/pkg/shell"
)
// GoMod command
type GoMod struct {
l log.Logger
cache cache.Namespace
parser *tree.Root
}
// ------------------------------------------------------------------------------------------------
// ~ Constructor
// ------------------------------------------------------------------------------------------------
// NewGoMod command
func NewGoMod(l log.Logger, cache cache.Cache) *GoMod {
inst := &GoMod{
l: l,
cache: cache.Get("gomod"),
}
pathArg := &tree.Arg{
Name: "path",
Optional: true,
Suggest: inst.completePaths,
}
inst.parser = &tree.Root{
Name: "gomod",
Nodes: []*tree.Node{
{
Name: "tidy",
Description: "run go mod tidy",
Args: []*tree.Arg{pathArg},
Execute: inst.tidy,
},
{
Name: "download",
Description: "run go mod download",
Args: []*tree.Arg{pathArg},
Execute: inst.download,
},
{
Name: "outdated",
Description: "show go mod outdated",
Args: []*tree.Arg{pathArg},
Execute: inst.outdated,
},
},
}
return inst
}
// ------------------------------------------------------------------------------------------------
// ~ Public methods
// ------------------------------------------------------------------------------------------------
func (c *GoMod) Name() string {
return c.parser.Name
}
func (c *GoMod) Description() string {
return "run go mod"
}
func (c *GoMod) Complete(ctx context.Context, r *readline.Readline, d prompt.Document) (suggests []prompt.Suggest) {
return c.parser.Complete(ctx, r)
}
func (c *GoMod) Execute(ctx context.Context, r *readline.Readline) error {
return c.parser.Execute(ctx, r)
}
func (c *GoMod) Help() string {
return `Looks for go.mod files and runs the given command.
Usage:
gomod [command] <path>
Available commands:
tidy run go mod tidy on specific or all paths
download run go mod download on specific or all paths
outdated list outdated packages on specific or all paths
Examples:
gomod tidy ./path
`
}
// ------------------------------------------------------------------------------------------------
// ~ Private methods
// ------------------------------------------------------------------------------------------------
func (c *GoMod) tidy(ctx context.Context, r *readline.Readline) error {
var paths []string
if r.Args().HasIndex(1) {
paths = []string{r.Args().At(1)}
} else {
paths = c.paths()
}
for _, value := range paths {
c.l.Info("go mod tidy:", value)
if err := shell.New(ctx, c.l,
"go", "mod", "tidy",
).
Args(r.AdditionalArgs()...).
Dir(value).
Run(); err != nil {
return err
}
}
return nil
}
func (c *GoMod) download(ctx context.Context, r *readline.Readline) error {
var paths []string
if r.Args().HasIndex(1) {
paths = []string{r.Args().At(1)}
} else {
paths = c.paths()
}
for _, value := range paths {
c.l.Info("go mod download:", value)
if err := shell.New(ctx, c.l,
"go", "mod", "tidy",
).
Args(r.AdditionalArgs()...).
Dir(value).
Run(); err != nil {
return err
}
}
return nil
}
func (c *GoMod) outdated(ctx context.Context, r *readline.Readline) error {
var paths []string
if r.Args().HasIndex(1) {
paths = []string{r.Args().At(1)}
} else {
paths = c.paths()
}
for _, value := range paths {
c.l.Info("go mod outdated:", value)
if err := shell.New(ctx, c.l,
"go", "list",
"-u", "-m", "-json", "all",
"|", "go-mod-outdated", "-update", "-direct",
).
Args(r.AdditionalArgs()...).
Dir(value).
Run(); err != nil {
return err
}
}
return nil
}
func (c *GoMod) completePaths(ctx context.Context, p *tree.Root, r *readline.Readline) (suggest []prompt.Suggest) {
for _, value := range c.paths() {
suggest = append(suggest, prompt.Suggest{Text: value})
}
return suggest
}
func (c *GoMod) paths() []string {
return c.cache.Get("paths", func() interface{} {
var ret []string
if err := fastwalk.Walk(&fastwalk.Config{
Follow: false,
}, ".", func(p string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.Name() == "go.mod" {
ret = append(ret, path.Dir(p))
}
return nil
}); err != nil {
c.l.Debug("failed to walk files", err.Error())
}
return ret
}).([]string)
}