From 36ef789f056d9ba55810c0a21bc4560b13325e74 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 19 May 2017 21:18:43 +0200 Subject: upgraded to lates release --- Dockerfile | 19 +++ Makefile | 14 +- README.md | 11 +- debian/changelog | 7 + .../patches/allow-dashes-in-repository-names.patch | 13 -- debian/patches/series | 1 - main.go | 146 +++++++++++---------- refs_test.go | 8 +- vendor/vendor.json | 19 +++ version.go | 27 ++-- version_test.go | 127 ------------------ 11 files changed, 160 insertions(+), 232 deletions(-) create mode 100644 Dockerfile delete mode 100644 debian/patches/allow-dashes-in-repository-names.patch delete mode 100644 debian/patches/series create mode 100644 vendor/vendor.json delete mode 100644 version_test.go diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3db7251 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM debian:jessie + +RUN apt-get update + +RUN apt-get install -y curl + +ENV VANITY_VERSION 0.1.3 + +ENV VANITY_URL https://github.com/xiam/vanity/releases/download/v${VANITY_VERSION}/vanity_linux_amd64.gz + +RUN curl --silent -L ${VANITY_URL} | gzip -d > /bin/vanity + +RUN chmod +x /bin/vanity + +RUN mkdir -p /var/run/vanity + +EXPOSE 8080 + +ENTRYPOINT ["/bin/vanity"] diff --git a/Makefile b/Makefile index 9cf51a6..b0db260 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,11 @@ GOX_OSARCH ?= "darwin/amd64 linux/amd64 linux/arm freebsd/386 freebsd/amd64 linux/386 windows/386" GOX_OUTPUT_DIR ?= bin -GH_ACCESS_TOKEN ?= Missing access token. +GH_ACCESS_TOKEN ?= MESSAGE ?= Latest release. -all: clean +all: build + +build: clean @mkdir -p $(GOX_OUTPUT_DIR) && \ gox -osarch=$(GOX_OSARCH) -output "$(GOX_OUTPUT_DIR)/{{.Dir}}_{{.OS}}_{{.Arch}}" && \ gzip bin/vanity_darwin_* && \ @@ -14,7 +16,10 @@ all: clean require-version: @if [[ -z "$$VERSION" ]]; then echo "Missing \$$VERSION"; exit 1; fi -release: require-version +require-access-token: + @if [[ -z "$(GH_ACCESS_TOKEN)" ]]; then echo "Missing \$$GH_ACCESS_TOKEN"; exit 1; fi + +release: require-version require-access-token build @RESP=$$(curl --silent --data '{ \ "tag_name": "v$(VERSION)", \ "name": "v$(VERSION)", \ @@ -36,3 +41,6 @@ release: require-version clean: @rm -rf $(GOX_OUTPUT_DIR) + +docker: + docker build -t xiam/vanity . diff --git a/README.md b/README.md index 6f2f3a2..34aaaa2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # vanity -Use `vanity` to provide pretty package names using your own custom domain: +Use `vanity` to provide pretty package import names using your own custom +domain: ```go import ( @@ -10,7 +11,7 @@ import ( ## A simple example -Let's see the available parameters: +See the available `vanity` parameters with `-h`: ``` vanity -h @@ -69,7 +70,7 @@ Hello, Go examples! ### Versioning support `vanity` also comes with versioning support from the original -[http://gopkg.in](http://gopkg.in) with no extra cost. For instance, the +[http://gopkg.in](http://gopkg.in) at no extra cost. For instance, the following import ``` @@ -154,8 +155,8 @@ curl "upper.io/db" -L ... ``` -You'll see some HTML gibberish made for humans, now request it again but this -time using the `go-get=1` parameter (this is what `go get` does): +You'll see some HTML gibberish made for human readers, now request it again but +this time using the `go-get=1` parameter (that is what `go get` does): ``` curl "upper.io/db?go-get=1" -L diff --git a/debian/changelog b/debian/changelog index bd91542..7bbf8ed 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +vanity (0.2-1) unstable; urgency=medium + + * new upstream release. + * drop all patches + + -- Christian Pointner Fri, 19 May 2017 21:17:47 +0200 + vanity (0.1.1-5) unstable; urgency=medium * fixed default config diff --git a/debian/patches/allow-dashes-in-repository-names.patch b/debian/patches/allow-dashes-in-repository-names.patch deleted file mode 100644 index 9fe5994..0000000 --- a/debian/patches/allow-dashes-in-repository-names.patch +++ /dev/null @@ -1,13 +0,0 @@ -This allows '-' for package names -see: https://github.com/xiam/vanity/pull/6 ---- a/main.go -+++ b/main.go -@@ -24,7 +24,7 @@ - repoRootFlag = flag.String("repo-root", "", "Git repository root URL (e.g.: https://github.com/upper).") - ) - --var packagePattern = regexp.MustCompile(`^/([a-zA-Z0-9]+)\.?(v[1-9][0-9]*)?(.*)$`) -+var packagePattern = regexp.MustCompile(`^/([-a-zA-Z0-9]+)\.?(v[1-9][0-9]*)?(.*)$`) - - var httpClient = &http.Client{Timeout: 10 * time.Second} - diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index f599fcd..0000000 --- a/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ -allow-dashes-in-repository-names.patch diff --git a/main.go b/main.go index c935f13..2ee0255 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,8 @@ import ( "strings" "text/template" "time" + + "github.com/coreos/go-semver/semver" ) var ( @@ -24,7 +26,7 @@ var ( repoRootFlag = flag.String("repo-root", "", "Git repository root URL (e.g.: https://github.com/upper).") ) -var packagePattern = regexp.MustCompile(`^/([a-zA-Z0-9]+)\.?(v[1-9][0-9]*)?(.*)$`) +var packagePattern = regexp.MustCompile(`^/([-a-zA-Z0-9]+)\.?(v([0-9]*))?(.*)$`) var httpClient = &http.Client{Timeout: 10 * time.Second} @@ -136,9 +138,8 @@ func NewRepoRoot(repoURL string, vanityURL string) (*RepoRoot, error) { // NewRepo creates a new repository. func (root *RepoRoot) NewRepo(name string) *Repo { return &Repo{ - Root: root, - Name: name, - FullVersion: InvalidVersion, + Root: root, + Name: name, } } @@ -146,25 +147,27 @@ func (root *RepoRoot) NewRepo(name string) *Repo { type Repo struct { Root *RepoRoot - Name string - MajorVersion Version + Name string + Major string + + RequestedVersion semver.Version // FullVersion is the best version in AllVersions that matches MajorVersion. // It defaults to InvalidVersion if there are no matches. - FullVersion Version + FullVersion *semver.Version // AllVersions holds all versions currently available in the repository, // either coming from branch names or from tag names. Version zero (v0) // is only present in the list if it really exists in the repository. - AllVersions VersionList + AllVersions semver.Versions } // SetVersions records in the relevant fields the details about which // package versions are available in the repository. -func (repo *Repo) SetVersions(all []Version) { +func (repo *Repo) SetVersions(all semver.Versions) { repo.AllVersions = all for _, v := range repo.AllVersions { - if v.Major == repo.MajorVersion.Major && v.Unstable == repo.MajorVersion.Unstable && repo.FullVersion.Less(v) { + if v.Major == repo.RequestedVersion.Major && (repo.FullVersion == nil || repo.FullVersion.LessThan(*v)) { repo.FullVersion = v } } @@ -182,7 +185,7 @@ func (repo *Repo) VanityRoot() string { // GitTree returns the repository tree name for the selected version. func (repo *Repo) GitTree() string { - if repo.FullVersion == InvalidVersion { + if repo.FullVersion == nil || repo.Major == "" { return "master" } return repo.FullVersion.String() @@ -190,7 +193,10 @@ func (repo *Repo) GitTree() string { // VanityPath returns the real package path, without a schema. func (repo *Repo) VanityPath() string { - return repo.VanityVersionRoot(repo.MajorVersion) + if repo.Major == "" { + return repo.VanityRoot() + } + return repo.VanityRoot() + ".v" + repo.Major } // VanityURL returns the vanity package's URL. @@ -203,25 +209,12 @@ func (repo *Repo) RepoRootURL() string { return repo.Root.repoURL.Scheme + "://" + repo.RepoRoot() } -// VanityVersionRoot returns the package's vanity root for the provided -// version, without a schema. -func (repo *Repo) VanityVersionRoot(version Version) string { - version.Minor = -1 - version.Patch = -1 - v := version.String() - if v == "v0" { - return repo.VanityRoot() - } - return repo.VanityRoot() + "." + v -} - func newHandler(repoRoot *RepoRoot) func(http.ResponseWriter, *http.Request) { return func(resp http.ResponseWriter, req *http.Request) { if req.URL.Path == "/health-check" { resp.Write([]byte("ok")) return } - log.Printf("%s requested %s", req.RemoteAddr, req.URL) if req.URL.Path == "/" { @@ -237,28 +230,20 @@ func newHandler(repoRoot *RepoRoot) func(http.ResponseWriter, *http.Request) { p := packagePattern.FindStringSubmatch(u.Path) - pkgName := p[1] - version := p[2] - extra := p[3] - + pkgName, _, version, extra := p[1], p[2], p[3], p[4] repo := repoRoot.NewRepo(pkgName) - if version == "" { - version = "v0" - } - - var ok bool - repo.MajorVersion, ok = parseVersion(version) - if !ok { - sendNotFound(resp, "Version %q improperly considered invalid; please warn the service maintainers.", version) - return + var requestedVersion semver.Version + if version != "" { + repo.Major = version + repo.RequestedVersion.Major, _ = strconv.ParseInt(repo.Major, 10, 64) } var changed []byte - var versions VersionList + var versions semver.Versions original, err := fetchRefs(repo) if err == nil { - changed, versions, err = changeRefs(original, repo.MajorVersion) + changed, versions, err = changeRefs(original, &repo.RequestedVersion) repo.SetVersions(versions) } @@ -269,14 +254,7 @@ func newHandler(repoRoot *RepoRoot) func(http.ResponseWriter, *http.Request) { sendNotFound(resp, "Git repository not found at https://%s", repo.RepoRoot()) return case ErrNoVersion: - major := repo.MajorVersion - suffix := "" - if major.Unstable { - major.Unstable = false - suffix = unstableSuffix - } - v := major.String() - sendNotFound(resp, `Git repository at https://%s has no branch or tag "%s%s", "%s.N%s" or "%s.N.M%s"`, repo.RepoRoot(), v, suffix, v, suffix, v, suffix) + sendNotFound(resp, `Git repository at https://%s has no tag %v`, repo.RepoRoot(), requestedVersion) return default: resp.WriteHeader(http.StatusBadGateway) @@ -286,8 +264,41 @@ func newHandler(repoRoot *RepoRoot) func(http.ResponseWriter, *http.Request) { switch extra { case `/git-upload-pack`: - resp.Header().Set("Location", "https://"+repo.RepoRoot()+"/git-upload-pack") - resp.WriteHeader(http.StatusMovedPermanently) + proxyURL := "https://" + repo.RepoRoot() + "/git-upload-pack" + + proxyReq, err := http.NewRequest(req.Method, proxyURL, req.Body) + if err != nil { + resp.WriteHeader(http.StatusInternalServerError) + return + } + for k, v := range req.Header { + proxyReq.Header[k] = v + } + + proxyRes, err := http.DefaultClient.Do(proxyReq) + if err != nil { + log.Printf("Proxy: %v", err) + resp.WriteHeader(http.StatusServiceUnavailable) + return + } + defer proxyRes.Body.Close() + + for k, v := range proxyRes.Header { + resp.Header()[k] = v + } + + buf, err := ioutil.ReadAll(proxyRes.Body) + if err != nil { + log.Printf("Proxy: %v", err) + resp.WriteHeader(http.StatusBadGateway) + return + } + + if _, err = resp.Write(buf); err != nil { + log.Printf("Proxy: %v", err) + resp.WriteHeader(http.StatusInternalServerError) + return + } return case `/info/refs`: resp.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement") @@ -349,16 +360,16 @@ func fetchRefs(repo *Repo) (data []byte, err error) { return data, err } -func changeRefs(data []byte, major Version) (changed []byte, versions VersionList, err error) { +func changeRefs(data []byte, major *semver.Version) (changed []byte, versions semver.Versions, err error) { var hlinei, hlinej int // HEAD reference line start/end var mlinei, mlinej int // master reference line start/end var vrefhash string var vrefname string - var vrefv = InvalidVersion + var vrefv *semver.Version // Record all available versions, the locations of the master and HEAD lines, // and details of the best reference satisfying the requested major version. - versions = make([]Version, 0) + versions = semver.Versions{} sdata := string(data) for i, j := 0, 0; i < len(data); i = j { size, err := strconv.ParseInt(sdata[i:i+4], 16, 32) @@ -402,28 +413,25 @@ func changeRefs(data []byte, major Version) (changed []byte, versions VersionLis mlinej = j } - if strings.HasPrefix(name, "refs/heads/v") || strings.HasPrefix(name, "refs/tags/v") { - if strings.HasSuffix(name, "^{}") { - // Annotated tag is peeled off and overrides the same version just parsed. - name = name[:len(name)-3] + if strings.HasPrefix(name, "refs/tags/v") { + if !strings.HasSuffix(name, "^{}") { + continue // Only accept annotated tags. } - v, ok := parseVersion(name[strings.IndexByte(name, 'v'):]) - if ok && major.Contains(v) && (v == vrefv || !vrefv.IsValid() || vrefv.Less(v)) { - vrefv = v - vrefhash = sdata[hashi:hashj] - vrefname = name - } - if ok { + // Annotated tag is peeled off and overrides the same version just parsed. + name = name[:len(name)-3] + + v, err := semver.NewVersion(name[strings.IndexByte(name, 'v')+1:]) + if err == nil { versions = append(versions, v) + if major.Major == v.Major && (vrefv == nil || v == vrefv || vrefv.LessThan(*v)) { + vrefv = v + vrefhash = sdata[hashi:hashj] + vrefname = name + } } } } - // If v0 was requested, accept the master as-is. - if major == (Version{0, -1, -1, false}) { - return data, nil, nil - } - // If the file has no HEAD line or the version was not found, report as unavailable. if hlinei == 0 || vrefhash == "" { return nil, nil, ErrNoVersion diff --git a/refs_test.go b/refs_test.go index 55580c5..cd02871 100644 --- a/refs_test.go +++ b/refs_test.go @@ -5,6 +5,8 @@ import ( "fmt" . "gopkg.in/check.v1" "sort" + + "github.com/coreos/go-semver/semver" ) var _ = Suite(&RefsSuite{}) @@ -173,9 +175,9 @@ func (s *RefsSuite) TestChangeRefs(c *C) { for _, test := range refsTests { c.Logf(test.summary) - v, ok := parseVersion(test.version) - if !ok { - c.Fatalf("Test has an invalid version: %q", test.version) + v, err := semver.NewVersion(test.version) + if err != nil { + c.Fatalf("Test has an invalid version: %q: %v", test.version, err) } changed, versions, err := changeRefs([]byte(test.original), v) diff --git a/vendor/vendor.json b/vendor/vendor.json new file mode 100644 index 0000000..f9c8c4a --- /dev/null +++ b/vendor/vendor.json @@ -0,0 +1,19 @@ +{ + "comment": "", + "ignore": "test", + "package": [ + { + "checksumSHA1": "butr+Orbf1fd1hcLqNXYwUDAjcI=", + "path": "github.com/coreos/go-semver/semver", + "revision": "8ab6407b697782a06568d4b7f1db25550ec2e4c6", + "revisionTime": "2016-07-13T22:46:27Z" + }, + { + "checksumSHA1": "UD3Xnjdx6vWSFVmKUopMjuTwuz0=", + "path": "gopkg.in/check.v1", + "revision": "11d3bc7aa68e238947792f30573146a3231fc0f1", + "revisionTime": "2015-07-29T08:04:31Z" + } + ], + "rootPath": "github.com/xiam/vanity" +} diff --git a/version.go b/version.go index 6fcb9c1..f2aaffd 100644 --- a/version.go +++ b/version.go @@ -70,34 +70,39 @@ func (v Version) Contains(other Version) bool { // IsValid returns trus if the version is valid. func (v Version) IsValid() bool { - return v != InvalidVersion + return v != *InvalidVersion } -// InvalidVersion represents a version that can't be parsed. -var InvalidVersion = Version{-1, -1, -1, false} +var ( + // InvalidVersion represents a version that can't be parsed. + InvalidVersion = &Version{-1, -1, -1, false} -func parseVersion(s string) (v Version, ok bool) { - v = InvalidVersion + // ZeroVersion represents the zero version. + ZeroVersion = &Version{0, 0, 0, false} +) + +func parseVersion(s string) (*Version, bool) { + defaultVersion := *InvalidVersion if len(s) < 2 { - return + return &defaultVersion, false } if s[0] != 'v' { - return + return &defaultVersion, false } - vout := InvalidVersion + vout := *InvalidVersion unstable := false i := 1 for _, vptr := range []*int{&vout.Major, &vout.Minor, &vout.Patch} { *vptr, unstable, i = parseVersionPart(s, i) if i < 0 { - return + return &defaultVersion, false } if i == len(s) { vout.Unstable = unstable - return vout, true + return &vout, true } } - return + return &defaultVersion, true } func parseVersionPart(s string, i int) (part int, unstable bool, newi int) { diff --git a/version_test.go b/version_test.go deleted file mode 100644 index 22774fd..0000000 --- a/version_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package main - -import ( - "testing" - - . "gopkg.in/check.v1" -) - -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&VersionSuite{}) - -type VersionSuite struct{} - -var versionParseTests = []struct { - major int - minor int - patch int - dev bool - s string -}{ - {-1, -1, -1, false, "v"}, - {-1, -1, -1, false, "v-1"}, - {-1, -1, -1, false, "v-deb"}, - {-1, -1, -1, false, "v01"}, - {-1, -1, -1, false, "v1.01"}, - {-1, -1, -1, false, "a1"}, - {-1, -1, -1, false, "v1a"}, - {-1, -1, -1, false, "v1..2"}, - {-1, -1, -1, false, "v1.2.3.4"}, - {-1, -1, -1, false, "v1."}, - {-1, -1, -1, false, "v1.2."}, - {-1, -1, -1, false, "v1.2.3."}, - - {0, -1, -1, false, "v0"}, - {0, -1, -1, true, "v0-unstable"}, - {1, -1, -1, false, "v1"}, - {1, -1, -1, true, "v1-unstable"}, - {1, 2, -1, false, "v1.2"}, - {1, 2, -1, true, "v1.2-unstable"}, - {1, 2, 3, false, "v1.2.3"}, - {1, 2, 3, true, "v1.2.3-unstable"}, - {12, 34, 56, false, "v12.34.56"}, - {12, 34, 56, true, "v12.34.56-unstable"}, -} - -func (s *VersionSuite) TestParse(c *C) { - for _, t := range versionParseTests { - got, ok := parseVersion(t.s) - if t.major == -1 { - if ok || got != InvalidVersion { - c.Fatalf("version %q is invalid but parsed as %#v", t.s, got) - } - } else { - want := Version{t.major, t.minor, t.patch, t.dev} - if got != want { - c.Fatalf("version %q must parse as %#v, got %#v", t.s, want, got) - } - if got.String() != t.s { - c.Fatalf("version %q got parsed as %#v and stringified as %q", t.s, got, got.String()) - } - } - } -} - -var versionLessTests = []struct { - oneMajor, oneMinor, onePatch int - oneUnstable bool - twoMajor, twoMinor, twoPatch int - twoUnstable, less bool -}{ - {0, 0, 0, false, 0, 0, 0, false, false}, - {1, 0, 0, false, 1, 0, 0, false, false}, - {1, 0, 0, false, 1, 1, 0, false, true}, - {1, 0, 0, false, 2, 0, 0, false, true}, - {0, 1, 0, false, 0, 1, 0, false, false}, - {0, 1, 0, false, 0, 1, 1, false, true}, - {0, 0, 0, false, 0, 2, 0, false, true}, - {0, 0, 1, false, 0, 0, 1, false, false}, - {0, 0, 1, false, 0, 0, 2, false, true}, - - {0, 0, 0, false, 0, 0, 0, true, false}, - {0, 0, 0, true, 0, 0, 0, false, true}, - {0, 0, 1, true, 0, 0, 0, false, false}, -} - -func (s *VersionSuite) TestLess(c *C) { - for _, t := range versionLessTests { - one := Version{t.oneMajor, t.oneMinor, t.onePatch, t.oneUnstable} - two := Version{t.twoMajor, t.twoMinor, t.twoPatch, t.twoUnstable} - if one.Less(two) != t.less { - c.Fatalf("version %s < %s returned %v", one, two, !t.less) - } - } -} - -var versionContainsTests = []struct { - oneMajor, oneMinor, onePatch int - oneUnstable bool - twoMajor, twoMinor, twoPatch int - twoUnstable, contains bool -}{ - {12, 34, 56, false, 12, 34, 56, false, true}, - {12, 34, 56, false, 12, 34, 78, false, false}, - {12, 34, -1, false, 12, 34, 56, false, true}, - {12, 34, -1, false, 12, 78, 56, false, false}, - {12, -1, -1, false, 12, 34, 56, false, true}, - {12, -1, -1, false, 78, 34, 56, false, false}, - - {12, -1, -1, true, 12, -1, -1, false, false}, - {12, -1, -1, false, 12, -1, -1, true, false}, -} - -func (s *VersionSuite) TestContains(c *C) { - for _, t := range versionContainsTests { - one := Version{t.oneMajor, t.oneMinor, t.onePatch, t.oneUnstable} - two := Version{t.twoMajor, t.twoMinor, t.twoPatch, t.twoUnstable} - if one.Contains(two) != t.contains { - c.Fatalf("version %s.Contains(%s) returned %v", one, two, !t.contains) - } - } -} - -func (s *VersionSuite) TestIsValid(c *C) { - c.Assert(InvalidVersion.IsValid(), Equals, false) - c.Assert(Version{0, 0, 0, false}.IsValid(), Equals, true) -} -- cgit v1.2.3