-
Notifications
You must be signed in to change notification settings - Fork 0
/
version.go
159 lines (135 loc) · 4.01 KB
/
version.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package files
import (
"bufio"
"fmt"
"path/filepath"
"regexp"
"strings"
)
type versionFileMatcher struct {
lineMatcher func(string) bool
notFoundError error
singleLineFile bool
versionRegex string
}
var tomlMatcher = versionFileMatcher{
lineMatcher: func(line string) bool {
return strings.Contains(line, "version =")
},
notFoundError: ErrGettingVersionFromTOML,
singleLineFile: false,
versionRegex: `(.*)(version *=* *"*)(?P<semver>\d+.\d+.\d+)(.*)`,
}
// not toml files, but version string is same format.
var gradleMatcher = versionFileMatcher{
lineMatcher: tomlMatcher.lineMatcher,
notFoundError: ErrGettingVersionFromBuildGradle,
singleLineFile: false,
versionRegex: tomlMatcher.versionRegex,
}
// versionFileMatchers contains the utilies to extract and update the version
// from the version file.
func versionFileMatchers() map[string]versionFileMatcher {
return map[string]versionFileMatcher{
"build.gradle": gradleMatcher,
"build.gradle.kts": gradleMatcher,
"Cargo.toml": tomlMatcher,
"CMakeLists.txt": {
lineMatcher: func(line string) bool {
return strings.Contains(line, "project(")
},
notFoundError: ErrGettingVersionFromCMakeLists,
singleLineFile: false,
versionRegex: `(project\(.*)(VERSION ){1}(?P<semver>\d+.\d+.\d+)(.*\))`,
},
"package.json": {
lineMatcher: func(line string) bool {
return strings.Contains(line, `"version": "`)
},
notFoundError: ErrGettingVersionFromPackageJSON,
singleLineFile: false,
versionRegex: `(.*)("version": *"){1}(?P<semver>\d+.\d+.\d+)(".*)`,
},
"pyproject.toml": tomlMatcher,
"setup.py": {
lineMatcher: func(line string) bool {
return strings.Contains(line, `version=`)
},
notFoundError: ErrGettingVersionFromSetupPy,
singleLineFile: false,
versionRegex: `(.*)(version=['"])(?P<semver>\d+.\d+.\d+)(.*)`,
},
"VERSION": {
lineMatcher: func(line string) bool {
// single line file so nothing to match on.
return true
},
notFoundError: ErrGettingVersionFromVERSION,
singleLineFile: true,
versionRegex: `(.*)(?P<semver>\d+.\d+.\d+)(.*)`,
},
}
}
// getVersionMatcher gets the relevant versionFileMatcher config for the
// provided input file or errors if there is no config for a file with that name.
func getVersionMatcher(inputFile string) (versionFileMatcher, error) {
// Split dir and file to support relative paths provided with `--file` CLI flag.
_, file := filepath.Split(inputFile)
matcher, exists := versionFileMatchers()[file]
if !exists {
return versionFileMatcher{}, fmt.Errorf("%s is not a supported version file type", file)
}
return matcher, nil
}
func (v versionFileMatcher) getVersion(scanner *bufio.Scanner) (string, error) {
for scanner.Scan() {
lineText := scanner.Text()
if v.singleLineFile && (lineText == "" || lineText == "\n") {
return "", v.notFoundError
}
if v.singleLineFile {
return lineText, nil
}
if v.lineMatcher(lineText) {
re := regexp.MustCompile(v.versionRegex)
result := make(map[string]string)
match := re.FindStringSubmatch(lineText)
if match == nil {
return "", v.notFoundError
}
for i, name := range re.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
semver, exists := result["semver"]
if !exists {
return "", v.notFoundError
}
return semver, nil
}
}
return "", v.notFoundError
}
func (v versionFileMatcher) updateVersionInPlace(scanner *bufio.Scanner, newVersion string) ([]string, error) {
if v.singleLineFile {
return []string{newVersion}, nil
}
foundVersion := false
allLines := []string{}
for scanner.Scan() {
lineText := scanner.Text()
if v.lineMatcher(lineText) {
re := regexp.MustCompile(v.versionRegex)
newVersionLine := re.ReplaceAllString(lineText, fmt.Sprintf(`${1}${2}%s${4}`, newVersion))
allLines = append(allLines, newVersionLine)
foundVersion = true
continue
}
allLines = append(allLines, lineText)
}
if !foundVersion {
return []string{}, v.notFoundError
}
return allLines, nil
}