decred.org/dcrwallet/v3@v3.1.0/version/version.go (about)

     1  // Copyright (c) 2013-2014 The btcsuite developers
     2  // Copyright (c) 2015-2021 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package version
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"strings"
    12  )
    13  
    14  // semverAlphabet is an alphabet of all characters allowed in semver prerelease
    15  // or build metadata identifiers, and the . separator.
    16  const semverAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-."
    17  
    18  // Constants defining the application version number.
    19  const (
    20  	Major = 1
    21  	Minor = 8
    22  	Patch = 1
    23  )
    24  
    25  // Integer is an integer encoding of the major.minor.patch version.
    26  const Integer = 1000000*Major + 10000*Minor + 100*Patch
    27  
    28  // PreRelease contains the prerelease name of the application.  It is a variable
    29  // so it can be modified at link time (e.g.
    30  // `-ldflags "-X decred.org/dcrwallet/v3/version.PreRelease=rc1"`).
    31  // It must only contain characters from the semantic version alphabet.
    32  var PreRelease = ""
    33  
    34  // BuildMetadata defines additional build metadata.  It is modified at link time
    35  // for official releases.  It must only contain characters from the semantic
    36  // version alphabet.
    37  var BuildMetadata = "release.local"
    38  
    39  func init() {
    40  	if BuildMetadata == "" {
    41  		BuildMetadata = vcsCommitID()
    42  	}
    43  }
    44  
    45  // String returns the application version as a properly formed string per the
    46  // semantic versioning 2.0.0 spec (https://semver.org/).
    47  func String() string {
    48  	// Start with the major, minor, and path versions.
    49  	version := fmt.Sprintf("%d.%d.%d", Major, Minor, Patch)
    50  
    51  	// Append pre-release version if there is one.  The hyphen called for
    52  	// by the semantic versioning spec is automatically appended and should
    53  	// not be contained in the pre-release string.  The pre-release version
    54  	// is not appended if it contains invalid characters.
    55  	preRelease := normalizeVerString(PreRelease)
    56  	if preRelease != "" {
    57  		version = version + "-" + preRelease
    58  	}
    59  
    60  	// Append build metadata if there is any.  The plus called for
    61  	// by the semantic versioning spec is automatically appended and should
    62  	// not be contained in the build metadata string.  The build metadata
    63  	// string is not appended if it contains invalid characters.
    64  	buildMetadata := normalizeVerString(BuildMetadata)
    65  	if buildMetadata != "" {
    66  		version = version + "+" + buildMetadata
    67  	}
    68  
    69  	return version
    70  }
    71  
    72  // normalizeVerString returns the passed string stripped of all characters which
    73  // are not valid according to the semantic versioning guidelines for pre-release
    74  // version and build metadata strings.  In particular they MUST only contain
    75  // characters in semanticAlphabet.
    76  func normalizeVerString(str string) string {
    77  	var buf bytes.Buffer
    78  	for _, r := range str {
    79  		if strings.ContainsRune(semverAlphabet, r) {
    80  			_, err := buf.WriteRune(r)
    81  			// Writing to a bytes.Buffer panics on OOM, and all
    82  			// errors are unexpected.
    83  			if err != nil {
    84  				panic(err)
    85  			}
    86  		}
    87  	}
    88  	return buf.String()
    89  }