diff --git a/README.md b/README.md index b6ca61d70401..4329dae09be7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Kibana 4.1.0-snapshot +# Kibana 4.1.0-snapshot [![Build Status](https://travis-ci.org/elasticsearch/kibana.svg?branch=master)](https://travis-ci.org/elasticsearch/kibana?branch=master) diff --git a/tasks/utils/updateVersion.js b/tasks/utils/updateVersion.js new file mode 100644 index 000000000000..b4cc19d43937 --- /dev/null +++ b/tasks/utils/updateVersion.js @@ -0,0 +1,134 @@ +var _ = require('lodash'); + +module.exports = updateVersion; + +var versions = [ + 'major', + 'minor', + 'patch', + 'tag' +]; + +/** + * change the version based on a basic expression + * + * Expressions have two pieces, the version piece to + * set and the new value. If the version peice is not + * "tag" then the new value can be left of and the preivous + * value will simply be incremented by one. if the version + * peice is tag, some special rules apply: + * 1. leaving the value empty will remove a tag + * 2. adding a new tag bumps the minor version + * + * examples: + * + * expr: minor + * 1.4.1 => 1.5.0 + * + * expr: minor=10 + * 1.5.5 => 1.10.0 + * + * expr: major=4 + * 0.0.1 => 4.0.0 + * + * expr: tag=beta2 + * 4.0.0-beta1 => 4.0.0-beta2 + * + * expr: tag=snapshot + * 4.0.0 => 4.1.0-snapshot + * + * expr: tag= + * 4.0.0-rc1 => 4.0.0 + * + */ +function updateVersion(version, expr) { + expr = String(expr).split('='); + + var change = { + name: expr[0], + val: expr[1] || null + }; + + if (!_.contains(versions, change.name)) { + throw new Error('version update expression needs to start with one of ' + versions.join(', ')); + } + + if (change.name === 'tag' && change.val) { + change.val = change.val.toLowerCase(); + } + + // parse the current version + var parts = _.chain(version.split('.')) + + // ensure that their are three pieces, either x.x.x or x.x.x-y + .tap(function (versionNumbers) { + if (versionNumbers.length !== 3) { + throw new Error('Version number "' + version + '" should have two dots, like 4.1.0'); + } + }) + + // describe all of the version parts with a name, parse + // the numbers, and extract tag from patch + .transform(function (parts, v, i) { + var name = versions[i]; + + if (name !== 'patch') { + parts[name] = _.parseInt(v); + return; + } + + // patch is two parts, a version number and an optional tag + v = v.split('-'); + parts.patch = _.parseInt(v.shift()); + parts.tag = v.join('-'); + }, {}) + + // sanity check + .tap(function (parts) { + + var valid = true; + valid = valid && _.isNumber(parts.major); + valid = valid && _.isNumber(parts.minor); + valid = valid && _.isNumber(parts.patch); + valid = valid && _.isString(parts.tag); + + if (!valid) { + throw new Error('Unable to parse version "' + version + '"'); + } + + }) + + // perform the change on parts + .tap(function (parts) { + if (change.name === 'tag' && change.val && !parts.tag) { + // special operation that doesn't follow the natural rules + parts.minor += 1; + parts.patch = 0; + parts.tag = change.val; + return; + } + + // since the version parts are in order from left to right, the update + // reset all of the values to the right of it: + // + // 0.12.3-beta -> 1.0.0 (increment major, reset everything else) + + // primary update + if (change.name === 'tag') { + parts[change.name] = change.val; + } else { + parts[change.name] = (change.val == null) ? parts[change.name] + 1 : change.val; + } + + // properties that are zero-d by the previous update + var emptyUpdates = versions.slice(versions.indexOf(change.name) + 1); + while(emptyUpdates.length) { + parts[emptyUpdates.shift()] = ''; + } + }) + .value(); + + return (parts.major || 0) + '.' + + (parts.minor || 0) + '.' + + (parts.patch || 0) + (parts.tag ? '-' + parts.tag : ''); +} \ No newline at end of file diff --git a/tasks/version.js b/tasks/version.js new file mode 100644 index 000000000000..392e87689885 --- /dev/null +++ b/tasks/version.js @@ -0,0 +1,48 @@ +module.exports = function (grunt) { + var root = require('path').resolve.bind(null, __dirname, '..'); + var updateVersion = require('./utils/updateVersion'); + + var README_PATH = root('README.md'); + var PKG_JSON_PATH = root('package.json'); + var START = ''; + var END = ''; + + grunt.registerTask('version', function (updateExpr) { + var oldVersion = grunt.config.get('pkg.version'); + var version = updateVersion(oldVersion, updateExpr); + grunt.log.debug('switching from %s to %s', oldVersion, version); + + // update grunt config + grunt.config.set('pkg.version', version); + + // write back to package.json + var pkgJson = grunt.file.read(PKG_JSON_PATH); + pkgJson = pkgJson.replace(JSON.stringify(oldVersion), JSON.stringify(version)); + grunt.file.write(PKG_JSON_PATH, pkgJson); + grunt.log.ok('updated package.json', version); + + // write the readme + var input = grunt.file.read(README_PATH); + var readme = ''; + + var startI, endI, before; + while (input.length) { + startI = input.indexOf(START); + endI = input.indexOf(END); + if (endI < startI) throw new Error('version tag mismatch in ' + input); + + if (startI < 0) { + readme += input; + break; + } + + before = input.substr(0, startI); + input = input.substr(endI ? endI + END.length : startI); + + readme += before + START + version + END; + } + + grunt.file.write(README_PATH, readme); + grunt.log.ok('updated readme', version); + }); +};