1 | 'use strict'
|
2 |
|
3 | const chalk = require('chalk')
|
4 | const checkpoint = require('../checkpoint')
|
5 | const conventionalRecommendedBump = require('conventional-recommended-bump')
|
6 | const detectIndent = require('detect-indent')
|
7 | const detectNewline = require('detect-newline')
|
8 | const figures = require('figures')
|
9 | const fs = require('fs')
|
10 | const DotGitignore = require('dotgitignore')
|
11 | const path = require('path')
|
12 | const presetLoader = require('../preset-loader')
|
13 | const runLifecycleScript = require('../run-lifecycle-script')
|
14 | const semver = require('semver')
|
15 | const stringifyPackage = require('stringify-package')
|
16 | const writeFile = require('../write-file')
|
17 |
|
18 | let configsToUpdate = {}
|
19 |
|
20 | function Bump (args, version) {
|
21 |
|
22 |
|
23 | configsToUpdate = {}
|
24 |
|
25 | if (args.skip.bump) return Promise.resolve()
|
26 | let newVersion = version
|
27 | return runLifecycleScript(args, 'prerelease')
|
28 | .then(runLifecycleScript.bind(this, args, 'prebump'))
|
29 | .then((stdout) => {
|
30 | if (stdout && stdout.trim().length) args.releaseAs = stdout.trim()
|
31 | return bumpVersion(args.releaseAs, version, args)
|
32 | })
|
33 | .then((release) => {
|
34 | if (!args.firstRelease) {
|
35 | let releaseType = getReleaseType(args.prerelease, release.releaseType, version)
|
36 | newVersion = semver.valid(releaseType) || semver.inc(version, releaseType, args.prerelease)
|
37 | updateConfigs(args, newVersion)
|
38 | } else {
|
39 | checkpoint(args, 'skip version bump on first release', [], chalk.red(figures.cross))
|
40 | }
|
41 | })
|
42 | .then(() => {
|
43 | return runLifecycleScript(args, 'postbump')
|
44 | })
|
45 | .then(() => {
|
46 | return newVersion
|
47 | })
|
48 | }
|
49 |
|
50 | Bump.getUpdatedConfigs = function () {
|
51 | return configsToUpdate
|
52 | }
|
53 |
|
54 | Bump.pkgFiles = [
|
55 | 'package.json',
|
56 | 'bower.json',
|
57 | 'manifest.json',
|
58 | 'composer.json'
|
59 | ]
|
60 |
|
61 | Bump.lockFiles = [
|
62 | 'package-lock.json',
|
63 | 'npm-shrinkwrap.json',
|
64 | 'composer.lock'
|
65 | ]
|
66 |
|
67 | function getReleaseType (prerelease, expectedReleaseType, currentVersion) {
|
68 | if (isString(prerelease)) {
|
69 | if (isInPrerelease(currentVersion)) {
|
70 | if (shouldContinuePrerelease(currentVersion, expectedReleaseType) ||
|
71 | getTypePriority(getCurrentActiveType(currentVersion)) > getTypePriority(expectedReleaseType)
|
72 | ) {
|
73 | return 'prerelease'
|
74 | }
|
75 | }
|
76 |
|
77 | return 'pre' + expectedReleaseType
|
78 | } else {
|
79 | return expectedReleaseType
|
80 | }
|
81 | }
|
82 |
|
83 | function isString (val) {
|
84 | return typeof val === 'string'
|
85 | }
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 | function shouldContinuePrerelease (version, expectType) {
|
97 | return getCurrentActiveType(version) === expectType
|
98 | }
|
99 |
|
100 | function isInPrerelease (version) {
|
101 | return Array.isArray(semver.prerelease(version))
|
102 | }
|
103 |
|
104 | let TypeList = ['major', 'minor', 'patch'].reverse()
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | function getCurrentActiveType (version) {
|
113 | let typelist = TypeList
|
114 | for (let i = 0; i < typelist.length; i++) {
|
115 | if (semver[typelist[i]](version)) {
|
116 | return typelist[i]
|
117 | }
|
118 | }
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | function getTypePriority (type) {
|
129 | return TypeList.indexOf(type)
|
130 | }
|
131 |
|
132 | function bumpVersion (releaseAs, currentVersion, args) {
|
133 | return new Promise((resolve, reject) => {
|
134 | if (releaseAs) {
|
135 | return resolve({
|
136 | releaseType: releaseAs
|
137 | })
|
138 | } else {
|
139 | const presetOptions = presetLoader(args)
|
140 | if (typeof presetOptions === 'object') {
|
141 | if (semver.lt(currentVersion, '1.0.0')) presetOptions.preMajor = true
|
142 | }
|
143 | conventionalRecommendedBump({
|
144 | debug: args.verbose && console.info.bind(console, 'conventional-recommended-bump'),
|
145 | preset: presetOptions,
|
146 | path: args.path
|
147 | }, function (err, release) {
|
148 | if (err) return reject(err)
|
149 | else return resolve(release)
|
150 | })
|
151 | }
|
152 | })
|
153 | }
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 | function updateConfigs (args, newVersion) {
|
164 | const dotgit = DotGitignore()
|
165 | Bump.pkgFiles.concat(Bump.lockFiles).forEach((filename) => {
|
166 | configsToUpdate[path.resolve(process.cwd(), filename)] = false
|
167 | })
|
168 | Object.keys(configsToUpdate).forEach(function (configPath) {
|
169 | try {
|
170 | if (dotgit.ignore(configPath)) return
|
171 | let stat = fs.lstatSync(configPath)
|
172 | if (stat.isFile()) {
|
173 | let data = fs.readFileSync(configPath, 'utf8')
|
174 | let indent = detectIndent(data).indent
|
175 | let newline = detectNewline(data)
|
176 | let config = JSON.parse(data)
|
177 | let filename = path.basename(configPath)
|
178 | checkpoint(args, 'bumping version in ' + filename + ' from %s to %s', [config.version, newVersion])
|
179 | config.version = newVersion
|
180 | writeFile(args, configPath, stringifyPackage(config, indent, newline))
|
181 |
|
182 |
|
183 | configsToUpdate[configPath] = true
|
184 | }
|
185 | } catch (err) {
|
186 | if (err.code !== 'ENOENT') console.warn(err.message)
|
187 | }
|
188 | })
|
189 | }
|
190 |
|
191 | module.exports = Bump
|