type XenVersion string
+// XenVersionMaster is always the 'maximum'
const XenVersionMaster = XenVersion("master")
+const XenVersionMin = XenVersion("MIN")
// This is a bit weird but it hides the implementation
func (v XenVersion) String() string {
}
func (v XenVersion) parse() (major, minor int, err error) {
- if v == "master" {
- // NB if Xen's major ever exceeds 2 billion, we'll
+ switch v {
+ case XenVersionMaster:
+ // NB if Xen's major ever exceeds 2 billion-1, we'll
// need to deprecate the 32-bit build of this tool.
return math.MaxInt32, 0, nil
+ case XenVersionMin:
+ return -1, 0, nil
}
major = -1
minor = -1
- submatch := regexp.MustCompile("^([0-9]+).([0-9]+)$").FindStringSubmatch(string(v))
+ submatch := regexp.MustCompile("^([0-9]+)\\.([0-9]+)$").FindStringSubmatch(string(v))
if len(submatch) != 3 {
err = fmt.Errorf("Bad XenVersion: %s", string(v))
return err == nil
}
+func XenVersionFromString(s string) (v XenVersion, err error) {
+ v = XenVersion(s)
+ _, _, err = v.parse()
+ if err != nil {
+ v = ""
+ }
+ return
+}
+
func (v XenVersion) gt(v2 XenVersion, orEqual bool) bool {
majorA, minorA, err := v.parse()
if err != nil {
vl[i] = tmp
}
+func (vl XenVersionSlice) Present(v XenVersion) (found bool) {
+ for _, cv := range vl {
+ if cv == v {
+ found = true
+ break
+ }
+ }
+ return
+}
+
+func (a XenVersionSlice) IsEqual(b XenVersionSlice) bool {
+ if a == nil && b == nil {
+ return true;
+ }
+
+ if a == nil || b == nil {
+ return false;
+ }
+
+ if len(a) != len(b) {
+ return false
+ }
+
+ for i := range a {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+
+ return true
+}
+
+// NB that this list goes high to low
+// all: All versions in the current xsa (or all with patches)
+// <v>: One particular version
+// <v1>..<v2>: All versions between <v1> and <v2>
+// <v>.. : All versions newer than <v>
+// ..<v> : All versions older than <v>
+// TODO: Maybe add ','?
+func VersionsFromString(s string, validVersions XenVersionSlice, filter func(v XenVersion) bool) (vl XenVersionSlice, err error) {
+ // If it parses as a single version, just pass that back.
+ if _, _, terr := XenVersion(s).parse(); terr == nil {
+ v := XenVersion(s)
+
+ if validVersions != nil && !validVersions.Present(v) {
+ err = fmt.Errorf("Version %v not listed", v)
+ return
+ }
+
+ if filter != nil && !filter(v) {
+ err = fmt.Errorf("Only value filtered")
+ return
+ }
+
+ vl = XenVersionSlice{v}
+ return
+ }
+
+ vmin := XenVersionMin;
+ vmax := XenVersionMaster;
+
+ if s != "all" {
+ submatch := regexp.MustCompile("^([0-9.]*|master)\\.\\.([0-9.]*)$").FindStringSubmatch(s)
+ if len(submatch) != 3 {
+ err = fmt.Errorf("Cannot parse version list")
+ return
+ }
+
+ if submatch[1] != "" {
+ vmax = XenVersion(submatch[1])
+ }
+
+ if submatch[2] != "" {
+ vmin = XenVersion(submatch[2])
+ }
+
+ if !vmin.Check() {
+ err = fmt.Errorf("Invalid version: %s", vmin)
+ return
+ }
+
+ if !vmax.Check() {
+ err = fmt.Errorf("Invalid version: %s", vmax)
+ return
+ }
+ }
+
+ if !vmax.IsGreaterEqualThan(vmin) {
+ err = fmt.Errorf("Range max %v less than min %v", vmax, vmin)
+ return
+ }
+
+ // We have a list of valid versions, so just go through the list picking
+ // out the valid ones
+ if validVersions != nil {
+ if vmin != XenVersionMin && !validVersions.Present(vmin) {
+ err = fmt.Errorf("Version %v not listed", vmin)
+ return
+ }
+ if vmax != XenVersionMaster && !validVersions.Present(vmax) {
+ err = fmt.Errorf("Version %v not listed", vmax)
+ return
+ }
+
+ for _, cv := range validVersions {
+ // FIXME: Should a filter failure cause a 'break' instead?
+ if cv.IsGreaterEqualThan(vmin) &&
+ vmax.IsGreaterEqualThan(cv) &&
+ (filter == nil || filter(cv)) {
+ vl = append(vl, cv)
+ }
+ }
+
+ return
+ }
+
+ // We don't have any users w/o valid versions yet; implement
+ // this when we need to
+ err = fmt.Errorf("INTERNAL ERROR: Parsing w/o valid versions not implemented")
+
+ return
+}
+
type XenVersionFull string
func (v XenVersionFull) String() string {
return (err == nil)
}
+func XenVersionFullFromString(s string) (fv XenVersionFull, err error) {
+ fv = XenVersionFull(s)
+ _, _, err = fv.parse()
+ if err != nil {
+ fv = ""
+ }
+ return
+}
+
func (v XenVersionFull) XenVersion() XenVersion {
ver, _, err := v.parse()
if err != nil {