2017-05-02 19:26:49 +03:00
|
|
|
// Copyright 2017 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2016-07-12 21:56:12 +03:00
|
|
|
package gps
|
2016-03-16 23:34:09 +03:00
|
|
|
|
2016-08-31 03:43:18 +03:00
|
|
|
import (
|
2017-01-15 23:41:23 +03:00
|
|
|
"fmt"
|
2016-08-31 03:43:18 +03:00
|
|
|
"sort"
|
|
|
|
|
|
|
|
"github.com/Masterminds/semver"
|
2017-09-04 16:45:28 +03:00
|
|
|
"github.com/golang/dep/internal/gps/internal/pb"
|
2016-08-31 03:43:18 +03:00
|
|
|
)
|
2016-03-16 23:34:09 +03:00
|
|
|
|
2016-12-16 03:39:24 +03:00
|
|
|
// VersionType indicates a type for a Version that conveys some additional
|
|
|
|
// semantics beyond that which is literally embedded on the Go type.
|
|
|
|
type VersionType uint8
|
|
|
|
|
|
|
|
// VersionTypes for the four major classes of version we deal with
|
|
|
|
const (
|
|
|
|
IsRevision VersionType = iota
|
|
|
|
IsVersion
|
|
|
|
IsSemver
|
|
|
|
IsBranch
|
|
|
|
)
|
|
|
|
|
2016-07-12 21:56:12 +03:00
|
|
|
// Version represents one of the different types of versions used by gps.
|
2016-04-15 05:17:18 +03:00
|
|
|
//
|
2016-04-16 05:46:39 +03:00
|
|
|
// Version composes Constraint, because all versions can be used as a constraint
|
|
|
|
// (where they allow one, and only one, version - themselves), but constraints
|
|
|
|
// are not necessarily discrete versions.
|
|
|
|
//
|
2016-04-15 05:17:18 +03:00
|
|
|
// Version is an interface, but it contains private methods, which restricts it
|
2016-07-12 21:56:12 +03:00
|
|
|
// to gps's own internal implementations. We do this for the confluence of
|
2016-06-29 22:33:14 +03:00
|
|
|
// two reasons: the implementation of Versions is complete (there is no case in
|
|
|
|
// which we'd need other types), and the implementation relies on type magic
|
|
|
|
// under the hood, which would be unsafe to do if other dynamic types could be
|
|
|
|
// hiding behind the interface.
|
2016-04-15 05:30:10 +03:00
|
|
|
type Version interface {
|
2016-04-16 05:46:39 +03:00
|
|
|
Constraint
|
2016-08-03 16:34:41 +03:00
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
// Indicates the type of version - Revision, Branch, Version, or Semver
|
2016-12-16 03:39:24 +03:00
|
|
|
Type() VersionType
|
2016-04-15 05:17:18 +03:00
|
|
|
}
|
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
// PairedVersion represents a normal Version, but paired with its corresponding,
|
2016-04-15 05:30:10 +03:00
|
|
|
// underlying Revision.
|
2016-04-15 19:21:44 +03:00
|
|
|
type PairedVersion interface {
|
2016-04-15 05:30:10 +03:00
|
|
|
Version
|
2016-08-03 16:34:41 +03:00
|
|
|
|
2017-06-14 17:40:36 +03:00
|
|
|
// Revision returns the immutable Revision that identifies this Version.
|
|
|
|
Revision() Revision
|
2016-08-03 16:34:41 +03:00
|
|
|
|
|
|
|
// Unpair returns the surface-level UnpairedVersion that half of the pair.
|
|
|
|
//
|
|
|
|
// It does NOT modify the original PairedVersion
|
|
|
|
Unpair() UnpairedVersion
|
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
// Ensures it is impossible to be both a PairedVersion and an
|
|
|
|
// UnpairedVersion
|
2016-04-15 05:30:10 +03:00
|
|
|
_pair(int)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnpairedVersion represents a normal Version, with a method for creating a
|
|
|
|
// VersionPair by indicating the version's corresponding, underlying Revision.
|
|
|
|
type UnpairedVersion interface {
|
|
|
|
Version
|
2017-06-14 17:44:59 +03:00
|
|
|
// Pair takes the underlying Revision that this UnpairedVersion corresponds
|
2016-04-15 19:21:44 +03:00
|
|
|
// to and unites them into a PairedVersion.
|
2017-06-14 17:44:59 +03:00
|
|
|
Pair(Revision) PairedVersion
|
2016-04-15 19:21:44 +03:00
|
|
|
// Ensures it is impossible to be both a PairedVersion and an
|
|
|
|
// UnpairedVersion
|
2016-04-15 05:30:10 +03:00
|
|
|
_pair(bool)
|
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
// types are weird
|
|
|
|
func (branchVersion) _pair(bool) {}
|
|
|
|
func (plainVersion) _pair(bool) {}
|
|
|
|
func (semVersion) _pair(bool) {}
|
|
|
|
func (versionPair) _pair(int) {}
|
2016-04-15 05:17:18 +03:00
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
// NewBranch creates a new Version to represent a floating version (in
|
2016-04-15 05:17:18 +03:00
|
|
|
// general, a branch).
|
2016-04-16 05:46:39 +03:00
|
|
|
func NewBranch(body string) UnpairedVersion {
|
2016-09-15 05:09:08 +03:00
|
|
|
return branchVersion{
|
|
|
|
name: body,
|
|
|
|
// We always set isDefault to false here, because the property is
|
|
|
|
// specifically designed to be internal-only: only the SourceManager
|
|
|
|
// gets to mark it. This is OK because nothing that client code is
|
|
|
|
// responsible for needs to care about has to touch it it.
|
|
|
|
//
|
|
|
|
// TODO(sdboyer) ...maybe. this just ugly.
|
|
|
|
isDefault: false,
|
|
|
|
}
|
2016-04-15 05:17:18 +03:00
|
|
|
}
|
|
|
|
|
2016-09-15 06:26:47 +03:00
|
|
|
func newDefaultBranch(body string) UnpairedVersion {
|
|
|
|
return branchVersion{
|
|
|
|
name: body,
|
|
|
|
isDefault: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 05:17:18 +03:00
|
|
|
// NewVersion creates a Semver-typed Version if the provided version string is
|
|
|
|
// valid semver, and a plain/non-semver version if not.
|
2016-04-15 05:30:10 +03:00
|
|
|
func NewVersion(body string) UnpairedVersion {
|
2016-04-15 05:17:18 +03:00
|
|
|
sv, err := semver.NewVersion(body)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return plainVersion(body)
|
|
|
|
}
|
2016-04-16 05:46:39 +03:00
|
|
|
return semVersion{sv: sv}
|
|
|
|
}
|
|
|
|
|
2016-04-15 05:17:18 +03:00
|
|
|
// A Revision represents an immutable versioning identifier.
|
2016-04-17 03:33:07 +03:00
|
|
|
type Revision string
|
2016-03-31 19:32:47 +03:00
|
|
|
|
2016-04-15 05:17:18 +03:00
|
|
|
// String converts the Revision back into a string.
|
2016-04-17 03:33:07 +03:00
|
|
|
func (r Revision) String() string {
|
2016-04-15 04:36:46 +03:00
|
|
|
return string(r)
|
2016-03-16 23:34:09 +03:00
|
|
|
}
|
2016-03-31 19:32:47 +03:00
|
|
|
|
2017-09-12 02:19:55 +03:00
|
|
|
// ImpliedCaretString follows the same rules as String(), but in accordance with
|
|
|
|
// the Constraint interface will always print a leading "=", as all Versions,
|
|
|
|
// when acting as a Constraint, act as exact matches.
|
2017-05-24 20:26:48 +03:00
|
|
|
func (r Revision) ImpliedCaretString() string {
|
|
|
|
return r.String()
|
|
|
|
}
|
|
|
|
|
2017-04-15 07:50:12 +03:00
|
|
|
func (r Revision) typedString() string {
|
|
|
|
return "r-" + string(r)
|
|
|
|
}
|
|
|
|
|
2016-12-04 06:14:38 +03:00
|
|
|
// Type indicates the type of version - for revisions, "revision".
|
2016-12-16 03:39:24 +03:00
|
|
|
func (r Revision) Type() VersionType {
|
|
|
|
return IsRevision
|
2016-04-16 05:46:39 +03:00
|
|
|
}
|
|
|
|
|
2016-05-18 04:14:18 +03:00
|
|
|
// Matches is the Revision acting as a constraint; it checks to see if the provided
|
2016-04-15 05:17:18 +03:00
|
|
|
// version is the same Revision as itself.
|
2016-04-17 03:33:07 +03:00
|
|
|
func (r Revision) Matches(v Version) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tv := v.(type) {
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tv.Matches(r)
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-15 18:24:57 +03:00
|
|
|
return r == tv
|
|
|
|
case versionPair:
|
|
|
|
return r == tv.r
|
2016-04-15 04:36:46 +03:00
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-15 04:36:46 +03:00
|
|
|
return false
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2016-05-18 04:14:18 +03:00
|
|
|
// MatchesAny is the Revision acting as a constraint; it checks to see if the provided
|
2016-04-15 05:17:18 +03:00
|
|
|
// version is the same Revision as itself.
|
2016-04-17 03:33:07 +03:00
|
|
|
func (r Revision) MatchesAny(c Constraint) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return true
|
|
|
|
case noneConstraint:
|
|
|
|
return false
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.MatchesAny(r)
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-15 18:24:57 +03:00
|
|
|
return r == tc
|
|
|
|
case versionPair:
|
|
|
|
return r == tc.r
|
2016-04-15 04:36:46 +03:00
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-15 04:36:46 +03:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-10-22 04:35:08 +03:00
|
|
|
// Intersect computes the intersection of the Constraint with the provided
|
|
|
|
// Constraint. For Revisions, this can only be another, exactly equal
|
|
|
|
// Revision, or a PairedVersion whose underlying Revision is exactly equal.
|
2016-04-17 03:33:07 +03:00
|
|
|
func (r Revision) Intersect(c Constraint) Constraint {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return r
|
|
|
|
case noneConstraint:
|
|
|
|
return none
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.Intersect(r)
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-15 18:24:57 +03:00
|
|
|
if r == tc {
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
case versionPair:
|
|
|
|
if r == tc.r {
|
2016-04-15 04:36:46 +03:00
|
|
|
return r
|
|
|
|
}
|
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
return none
|
2016-04-15 04:36:46 +03:00
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
|
2017-07-19 16:30:05 +03:00
|
|
|
func (r Revision) identical(c Constraint) bool {
|
2017-06-15 02:30:21 +03:00
|
|
|
r2, ok := c.(Revision)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return r == r2
|
|
|
|
}
|
|
|
|
|
2017-09-04 16:45:28 +03:00
|
|
|
func (r Revision) copyTo(msg *pb.Constraint) {
|
|
|
|
msg.Type = pb.Constraint_Revision
|
|
|
|
msg.Value = string(r)
|
|
|
|
}
|
|
|
|
|
2016-09-15 05:09:08 +03:00
|
|
|
type branchVersion struct {
|
|
|
|
name string
|
|
|
|
isDefault bool
|
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
func (v branchVersion) String() string {
|
2016-09-15 05:09:08 +03:00
|
|
|
return string(v.name)
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2017-05-24 20:26:48 +03:00
|
|
|
func (v branchVersion) ImpliedCaretString() string {
|
|
|
|
return v.String()
|
|
|
|
}
|
|
|
|
|
2017-04-15 07:50:12 +03:00
|
|
|
func (v branchVersion) typedString() string {
|
|
|
|
return fmt.Sprintf("b-%s", v.String())
|
|
|
|
}
|
|
|
|
|
2016-12-16 03:39:24 +03:00
|
|
|
func (v branchVersion) Type() VersionType {
|
|
|
|
return IsBranch
|
2016-04-16 05:46:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v branchVersion) Matches(v2 Version) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tv := v2.(type) {
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tv.Matches(v)
|
2016-04-16 05:46:39 +03:00
|
|
|
case branchVersion:
|
2016-09-15 05:09:08 +03:00
|
|
|
return v.name == tv.name
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
2016-04-16 05:46:39 +03:00
|
|
|
if tv2, ok := tv.v.(branchVersion); ok {
|
2016-09-15 05:09:08 +03:00
|
|
|
return tv2.name == v.name
|
2016-04-15 18:24:57 +03:00
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
func (v branchVersion) MatchesAny(c Constraint) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return true
|
|
|
|
case noneConstraint:
|
|
|
|
return false
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.MatchesAny(v)
|
2016-04-16 05:46:39 +03:00
|
|
|
case branchVersion:
|
2016-09-15 05:09:08 +03:00
|
|
|
return v.name == tc.name
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
2016-04-16 05:46:39 +03:00
|
|
|
if tc2, ok := tc.v.(branchVersion); ok {
|
2016-09-15 05:09:08 +03:00
|
|
|
return tc2.name == v.name
|
2016-04-15 18:24:57 +03:00
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-14 21:09:24 +03:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
func (v branchVersion) Intersect(c Constraint) Constraint {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return v
|
|
|
|
case noneConstraint:
|
|
|
|
return none
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.Intersect(v)
|
2016-04-16 05:46:39 +03:00
|
|
|
case branchVersion:
|
2016-09-15 05:09:08 +03:00
|
|
|
if v.name == tc.name {
|
2016-04-14 21:09:24 +03:00
|
|
|
return v
|
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
2016-04-16 05:46:39 +03:00
|
|
|
if tc2, ok := tc.v.(branchVersion); ok {
|
2016-09-15 05:09:08 +03:00
|
|
|
if v.name == tc2.name {
|
2016-04-15 18:24:57 +03:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
return none
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2017-06-14 17:44:59 +03:00
|
|
|
func (v branchVersion) Pair(r Revision) PairedVersion {
|
2016-04-15 18:24:57 +03:00
|
|
|
return versionPair{
|
|
|
|
v: v,
|
|
|
|
r: r,
|
2016-04-15 05:30:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-19 16:30:05 +03:00
|
|
|
func (v branchVersion) identical(c Constraint) bool {
|
2017-06-15 02:30:21 +03:00
|
|
|
v2, ok := c.(branchVersion)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return v == v2
|
|
|
|
}
|
|
|
|
|
2017-09-04 16:45:28 +03:00
|
|
|
func (v branchVersion) copyTo(msg *pb.Constraint) {
|
|
|
|
if v.isDefault {
|
|
|
|
msg.Type = pb.Constraint_DefaultBranch
|
|
|
|
} else {
|
|
|
|
msg.Type = pb.Constraint_Branch
|
|
|
|
}
|
|
|
|
msg.Value = v.name
|
|
|
|
}
|
|
|
|
|
2016-04-15 05:17:18 +03:00
|
|
|
type plainVersion string
|
2016-04-14 21:09:24 +03:00
|
|
|
|
|
|
|
func (v plainVersion) String() string {
|
2016-04-15 05:17:18 +03:00
|
|
|
return string(v)
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2017-05-24 20:26:48 +03:00
|
|
|
func (v plainVersion) ImpliedCaretString() string {
|
|
|
|
return v.String()
|
|
|
|
}
|
|
|
|
|
2017-04-15 07:50:12 +03:00
|
|
|
func (v plainVersion) typedString() string {
|
|
|
|
return fmt.Sprintf("pv-%s", v.String())
|
|
|
|
}
|
|
|
|
|
2016-12-16 03:39:24 +03:00
|
|
|
func (v plainVersion) Type() VersionType {
|
|
|
|
return IsVersion
|
2016-04-16 05:46:39 +03:00
|
|
|
}
|
|
|
|
|
2016-04-15 06:19:10 +03:00
|
|
|
func (v plainVersion) Matches(v2 Version) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tv := v2.(type) {
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tv.Matches(v)
|
2016-04-15 18:24:57 +03:00
|
|
|
case plainVersion:
|
|
|
|
return v == tv
|
|
|
|
case versionPair:
|
|
|
|
if tv2, ok := tv.v.(plainVersion); ok {
|
|
|
|
return tv2 == v
|
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-04-15 06:19:10 +03:00
|
|
|
func (v plainVersion) MatchesAny(c Constraint) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return true
|
|
|
|
case noneConstraint:
|
|
|
|
return false
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.MatchesAny(v)
|
2016-04-15 18:24:57 +03:00
|
|
|
case plainVersion:
|
|
|
|
return v == tc
|
|
|
|
case versionPair:
|
|
|
|
if tc2, ok := tc.v.(plainVersion); ok {
|
|
|
|
return tc2 == v
|
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-14 21:09:24 +03:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v plainVersion) Intersect(c Constraint) Constraint {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return v
|
|
|
|
case noneConstraint:
|
|
|
|
return none
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.Intersect(v)
|
2016-04-15 18:24:57 +03:00
|
|
|
case plainVersion:
|
|
|
|
if v == tc {
|
2016-04-14 21:09:24 +03:00
|
|
|
return v
|
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
|
|
|
if tc2, ok := tc.v.(plainVersion); ok {
|
|
|
|
if v == tc2 {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
2016-04-15 18:24:57 +03:00
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
return none
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2017-06-14 17:44:59 +03:00
|
|
|
func (v plainVersion) Pair(r Revision) PairedVersion {
|
2016-04-15 18:24:57 +03:00
|
|
|
return versionPair{
|
|
|
|
v: v,
|
|
|
|
r: r,
|
2016-04-15 05:30:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-19 16:30:05 +03:00
|
|
|
func (v plainVersion) identical(c Constraint) bool {
|
2017-06-15 02:30:21 +03:00
|
|
|
v2, ok := c.(plainVersion)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return v == v2
|
|
|
|
}
|
|
|
|
|
2017-09-04 16:45:28 +03:00
|
|
|
func (v plainVersion) copyTo(msg *pb.Constraint) {
|
|
|
|
msg.Type = pb.Constraint_Version
|
|
|
|
msg.Value = string(v)
|
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
type semVersion struct {
|
2017-05-14 06:01:29 +03:00
|
|
|
sv semver.Version
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
func (v semVersion) String() string {
|
2016-09-03 01:40:07 +03:00
|
|
|
str := v.sv.Original()
|
|
|
|
if str == "" {
|
|
|
|
str = v.sv.String()
|
|
|
|
}
|
|
|
|
return str
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2017-05-24 20:26:48 +03:00
|
|
|
func (v semVersion) ImpliedCaretString() string {
|
|
|
|
return v.sv.ImpliedCaretString()
|
|
|
|
}
|
|
|
|
|
2017-04-15 07:50:12 +03:00
|
|
|
func (v semVersion) typedString() string {
|
|
|
|
return fmt.Sprintf("sv-%s", v.String())
|
|
|
|
}
|
|
|
|
|
2016-12-16 03:39:24 +03:00
|
|
|
func (v semVersion) Type() VersionType {
|
|
|
|
return IsSemver
|
2016-04-16 05:46:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v semVersion) Matches(v2 Version) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tv := v2.(type) {
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tv.Matches(v)
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
2016-04-15 18:24:57 +03:00
|
|
|
return v.sv.Equal(tv.sv)
|
|
|
|
case versionPair:
|
2016-04-16 05:46:39 +03:00
|
|
|
if tv2, ok := tv.v.(semVersion); ok {
|
2016-04-15 18:24:57 +03:00
|
|
|
return tv2.sv.Equal(v.sv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
func (v semVersion) MatchesAny(c Constraint) bool {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return true
|
|
|
|
case noneConstraint:
|
|
|
|
return false
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.MatchesAny(v)
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
2016-04-15 18:24:57 +03:00
|
|
|
return v.sv.Equal(tc.sv)
|
2016-05-18 04:14:18 +03:00
|
|
|
case semverConstraint:
|
|
|
|
return tc.Intersect(v) != none
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
2016-04-16 05:46:39 +03:00
|
|
|
if tc2, ok := tc.v.(semVersion); ok {
|
2016-04-15 18:24:57 +03:00
|
|
|
return tc2.sv.Equal(v.sv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
func (v semVersion) Intersect(c Constraint) Constraint {
|
2016-04-15 18:24:57 +03:00
|
|
|
switch tc := c.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return v
|
|
|
|
case noneConstraint:
|
|
|
|
return none
|
2016-05-17 21:34:09 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.Intersect(v)
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
2016-04-15 18:24:57 +03:00
|
|
|
if v.sv.Equal(tc.sv) {
|
|
|
|
return v
|
|
|
|
}
|
2016-05-18 04:14:18 +03:00
|
|
|
case semverConstraint:
|
|
|
|
return tc.Intersect(v)
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
2016-04-16 05:46:39 +03:00
|
|
|
if tc2, ok := tc.v.(semVersion); ok {
|
2016-04-15 18:24:57 +03:00
|
|
|
if v.sv.Equal(tc2.sv) {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
return none
|
2016-04-15 18:24:57 +03:00
|
|
|
}
|
|
|
|
|
2017-06-14 17:44:59 +03:00
|
|
|
func (v semVersion) Pair(r Revision) PairedVersion {
|
2016-04-15 18:24:57 +03:00
|
|
|
return versionPair{
|
|
|
|
v: v,
|
|
|
|
r: r,
|
2016-04-15 05:30:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-19 16:30:05 +03:00
|
|
|
func (v semVersion) identical(c Constraint) bool {
|
2017-06-15 02:30:21 +03:00
|
|
|
v2, ok := c.(semVersion)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return v == v2
|
|
|
|
}
|
|
|
|
|
2017-09-04 16:45:28 +03:00
|
|
|
func (v semVersion) copyTo(msg *pb.Constraint) {
|
|
|
|
msg.Type = pb.Constraint_Semver
|
|
|
|
msg.Value = v.String() //TODO better encoding which doesn't require re-parsing
|
|
|
|
}
|
|
|
|
|
2016-04-15 18:24:57 +03:00
|
|
|
type versionPair struct {
|
2016-04-17 05:47:00 +03:00
|
|
|
v UnpairedVersion
|
2016-04-17 03:33:07 +03:00
|
|
|
r Revision
|
2016-04-15 18:24:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v versionPair) String() string {
|
|
|
|
return v.v.String()
|
2016-04-14 21:09:24 +03:00
|
|
|
}
|
|
|
|
|
2017-05-24 20:26:48 +03:00
|
|
|
func (v versionPair) ImpliedCaretString() string {
|
|
|
|
return v.v.ImpliedCaretString()
|
|
|
|
}
|
|
|
|
|
2017-04-15 07:50:12 +03:00
|
|
|
func (v versionPair) typedString() string {
|
2017-06-14 17:40:36 +03:00
|
|
|
return fmt.Sprintf("%s-%s", v.Unpair().typedString(), v.Revision().typedString())
|
2017-04-15 07:50:12 +03:00
|
|
|
}
|
|
|
|
|
2016-12-16 03:39:24 +03:00
|
|
|
func (v versionPair) Type() VersionType {
|
2016-04-16 05:46:39 +03:00
|
|
|
return v.v.Type()
|
|
|
|
}
|
|
|
|
|
2017-06-14 17:40:36 +03:00
|
|
|
func (v versionPair) Revision() Revision {
|
2016-04-15 18:24:57 +03:00
|
|
|
return v.r
|
2016-04-14 22:25:50 +03:00
|
|
|
}
|
|
|
|
|
2016-08-03 16:34:41 +03:00
|
|
|
func (v versionPair) Unpair() UnpairedVersion {
|
|
|
|
return v.v
|
|
|
|
}
|
|
|
|
|
2016-04-15 18:24:57 +03:00
|
|
|
func (v versionPair) Matches(v2 Version) bool {
|
|
|
|
switch tv2 := v2.(type) {
|
2016-05-18 04:48:41 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tv2.Matches(v)
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
|
|
|
return v.r == tv2.r
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-15 18:24:57 +03:00
|
|
|
return v.r == tv2
|
|
|
|
}
|
|
|
|
|
|
|
|
switch tv := v.v.(type) {
|
2016-09-14 16:12:40 +03:00
|
|
|
case plainVersion, branchVersion:
|
2016-04-15 18:24:57 +03:00
|
|
|
if tv.Matches(v2) {
|
|
|
|
return true
|
|
|
|
}
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
|
|
|
if tv2, ok := v2.(semVersion); ok {
|
2016-04-15 18:24:57 +03:00
|
|
|
if tv.sv.Equal(tv2.sv) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v versionPair) MatchesAny(c2 Constraint) bool {
|
|
|
|
return c2.Matches(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v versionPair) Intersect(c2 Constraint) Constraint {
|
2016-05-18 04:14:18 +03:00
|
|
|
switch tc := c2.(type) {
|
2016-04-25 05:15:52 +03:00
|
|
|
case anyConstraint:
|
|
|
|
return v
|
|
|
|
case noneConstraint:
|
|
|
|
return none
|
2016-05-18 04:48:41 +03:00
|
|
|
case versionTypeUnion:
|
|
|
|
return tc.Intersect(v)
|
2016-04-15 18:24:57 +03:00
|
|
|
case versionPair:
|
2016-05-18 04:14:18 +03:00
|
|
|
if v.r == tc.r {
|
2016-04-15 18:24:57 +03:00
|
|
|
return v.r
|
|
|
|
}
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-05-18 04:14:18 +03:00
|
|
|
if v.r == tc {
|
2016-04-15 18:24:57 +03:00
|
|
|
return v.r
|
|
|
|
}
|
2016-05-18 04:14:18 +03:00
|
|
|
case semverConstraint:
|
|
|
|
if tv, ok := v.v.(semVersion); ok {
|
|
|
|
if tc.Intersect(tv) == v.v {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If the semver intersection failed, we know nothing could work
|
|
|
|
return none
|
2016-04-15 18:24:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch tv := v.v.(type) {
|
2016-04-16 05:46:39 +03:00
|
|
|
case plainVersion, branchVersion:
|
2016-04-15 18:24:57 +03:00
|
|
|
if c2.Matches(v) {
|
|
|
|
return v
|
|
|
|
}
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
|
|
|
if tv2, ok := c2.(semVersion); ok {
|
2016-04-15 18:24:57 +03:00
|
|
|
if tv.sv.Equal(tv2.sv) {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 19:21:44 +03:00
|
|
|
return none
|
2016-04-14 22:25:50 +03:00
|
|
|
}
|
|
|
|
|
2017-07-19 16:30:05 +03:00
|
|
|
func (v versionPair) identical(c Constraint) bool {
|
2017-06-15 02:30:21 +03:00
|
|
|
v2, ok := c.(versionPair)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if v.r != v2.r {
|
|
|
|
return false
|
|
|
|
}
|
2017-07-19 16:30:05 +03:00
|
|
|
return v.v.identical(v2.v)
|
2017-06-15 02:30:21 +03:00
|
|
|
}
|
|
|
|
|
2017-09-04 16:45:28 +03:00
|
|
|
func (v versionPair) copyTo(*pb.Constraint) {
|
|
|
|
panic("versionPair should never be serialized; it is solver internal-only")
|
|
|
|
}
|
|
|
|
|
2016-04-15 05:17:18 +03:00
|
|
|
// compareVersionType is a sort func helper that makes a coarse-grained sorting
|
|
|
|
// decision based on version type.
|
|
|
|
//
|
2016-04-15 19:21:44 +03:00
|
|
|
// Make sure that l and r have already been converted from versionPair (if
|
2016-04-15 05:17:18 +03:00
|
|
|
// applicable).
|
2016-04-15 05:30:10 +03:00
|
|
|
func compareVersionType(l, r Version) int {
|
2016-04-14 22:25:50 +03:00
|
|
|
// Big fugly double type switch. No reflect, because this can be smack in a hot loop
|
|
|
|
switch l.(type) {
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-14 22:25:50 +03:00
|
|
|
switch r.(type) {
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-14 22:25:50 +03:00
|
|
|
return 0
|
2016-04-16 05:46:39 +03:00
|
|
|
case branchVersion, plainVersion, semVersion:
|
2016-04-15 04:36:46 +03:00
|
|
|
return 1
|
2016-04-14 22:25:50 +03:00
|
|
|
}
|
2016-09-15 03:25:39 +03:00
|
|
|
|
|
|
|
case plainVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
switch r.(type) {
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision:
|
2016-04-15 04:36:46 +03:00
|
|
|
return -1
|
2016-09-15 03:25:39 +03:00
|
|
|
case plainVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
return 0
|
2016-09-15 03:25:39 +03:00
|
|
|
case branchVersion, semVersion:
|
2016-04-15 04:36:46 +03:00
|
|
|
return 1
|
2016-04-14 22:25:50 +03:00
|
|
|
}
|
|
|
|
|
2016-09-15 03:25:39 +03:00
|
|
|
case branchVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
switch r.(type) {
|
2016-09-15 03:25:39 +03:00
|
|
|
case Revision, plainVersion:
|
2016-04-15 04:36:46 +03:00
|
|
|
return -1
|
2016-09-15 03:25:39 +03:00
|
|
|
case branchVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
return 0
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
2016-04-15 04:36:46 +03:00
|
|
|
return 1
|
2016-04-14 22:25:50 +03:00
|
|
|
}
|
|
|
|
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
switch r.(type) {
|
2016-04-17 03:33:07 +03:00
|
|
|
case Revision, branchVersion, plainVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
return -1
|
2016-04-16 05:46:39 +03:00
|
|
|
case semVersion:
|
2016-04-14 22:25:50 +03:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
}
|
2016-07-29 04:34:17 +03:00
|
|
|
panic("unknown version type")
|
2016-04-14 22:25:50 +03:00
|
|
|
}
|
2017-01-15 23:41:23 +03:00
|
|
|
|
2016-08-31 03:43:18 +03:00
|
|
|
// SortForUpgrade sorts a slice of []Version in roughly descending order, so
|
|
|
|
// that presumably newer versions are visited first. The rules are:
|
|
|
|
//
|
|
|
|
// - All semver versions come first, and sort mostly according to the semver
|
|
|
|
// 2.0 spec (as implemented by github.com/Masterminds/semver lib), with one
|
|
|
|
// exception:
|
|
|
|
// - Semver versions with a prerelease are after *all* non-prerelease semver.
|
2016-10-21 15:27:14 +03:00
|
|
|
// Within this subset they are sorted first by their numerical component, then
|
2016-08-31 03:43:18 +03:00
|
|
|
// lexicographically by their prerelease version.
|
2016-10-21 15:27:14 +03:00
|
|
|
// - The default branch(es) is next; the exact semantics of that are specific
|
|
|
|
// to the underlying source.
|
|
|
|
// - All other branches come next, sorted lexicographically.
|
|
|
|
// - All non-semver versions (tags) are next, sorted lexicographically.
|
|
|
|
// - Revisions, if any, are last, sorted lexicographically. Revisions do not
|
|
|
|
// typically appear in version lists, so the only invariant we maintain is
|
|
|
|
// determinism - deeper semantics, like chronology or topology, do not matter.
|
2016-08-31 03:43:18 +03:00
|
|
|
//
|
|
|
|
// So, given a slice of the following versions:
|
|
|
|
//
|
|
|
|
// - Branch: master devel
|
|
|
|
// - Semver tags: v1.0.0, v1.1.0, v1.1.0-alpha1
|
|
|
|
// - Non-semver tags: footag
|
|
|
|
// - Revision: f6e74e8d
|
|
|
|
//
|
|
|
|
// Sorting for upgrade will result in the following slice.
|
|
|
|
//
|
|
|
|
// [v1.1.0 v1.0.0 v1.1.0-alpha1 footag devel master f6e74e8d]
|
|
|
|
func SortForUpgrade(vl []Version) {
|
|
|
|
sort.Sort(upgradeVersionSorter(vl))
|
|
|
|
}
|
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
// SortPairedForUpgrade has the same behavior as SortForUpgrade, but operates on
|
|
|
|
// []PairedVersion types.
|
|
|
|
func SortPairedForUpgrade(vl []PairedVersion) {
|
2017-04-03 19:13:14 +03:00
|
|
|
sort.Sort(pvupgradeVersionSorter(vl))
|
2017-04-03 18:28:07 +03:00
|
|
|
}
|
|
|
|
|
2016-08-31 03:43:18 +03:00
|
|
|
// SortForDowngrade sorts a slice of []Version in roughly ascending order, so
|
|
|
|
// that presumably older versions are visited first.
|
|
|
|
//
|
2016-09-15 03:25:39 +03:00
|
|
|
// This is *not* the same as reversing SortForUpgrade (or you could simply
|
|
|
|
// sort.Reverse()). The type precedence is the same, including the semver vs.
|
2016-10-21 15:27:14 +03:00
|
|
|
// semver-with-prerelease relation. Lexicographical comparisons within
|
|
|
|
// non-semver tags, branches, and revisions remains the same as well; because we
|
|
|
|
// treat these domains as having no ordering relation, there can be no real
|
|
|
|
// concept of "upgrade" vs "downgrade", so there is no reason to reverse them.
|
2016-08-31 03:43:18 +03:00
|
|
|
//
|
2016-09-15 03:25:39 +03:00
|
|
|
// Thus, the only binary relation that is reversed for downgrade is within-type
|
2016-10-21 15:27:14 +03:00
|
|
|
// comparisons for semver.
|
2016-08-31 03:43:18 +03:00
|
|
|
//
|
|
|
|
// So, given a slice of the following versions:
|
|
|
|
//
|
|
|
|
// - Branch: master devel
|
|
|
|
// - Semver tags: v1.0.0, v1.1.0, v1.1.0-alpha1
|
|
|
|
// - Non-semver tags: footag
|
|
|
|
// - Revision: f6e74e8d
|
|
|
|
//
|
|
|
|
// Sorting for downgrade will result in the following slice.
|
|
|
|
//
|
|
|
|
// [v1.0.0 v1.1.0 v1.1.0-alpha1 footag devel master f6e74e8d]
|
|
|
|
func SortForDowngrade(vl []Version) {
|
|
|
|
sort.Sort(downgradeVersionSorter(vl))
|
|
|
|
}
|
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
// SortPairedForDowngrade has the same behavior as SortForDowngrade, but
|
|
|
|
// operates on []PairedVersion types.
|
|
|
|
func SortPairedForDowngrade(vl []PairedVersion) {
|
2017-04-15 07:21:12 +03:00
|
|
|
sort.Sort(pvdowngradeVersionSorter(vl))
|
2017-04-06 12:26:05 +03:00
|
|
|
}
|
|
|
|
|
2016-08-31 03:43:18 +03:00
|
|
|
type upgradeVersionSorter []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 upgradeVersionSorter) Less(i, j int) bool {
|
|
|
|
l, r := vs[i], vs[j]
|
2017-04-06 12:26:05 +03:00
|
|
|
return vLess(l, r, false)
|
2016-08-31 03:43:18 +03:00
|
|
|
}
|
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
type pvupgradeVersionSorter []PairedVersion
|
|
|
|
|
2017-04-03 19:13:14 +03:00
|
|
|
func (vs pvupgradeVersionSorter) Len() int {
|
|
|
|
return len(vs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (vs pvupgradeVersionSorter) Swap(i, j int) {
|
|
|
|
vs[i], vs[j] = vs[j], vs[i]
|
|
|
|
}
|
|
|
|
func (vs pvupgradeVersionSorter) Less(i, j int) bool {
|
2017-04-06 12:26:05 +03:00
|
|
|
l, r := vs[i], vs[j]
|
|
|
|
return vLess(l, r, false)
|
|
|
|
}
|
2017-04-03 19:13:14 +03:00
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
type downgradeVersionSorter []Version
|
2017-04-03 19:13:14 +03:00
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
func (vs downgradeVersionSorter) Len() int {
|
|
|
|
return len(vs)
|
|
|
|
}
|
2017-04-03 19:13:14 +03:00
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
func (vs downgradeVersionSorter) Swap(i, j int) {
|
|
|
|
vs[i], vs[j] = vs[j], vs[i]
|
2017-04-03 19:13:14 +03:00
|
|
|
}
|
|
|
|
|
2016-08-31 03:43:18 +03:00
|
|
|
func (vs downgradeVersionSorter) Less(i, j int) bool {
|
|
|
|
l, r := vs[i], vs[j]
|
2017-04-06 12:26:05 +03:00
|
|
|
return vLess(l, r, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
type pvdowngradeVersionSorter []PairedVersion
|
|
|
|
|
|
|
|
func (vs pvdowngradeVersionSorter) Len() int {
|
|
|
|
return len(vs)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (vs pvdowngradeVersionSorter) Swap(i, j int) {
|
|
|
|
vs[i], vs[j] = vs[j], vs[i]
|
|
|
|
}
|
|
|
|
func (vs pvdowngradeVersionSorter) Less(i, j int) bool {
|
|
|
|
l, r := vs[i], vs[j]
|
|
|
|
return vLess(l, r, true)
|
|
|
|
}
|
2016-08-31 03:43:18 +03:00
|
|
|
|
2017-04-06 12:26:05 +03:00
|
|
|
func vLess(l, r Version, down bool) bool {
|
2016-08-31 03:43:18 +03:00
|
|
|
if tl, ispair := l.(versionPair); ispair {
|
|
|
|
l = tl.v
|
|
|
|
}
|
|
|
|
if tr, ispair := r.(versionPair); ispair {
|
|
|
|
r = tr.v
|
|
|
|
}
|
|
|
|
|
|
|
|
switch compareVersionType(l, r) {
|
|
|
|
case -1:
|
|
|
|
return true
|
|
|
|
case 1:
|
|
|
|
return false
|
|
|
|
case 0:
|
|
|
|
break
|
|
|
|
default:
|
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
|
2016-09-15 05:09:08 +03:00
|
|
|
switch tl := l.(type) {
|
|
|
|
case branchVersion:
|
|
|
|
tr := r.(branchVersion)
|
|
|
|
if tl.isDefault != tr.isDefault {
|
|
|
|
// If they're not both defaults, then return the left val: if left
|
|
|
|
// is the default, then it is "less" (true) b/c we want it earlier.
|
|
|
|
// Else the right is the default, and so the left should be later
|
|
|
|
// (false).
|
|
|
|
return tl.isDefault
|
|
|
|
}
|
|
|
|
return l.String() < r.String()
|
|
|
|
case Revision, plainVersion:
|
|
|
|
// All that we can do now is alpha sort
|
2016-08-31 03:43:18 +03:00
|
|
|
return l.String() < r.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// This ensures that pre-release versions are always sorted after ALL
|
|
|
|
// full-release versions
|
|
|
|
lsv, rsv := l.(semVersion).sv, r.(semVersion).sv
|
|
|
|
lpre, rpre := lsv.Prerelease() == "", rsv.Prerelease() == ""
|
|
|
|
if (lpre && !rpre) || (!lpre && rpre) {
|
|
|
|
return lpre
|
|
|
|
}
|
2017-04-06 12:26:05 +03:00
|
|
|
|
|
|
|
if down {
|
|
|
|
return lsv.LessThan(rsv)
|
|
|
|
}
|
|
|
|
return lsv.GreaterThan(rsv)
|
2016-08-31 03:43:18 +03:00
|
|
|
}
|
2017-03-29 19:54:05 +03:00
|
|
|
|
|
|
|
func hidePair(pvl []PairedVersion) []Version {
|
|
|
|
vl := make([]Version, 0, len(pvl))
|
|
|
|
for _, v := range pvl {
|
|
|
|
vl = append(vl, v)
|
|
|
|
}
|
|
|
|
return vl
|
|
|
|
}
|
2017-04-10 20:55:14 +03:00
|
|
|
|
2017-04-14 03:23:20 +03:00
|
|
|
// VersionComponentStrings decomposes a Version into the underlying number, branch and revision
|
|
|
|
func VersionComponentStrings(v Version) (revision string, branch string, version string) {
|
2017-04-10 20:55:14 +03:00
|
|
|
switch tv := v.(type) {
|
|
|
|
case UnpairedVersion:
|
|
|
|
case Revision:
|
|
|
|
revision = tv.String()
|
|
|
|
case PairedVersion:
|
2017-06-14 17:40:36 +03:00
|
|
|
revision = tv.Revision().String()
|
2017-04-10 20:55:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch v.Type() {
|
|
|
|
case IsBranch:
|
|
|
|
branch = v.String()
|
|
|
|
case IsSemver, IsVersion:
|
|
|
|
version = v.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|