github.com/olliephillips/hugo@v0.42.2/helpers/hugo.go (about)

     1  // Copyright 2015 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package helpers
    15  
    16  import (
    17  	"fmt"
    18  	"strings"
    19  
    20  	"github.com/gohugoio/hugo/compare"
    21  	"github.com/spf13/cast"
    22  )
    23  
    24  // HugoVersion represents the Hugo build version.
    25  type HugoVersion struct {
    26  	// Major and minor version.
    27  	Number float32
    28  
    29  	// Increment this for bug releases
    30  	PatchLevel int
    31  
    32  	// HugoVersionSuffix is the suffix used in the Hugo version string.
    33  	// It will be blank for release versions.
    34  	Suffix string
    35  }
    36  
    37  var (
    38  	_ compare.Eqer     = (*HugoVersionString)(nil)
    39  	_ compare.Comparer = (*HugoVersionString)(nil)
    40  )
    41  
    42  type HugoVersionString string
    43  
    44  func (v HugoVersion) String() string {
    45  	return hugoVersion(v.Number, v.PatchLevel, v.Suffix)
    46  }
    47  
    48  func (v HugoVersion) Version() HugoVersionString {
    49  	return HugoVersionString(v.String())
    50  }
    51  
    52  func (h HugoVersionString) String() string {
    53  	return string(h)
    54  }
    55  
    56  // Implements compare.Comparer
    57  func (h HugoVersionString) Compare(other interface{}) int {
    58  	v := MustParseHugoVersion(h.String())
    59  	return compareVersionsWithSuffix(v.Number, v.PatchLevel, v.Suffix, other)
    60  }
    61  
    62  // Implements compare.Eqer
    63  func (h HugoVersionString) Eq(other interface{}) bool {
    64  	s, err := cast.ToStringE(other)
    65  	if err != nil {
    66  		return false
    67  	}
    68  	return s == h.String()
    69  }
    70  
    71  var versionSuffixes = []string{"-test", "-DEV"}
    72  
    73  // ParseHugoVersion parses a version string.
    74  func ParseHugoVersion(s string) (HugoVersion, error) {
    75  	var vv HugoVersion
    76  	for _, suffix := range versionSuffixes {
    77  		if strings.HasSuffix(s, suffix) {
    78  			vv.Suffix = suffix
    79  			s = strings.TrimSuffix(s, suffix)
    80  		}
    81  	}
    82  
    83  	v, p := parseVersion(s)
    84  
    85  	vv.Number = v
    86  	vv.PatchLevel = p
    87  
    88  	return vv, nil
    89  }
    90  
    91  // MustParseHugoVersion parses a version string
    92  // and panics if any error occurs.
    93  func MustParseHugoVersion(s string) HugoVersion {
    94  	vv, err := ParseHugoVersion(s)
    95  	if err != nil {
    96  		panic(err)
    97  	}
    98  	return vv
    99  }
   100  
   101  // ReleaseVersion represents the release version.
   102  func (v HugoVersion) ReleaseVersion() HugoVersion {
   103  	v.Suffix = ""
   104  	return v
   105  }
   106  
   107  // Next returns the next Hugo release version.
   108  func (v HugoVersion) Next() HugoVersion {
   109  	return HugoVersion{Number: v.Number + 0.01}
   110  }
   111  
   112  // Prev returns the previous Hugo release version.
   113  func (v HugoVersion) Prev() HugoVersion {
   114  	return HugoVersion{Number: v.Number - 0.01}
   115  }
   116  
   117  // NextPatchLevel returns the next patch/bugfix Hugo version.
   118  // This will be a patch increment on the previous Hugo version.
   119  func (v HugoVersion) NextPatchLevel(level int) HugoVersion {
   120  	return HugoVersion{Number: v.Number - 0.01, PatchLevel: level}
   121  }
   122  
   123  // CurrentHugoVersion represents the current build version.
   124  // This should be the only one.
   125  var CurrentHugoVersion = HugoVersion{
   126  	Number:     0.42,
   127  	PatchLevel: 2,
   128  	Suffix:     "",
   129  }
   130  
   131  func hugoVersion(version float32, patchVersion int, suffix string) string {
   132  	if patchVersion > 0 {
   133  		return fmt.Sprintf("%.2f.%d%s", version, patchVersion, suffix)
   134  	}
   135  	return fmt.Sprintf("%.2f%s", version, suffix)
   136  }
   137  
   138  // CompareVersion compares the given version string or number against the
   139  // running Hugo version.
   140  // It returns -1 if the given version is less than, 0 if equal and 1 if greater than
   141  // the running version.
   142  func CompareVersion(version interface{}) int {
   143  	return compareVersionsWithSuffix(CurrentHugoVersion.Number, CurrentHugoVersion.PatchLevel, CurrentHugoVersion.Suffix, version)
   144  }
   145  
   146  func compareVersions(inVersion float32, inPatchVersion int, in interface{}) int {
   147  	return compareVersionsWithSuffix(inVersion, inPatchVersion, "", in)
   148  }
   149  
   150  func compareVersionsWithSuffix(inVersion float32, inPatchVersion int, suffix string, in interface{}) int {
   151  	var c int
   152  	switch d := in.(type) {
   153  	case float64:
   154  		c = compareFloatVersions(inVersion, float32(d))
   155  	case float32:
   156  		c = compareFloatVersions(inVersion, d)
   157  	case int:
   158  		c = compareFloatVersions(inVersion, float32(d))
   159  	case int32:
   160  		c = compareFloatVersions(inVersion, float32(d))
   161  	case int64:
   162  		c = compareFloatVersions(inVersion, float32(d))
   163  	default:
   164  		s, err := cast.ToStringE(in)
   165  		if err != nil {
   166  			return -1
   167  		}
   168  
   169  		v, err := ParseHugoVersion(s)
   170  		if err != nil {
   171  			return -1
   172  		}
   173  
   174  		if v.Number == inVersion && v.PatchLevel == inPatchVersion {
   175  			return strings.Compare(suffix, v.Suffix)
   176  		}
   177  
   178  		if v.Number < inVersion || (v.Number == inVersion && v.PatchLevel < inPatchVersion) {
   179  			return -1
   180  		}
   181  
   182  		return 1
   183  	}
   184  
   185  	if c == 0 && suffix != "" {
   186  		return 1
   187  	}
   188  
   189  	return c
   190  }
   191  
   192  func parseVersion(s string) (float32, int) {
   193  	var (
   194  		v float32
   195  		p int
   196  	)
   197  
   198  	if strings.Count(s, ".") == 2 {
   199  		li := strings.LastIndex(s, ".")
   200  		p = cast.ToInt(s[li+1:])
   201  		s = s[:li]
   202  	}
   203  
   204  	v = float32(cast.ToFloat64(s))
   205  
   206  	return v, p
   207  }
   208  
   209  func compareFloatVersions(version float32, v float32) int {
   210  	if v == version {
   211  		return 0
   212  	}
   213  	if v < version {
   214  		return -1
   215  	}
   216  	return 1
   217  }