Skip to content

Commit

Permalink
Add support for sorting version lists
Browse files Browse the repository at this point in the history
Fixes golang#3.
  • Loading branch information
sdboyer committed Apr 1, 2016
1 parent e879502 commit 48f48dc
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 4 deletions.
20 changes: 18 additions & 2 deletions bestiary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package vsolver

import (
"fmt"
"sort"
"strings"

"github.com/Masterminds/semver"
Expand Down Expand Up @@ -160,8 +161,7 @@ var fixtures = []fixture{
"root 0.0.0",
"a 1.0.0",
"b 1.0.0",
"shared 3.0.0",
//"shared 3.6.9", // this will be correct once #3 is in and we
"shared 3.6.9",
//default to upgrading
),
},
Expand Down Expand Up @@ -189,10 +189,20 @@ var fixtures = []fixture{

type depspecSourceManager struct {
specs []depspec
//map[ProjectAtom][]Version
sortup bool
}

var _ SourceManager = &depspecSourceManager{}

func newdepspecSM(ds []depspec, upgrade bool) *depspecSourceManager {
//TODO precompute the version lists, for speediness?
return &depspecSourceManager{
specs: ds,
sortup: upgrade,
}
}

func (sm *depspecSourceManager) GetProjectInfo(pa ProjectAtom) (ProjectInfo, error) {
for _, ds := range sm.specs {
if pa.Name == ds.name.Name && pa.Version.Info == ds.name.Version.Info {
Expand All @@ -219,6 +229,12 @@ func (sm *depspecSourceManager) ListVersions(name ProjectName) (pi []Version, er
err = fmt.Errorf("Project '%s' could not be found", name)
}

if sm.sortup {
sort.Sort(upgradeVersionSorter(pi))
} else {
sort.Sort(downgradeVersionSorter(pi))
}

return
}

Expand Down
12 changes: 12 additions & 0 deletions project_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package vsolver

import (
"fmt"
"sort"
"sync"

"github.com/Masterminds/semver"
Expand Down Expand Up @@ -32,6 +33,9 @@ type projectManager struct {
// The list of versions. Kept separate from the data cache because this is
// accessed in the hot loop; we don't want to rebuild and realloc for it.
vlist []Version
// Direction to sort the version list in (true is for upgrade, false for
// downgrade)
sortup bool
// The project metadata cache. This is persisted to disk, for reuse across
// solver runs.
dc *projectDataCache
Expand Down Expand Up @@ -91,6 +95,14 @@ func (pm *projectManager) ListVersions() (vlist []Version, err error) {
pm.dc.VMap[v] = v.Underlying
pm.dc.RMap[v.Underlying] = append(pm.dc.RMap[v.Underlying], v)
}

// Sort the versions
// TODO do this as a heap in the original call
if pm.sortup {
sort.Sort(upgradeVersionSorter(pm.vlist))
} else {
sort.Sort(downgradeVersionSorter(pm.vlist))
}
}

return pm.vlist, nil
Expand Down
2 changes: 1 addition & 1 deletion solve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestBasicSolves(t *testing.T) {

func solveAndBasicChecks(fixnum int, t *testing.T) Result {
fix := fixtures[fixnum]
sm := &depspecSourceManager{specs: fix.ds}
sm := newdepspecSM(fix.ds, true)
l := logrus.New()

if testing.Verbose() {
Expand Down
69 changes: 68 additions & 1 deletion source_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type sourceManager struct {
cachedir, basedir string
pms map[ProjectName]*pmState
anafac func(ProjectName) ProjectAnalyzer
sortup bool
//pme map[ProjectName]error
}

Expand All @@ -44,11 +45,12 @@ type pmState struct {
vlist []Version // TODO temporary until we have a coherent, overall cache structure
}

func NewSourceManager(cachedir, basedir string) (SourceManager, error) {
func NewSourceManager(cachedir, basedir string, upgrade bool) (SourceManager, error) {
// TODO try to create dir if doesn't exist
return &sourceManager{
cachedir: cachedir,
pms: make(map[ProjectName]*pmState),
sortup: upgrade,
}, nil

// TODO drop file lock on cachedir somewhere, here. Caller needs a panic
Expand Down Expand Up @@ -125,3 +127,68 @@ func (sm *sourceManager) getProjectManager(n ProjectName) (*pmState, error) {
sm.pms[n] = pms
return pms, nil
}

type upgradeVersionSorter []Version
type downgradeVersionSorter []Version

func (vs upgradeVersionSorter) Len() int {
return len(vs)
}

func (vs upgradeVersionSorter) Swap(i, j int) {
vs[i], vs[j] = vs[j], vs[i]
}

func (vs downgradeVersionSorter) Len() int {
return len(vs)
}

func (vs downgradeVersionSorter) Swap(i, j int) {
vs[i], vs[j] = vs[j], vs[i]
}

func (vs upgradeVersionSorter) Less(i, j int) bool {
l, r := vs[i], vs[j]

// Start by always sorting higher vtypes earlier
// TODO need a new means when we get rid of those types
if l.Type != r.Type {
return l.Type > r.Type
}

switch l.Type {
case V_Branch, V_Version, V_Revision:
return l.Info < r.Info
}

// This ensures that pre-release versions are always sorted after ALL
// full-release versions
lpre, rpre := l.SemVer.Prerelease() == "", r.SemVer.Prerelease() == ""
if (lpre && !rpre) || (!lpre && rpre) {
return lpre
}
return l.SemVer.GreaterThan(r.SemVer)
}

func (vs downgradeVersionSorter) Less(i, j int) bool {
l, r := vs[i], vs[j]

// Start by always sorting higher vtypes earlier
// TODO need a new means when we get rid of those types
if l.Type != r.Type {
return l.Type > r.Type
}

switch l.Type {
case V_Branch, V_Version, V_Revision:
return l.Info < r.Info
}

// This ensures that pre-release versions are always sorted after ALL
// full-release versions
lpre, rpre := l.SemVer.Prerelease() == "", r.SemVer.Prerelease() == ""
if (lpre && !rpre) || (!lpre && rpre) {
return lpre
}
return l.SemVer.LessThan(r.SemVer)
}

0 comments on commit 48f48dc

Please sign in to comment.