44 "errors"
55 "fmt"
66 "os"
7+ "os/exec"
78 "path/filepath"
89
910 "gopkg.in/yaml.v2"
@@ -20,11 +21,18 @@ type Config struct {
2021}
2122
2223type PluginConfig struct {
23- ID string `yaml:"id"`
24- Name string `yaml:"name"`
25- Command string `yaml:"command"`
26- Args []string `yaml:"args"`
27- WorkDir string `yaml:"work_dir"`
24+ ID string `yaml:"id"`
25+ Name string `yaml:"name"`
26+ Command string `yaml:"command"`
27+ Args []string `yaml:"args"`
28+ WorkDir struct {
29+ Git struct {
30+ Enabled bool `yaml:"enabled"`
31+ Persistent bool `yaml:"persistent"`
32+ Version string `yaml:"version"`
33+ } `yaml:"git"`
34+ Path string `yaml:"path"`
35+ } `yaml:"work_dir"`
2836 Env map [string ]string `yaml:"env"`
2937 Address string `yaml:"address"`
3038}
@@ -53,14 +61,61 @@ func LoadConfig(path string) (Config, error) {
5361 cfg .HelloTimeoutMs = 2000
5462 }
5563 for i := range cfg .Plugins {
56- if cfg .Plugins [i ].ID == "" {
57- cfg .Plugins [i ].ID = fmt .Sprintf ("plugin-%d" , i + 1 )
64+ pl := & cfg .Plugins [i ]
65+ if pl .ID == "" {
66+ pl .ID = fmt .Sprintf ("plugin-%d" , i + 1 )
5867 }
59- if cfg .Plugins [i ].Command != "" && cfg .Plugins [i ].WorkDir != "" {
60- if ! filepath .IsAbs (cfg .Plugins [i ].WorkDir ) {
61- cfg .Plugins [i ].WorkDir = filepath .Clean (cfg .Plugins [i ].WorkDir )
68+ if pl .Command == "" || pl .WorkDir .Path == "" {
69+ continue
70+ }
71+
72+ if pl .WorkDir .Git .Enabled {
73+ path := filepath .Join (os .TempDir (), pl .ID )
74+ remote := pl .WorkDir .Path
75+
76+ needClone := true
77+ if pl .WorkDir .Git .Persistent {
78+ if _ , err := os .Stat (path ); err == nil {
79+ needClone = false
80+ } else if ! errors .Is (err , os .ErrNotExist ) {
81+ return cfg , fmt .Errorf ("stat remote plugin %q: %w" , pl .ID , err )
82+ }
83+ } else {
84+ if err := os .RemoveAll (path ); err != nil {
85+ return cfg , fmt .Errorf ("reset remote plugin %q: %w" , pl .ID , err )
86+ }
6287 }
88+
89+ if needClone {
90+ if err := run ("git" , "" , "clone" , remote , path , "--depth=1" ); err != nil {
91+ return cfg , fmt .Errorf ("clone remote plugin %q: %w" , pl .ID , err )
92+ }
93+
94+ if pl .WorkDir .Git .Version != "" {
95+ if err := run ("git" , path , "checkout" , "--detach" , pl .WorkDir .Git .Version ); err != nil {
96+ return cfg , err
97+ }
98+ }
99+ }
100+
101+ pl .WorkDir .Path = path
102+ }
103+
104+ if ! filepath .IsAbs (pl .WorkDir .Path ) {
105+ pl .WorkDir .Path = filepath .Clean (pl .WorkDir .Path )
63106 }
64107 }
65108 return cfg , nil
66109}
110+
111+ func run (bin string , path string , args ... string ) error {
112+ cmd := exec .Command (bin , args ... )
113+ cmd .Stdout = os .Stdout
114+ cmd .Stderr = os .Stderr
115+
116+ if path != "" {
117+ cmd .Dir = path
118+ }
119+
120+ return cmd .Run ()
121+ }
0 commit comments