Skip to content

Commit

Permalink
Merge pull request #182 from carolynvs/fix-ls
Browse files Browse the repository at this point in the history
Fix ls-remote
  • Loading branch information
carolynvs authored Oct 23, 2017
2 parents 0775b73 + 8d104c6 commit f3e3cc9
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ validate:
-go list ./... | grep -v /vendor/ | xargs -L1 golint --set_exit_status

test: local
go test -v $(GOFILES_NOVENDOR)
go test $(GOFILES_NOVENDOR)
eval "$( ./dvm-helper --bash-completion )"
./dvm-helper/dvm-helper --version

Expand Down
1 change: 0 additions & 1 deletion dvm-helper/dockerversion/dockerversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func (version Version) BuildDownloadURL(mirror string) (url string, archived boo

var edgeVersion Version
if version.IsEdge() {
// TODO: Figure out the latest edge version
edgeVersion, err = findLatestEdgeVersion(mirror)
if err != nil {
return
Expand Down
50 changes: 2 additions & 48 deletions dvm-helper/dockerversion/edge_version.go
Original file line number Diff line number Diff line change
@@ -1,55 +1,9 @@
package dockerversion

import (
"fmt"
"net/http"
"net/url"

"bytes"
"regexp"

"github.com/pkg/errors"
)

var hrefRegex = regexp.MustCompile("href=\"docker-(.*).tgz\"")

func findLatestEdgeVersion(mirrorURL string) (Version, error) {
if mirrorURL == "" {
mirrorURL = "https://download.docker.com"
}

mirror, err := url.Parse(mirrorURL)
if err != nil {
return Version{}, errors.Wrapf(err, "Unable to parse the mirror URL: %s", mirrorURL)
}

edgeReleasesUrl := fmt.Sprintf("%s://%s/%s/static/edge/%s", mirror.Scheme, mirror.Host, mobyOS, dockerArch)
response, err := http.Get(edgeReleasesUrl)
results, err := ListVersions(mirrorURL, Edge)
if err != nil {
return Version{}, errors.Wrapf(err, "Unable to list edge releases at %s", edgeReleasesUrl)
}
defer response.Body.Close()

b := bytes.Buffer{}
_, err = b.ReadFrom(response.Body)
if err != nil {
}
errors.Wrapf(err, "Unable to read the listing of edge releases at %s", edgeReleasesUrl)

matches := hrefRegex.FindAllStringSubmatch(b.String(), -1)
var results []Version
for _, match := range matches {
version := Parse(match[1])
if version.semver == nil {
continue
}
results = append(results, version)
}

Sort(results)

if len(results) == 0 {
return Version{}, errors.Errorf("No valid edge versions were found at %s", edgeReleasesUrl)
return Version{}, err
}

last := len(results) - 1
Expand Down
64 changes: 64 additions & 0 deletions dvm-helper/dockerversion/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package dockerversion

import (
"bytes"
"fmt"
"net/http"
"net/url"

"regexp"

"github.com/pkg/errors"
)

type ReleaseType string

const (
Edge ReleaseType = "edge"
Test ReleaseType = "test"
Stable ReleaseType = "stable"
)

var hrefRegex = regexp.MustCompile(fmt.Sprintf(`href="docker-(.*)\%s"`, archiveFileExt))

func ListVersions(mirrorURL string, releaseType ReleaseType) ([]Version, error) {
if mirrorURL == "" {
mirrorURL = "https://download.docker.com"
}

mirror, err := url.Parse(mirrorURL)
if err != nil {
return nil, errors.Wrapf(err, "Unable to parse the mirror URL: %s", mirrorURL)
}

indexURL := fmt.Sprintf("%s://%s/%s/static/%s/%s", mirror.Scheme, mirror.Host, mobyOS, releaseType, dockerArch)
response, err := http.Get(indexURL)
if err != nil {
return nil, errors.Wrapf(err, "Unable to list %s releases at %s", releaseType, indexURL)
}
defer response.Body.Close()

b := bytes.Buffer{}
_, err = b.ReadFrom(response.Body)
if err != nil {
}
errors.Wrapf(err, "Unable to read the listing of %s releases at %s", releaseType, indexURL)

matches := hrefRegex.FindAllStringSubmatch(b.String(), -1)
var results []Version
for _, match := range matches {
version := Parse(match[1])
if version.semver == nil {
continue
}
results = append(results, version)
}

if len(results) == 0 {
return nil, errors.Errorf("No valid %s versions were found at %s", releaseType, indexURL)
}

Sort(results)

return results, nil
}
77 changes: 60 additions & 17 deletions dvm-helper/dvm-helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"context"
"errors"
"fmt"
"io/ioutil"
neturl "net/url"
Expand All @@ -20,6 +19,7 @@ import (
"github.com/google/go-github/github"
"github.com/howtowhale/dvm/dvm-helper/dockerversion"
"github.com/howtowhale/dvm/dvm-helper/url"
"github.com/pkg/errors"
"github.com/ryanuber/go-glob"
"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -326,7 +326,7 @@ func detect() {
}

// Find the highest version that satisfies the client version range
availableVersions := getAvailableVersions("")
availableVersions := getAvailableVersions("", true)
for i := len(availableVersions) - 1; i >= 0; i-- {
v := availableVersions[i]

Expand Down Expand Up @@ -393,7 +393,7 @@ func list(pattern string) {
current, _ := getCurrentDockerVersion()

for _, version := range versions {
if current.Equals(version) {
if current.String() == version.String() {
color.Green("->\t%s", version)
} else {
writeInfo("\t%s", version)
Expand Down Expand Up @@ -721,11 +721,8 @@ func getDockerVersion(dockerPath string, includeBuild bool) (dockerversion.Versi
}

func listRemote(prefix string) {
versions := getAvailableVersions(prefix)
versions := getAvailableVersions(prefix, includePrereleases)
for _, version := range versions {
if !includePrereleases && version.IsPrerelease() {
continue
}
writeInfo(version.String())
}
}
Expand Down Expand Up @@ -762,21 +759,71 @@ func getInstalledVersions(pattern string) []dockerversion.Version {
return results
}

func getAvailableVersions(pattern string) []dockerversion.Version {
func getAvailableVersions(pattern string, includePrereleases bool) []dockerversion.Version {
versions := make(map[string]dockerversion.Version)

writeDebug("Retrieving legacy Docker releases")
legacyVersions, err := listLegacyDockerVersions()
if err != nil {
die("", err, retCodeRuntimeError)
}
for _, v := range legacyVersions {
if !includePrereleases && v.IsPrerelease() {
continue
}
if strings.HasPrefix(v.Value(), pattern) {
versions[v.String()] = v
}
}

writeDebug("Retrieving Docker releases")
stableVersions, err := dockerversion.ListVersions(mirrorURL, dockerversion.Stable)
if err != nil {
die("", err, retCodeRuntimeError)
}
for _, v := range stableVersions {
if strings.HasPrefix(v.Value(), pattern) {
versions[v.String()] = v
}
}

if includePrereleases {
writeDebug("Retrieving Docker pre-releases")
prereleaseVersions, err := dockerversion.ListVersions(mirrorURL, dockerversion.Test)
if err != nil {
die("", err, retCodeRuntimeError)
}
for _, v := range prereleaseVersions {
if strings.HasPrefix(v.Value(), pattern) {
versions[v.String()] = v
}
}
}

results := make([]dockerversion.Version, 0, len(versions))
for _, v := range versions {
results = append(results, v)
}

dockerversion.Sort(results)

return results
}

func listLegacyDockerVersions() ([]dockerversion.Version, error) {
gh := buildGithubClient()
options := &github.ListOptions{PerPage: 100}

var allReleases []github.RepositoryRelease
for {
releases, response, err := gh.Repositories.ListReleases("docker", "docker", options)
releases, response, err := gh.Repositories.ListReleases("moby", "moby", options)
if err != nil {
warnWhenRateLimitExceeded(err, response)
die("Unable to retrieve list of Docker releases from GitHub", err, retCodeRuntimeError)
return nil, errors.Wrap(err, "Unable to retrieve list of Docker releases from GitHub")
}
allReleases = append(allReleases, releases...)
if response.StatusCode != 200 {
die("Unable to retrieve list of Docker releases from GitHub (Status %s).", nil, retCodeRuntimeError, response.StatusCode)
return nil, errors.Errorf("Unable to retrieve list of Docker releases from GitHub (Status %s).", response.StatusCode)
}
if response.NextPage == 0 {
break
Expand All @@ -792,14 +839,10 @@ func getAvailableVersions(pattern string) []dockerversion.Version {
writeDebug("Ignoring non-semver Docker release: %s", version)
continue
}

if strings.HasPrefix(v.Value(), pattern) {
results = append(results, v)
}
results = append(results, v)
}

dockerversion.Sort(results)
return results
return results, nil
}

func isUpgradeAvailable() (bool, string) {
Expand Down
2 changes: 1 addition & 1 deletion dvm-helper/dvm-helper.nix.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func upgradeSelf(version string) {

func getCleanPathRegex() string {
versionDir := getVersionsDir()
return versionDir + `/(\d+\.\d+\.\d+|edge):`
return versionDir + `/[^:]+:`
}

func validateShellFlag() {
Expand Down
2 changes: 1 addition & 1 deletion dvm-helper/dvm-helper.windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func writeUpgradeScript() {
func getCleanPathRegex() string {
versionDir := getVersionsDir()
escapedVersionDir := strings.Replace(versionDir, `\`, `\\`, -1)
return escapedVersionDir + `\\(\d+\.\d+\.\d+|edge);`
return escapedVersionDir + `\\[^:]+;`
}

func validateShellFlag() {
Expand Down
15 changes: 10 additions & 5 deletions dvm-helper/dvm-helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func githubReleasesHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")

switch r.RequestURI {
case "/repos/docker/docker/releases?per_page=100":
case "/repos/moby/moby/releases?per_page=100":
fmt.Fprintln(w, test.LoadTestData("github-docker-releases.json"))
default:
w.WriteHeader(404)
Expand Down Expand Up @@ -118,12 +118,16 @@ func TestListRemote(t *testing.T) {
color.Output = outputCapture

dvm := makeCliApp()
dvm.Run([]string{"dvm", "--debug", "list-remote", "1.12"})
dvm.Run([]string{"dvm", "--debug", "list-remote"})

output := outputCapture.String()
assert.NotEmpty(t, output, "Should have captured stdout")
assert.NotContains(t, output, "1.12.5-rc1", "Should not have listed a prerelease version")

assert.Contains(t, output, "1.12.5", "Should have listed a legacy stable version")
assert.NotContains(t, output, "1.12.5-rc1", "Should not have listed a legacy prerelease version")

assert.Contains(t, output, "17.09.0-ce", "Should have listed a stable version")
assert.NotContains(t, output, "17.10.0-ce-rc1", "Should not have listed a prerelease version")
}

func TestListRemoteWithPrereleases(t *testing.T) {
Expand All @@ -134,12 +138,13 @@ func TestListRemoteWithPrereleases(t *testing.T) {
color.Output = outputCapture

dvm := makeCliApp()
dvm.Run([]string{"dvm-helper", "--debug", "list-remote", "--pre", "1.12"})
dvm.Run([]string{"dvm-helper", "--debug", "list-remote", "--pre"})

output := outputCapture.String()
assert.NotEmpty(t, output, "Should have captured stdout")
assert.Contains(t, output, "1.12.5-rc1", "Should have listed a prerelease version")

assert.Contains(t, output, "1.12.5-rc1", "Should have listed a legacy prerelease version")
assert.Contains(t, output, "17.10.0-ce-rc1", "Should have listed a prerelease version")
}

func TestInstallPrereleases(t *testing.T) {
Expand Down

0 comments on commit f3e3cc9

Please sign in to comment.