Skip to content

Commit

Permalink
Improve 'gvm available' (#41)
Browse files Browse the repository at this point in the history
This improves the `gvm available` command to ensure the data returned is as accurate as possible.
It addresses a few different issues.

The command uses the a cached copy of the Go git repo to list the available version tags. This will
now refresh the source repo if the cache is not from the current day.

The tags from the source repo were the only ones that were listed in the output. Each of those versions
were then annotated with whether a binary version is available. So if the source repo was stale you
would never newly released binary versions. This changes the output to merge the list of source repo
tags and binary releases so that you generally always see the latest data.

Fixes #39
  • Loading branch information
andrewkroh authored Nov 4, 2021
1 parent 3a4b87f commit 6cd36dd
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

- Use Go 1.17 to build project. [#40](https://github.com/andrewkroh/gvm/pull/40)

### Fixed

- Fix staleness issues with the `gvm available` output. [#39](https://github.com/andrewkroh/gvm/issues/39) [#41](https://github.com/andrewkroh/gvm/pull/41)

## [0.3.0]

### Added
Expand Down
10 changes: 3 additions & 7 deletions cmd/gvm/avail.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,13 @@ import (

func availCommand(cmd *kingpin.CmdClause) func(*gvm.Manager) error {
return func(manager *gvm.Manager) error {
list, hasBin, err := manager.Available()
list, err := manager.Available()
if err != nil {
return err
}

for i, v := range list {
if hasBin[i] {
fmt.Printf("%v\t(source, binary)\n", v)
} else {
fmt.Printf("%v\t(source)\n", v)
}
for _, v := range list {
fmt.Println(v)
}
return nil
}
Expand Down
66 changes: 54 additions & 12 deletions gvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,33 @@ import (
"os"
"path/filepath"
"runtime"
"sort"
"strings"

"github.com/sirupsen/logrus"

"github.com/andrewkroh/gvm/common"
)

type AvailableVersion struct {
Version *GoVersion
Source bool // Available to install from source.
Binary bool // Available to download as a binary.
}

func (av AvailableVersion) String() string {
switch {
case av.Source && av.Binary:
return fmt.Sprintf("%v\t(source, binary)", av.Version)
case av.Source:
return fmt.Sprintf("%v\t(source)", av.Version)
case av.Binary:
return fmt.Sprintf("%v\t(binary)", av.Version)
default:
return av.Version.String()
}
}

type Manager struct {
// GVM Home directory. Defaults to $HOME/.gvm
Home string
Expand Down Expand Up @@ -94,36 +114,58 @@ func (m *Manager) ensureDirStruct() error {
return nil
}

func (m *Manager) Available() ([]*GoVersion, []bool, error) {
func (m *Manager) Available() ([]AvailableVersion, error) {
if !m.hasSrcCache() {
versions, err := m.AvailableBinaries()
if err != nil {
return nil, nil, err
return nil, err
}

hasBin := make([]bool, len(versions))
for i := range hasBin {
hasBin[i] = true
available := make([]AvailableVersion, 0, len(versions))
for _, ver := range versions {
available = append(available, AvailableVersion{Version: ver, Binary: true})
}
return versions, hasBin, nil
return available, nil
}

src, err := m.AvailableSource()
if err != nil {
return nil, nil, err
return nil, err
}

versionSet := make(map[string]*AvailableVersion, len(src))
for _, ver := range src {
versionSet[ver.String()] = &AvailableVersion{Version: ver, Source: true}
}

toSlice := func() []AvailableVersion {
available := make([]AvailableVersion, 0, len(versionSet))
for _, ver := range versionSet {
available = append(available, *ver)
}
sort.Slice(available, func(i, j int) bool {
return available[i].Version.LessThan(available[j].Version)
})
return available
}

hasBin := make([]bool, len(src))
bin, err := m.AvailableBinaries()
if err != nil {
return src, hasBin, nil
// Return the source versions if we cannot get binary info.
m.Logger.WithError(err).Info("Failed to list available binary versions.")
return toSlice(), nil
}

for i, ver := range src {
hasBin[i] = findVersion(ver, bin) >= 0
// Merge source and binary versions.
for _, ver := range bin {
if avail, found := versionSet[ver.String()]; found {
avail.Binary = true
continue
}
versionSet[ver.String()] = &AvailableVersion{Version: ver, Binary: true}
}

return src, hasBin, nil
return toSlice(), nil
}

func (m *Manager) Remove(version *GoVersion) error {
Expand Down
17 changes: 11 additions & 6 deletions srcrepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -220,7 +221,7 @@ func (m *Manager) tryRefreshSrcCache() (bool, error) {
}

// don't refresh cache if still same day
if updTS.Day() == now.Day() && updTS.Month() == now.Month() && updTS.Year() == updTS.Year() {
if updTS.Day() == now.Day() && updTS.Month() == now.Month() && updTS.Year() == now.Year() {
return false, nil
}

Expand Down Expand Up @@ -249,6 +250,12 @@ func (m *Manager) tryRefreshSrcCache() (bool, error) {
}

func (m *Manager) AvailableSource() ([]*GoVersion, error) {
if updates, err := m.tryRefreshSrcCache(); err != nil {
return nil, fmt.Errorf("failed to refresh source cache: %w", err)
} else if updates {
log.Println("Source cache was updated.")
}

localGoSrc := m.srcCacheDir()
var versions []*GoVersion
err := gitListTags(m.Logger, localGoSrc, func(tag string) {
Expand Down Expand Up @@ -309,14 +316,12 @@ func gitLastCommitTs(logger logrus.FieldLogger, path string) (time.Time, error)
}

i, err := strconv.ParseInt(tsLine, 10, 64)
if err != nil {
return time.Time{}, err
}
return time.Unix(i, 0), nil
}

func gitFetch(logger logrus.FieldLogger, path string) error {
logger.Println("git fetch:")
return makeCommand("git", "fetch").WithDir(path).WithLogger(logger).Exec()
}

func gitPull(logger logrus.FieldLogger, path string) error {
logger.Println("git pull:")
return makeCommand("git", "pull").WithDir(path).WithLogger(logger).Exec()
Expand Down
12 changes: 0 additions & 12 deletions version.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,3 @@ func sortVersions(versions []*GoVersion) {
func (v *GoVersion) IsTip() bool {
return v.in == "tip"
}

func findVersion(version *GoVersion, versions []*GoVersion) int {
i := sort.Search(len(versions), func(i int) bool {
ver := versions[i]
return version.in == ver.in || version.LessThan(ver)
})

if i < len(versions) && versions[i].in == version.in {
return i
}
return -1
}

0 comments on commit 6cd36dd

Please sign in to comment.