add support for custom vcs handlers
This commit is contained in:
parent
fc10c1c983
commit
5fed7316c6
@ -97,6 +97,7 @@ func (f *listFlag) Set(s string) error { *f = append(*f, s); return nil }
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
gitPaths := listFlag{}
|
gitPaths := listFlag{}
|
||||||
|
vcsPaths := listFlag{}
|
||||||
|
|
||||||
addr := flag.String("addr", ":0", "http server address")
|
addr := flag.String("addr", ":0", "http server address")
|
||||||
verbose := flag.Bool("v", false, "verbose logging")
|
verbose := flag.Bool("v", false, "verbose logging")
|
||||||
@ -108,6 +109,7 @@ func main() {
|
|||||||
memLimit := flag.Int64("mem", 256, "in-memory cache size in MB")
|
memLimit := flag.Int64("mem", 256, "in-memory cache size in MB")
|
||||||
workers := flag.Int("workers", 1, "number of parallel VCS workers")
|
workers := flag.Int("workers", 1, "number of parallel VCS workers")
|
||||||
flag.Var(&gitPaths, "git", "list of git settings")
|
flag.Var(&gitPaths, "git", "list of git settings")
|
||||||
|
flag.Var(&vcsPaths, "vcs", "list of custom VCS handlers")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -130,6 +132,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
options = append(options, api.Log(logger))
|
options = append(options, api.Log(logger))
|
||||||
|
|
||||||
|
for _, path := range vcsPaths {
|
||||||
|
kv := strings.SplitN(path, ":", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
log.Fatal("bad VCS syntax:", path)
|
||||||
|
}
|
||||||
|
options = append(options, api.CustomVCS(kv[0], kv[1]))
|
||||||
|
}
|
||||||
|
|
||||||
for _, path := range gitPaths {
|
for _, path := range gitPaths {
|
||||||
kv := strings.SplitN(path, ":", 2)
|
kv := strings.SplitN(path, ":", 2)
|
||||||
if len(kv) != 2 {
|
if len(kv) != 2 {
|
||||||
|
1
go.sum
1
go.sum
@ -19,6 +19,7 @@ github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnG
|
|||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=
|
github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=
|
||||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||||
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
|
@ -86,6 +86,17 @@ func Git(prefix string, auth string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CustomVCS(prefix string, cmd string) Option {
|
||||||
|
return func(api *api) {
|
||||||
|
api.vcsPaths = append(api.vcsPaths, vcsPath{
|
||||||
|
prefix: prefix,
|
||||||
|
vcs: func(module string) vcs.VCS {
|
||||||
|
return vcs.NewCommand(api.log, cmd, module)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Memory configures API to use in-memory cache for downloaded modules.
|
// Memory configures API to use in-memory cache for downloaded modules.
|
||||||
func Memory(log logger, limit int64) Option {
|
func Memory(log logger, limit int64) Option {
|
||||||
return func(api *api) {
|
return func(api *api) {
|
||||||
|
75
pkg/vcs/cmd.go
Normal file
75
pkg/vcs/cmd.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package vcs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cmdVCS struct {
|
||||||
|
log logger
|
||||||
|
module string
|
||||||
|
cmd string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCommand(l logger, cmd string, module string) VCS {
|
||||||
|
return &cmdVCS{log: l, cmd: cmd, module: module}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmdVCS) List(ctx context.Context) ([]Version, error) {
|
||||||
|
b, err := c.exec(ctx, "MODULE="+c.module, "ACTION=list", "VERSION=latest", "FILEPATH="+c.module+"/@v/list")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
versions := []Version{}
|
||||||
|
for _, line := range strings.Split(string(b), "\n") {
|
||||||
|
versions = append(versions, Version(line))
|
||||||
|
}
|
||||||
|
return versions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmdVCS) Timestamp(ctx context.Context, version Version) (time.Time, error) {
|
||||||
|
b, err := c.exec(ctx, "MODULE="+c.module, "ACTION=timestamp", "VERSION="+version.String(),
|
||||||
|
"FILEPATH="+c.module+"/@v/"+version.String()+".info")
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
info := struct {
|
||||||
|
Version string
|
||||||
|
Time time.Time
|
||||||
|
}{}
|
||||||
|
if json.Unmarshal(b, &info) == nil {
|
||||||
|
return info.Time, nil
|
||||||
|
}
|
||||||
|
if t, err := time.Parse(time.RFC3339, string(b)); err == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
if sec, err := strconv.ParseInt(string(b), 10, 64); err == nil {
|
||||||
|
return time.Unix(sec, 0), nil
|
||||||
|
}
|
||||||
|
return time.Time{}, errors.New("unknown time format")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmdVCS) Zip(ctx context.Context, version Version) (io.ReadCloser, error) {
|
||||||
|
b, err := c.exec(ctx, "MODULE="+c.module, "ACTION=zip", "VERSION="+version.String(),
|
||||||
|
"FILEPATH="+c.module+"/@v/"+version.String()+".zip")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ioutil.NopCloser(bytes.NewReader(b)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmdVCS) exec(ctx context.Context, env ...string) ([]byte, error) {
|
||||||
|
cmd := exec.Command("sh", "-c", c.cmd)
|
||||||
|
cmd.Env = append(os.Environ(), env...)
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
return cmd.Output()
|
||||||
|
}
|
@ -27,6 +27,11 @@ func (v Version) Hash() string {
|
|||||||
return fields[2]
|
return fields[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of a version
|
||||||
|
func (v Version) String() string {
|
||||||
|
return string(v)
|
||||||
|
}
|
||||||
|
|
||||||
// Module is a source code snapshot for which one can get the commit timestamp
|
// Module is a source code snapshot for which one can get the commit timestamp
|
||||||
// or the actual ZIP with the source code in it.
|
// or the actual ZIP with the source code in it.
|
||||||
type Module interface {
|
type Module interface {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user