forked from coop-cloud/tagcmp
Compare commits
3 Commits
5c77d1e4f3
...
0fed62dc8e
Author | SHA1 | Date |
---|---|---|
knoflook | 0fed62dc8e | |
decentral1se | da6a8b1949 | |
decentral1se | c7d03052cf |
|
@ -159,3 +159,7 @@ Output:
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[GPLv3+](./LICENSE)
|
[GPLv3+](./LICENSE)
|
||||||
|
|
||||||
|
## Who's using it?
|
||||||
|
|
||||||
|
- [`abra`](https://git.coopcloud.tech/coop-cloud/abra)
|
||||||
|
|
121
tagcmp.go
121
tagcmp.go
|
@ -19,6 +19,12 @@ type Tag struct {
|
||||||
Metadata string // metadata: what's after + and after the first "-"
|
Metadata string // metadata: what's after + and after the first "-"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TagDelta struct {
|
||||||
|
Major int // major semver difference
|
||||||
|
Minor int // minor semver difference
|
||||||
|
Patch int // patch semver difference
|
||||||
|
}
|
||||||
|
|
||||||
// ByTagAsc sorts tags in ascending order where the last element is the latest tag.
|
// ByTagAsc sorts tags in ascending order where the last element is the latest tag.
|
||||||
type ByTagAsc []Tag
|
type ByTagAsc []Tag
|
||||||
|
|
||||||
|
@ -148,6 +154,12 @@ func (t Tag) String() string {
|
||||||
return repr
|
return repr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t TagDelta) String() string {
|
||||||
|
var repr string
|
||||||
|
repr = fmt.Sprintf("%d.%d.%d", t.Major, t.Minor, t.Patch)
|
||||||
|
return repr
|
||||||
|
}
|
||||||
|
|
||||||
// IsCompatible determines if two tags can be compared together
|
// IsCompatible determines if two tags can be compared together
|
||||||
func (t Tag) IsCompatible(tag Tag) bool {
|
func (t Tag) IsCompatible(tag Tag) bool {
|
||||||
if t.UsesV && !tag.UsesV || tag.UsesV && !t.UsesV {
|
if t.UsesV && !tag.UsesV || tag.UsesV && !t.UsesV {
|
||||||
|
@ -175,43 +187,30 @@ func (t Tag) IsCompatible(tag Tag) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpgradeElement returns a Tag object which is the difference between an old and new tag
|
// UpgradeDelta returns a TagDelta object which is the difference between an old and new tag
|
||||||
// It can contain negative numbers if comparing with an older tag.
|
// It can contain negative numbers if comparing with an older tag.
|
||||||
func (curTag Tag) UpgradeElement(newTag Tag) (Tag, error) {
|
func (curTag Tag) UpgradeDelta(newTag Tag) (TagDelta, error) {
|
||||||
if !curTag.IsCompatible(newTag) {
|
if !curTag.IsCompatible(newTag) {
|
||||||
return Tag{}, fmt.Errorf("%s and %s are not compatible with each other", curTag.String(), newTag.String())
|
return TagDelta{}, fmt.Errorf("%s and %s are not compatible with each other", curTag.String(), newTag.String())
|
||||||
}
|
}
|
||||||
diff := curTag
|
diff := TagDelta{
|
||||||
curMajor, err := strconv.Atoi(curTag.Major)
|
Major: 0,
|
||||||
if err != nil {
|
Minor: 0,
|
||||||
return Tag{}, err
|
Patch: 0,
|
||||||
}
|
}
|
||||||
newMajor, err := strconv.Atoi(newTag.Major)
|
// assuming tags are correctly formatted
|
||||||
if err != nil {
|
curMajor, _ := strconv.Atoi(curTag.Major)
|
||||||
return Tag{}, err
|
newMajor, _ := strconv.Atoi(newTag.Major)
|
||||||
}
|
diff.Major = newMajor - curMajor
|
||||||
diff.Major = strconv.Itoa(newMajor - curMajor)
|
|
||||||
if !curTag.MissingMinor {
|
if !curTag.MissingMinor {
|
||||||
curMinor, err := strconv.Atoi(curTag.Minor)
|
curMinor, _ := strconv.Atoi(curTag.Minor)
|
||||||
if err != nil {
|
newMinor, _ := strconv.Atoi(newTag.Minor)
|
||||||
return Tag{}, err
|
diff.Minor = newMinor - curMinor
|
||||||
}
|
|
||||||
newMinor, err := strconv.Atoi(newTag.Minor)
|
|
||||||
if err != nil {
|
|
||||||
return Tag{}, err
|
|
||||||
}
|
|
||||||
diff.Minor = strconv.Itoa(newMinor - curMinor)
|
|
||||||
}
|
}
|
||||||
if !curTag.MissingPatch {
|
if !curTag.MissingPatch {
|
||||||
curPatch, err := strconv.Atoi(curTag.Patch)
|
curPatch, _ := strconv.Atoi(curTag.Patch)
|
||||||
if err != nil {
|
newPatch, _ := strconv.Atoi(newTag.Patch)
|
||||||
return Tag{}, err
|
diff.Patch = newPatch - curPatch
|
||||||
}
|
|
||||||
newPatch, err := strconv.Atoi(newTag.Patch)
|
|
||||||
if err != nil {
|
|
||||||
return Tag{}, err
|
|
||||||
}
|
|
||||||
diff.Patch = strconv.Itoa(newPatch - curPatch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff, nil
|
return diff, nil
|
||||||
|
@ -219,35 +218,23 @@ func (curTag Tag) UpgradeElement(newTag Tag) (Tag, error) {
|
||||||
|
|
||||||
// UpgradeType takes exit from UpgradeElemene and returns a numeric representation of upgrade or downgrade
|
// UpgradeType takes exit from UpgradeElemene and returns a numeric representation of upgrade or downgrade
|
||||||
// 1/-1: patch 2/-2: minor 4/-4: major 0: no change
|
// 1/-1: patch 2/-2: minor 4/-4: major 0: no change
|
||||||
func UpgradeType(t Tag) int {
|
func (d TagDelta) UpgradeType() int {
|
||||||
var major, minor, patch int
|
if d.Major > 0 {
|
||||||
major, _ = strconv.Atoi(t.Major)
|
|
||||||
if t.MissingMinor {
|
|
||||||
minor = 0
|
|
||||||
} else {
|
|
||||||
minor, _ = strconv.Atoi(t.Minor)
|
|
||||||
}
|
|
||||||
if t.MissingPatch {
|
|
||||||
patch = 0
|
|
||||||
} else {
|
|
||||||
patch, _ = strconv.Atoi(t.Patch)
|
|
||||||
}
|
|
||||||
if major > 0 {
|
|
||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
if major < 0 {
|
if d.Major < 0 {
|
||||||
return -4
|
return -4
|
||||||
}
|
}
|
||||||
if minor > 0 {
|
if d.Minor > 0 {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
if minor < 0 {
|
if d.Minor < 0 {
|
||||||
return -2
|
return -2
|
||||||
}
|
}
|
||||||
if patch > 0 {
|
if d.Patch > 0 {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if patch < 0 {
|
if d.Patch < 0 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -306,6 +293,42 @@ func parseVersionPart(part string) (int, error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseDelta converts a tag difference in the format of X, X.Y or X.Y.Z where
|
||||||
|
// X, Y, Z are positive or negative integers or 0
|
||||||
|
func ParseDelta(delta string) (TagDelta, error) {
|
||||||
|
tagDelta := TagDelta{
|
||||||
|
Major: 0,
|
||||||
|
Minor: 0,
|
||||||
|
Patch: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
splits := strings.Split(delta, ".")
|
||||||
|
if len(splits) > 3 {
|
||||||
|
return TagDelta{}, fmt.Errorf("'%s' has too much dots", delta)
|
||||||
|
}
|
||||||
|
major, err := strconv.Atoi(splits[0])
|
||||||
|
if err != nil {
|
||||||
|
return TagDelta{}, fmt.Errorf("Major part of '%s' is not an integer", delta)
|
||||||
|
}
|
||||||
|
tagDelta.Major = major
|
||||||
|
|
||||||
|
if len(splits) > 1 {
|
||||||
|
minor, err := strconv.Atoi(splits[1])
|
||||||
|
if err != nil {
|
||||||
|
return TagDelta{}, fmt.Errorf("Minor part of '%s' is not an integer", delta)
|
||||||
|
}
|
||||||
|
tagDelta.Minor = minor
|
||||||
|
}
|
||||||
|
if len(splits) > 2 {
|
||||||
|
patch, err := strconv.Atoi(splits[2])
|
||||||
|
if err != nil {
|
||||||
|
return TagDelta{}, fmt.Errorf("Minor part of '%s' is not an integer", delta)
|
||||||
|
}
|
||||||
|
tagDelta.Patch = patch
|
||||||
|
}
|
||||||
|
return tagDelta, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Parse converts an image tag into a structured data format. It aims to to
|
// Parse converts an image tag into a structured data format. It aims to to
|
||||||
// support the general case of tags which are "semver-like" and/or stable and
|
// support the general case of tags which are "semver-like" and/or stable and
|
||||||
// parseable by heuristics. Image tags follow no formal specification and
|
// parseable by heuristics. Image tags follow no formal specification and
|
||||||
|
|
Loading…
Reference in New Issue