/* * Copyright (c) 2013, 2014 Conformal Systems LLC * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package main import ( "bytes" "fmt" "strings" ) // semanticAlphabet const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" // These constants define the application version and follow the semantic // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 appMinor uint = 5 appPatch uint = 1 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. appPreRelease = "alpha" ) // appBuild is defined as a variable so it can be overridden during the build // process with '-ldflags "-X main.appBuild foo' if needed. It MUST only // contain characters from semanticAlphabet per the semantic versioning spec. var appBuild string // version returns the application version as a properly formed string per the // semantic versioning 2.0.0 spec (http://semver.org/). func version() string { // Start with the major, minor, and path versions. version := fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch) // Append pre-release version if there is one. The hyphen called for // by the semantic versioning spec is automatically appended and should // not be contained in the pre-release string. The pre-release version // is not appended if it contains invalid characters. preRelease := normalizeVerString(appPreRelease) if preRelease != "" { version = fmt.Sprintf("%s-%s", version, preRelease) } // Append build metadata if there is any. The plus called for // by the semantic versioning spec is automatically appended and should // not be contained in the build metadata string. The build metadata // string is not appended if it contains invalid characters. build := normalizeVerString(appBuild) if build != "" { version = fmt.Sprintf("%s+%s", version, build) } return version } // normalizeVerString returns the passed string stripped of all characters which // are not valid according to the semantic versioning guidelines for pre-release // version and build metadata strings. In particular they MUST only contain // characters in semanticAlphabet. func normalizeVerString(str string) string { result := bytes.Buffer{} for _, r := range str { if strings.ContainsRune(semanticAlphabet, r) { _, err := result.WriteRune(r) // Writing to a bytes.Buffer panics on OOM, and all // errors are unexpected. if err != nil { panic(err) } } } return result.String() }