Compare commits
2 Commits
v0.2.3
...
feature/in
Author | SHA1 | Date | |
---|---|---|---|
|
177b4914c5 | ||
|
f906c8009a |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,5 +15,3 @@
|
||||
# Misc
|
||||
_gopath
|
||||
_gocache
|
||||
|
||||
dist/
|
||||
|
@@ -1,37 +0,0 @@
|
||||
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||
# Make sure to check the documentation at https://goreleaser.com
|
||||
before:
|
||||
hooks:
|
||||
# You may remove this if you don't use go modules.
|
||||
- go mod tidy
|
||||
# you may remove this if you don't need go generate
|
||||
- go generate ./...
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- arm64
|
||||
- amd64
|
||||
- 386
|
||||
main: ./cmd/gomodproxy/main.go
|
||||
archives:
|
||||
- replacements:
|
||||
darwin: Darwin
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
386: i386
|
||||
amd64: x86_64
|
||||
arm64: Arm64
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ incpatch .Version }}-next"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
11
Dockerfile
11
Dockerfile
@@ -1,11 +0,0 @@
|
||||
FROM golang:1.16.7 as build
|
||||
ENV HOME /opt/app
|
||||
COPY . $HOME
|
||||
WORKDIR $HOME
|
||||
RUN ls $HOME
|
||||
RUN go build cmd/gomodproxy/main.go && \
|
||||
go clean
|
||||
|
||||
FROM debian:buster
|
||||
COPY --from=build /go/bin/ /go/bin/
|
||||
ENTRYPOINT ["/go/bin/gomodproxy"]
|
@@ -8,10 +8,6 @@ gomodproxy is a caching proxy for [Go modules].
|
||||
|
||||
Go 1.11 has introduced optional proxy support via GOPROXY environment variable. It is essential for use cases where you want to have better control over your dependencies and handle scenarios when GitHub is down or some open-source dependency has been removed.
|
||||
|
||||
## Releasing
|
||||
|
||||
See https://goreleaser.com/quick-start/
|
||||
|
||||
## Getting started
|
||||
|
||||
gomodproxy requires Go 1.11 or newer. There are no plans to support `vgo` or Go 1.11 beta versions.
|
||||
|
@@ -16,7 +16,7 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/bilus/gomodproxy/pkg/api"
|
||||
"github.com/sixt/gomodproxy/pkg/api"
|
||||
|
||||
"expvar"
|
||||
_ "net/http/pprof"
|
||||
@@ -137,8 +137,7 @@ func main() {
|
||||
if len(kv) != 2 {
|
||||
log.Fatal("bad git path:", path)
|
||||
}
|
||||
password := os.Getenv("SSH_PASSPHRASE")
|
||||
options = append(options, api.GitWithEphemeralTags(kv[0], kv[1], password))
|
||||
options = append(options, api.Git(kv[0], kv[1]))
|
||||
}
|
||||
|
||||
for _, path := range vcsPaths {
|
||||
|
4
go.mod
4
go.mod
@@ -1,5 +1,5 @@
|
||||
module github.com/bilus/gomodproxy
|
||||
module github.com/sixt/gomodproxy
|
||||
|
||||
go 1.16
|
||||
go 1.13
|
||||
|
||||
require gopkg.in/src-d/go-git.v4 v4.13.1
|
||||
|
14
go.sum
14
go.sum
@@ -1,37 +1,27 @@
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
@@ -39,7 +29,6 @@ github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
@@ -58,15 +47,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
|
||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
|
@@ -15,8 +15,8 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/bilus/gomodproxy/pkg/store"
|
||||
"github.com/bilus/gomodproxy/pkg/vcs"
|
||||
"github.com/sixt/gomodproxy/pkg/store"
|
||||
"github.com/sixt/gomodproxy/pkg/vcs"
|
||||
)
|
||||
|
||||
type logger = func(v ...interface{})
|
||||
@@ -27,8 +27,6 @@ type api struct {
|
||||
vcsPaths []vcsPath
|
||||
stores []store.Store
|
||||
semc chan struct{}
|
||||
|
||||
ephemeralTagStorage *vcs.EphemeralTagStorage
|
||||
}
|
||||
|
||||
type vcsPath struct {
|
||||
@@ -44,7 +42,6 @@ var (
|
||||
apiInfo = regexp.MustCompile(`^/(?P<module>.*)/@v/(?P<version>.*).info$`)
|
||||
apiMod = regexp.MustCompile(`^/(?P<module>.*)/@v/(?P<version>.*).mod$`)
|
||||
apiZip = regexp.MustCompile(`^/(?P<module>.*)/@v/(?P<version>.*).zip$`)
|
||||
apiTag = regexp.MustCompile(`^/tags/(?P<module>.*)/@v/(?P<version>.*)$`)
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -74,9 +71,9 @@ func GitDir(dir string) Option { return func(api *api) { api.gitdir = dir } }
|
||||
// Git configures API to use a specific git client when trying to download a
|
||||
// repository with the given prefix. Auth string can be a path to the SSK key,
|
||||
// or a colon-separated username:password string.
|
||||
func Git(prefix, key, password string) Option {
|
||||
a := vcs.Key(key, password)
|
||||
if creds := strings.SplitN(key, ":", 2); len(creds) == 2 {
|
||||
func Git(prefix string, auth string) Option {
|
||||
a := vcs.Key(auth)
|
||||
if creds := strings.SplitN(auth, ":", 2); len(creds) == 2 {
|
||||
a = vcs.Password(creds[0], creds[1])
|
||||
}
|
||||
return func(api *api) {
|
||||
@@ -89,29 +86,6 @@ func Git(prefix, key, password string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// GitWithEphemeralTags configures API to use a specific git client when trying
|
||||
// to download a repository with the given prefix. Auth string can be a path to
|
||||
// the SSK key, or a colon-separated username:password string.
|
||||
func GitWithEphemeralTags(prefix, key, password string) Option {
|
||||
// TODO(bilus): Ugly but we don't want to mess with the : encoding so
|
||||
// we'll work around the issue of having to pass a passphrase
|
||||
// to decrypt a key.
|
||||
storage := vcs.NewEphemeralTagStorage()
|
||||
a := vcs.Key(key, password)
|
||||
if creds := strings.SplitN(key, ":", 2); len(creds) == 2 {
|
||||
a = vcs.Password(creds[0], creds[1])
|
||||
}
|
||||
return func(api *api) {
|
||||
api.ephemeralTagStorage = storage
|
||||
api.vcsPaths = append(api.vcsPaths, vcsPath{
|
||||
prefix: prefix,
|
||||
vcs: func(module string) vcs.VCS {
|
||||
return vcs.NewGitWithEphemeralTags(api.log, api.gitdir, module, a, storage)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func CustomVCS(prefix string, cmd string) Option {
|
||||
return func(api *api) {
|
||||
api.vcsPaths = append(api.vcsPaths, vcsPath{
|
||||
@@ -177,7 +151,6 @@ func (api *api) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
{"info", apiInfo, api.info},
|
||||
{"api", apiMod, api.mod},
|
||||
{"zip", apiZip, api.zip},
|
||||
{"tag", apiTag, api.tag},
|
||||
} {
|
||||
if m := route.regexp.FindStringSubmatch(r.URL.Path); m != nil {
|
||||
module, version := m[1], ""
|
||||
@@ -328,35 +301,3 @@ func (api *api) delete(w http.ResponseWriter, r *http.Request, module, version s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (api *api) tag(w http.ResponseWriter, r *http.Request, module, version string) {
|
||||
api.log("api.tag", "module", module, "version", version)
|
||||
|
||||
taggable, ok := api.vcs(r.Context(), module).(vcs.Taggable)
|
||||
if !ok {
|
||||
err := fmt.Errorf("repository for module %v is not taggable", module)
|
||||
api.log("api.tag", "module", module, "version", version, "error", err)
|
||||
httpErrors.Add(module, 1)
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
req := struct {
|
||||
Short string `json:"short"`
|
||||
}{}
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
api.log("api.tag", "module", module, "version", version, "error", err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = taggable.Tag(r.Context(), vcs.Version(version), req.Short)
|
||||
if err != nil {
|
||||
api.log("api.tag", "module", module, "version", version, "error", err)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bilus/gomodproxy/pkg/vcs"
|
||||
"github.com/sixt/gomodproxy/pkg/vcs"
|
||||
)
|
||||
|
||||
type disk string
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/bilus/gomodproxy/pkg/vcs"
|
||||
"github.com/sixt/gomodproxy/pkg/vcs"
|
||||
)
|
||||
|
||||
type memory struct {
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/bilus/gomodproxy/pkg/vcs"
|
||||
"github.com/sixt/gomodproxy/pkg/vcs"
|
||||
)
|
||||
|
||||
type logger = func(...interface{})
|
||||
|
@@ -34,8 +34,6 @@ type gitVCS struct {
|
||||
auth Auth
|
||||
}
|
||||
|
||||
var ErrNoMatchingVersion = errors.New("no matching versions")
|
||||
|
||||
// NewGit return a go-git VCS client implementation that provides information
|
||||
// about the specific module using the pgiven authentication mechanism.
|
||||
func NewGit(l logger, dir string, module string, auth Auth) VCS {
|
||||
@@ -63,6 +61,7 @@ func (g *gitVCS) List(ctx context.Context) ([]Version, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := []Version{}
|
||||
masterHash := ""
|
||||
tagPrefix := ""
|
||||
@@ -82,55 +81,18 @@ func (g *gitVCS) List(ctx context.Context) ([]Version, error) {
|
||||
if masterHash == "" {
|
||||
return nil, errors.New("no tags and no master branch found")
|
||||
}
|
||||
|
||||
short := masterHash[:12]
|
||||
version, err := g.versionFromHash(ctx, short)
|
||||
t, err := g.Timestamp(ctx, Version("v0.0.0-20060102150405-"+short))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
masterCommit, err := g.commit(ctx, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tree, err := masterCommit.Tree()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// No tags while it's a module.
|
||||
if g.isModule(tree) {
|
||||
return nil, ErrNoMatchingVersion
|
||||
}
|
||||
|
||||
list = []Version{version}
|
||||
list = []Version{Version(fmt.Sprintf("v0.0.0-%s-%s", t.Format("20060102150405"), short))}
|
||||
}
|
||||
|
||||
g.log("gitVCS.List", "module", g.module, "list", list)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (g *gitVCS) versionFromHash(ctx context.Context, hash string) (Version, error) {
|
||||
t, err := g.Timestamp(ctx, Version("v0.0.0-20060102150405-"+hash))
|
||||
if err != nil {
|
||||
return Version(""), err
|
||||
}
|
||||
v := Version(fmt.Sprintf("v0.0.0-%s-%s", t.Format("20060102150405"), hash))
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (g *gitVCS) isModule(tree *object.Tree) bool {
|
||||
mod := "go.mod"
|
||||
for path := g.prefix; path != "."; path = filepath.Dir(path) {
|
||||
_, err := tree.FindEntry(filepath.Join(path, mod))
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *gitVCS) Timestamp(ctx context.Context, version Version) (time.Time, error) {
|
||||
g.log("gitVCS.Timestamp", "module", g.module, "version", version)
|
||||
ci, err := g.commit(ctx, version)
|
||||
@@ -154,11 +116,6 @@ func isVendoredPackage(name string) bool {
|
||||
}
|
||||
|
||||
func (g *gitVCS) Zip(ctx context.Context, version Version) (io.ReadCloser, error) {
|
||||
dirName := g.module + "@" + string(version)
|
||||
return g.zipAs(ctx, version, dirName)
|
||||
}
|
||||
|
||||
func (g *gitVCS) zipAs(ctx context.Context, version Version, dirName string) (io.ReadCloser, error) {
|
||||
g.log("gitVCS.Zip", "module", g.module, "version", version)
|
||||
ci, err := g.commit(ctx, version)
|
||||
if err != nil {
|
||||
@@ -219,7 +176,7 @@ func (g *gitVCS) zipAs(ctx context.Context, version Version, dirName string) (io
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
w, err := zw.Create(filepath.Join(dirName, name))
|
||||
w, err := zw.Create(filepath.Join(g.module+"@"+string(version), name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -283,10 +240,6 @@ func (g *gitVCS) commit(ctx context.Context, version Version) (*object.Commit, e
|
||||
if err != nil && err != git.NoErrAlreadyUpToDate {
|
||||
return nil, err
|
||||
}
|
||||
tagPrefix := ""
|
||||
if g.prefix != "" {
|
||||
tagPrefix = g.prefix + "/"
|
||||
}
|
||||
|
||||
version = Version(strings.TrimSuffix(string(version), "+incompatible"))
|
||||
hash := version.Hash()
|
||||
@@ -296,7 +249,7 @@ func (g *gitVCS) commit(ctx context.Context, version Version) (*object.Commit, e
|
||||
return nil, err
|
||||
}
|
||||
tags.ForEach(func(t *plumbing.Reference) error {
|
||||
if t.Name().String() == path.Join("refs/tags", tagPrefix, string(version)) {
|
||||
if t.Name().String() == "refs/tags/"+string(version) {
|
||||
hash = t.Hash().String()
|
||||
annotated, err := repo.TagObject(t.Hash())
|
||||
if err == nil {
|
||||
@@ -324,7 +277,7 @@ func (g *gitVCS) commit(ctx context.Context, version Version) (*object.Commit, e
|
||||
|
||||
func (g *gitVCS) authMethod() (transport.AuthMethod, error) {
|
||||
if g.auth.Key != "" {
|
||||
return ssh.NewPublicKeysFromFile("git", g.auth.Key, g.auth.Password)
|
||||
return ssh.NewPublicKeysFromFile("git", g.auth.Key, "")
|
||||
} else if g.auth.Username != "" {
|
||||
return &http.BasicAuth{Username: g.auth.Username, Password: g.auth.Password}, nil
|
||||
}
|
||||
|
@@ -82,6 +82,6 @@ func (g *goVCS) download(ctx context.Context, version string) error {
|
||||
}
|
||||
|
||||
func (g *goVCS) file(name string) ([]byte, error) {
|
||||
path := filepath.Join(g.dir, "pkg", "mod", "cache", "download", encodeBangs(g.module), "@v", name)
|
||||
path := filepath.Join(g.dir, "pkg", "mod", "cache", "download", g.module, "@v", name)
|
||||
return ioutil.ReadFile(path)
|
||||
}
|
||||
|
142
pkg/vcs/tags.go
142
pkg/vcs/tags.go
@@ -1,142 +0,0 @@
|
||||
package vcs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ephemeralTag struct {
|
||||
semVer Version
|
||||
short string
|
||||
}
|
||||
|
||||
type EphemeralTagStorage struct {
|
||||
tagsByModule map[moduleName][]ephemeralTag
|
||||
}
|
||||
|
||||
func NewEphemeralTagStorage() *EphemeralTagStorage {
|
||||
return &EphemeralTagStorage{
|
||||
tagsByModule: make(map[moduleName][]ephemeralTag),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EphemeralTagStorage) Tag(module string, semVer Version, short string) error {
|
||||
tags := s.tagsByModule[module]
|
||||
tmp := tags[:0]
|
||||
for _, t := range tags {
|
||||
if t.semVer != semVer {
|
||||
tmp = append(tmp, t)
|
||||
}
|
||||
}
|
||||
s.tagsByModule[module] = append(tmp, ephemeralTag{semVer, short})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *EphemeralTagStorage) tags(module string) []ephemeralTag {
|
||||
return s.tagsByModule[module]
|
||||
}
|
||||
|
||||
type moduleName = string
|
||||
|
||||
type taggableVCS struct {
|
||||
wrapped *gitVCS
|
||||
module string
|
||||
storage *EphemeralTagStorage
|
||||
}
|
||||
|
||||
type Taggable interface {
|
||||
Tag(ctx context.Context, semVer Version, short string) error
|
||||
}
|
||||
|
||||
// NewGitWithEphemeralTags return a go-git VCS client implementation that
|
||||
// provides information about the specific module using the given
|
||||
// authentication mechanism while adding support to ephemeral tags.
|
||||
func NewGitWithEphemeralTags(l logger, dir string, module string, auth Auth, storage *EphemeralTagStorage) VCS {
|
||||
git := NewGit(l, dir, module, auth).(*gitVCS)
|
||||
return &taggableVCS{
|
||||
wrapped: git,
|
||||
module: module,
|
||||
storage: storage,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *taggableVCS) safeList(ctx context.Context) ([]Version, error) {
|
||||
remoteVersions, err := v.wrapped.List(ctx)
|
||||
if err != nil {
|
||||
// Ignore this error, we can still count on ephemeral tags.
|
||||
if err != ErrNoMatchingVersion {
|
||||
return nil, err
|
||||
}
|
||||
v.wrapped.log("No remote version tags yet:", err)
|
||||
}
|
||||
return remoteVersions, nil
|
||||
}
|
||||
|
||||
func (v *taggableVCS) Tag(ctx context.Context, semVer Version, short string) error {
|
||||
remoteVersions, err := v.safeList(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if versionExists(remoteVersions, semVer) {
|
||||
return fmt.Errorf("remote version %s already exists for module %s", semVer, v.module)
|
||||
}
|
||||
return v.storage.Tag(v.module, semVer, short)
|
||||
}
|
||||
|
||||
func (v *taggableVCS) List(ctx context.Context) ([]Version, error) {
|
||||
remoteVersions, err := v.safeList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tags := v.storage.tags(v.module)
|
||||
// Remote versions win.
|
||||
return appendEphemeralVersion(remoteVersions, tags...), nil
|
||||
}
|
||||
|
||||
func appendEphemeralVersion(versions []Version, tags ...ephemeralTag) []Version {
|
||||
ephemeral := make([]Version, 0)
|
||||
for _, tag := range tags {
|
||||
if !versionExists(versions, tag.semVer) {
|
||||
ephemeral = append(ephemeral, tag.semVer)
|
||||
}
|
||||
}
|
||||
return append(versions, ephemeral...)
|
||||
}
|
||||
|
||||
func versionExists(versions []Version, v Version) bool {
|
||||
for _, v2 := range versions {
|
||||
if v == v2 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (v *taggableVCS) Timestamp(ctx context.Context, version Version) (time.Time, error) {
|
||||
version2, err := v.resolveVersion(ctx, version)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return v.wrapped.Timestamp(ctx, version2)
|
||||
}
|
||||
|
||||
func (v *taggableVCS) Zip(ctx context.Context, version Version) (io.ReadCloser, error) {
|
||||
version2, err := v.resolveVersion(ctx, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Zip must contain the ephemeral version.
|
||||
dirName := v.module + "@" + string(version)
|
||||
return v.wrapped.zipAs(ctx, version2, dirName)
|
||||
}
|
||||
|
||||
func (v *taggableVCS) resolveVersion(ctx context.Context, version Version) (Version, error) {
|
||||
for _, tag := range v.storage.tags(v.module) {
|
||||
if tag.semVer == version {
|
||||
return v.wrapped.versionFromHash(ctx, tag.short)
|
||||
}
|
||||
}
|
||||
return version, nil
|
||||
}
|
@@ -61,4 +61,4 @@ func NoAuth() Auth { return Auth{} }
|
||||
func Password(username, password string) Auth { return Auth{Username: username, Password: password} }
|
||||
|
||||
// Key returns an Auth implementation that uses key file authentication mechanism.
|
||||
func Key(key, password string) Auth { return Auth{Key: key, Password: password} }
|
||||
func Key(key string) Auth { return Auth{Key: key} }
|
||||
|
Reference in New Issue
Block a user