mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
Initial commit
This commit is contained in:
21
vendor/github.com/gobuffalo/buffalo-plugins/LICENSE
generated
vendored
Normal file
21
vendor/github.com/gobuffalo/buffalo-plugins/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2018 Mark Bates
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
96
vendor/github.com/gobuffalo/buffalo-plugins/plugins/cache.go
generated
vendored
Normal file
96
vendor/github.com/gobuffalo/buffalo-plugins/plugins/cache.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/gobuffalo/envy"
|
||||
)
|
||||
|
||||
type cachedPlugin struct {
|
||||
Commands Commands `json:"commands"`
|
||||
CheckSum string `json:"check_sum"`
|
||||
}
|
||||
|
||||
type cachedPlugins map[string]cachedPlugin
|
||||
|
||||
var cachePath = func() string {
|
||||
home := "."
|
||||
if usr, err := user.Current(); err == nil {
|
||||
home = usr.HomeDir
|
||||
}
|
||||
return filepath.Join(home, ".buffalo", "plugin.cache")
|
||||
}()
|
||||
|
||||
var cacheMoot sync.RWMutex
|
||||
|
||||
var cacheOn = envy.Get("BUFFALO_PLUGIN_CACHE", "on")
|
||||
|
||||
var cache = func() cachedPlugins {
|
||||
m := cachedPlugins{}
|
||||
if cacheOn != "on" {
|
||||
return m
|
||||
}
|
||||
f, err := os.Open(cachePath)
|
||||
if err != nil {
|
||||
return m
|
||||
}
|
||||
defer f.Close()
|
||||
if err := json.NewDecoder(f).Decode(&m); err != nil {
|
||||
f.Close()
|
||||
os.Remove(f.Name())
|
||||
}
|
||||
return m
|
||||
}()
|
||||
|
||||
func findInCache(path string) (cachedPlugin, bool) {
|
||||
cacheMoot.RLock()
|
||||
defer cacheMoot.RUnlock()
|
||||
cp, ok := cache[path]
|
||||
return cp, ok
|
||||
}
|
||||
|
||||
func saveCache() error {
|
||||
if cacheOn != "on" {
|
||||
return nil
|
||||
}
|
||||
cacheMoot.Lock()
|
||||
defer cacheMoot.Unlock()
|
||||
os.MkdirAll(filepath.Dir(cachePath), 0744)
|
||||
f, err := os.Create(cachePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(f).Encode(cache)
|
||||
}
|
||||
|
||||
func sum(path string) string {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer f.Close()
|
||||
hash := sha256.New()
|
||||
if _, err := io.Copy(hash, f); err != nil {
|
||||
return ""
|
||||
}
|
||||
sum := hash.Sum(nil)
|
||||
|
||||
s := fmt.Sprintf("%x", sum)
|
||||
return s
|
||||
}
|
||||
|
||||
func addToCache(path string, cp cachedPlugin) {
|
||||
if cp.CheckSum == "" {
|
||||
cp.CheckSum = sum(path)
|
||||
}
|
||||
cacheMoot.Lock()
|
||||
defer cacheMoot.Unlock()
|
||||
cache[path] = cp
|
||||
}
|
||||
19
vendor/github.com/gobuffalo/buffalo-plugins/plugins/command.go
generated
vendored
Normal file
19
vendor/github.com/gobuffalo/buffalo-plugins/plugins/command.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package plugins
|
||||
|
||||
// Command that the plugin supplies
|
||||
type Command struct {
|
||||
// Name "foo"
|
||||
Name string `json:"name"`
|
||||
// UseCommand "bar"
|
||||
UseCommand string `json:"use_command"`
|
||||
// BuffaloCommand "generate"
|
||||
BuffaloCommand string `json:"buffalo_command"`
|
||||
// Description "generates a foo"
|
||||
Description string `json:"description,omitempty"`
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
Binary string `json:"-"`
|
||||
Flags []string `json:"flags,omitempty"`
|
||||
}
|
||||
|
||||
// Commands is a slice of Command
|
||||
type Commands []Command
|
||||
98
vendor/github.com/gobuffalo/buffalo-plugins/plugins/decorate.go
generated
vendored
Normal file
98
vendor/github.com/gobuffalo/buffalo-plugins/plugins/decorate.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/gobuffalo/envy"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// ErrPlugMissing ...
|
||||
var ErrPlugMissing = errors.New("plugin missing")
|
||||
|
||||
func Decorate(c Command) *cobra.Command {
|
||||
var flags []string
|
||||
if len(c.Flags) > 0 {
|
||||
for _, f := range c.Flags {
|
||||
flags = append(flags, f)
|
||||
}
|
||||
}
|
||||
cc := &cobra.Command{
|
||||
Use: c.Name,
|
||||
Short: fmt.Sprintf("[PLUGIN] %s", c.Description),
|
||||
Aliases: c.Aliases,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
plugCmd := c.Name
|
||||
if c.UseCommand != "" {
|
||||
plugCmd = c.UseCommand
|
||||
}
|
||||
|
||||
ax := []string{plugCmd}
|
||||
if plugCmd == "-" {
|
||||
ax = []string{}
|
||||
}
|
||||
|
||||
ax = append(ax, args...)
|
||||
ax = append(ax, flags...)
|
||||
|
||||
bin, err := LookPath(c.Binary)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
ex := exec.Command(bin, ax...)
|
||||
if runtime.GOOS != "windows" {
|
||||
ex.Env = append(envy.Environ(), "BUFFALO_PLUGIN=1")
|
||||
}
|
||||
ex.Stdin = os.Stdin
|
||||
ex.Stdout = os.Stdout
|
||||
ex.Stderr = os.Stderr
|
||||
return log(strings.Join(ex.Args, " "), ex.Run)
|
||||
},
|
||||
}
|
||||
cc.DisableFlagParsing = true
|
||||
return cc
|
||||
}
|
||||
|
||||
// LookPath ...
|
||||
func LookPath(s string) (string, error) {
|
||||
if _, err := os.Stat(s); err == nil {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
if lp, err := exec.LookPath(s); err == nil {
|
||||
return lp, err
|
||||
}
|
||||
|
||||
var bin string
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
var looks []string
|
||||
if from, err := envy.MustGet("BUFFALO_PLUGIN_PATH"); err == nil {
|
||||
looks = append(looks, from)
|
||||
} else {
|
||||
looks = []string{filepath.Join(pwd, "plugins"), filepath.Join(envy.GoPath(), "bin"), envy.Get("PATH", "")}
|
||||
}
|
||||
|
||||
for _, p := range looks {
|
||||
lp := filepath.Join(p, s)
|
||||
if lp, err = filepath.EvalSymlinks(lp); err == nil {
|
||||
bin = lp
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(bin) == 0 {
|
||||
return "", errors.Wrapf(ErrPlugMissing, "could not find %s in %q", s, looks)
|
||||
}
|
||||
return bin, nil
|
||||
}
|
||||
7
vendor/github.com/gobuffalo/buffalo-plugins/plugins/events.go
generated
vendored
Normal file
7
vendor/github.com/gobuffalo/buffalo-plugins/plugins/events.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package plugins
|
||||
|
||||
const (
|
||||
EvtSetupStarted = "buffalo-plugins:setup:started"
|
||||
EvtSetupErr = "buffalo-plugins:setup:err"
|
||||
EvtSetupFinished = "buffalo-plugins:setup:finished"
|
||||
)
|
||||
7
vendor/github.com/gobuffalo/buffalo-plugins/plugins/log.go
generated
vendored
Normal file
7
vendor/github.com/gobuffalo/buffalo-plugins/plugins/log.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
//+build !debug
|
||||
|
||||
package plugins
|
||||
|
||||
func log(_ string, fn func() error) error {
|
||||
return fn()
|
||||
}
|
||||
14
vendor/github.com/gobuffalo/buffalo-plugins/plugins/log_debug.go
generated
vendored
Normal file
14
vendor/github.com/gobuffalo/buffalo-plugins/plugins/log_debug.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
//+build debug
|
||||
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func log(name string, fn func() error) error {
|
||||
start := time.Now()
|
||||
defer fmt.Println(name, time.Now().Sub(start))
|
||||
return fn()
|
||||
}
|
||||
16
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/command.go
generated
vendored
Normal file
16
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/command.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package plugdeps
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// Command is the plugin command you want to control further
|
||||
type Command struct {
|
||||
Name string `toml:"name" json:"name"`
|
||||
Flags []string `toml:"flags,omitempty" json:"flags,omitempty"`
|
||||
Commands []Command `toml:"command,omitempty" json:"commands,omitempty"`
|
||||
}
|
||||
|
||||
// String implementation of fmt.Stringer
|
||||
func (p Command) String() string {
|
||||
b, _ := json.Marshal(p)
|
||||
return string(b)
|
||||
}
|
||||
88
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/plugdeps.go
generated
vendored
Normal file
88
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/plugdeps.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package plugdeps
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gobuffalo/meta"
|
||||
"github.com/karrick/godirwalk"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrMissingConfig is if config/buffalo-plugins.toml file is not found. Use plugdeps#On(app) to test if plugdeps are being used
|
||||
var ErrMissingConfig = errors.Errorf("could not find a buffalo-plugins config file at %s", ConfigPath(meta.New(".")))
|
||||
|
||||
// List all of the plugins the application depeneds on. Will return ErrMissingConfig
|
||||
// if the app is not using config/buffalo-plugins.toml to manage their plugins.
|
||||
// Use plugdeps#On(app) to test if plugdeps are being used.
|
||||
func List(app meta.App) (*Plugins, error) {
|
||||
plugs := New()
|
||||
if app.WithPop {
|
||||
plugs.Add(pop)
|
||||
}
|
||||
|
||||
lp, err := listLocal(app)
|
||||
if err != nil {
|
||||
return plugs, errors.WithStack(err)
|
||||
}
|
||||
plugs.Add(lp.List()...)
|
||||
|
||||
if !On(app) {
|
||||
return plugs, ErrMissingConfig
|
||||
}
|
||||
|
||||
p := ConfigPath(app)
|
||||
tf, err := os.Open(p)
|
||||
if err != nil {
|
||||
return plugs, errors.WithStack(err)
|
||||
}
|
||||
if err := plugs.Decode(tf); err != nil {
|
||||
return plugs, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return plugs, nil
|
||||
}
|
||||
|
||||
func listLocal(app meta.App) (*Plugins, error) {
|
||||
plugs := New()
|
||||
proot := filepath.Join(app.Root, "plugins")
|
||||
if _, err := os.Stat(proot); err != nil {
|
||||
return plugs, nil
|
||||
}
|
||||
err := godirwalk.Walk(proot, &godirwalk.Options{
|
||||
FollowSymbolicLinks: true,
|
||||
Callback: func(path string, info *godirwalk.Dirent) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
base := filepath.Base(path)
|
||||
if strings.HasPrefix(base, "buffalo-") {
|
||||
plugs.Add(Plugin{
|
||||
Binary: base,
|
||||
Local: "." + strings.TrimPrefix(path, app.Root),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return plugs, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return plugs, nil
|
||||
}
|
||||
|
||||
// ConfigPath returns the path to the config/buffalo-plugins.toml file
|
||||
// relative to the app
|
||||
func ConfigPath(app meta.App) string {
|
||||
return filepath.Join(app.Root, "config", "buffalo-plugins.toml")
|
||||
}
|
||||
|
||||
// On checks for the existence of config/buffalo-plugins.toml if this
|
||||
// file exists its contents will be used to list plugins. If the file is not
|
||||
// found, then the BUFFALO_PLUGIN_PATH and ./plugins folders are consulted.
|
||||
func On(app meta.App) bool {
|
||||
_, err := os.Stat(ConfigPath(app))
|
||||
return err == nil
|
||||
}
|
||||
26
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/plugin.go
generated
vendored
Normal file
26
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/plugin.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package plugdeps
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gobuffalo/meta"
|
||||
)
|
||||
|
||||
// Plugin represents a Go plugin for Buffalo applications
|
||||
type Plugin struct {
|
||||
Binary string `toml:"binary" json:"binary"`
|
||||
GoGet string `toml:"go_get,omitempty" json:"go_get,omitempty"`
|
||||
Local string `toml:"local,omitempty" json:"local,omitempty"`
|
||||
Commands []Command `toml:"command,omitempty" json:"commands,omitempty"`
|
||||
Tags meta.BuildTags `toml:"tags,omitempty" json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
// String implementation of fmt.Stringer
|
||||
func (p Plugin) String() string {
|
||||
b, _ := json.Marshal(p)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (p Plugin) key() string {
|
||||
return p.Binary + p.GoGet + p.Local
|
||||
}
|
||||
98
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/plugins.go
generated
vendored
Normal file
98
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/plugins.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package plugdeps
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Plugins manages the config/buffalo-plugins.toml file
|
||||
// as well as the plugins available from the file.
|
||||
type Plugins struct {
|
||||
plugins map[string]Plugin
|
||||
moot *sync.RWMutex
|
||||
}
|
||||
|
||||
// Encode the list of plugins, in TOML format, to the reader
|
||||
func (plugs *Plugins) Encode(w io.Writer) error {
|
||||
tp := tomlPlugins{
|
||||
Plugins: plugs.List(),
|
||||
}
|
||||
|
||||
if err := toml.NewEncoder(w).Encode(tp); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decode the list of plugins, in TOML format, from the reader
|
||||
func (plugs *Plugins) Decode(r io.Reader) error {
|
||||
tp := &tomlPlugins{
|
||||
Plugins: []Plugin{},
|
||||
}
|
||||
if _, err := toml.DecodeReader(r, tp); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
for _, p := range tp.Plugins {
|
||||
plugs.Add(p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// List of dependent plugins listed in order of Plugin.String()
|
||||
func (plugs *Plugins) List() []Plugin {
|
||||
m := map[string]Plugin{}
|
||||
plugs.moot.RLock()
|
||||
for _, p := range plugs.plugins {
|
||||
m[p.key()] = p
|
||||
}
|
||||
plugs.moot.RUnlock()
|
||||
var pp []Plugin
|
||||
for _, v := range m {
|
||||
pp = append(pp, v)
|
||||
}
|
||||
sort.Slice(pp, func(a, b int) bool {
|
||||
return pp[a].Binary < pp[b].Binary
|
||||
})
|
||||
return pp
|
||||
}
|
||||
|
||||
// Add plugin(s) to the list of dependencies
|
||||
func (plugs *Plugins) Add(pp ...Plugin) {
|
||||
plugs.moot.Lock()
|
||||
for _, p := range pp {
|
||||
plugs.plugins[p.key()] = p
|
||||
}
|
||||
plugs.moot.Unlock()
|
||||
}
|
||||
|
||||
// Remove plugin(s) from the list of dependencies
|
||||
func (plugs *Plugins) Remove(pp ...Plugin) {
|
||||
plugs.moot.Lock()
|
||||
for _, p := range pp {
|
||||
delete(plugs.plugins, p.key())
|
||||
}
|
||||
plugs.moot.Unlock()
|
||||
}
|
||||
|
||||
// New returns a configured *Plugins value
|
||||
func New() *Plugins {
|
||||
plugs := &Plugins{
|
||||
plugins: map[string]Plugin{},
|
||||
moot: &sync.RWMutex{},
|
||||
}
|
||||
plugs.Add(self)
|
||||
return plugs
|
||||
}
|
||||
|
||||
type tomlPlugins struct {
|
||||
Plugins []Plugin `toml:"plugin"`
|
||||
}
|
||||
|
||||
var self = Plugin{
|
||||
Binary: "buffalo-plugins",
|
||||
GoGet: "github.com/gobuffalo/buffalo-plugins",
|
||||
}
|
||||
6
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/pop.go
generated
vendored
Normal file
6
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugdeps/pop.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
package plugdeps
|
||||
|
||||
var pop = Plugin{
|
||||
Binary: "buffalo-pop",
|
||||
GoGet: "github.com/gobuffalo/buffalo-pop",
|
||||
}
|
||||
232
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugins.go
generated
vendored
Normal file
232
vendor/github.com/gobuffalo/buffalo-plugins/plugins/plugins.go
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gobuffalo/buffalo-plugins/plugins/plugdeps"
|
||||
"github.com/gobuffalo/envy"
|
||||
"github.com/gobuffalo/meta"
|
||||
"github.com/karrick/godirwalk"
|
||||
"github.com/markbates/oncer"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const timeoutEnv = "BUFFALO_PLUGIN_TIMEOUT"
|
||||
|
||||
var t = time.Second * 2
|
||||
|
||||
func timeout() time.Duration {
|
||||
oncer.Do("plugins.timeout", func() {
|
||||
rawTimeout, err := envy.MustGet(timeoutEnv)
|
||||
if err == nil {
|
||||
if parsed, err := time.ParseDuration(rawTimeout); err == nil {
|
||||
t = parsed
|
||||
} else {
|
||||
logrus.Errorf("%q value is malformed assuming default %q: %v", timeoutEnv, t, err)
|
||||
}
|
||||
} else {
|
||||
logrus.Debugf("%q not set, assuming default of %v", timeoutEnv, t)
|
||||
}
|
||||
})
|
||||
return t
|
||||
}
|
||||
|
||||
// List maps a Buffalo command to a slice of Command
|
||||
type List map[string]Commands
|
||||
|
||||
var _list List
|
||||
|
||||
// Available plugins for the `buffalo` command.
|
||||
// It will look in $GOPATH/bin and the `./plugins` directory.
|
||||
// This can be changed by setting the $BUFFALO_PLUGIN_PATH
|
||||
// environment variable.
|
||||
//
|
||||
// Requirements:
|
||||
// * file/command must be executable
|
||||
// * file/command must start with `buffalo-`
|
||||
// * file/command must respond to `available` and return JSON of
|
||||
// plugins.Commands{}
|
||||
//
|
||||
// Limit full path scan with direct plugin path
|
||||
//
|
||||
// If a file/command doesn't respond to being invoked with `available`
|
||||
// within one second, buffalo will assume that it is unable to load. This
|
||||
// can be changed by setting the $BUFFALO_PLUGIN_TIMEOUT environment
|
||||
// variable. It must be set to a duration that `time.ParseDuration` can
|
||||
// process.
|
||||
func Available() (List, error) {
|
||||
var err error
|
||||
oncer.Do("plugins.Available", func() {
|
||||
defer func() {
|
||||
if err := saveCache(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
app := meta.New(".")
|
||||
|
||||
if plugdeps.On(app) {
|
||||
_list, err = listPlugDeps(app)
|
||||
return
|
||||
}
|
||||
|
||||
paths := []string{"plugins"}
|
||||
|
||||
from, err := envy.MustGet("BUFFALO_PLUGIN_PATH")
|
||||
if err != nil {
|
||||
from, err = envy.MustGet("GOPATH")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
from = filepath.Join(from, "bin")
|
||||
}
|
||||
|
||||
paths = append(paths, strings.Split(from, string(os.PathListSeparator))...)
|
||||
|
||||
list := List{}
|
||||
for _, p := range paths {
|
||||
if ignorePath(p) {
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
err := godirwalk.Walk(p, &godirwalk.Options{
|
||||
FollowSymbolicLinks: true,
|
||||
Callback: func(path string, info *godirwalk.Dirent) error {
|
||||
if err != nil {
|
||||
// May indicate a permissions problem with the path, skip it
|
||||
return nil
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
base := filepath.Base(path)
|
||||
if strings.HasPrefix(base, "buffalo-") {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout())
|
||||
commands := askBin(ctx, path)
|
||||
cancel()
|
||||
for _, c := range commands {
|
||||
bc := c.BuffaloCommand
|
||||
if _, ok := list[bc]; !ok {
|
||||
list[bc] = Commands{}
|
||||
}
|
||||
c.Binary = path
|
||||
list[bc] = append(list[bc], c)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
_list = list
|
||||
})
|
||||
return _list, err
|
||||
}
|
||||
|
||||
func askBin(ctx context.Context, path string) Commands {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
logrus.Debugf("askBin %s=%.4f s", path, time.Since(start).Seconds())
|
||||
}()
|
||||
|
||||
commands := Commands{}
|
||||
defer func() {
|
||||
addToCache(path, cachedPlugin{
|
||||
Commands: commands,
|
||||
})
|
||||
}()
|
||||
if cp, ok := findInCache(path); ok {
|
||||
s := sum(path)
|
||||
if s == cp.CheckSum {
|
||||
logrus.Debugf("cache hit: %s", path)
|
||||
commands = cp.Commands
|
||||
return commands
|
||||
}
|
||||
}
|
||||
logrus.Debugf("cache miss: %s", path)
|
||||
if strings.HasPrefix(filepath.Base(path), "buffalo-no-sqlite") {
|
||||
return commands
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, path, "available")
|
||||
bb := &bytes.Buffer{}
|
||||
cmd.Stdout = bb
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return commands
|
||||
}
|
||||
msg := bb.String()
|
||||
for len(msg) > 0 {
|
||||
err = json.NewDecoder(strings.NewReader(msg)).Decode(&commands)
|
||||
if err == nil {
|
||||
return commands
|
||||
}
|
||||
msg = msg[1:]
|
||||
}
|
||||
logrus.Errorf("[PLUGIN] error decoding plugin %s: %s\n%s\n", path, err, msg)
|
||||
return commands
|
||||
}
|
||||
|
||||
func ignorePath(p string) bool {
|
||||
p = strings.ToLower(p)
|
||||
for _, x := range []string{`c:\windows`, `c:\program`} {
|
||||
if strings.HasPrefix(p, x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func listPlugDeps(app meta.App) (List, error) {
|
||||
list := List{}
|
||||
plugs, err := plugdeps.List(app)
|
||||
if err != nil {
|
||||
return list, err
|
||||
}
|
||||
for _, p := range plugs.List() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout())
|
||||
defer cancel()
|
||||
bin := p.Binary
|
||||
if len(p.Local) != 0 {
|
||||
bin = p.Local
|
||||
}
|
||||
bin, err := LookPath(bin)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != ErrPlugMissing {
|
||||
return list, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
commands := askBin(ctx, bin)
|
||||
cancel()
|
||||
for _, c := range commands {
|
||||
bc := c.BuffaloCommand
|
||||
if _, ok := list[bc]; !ok {
|
||||
list[bc] = Commands{}
|
||||
}
|
||||
c.Binary = p.Binary
|
||||
for _, pc := range p.Commands {
|
||||
if c.Name == pc.Name {
|
||||
c.Flags = pc.Flags
|
||||
break
|
||||
}
|
||||
}
|
||||
list[bc] = append(list[bc], c)
|
||||
}
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
3
vendor/github.com/gobuffalo/buffalo-plugins/plugins/version.go
generated
vendored
Normal file
3
vendor/github.com/gobuffalo/buffalo-plugins/plugins/version.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
package plugins
|
||||
|
||||
const Version = "v1.11.0"
|
||||
Reference in New Issue
Block a user