blob: a0825b2106af0c1cc1d15261b25cf00892464254 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package version
import (
"math"
"regexp"
"strconv"
"strings"
)
// Version represents a browser version in the format of "(major).(minor).(build).(patch)".
type Version struct {
components [4]int64
}
var versionRegexp = regexp.MustCompile(`(\d+).(\d+).(\d+).(\d+)`)
// New creates a new instance of Version with version components.
func New(major, minor, build, patch int64) *Version {
return &Version{
components: [4]int64{major, minor, build, patch},
}
}
// Parse creates a new instance of Version from a given string expression of version.
func Parse(version string) Version {
v := Version{}
parts := versionRegexp.FindStringSubmatch(version)
if parts != nil {
for id, part := range parts[1:] {
number, err := strconv.ParseInt(part, 10, 64)
if err != nil {
return Version{}
}
v.components[id] = number
}
}
return v
}
// GetString returns a version string. e,g, "99.0.1.0"
func (v *Version) GetString() string {
var version []string
for _, component := range v.components {
version = append(version, strconv.FormatInt(component, 10))
}
return strings.Join(version, ".")
}
// Major returns a major version component.
func (v *Version) Major() int64 {
return v.components[0]
}
// Minor returns a minor version component.
func (v *Version) Minor() int64 {
return v.components[1]
}
// Build returns a build version component.
func (v *Version) Build() int64 {
return v.components[2]
}
// Patch returns a patch version component.
func (v *Version) Patch() int64 {
return v.components[3]
}
// Increment increases version by given components, returns a copy of it.
func (v *Version) Increment(o *Version) Version {
v.components[0] += o.components[0]
v.components[1] += o.components[1]
v.components[2] += o.components[2]
v.components[3] += o.components[3]
return *v
}
// Decrement decreases version by given components, returns a copy of it.
func (v *Version) Decrement(o *Version) Version {
v.components[0] -= o.components[0]
v.components[1] -= o.components[1]
v.components[2] -= o.components[2]
v.components[3] -= o.components[3]
return *v
}
// IsNewerThan compares two version and returns true when lhs is newer than rhs.
func (v *Version) IsNewerThan(rhs Version) bool {
for i, component := range v.components {
o := rhs.components[i]
if component != o {
return component > o
}
}
return false
}
// IsOlderThan compares two version and returns true when lhs is older than rhs.
func (v *Version) IsOlderThan(rhs Version) bool {
return rhs.IsNewerThan(*v)
}
// IsEqualTo returns true when the two versions are the same.
func (v *Version) IsEqualTo(rhs Version) bool {
return v.components[0] == rhs.components[0] && v.components[1] == rhs.components[1] && v.components[2] == rhs.components[2] && v.components[3] == rhs.components[3]
}
// IsValid checks if the version is set with valid numbers.
func (v *Version) IsValid() bool {
return v.GetString() != "0.0.0.0"
}
// IsSkewValid returns whether it is a valid version skew that is compatible with the given ash/OS version.
func (v *Version) IsSkewValid(ash Version) bool {
// TODO(crbug.com/1258138): Update version skew policy for Tast. Currently, it is [-1, inf] but should be [0, +2] as soon as the issue is resolved.
// Note that this version skew policy should be in line with the production code.
// See LacrosInstallerPolicy::ComponentReady at
// https://osscs.corp.google.com/chromium/chromium/src/+/main:chrome/browser/component_updater/cros_component_installer_chromeos.cc
const minMajorVersionSkew = -1
return v.components[0] >= ash.components[0]+minMajorVersionSkew &&
v.components[0] <= math.MaxInt64
}