2018-05-22 21:43:36 +02:00
|
|
|
// Copyright 2016-2018, Pulumi Corporation.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2018-04-25 03:43:39 +02:00
|
|
|
package buildutil
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"regexp"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
releaseVersionRegex = regexp.MustCompile(
|
2018-11-13 00:31:03 +01:00
|
|
|
`^v(?P<version>\d+\.\d+\.\d+)(?P<dirty>\+dirty)?$`)
|
2018-04-25 03:43:39 +02:00
|
|
|
rcVersionRegex = regexp.MustCompile(
|
2018-11-13 00:31:03 +01:00
|
|
|
`^v(?P<version>\d+\.\d+\.\d+)-rc\.(?P<rcN>\d+)(?P<dirty>\+dirty)?$`)
|
2018-04-25 03:43:39 +02:00
|
|
|
devVersionRegex = regexp.MustCompile(
|
2018-11-13 00:31:03 +01:00
|
|
|
`^v(?P<version>\d+\.\d+\.\d+)-dev\.(?P<time>\d+)\+(?P<gitInfo>g[a-z0-9]+)(?P<dirty>.dirty)?$`)
|
2018-04-25 03:43:39 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// PyPiVersionFromNpmVersion returns a PEP-440 compliant version for a given semver version. This method does not
|
|
|
|
// support all possible semver strings, but instead just supports versions that we generate for our node packages.
|
2018-06-11 18:40:36 +02:00
|
|
|
//
|
|
|
|
// NOTE: We do not include git information in the generated version (even within the local part, which PEP440 would
|
|
|
|
// allow) because we publish dev packages to PyPI, which does not allow local parts. Instead, we only add a local part
|
|
|
|
// when the build is dirty (which has the nice side effect of preventing us from publishing a build from dirty bits).
|
2018-04-25 03:43:39 +02:00
|
|
|
func PyPiVersionFromNpmVersion(s string) (string, error) {
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
|
|
|
if releaseVersionRegex.MatchString(s) {
|
|
|
|
capMap := captureToMap(releaseVersionRegex, s)
|
|
|
|
mustFprintf(&b, "%s", capMap["version"])
|
2018-11-13 00:31:03 +01:00
|
|
|
if capMap["dirty"] != "" {
|
|
|
|
mustFprintf(&b, "+dirty")
|
|
|
|
}
|
2018-04-25 03:43:39 +02:00
|
|
|
return b.String(), nil
|
|
|
|
} else if rcVersionRegex.MatchString(s) {
|
|
|
|
capMap := captureToMap(rcVersionRegex, s)
|
|
|
|
mustFprintf(&b, "%src%s", capMap["version"], capMap["rcN"])
|
2018-11-13 00:31:03 +01:00
|
|
|
if capMap["dirty"] != "" {
|
|
|
|
mustFprintf(&b, "+dirty")
|
|
|
|
}
|
2018-04-25 03:43:39 +02:00
|
|
|
return b.String(), nil
|
|
|
|
} else if devVersionRegex.MatchString(s) {
|
|
|
|
capMap := captureToMap(devVersionRegex, s)
|
2018-06-11 18:40:36 +02:00
|
|
|
mustFprintf(&b, "%s.dev%s", capMap["version"], capMap["time"])
|
2018-04-25 03:43:39 +02:00
|
|
|
if capMap["dirty"] != "" {
|
2018-06-11 18:40:36 +02:00
|
|
|
mustFprintf(&b, "+dirty")
|
2018-04-25 03:43:39 +02:00
|
|
|
}
|
|
|
|
return b.String(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return "", errors.Errorf("can not parse version string '%s'", s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func captureToMap(r *regexp.Regexp, s string) map[string]string {
|
|
|
|
matches := r.FindStringSubmatch(s)
|
|
|
|
capMap := make(map[string]string)
|
|
|
|
for i, name := range r.SubexpNames() {
|
|
|
|
if name != "" {
|
|
|
|
capMap[name] = matches[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return capMap
|
|
|
|
}
|
|
|
|
|
|
|
|
func mustFprintf(w io.Writer, format string, a ...interface{}) {
|
|
|
|
_, err := fmt.Fprintf(w, format, a...)
|
|
|
|
contract.AssertNoError(err)
|
|
|
|
}
|