├── .gitignore ├── test ├── mocha.opts ├── setup.js ├── support │ └── cli.js ├── cli.js └── test.js ├── .travis.yml ├── lib └── matcher.js ├── package.json ├── Help.txt ├── LICENSE ├── History.md ├── Readme.md ├── index.js └── bin └── bump /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | -R progress 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: ["0.10"] 3 | 4 | notifications: 5 | email: 6 | recipients: 7 | - dropbox+travis@ricostacruz.com 8 | on_success: change 9 | on_failure: change 10 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | global.expect = require('chai').expect; 2 | require('chai').use(require('sinon-chai')); 3 | 4 | function useSinon() { 5 | beforeEach(function () { 6 | global.sinon = require('sinon').sandbox.create(); 7 | }); 8 | 9 | afterEach(function () { 10 | global.sinon.restore(); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /lib/matcher.js: -------------------------------------------------------------------------------- 1 | function Matcher (re) { 2 | this.re = re; 3 | } 4 | 5 | Matcher.prototype.compile = function (key, flags) { 6 | var self = this; 7 | var regexp = this.re[key]; 8 | if (regexp.source) regexp = regexp.source; 9 | regexp = regexp.replace(/{(.*?)}/g, function (_, subkey) { 10 | return '(?:' + self.compile(subkey) + ')'; 11 | }); 12 | 13 | if (flags) 14 | return new RegExp(regexp, flags); 15 | else 16 | return regexp; 17 | }; 18 | 19 | module.exports = Matcher; 20 | 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rstacruz/bump-cli", 3 | "version": "2.0.1", 4 | "description": "Increments version numbers in files", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/rstacruz/bump-cli.git" 12 | }, 13 | "scripts": { 14 | "test": "mocha" 15 | }, 16 | "author": "Rico Sta. Cruz ", 17 | "license": "MIT", 18 | "bin": { 19 | "bump": "bin/bump" 20 | }, 21 | "devDependencies": { 22 | "chai": "^4.3.4", 23 | "mocha": "^9.0.1", 24 | "sinon": "^11.1.1", 25 | "sinon-chai": "^3.7.0" 26 | }, 27 | "dependencies": { 28 | "minimist": "^1.2.5", 29 | "semver": "^7.3.5" 30 | }, 31 | "publishConfig": { 32 | "registry": "https://registry.npmjs.org", 33 | "access": "public" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Help.txt: -------------------------------------------------------------------------------- 1 | Usage: 2 | $0 FILES [options] 3 | 4 | Options: 5 | -h, --help print usage information 6 | -V, --version show version info and exit 7 | 8 | Interactivity: 9 | -y, --yes assume yes, don't prompt 10 | -q, --quiet supress messages (implies -y) 11 | -n, --dry-run don't do anything, just simulate 12 | 13 | Bumping: 14 | -v, --to VERSION use this version 15 | -p, --patch bump patch version (2.3.4 -> 2.3.5) - default 16 | -m, --minor bump minor version (2.3.4 -> 2.4.0) 17 | -M, --major bump major version (2.3.4 -> 3.0.0) 18 | 19 | Preleases: 20 | --pre same as --prerelease 21 | --prerelease bump a prerelease number (2.3.4-8 -> 2.3.4-9) 22 | --prepatch bump patch and add prerelease (2.3.4 -> 2.3.5-0) 23 | --preminor bump minor and add prerelease (2.3.4 -> 2.4.0-0) 24 | --premajor bump major and add prerelease (2.3.4 -> 3.0.0-0) 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Rico Sta. Cruz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | ## v2.0.1 - July 10, 2021 2 | 3 | * Upgrade `semver` dependency to fix vulnerability. 4 | 5 | ## v2.0.0 - April 16, 2021 6 | 7 | * Republish as [`@rstacruz/bump-cli`](https://npmjs.com). The `bump-cli` package name will be donated. 8 | 9 | ## v1.1.3 - August 13, 2014 10 | 11 | * No actual changes; just add `repository` metadata in the npm package. 12 | 13 | ## v1.1.2 - August 11, 2014 14 | 15 | * Fix execution error. 16 | 17 | ## v1.1.1 - August 11, 2014 18 | 19 | * Return a non-zero exit code when aborted. 20 | 21 | ## v1.1.0 - August 11, 2014 22 | 23 | * Implement `--dry-run` (`-n`) to simulate. 24 | * Implement `--pre` as an alias for `--prerelease`. 25 | * Supress the 'Done' message when using `--yes`. 26 | * Remove dependency with the *prompt* npm package. 27 | 28 | ## v1.0.4 - August 11, 2014 29 | 30 | * Fix `--version` not working. 31 | * Improve `--help` appearance. 32 | 33 | ## v1.0.3 - August 11, 2014 34 | 35 | * Minor print formatting improvements. 36 | 37 | ## v1.0.2 - August 11, 2014 38 | 39 | * Fix the 'bump' executable not being exposed. 40 | 41 | ## v1.0.1 - August 11, 2014 42 | 43 | * Minor print formatting improvements. Also, testing out the package itself to 44 | bump its version, heh. 45 | 46 | ## v1.0.0 - August 11, 2014 47 | 48 | * Initial release. 49 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # @rstacruz/bump-cli 2 | 3 | Bumps semantic versions according to [semver] guidelines. 4 | 5 | ![Screenshot]( http://cdn.rawgit.com/rstacruz/bump-cli/a251c63/bump.png ) 6 | 7 | [![Status](https://travis-ci.org/rstacruz/bump-cli.svg?branch=master)](https://travis-ci.org/rstacruz/bump-cli) 8 | 9 | ## Install 10 | 11 | ```sh 12 | npx @rstacruz/bump-cli --help 13 | ``` 14 | 15 | See [command line options][options]. 16 | 17 | [![npm version](https://badge.fury.io/js/bump-cli.svg)](https://npmjs.org/package/bump-cli "View this project on npm") 18 | 19 | ## Note on upgrading 20 | 21 | Version `1.x` and below was published under `bump-cli`, but the newer versions are published under `@rstacruz/bump-cli`. 22 | 23 | ## Thanks 24 | 25 | Inspired by [@marksteve]'s [bump][bump-py]. `bump-cli` is backwards-compatible 26 | (mostly) with the old 2013 version bump. 27 | 28 | [@marksteve]: https://github.com/marksteve 29 | [bump-py]: https://github.com/marksteve/bump 30 | 31 | :copyright: 32 | 33 | **@rstacruz/bump-cli** © 2014-2021, Rico Sta. Cruz. Released under the [MIT] License.
34 | Authored and maintained by Rico Sta. Cruz with help from contributors. [(list)][contributors] 35 | 36 | > [ricostacruz.com](http://ricostacruz.com)  ·  37 | > GitHub [@rstacruz](https://github.com/rstacruz)  ·  38 | > Twitter [@rstacruz](https://twitter.com/rstacruz) 39 | 40 | [MIT]: http://mit-license.org/ 41 | [contributors]: http://github.com/rstacruz/bump-cli/contributors 42 | [semver]: https://www.npmjs.org/package/semver 43 | [options]: Help.txt 44 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var Semver = require('semver'); 2 | var Matcher = require('./lib/matcher'); 3 | 4 | var expr = new Matcher({ 5 | before: /([\s\S]*?)/, 6 | prefix: /([^\n]*(?!xml )version.*)/, 7 | trio: /\d+\.\d+\.\d+/, 8 | prerelease: /\-[a-z0-9]+/, 9 | build: /\+[a-z0-9]+/, 10 | after: /([^\n]*)([\s\S]*)/, 11 | regex: "^{before}{prefix}({trio}{prerelease}?{build}?){after}$" 12 | }).compile('regex', 'mi'); 13 | 14 | /** 15 | * Context : new Context(src, options) 16 | * Represents a file with contents `src`. 17 | * Options are: 18 | * 19 | * ~ inc (String): what to increment (major, minor, 20 | * patch, etc). Defaults to `patch`. 21 | * ~ version (String): what version to upgrade to. 22 | * when this is set, `inc` is bypassed. 23 | * 24 | * c = new Context("version = 2.2.5", "file.json", { inc: 'minor' }) 25 | * c.version => "2.2.5" 26 | * c.newVersion => "2.3.0" 27 | * c.toString() => "version = 2.3.0" 28 | */ 29 | 30 | function Context (src, filename, options) { 31 | if (!options) options = {}; 32 | this.src = src; 33 | this.filename = filename; 34 | 35 | if (options.version) 36 | this.newVersion = options.version; 37 | else 38 | this.inc = options.inc || 'patch'; 39 | 40 | this.proc(); 41 | } 42 | 43 | /** 44 | * proc(): 45 | * (private) processes the source code (`src`) 46 | */ 47 | 48 | Context.prototype.proc = function () { 49 | var m = this.src.match(expr); 50 | if (m) { 51 | this.valid = true; 52 | this.before = m[1]; 53 | this.lineBefore = m[2]; 54 | this.version = m[3]; 55 | if (!this.newVersion) 56 | this.newVersion = Semver.inc(m[3], this.inc); 57 | this.lineAfter = m[4]; 58 | this.after = m[5]; 59 | this.line = this.before.split('\n').length; 60 | } else { 61 | this.valid = false; 62 | } 63 | }; 64 | 65 | /** 66 | * toString(): 67 | * Reconstructs the source code using the new upgraded version number. 68 | */ 69 | 70 | Context.prototype.toString = function () { 71 | return [ 72 | this.before, 73 | this.lineBefore, 74 | this.newVersion, 75 | this.lineAfter, 76 | this.after 77 | ].join(""); 78 | }; 79 | 80 | 81 | /** 82 | * preview(): 83 | * (private) renders a console preview of changes to be done 84 | */ 85 | 86 | Context.prototype.preview = function () { 87 | this.lines = []; 88 | this.lines.push(c(1, this.filename)); 89 | this.lines.push([ 90 | ' ', 91 | c('30', this.line), 92 | ' ', 93 | this.lineBefore, 94 | c('32;4', this.newVersion), 95 | this.lineAfter, 96 | ' ', 97 | c('31', '(was ' + this.version + ')') 98 | ].join("")); 99 | return this.lines.join("\n"); 100 | }; 101 | 102 | function c (color, str) { 103 | return "\033["+color+"m"+str+"\033[0m"; 104 | } 105 | 106 | exports.Context = Context; 107 | -------------------------------------------------------------------------------- /bin/bump: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var Context = require('../index').Context; 3 | var fs = require('fs'); 4 | 5 | var args = require('minimist')(process.argv.slice(2), { 6 | string: 'to', 7 | boolean: ['patch', 'minor', 'major', 'premajor', 'preminor', 'prepatch', 'prerelease', 'yes', 'quiet', 'dry-run', 'pre'], 8 | alias: { h: 'help', V: 'version', v: 'to', p: 'patch', m: 'minor', M: 'major', y: 'yes', q: 'quiet', n: 'dry-run' } 9 | }); 10 | 11 | if (args.version) { 12 | console.log(require('../package.json').version); 13 | process.exit(); 14 | } 15 | 16 | if (args.help || !args._[0]) { 17 | var cmd = require('path').basename(process.argv[1]); 18 | console.log(require('fs').readFileSync(__dirname+'/../Help.txt','utf-8').replace(/\$0/g, cmd).trim()); 19 | process.exit(); 20 | } 21 | 22 | try { 23 | var contexts = []; 24 | var options = toOptions(args); 25 | 26 | args._.forEach(function (fname) { 27 | var contents = require('fs').readFileSync(fname, 'utf-8'); 28 | var ctx = new Context(contents, fname, options); 29 | if (!ctx.valid) { throw new Error("ENOVERSION, no version found on '" + fname + "'"); } 30 | contexts.push(ctx); 31 | }); 32 | 33 | contexts.forEach(function (ctx) { 34 | print(); 35 | print(ctx.preview()); 36 | }); 37 | 38 | // don't proceed with --dry-run 39 | if (args['dry-run']) return; 40 | 41 | askToProceed(function (res) { 42 | if (res) { 43 | contexts.forEach(function (ctx) { 44 | fs.writeFileSync(ctx.filename, ctx.toString(), 'utf-8'); 45 | }); 46 | if (!args.yes) print('\033[1A\033[2K\033[32m✓\033[0m', 'done!'); 47 | } else { 48 | if (!args.yes) print('\033[1A\033[2K\033[31m✗\033[0m', 'cancelled'); 49 | process.exit(16); 50 | } 51 | }); 52 | 53 | } catch (e) { 54 | console.warn('\033[31m✗\033[0m', e.message); 55 | process.exit(8); 56 | } 57 | 58 | function print () { 59 | if (args.quiet) return; 60 | console.warn.apply(console, arguments); 61 | } 62 | 63 | function askToProceed (fn) { 64 | if (args.yes || args.quiet) return fn(true); 65 | print(); 66 | ask('proceed? [Yn] ', function (res) { 67 | if (res.toLowerCase() === 'y' || !res) 68 | fn(true); 69 | else 70 | fn(false); 71 | }); 72 | } 73 | 74 | /** 75 | * toOptions(): 76 | * (private) 77 | */ 78 | 79 | function toOptions (args) { 80 | var options = {}; 81 | 82 | if (args.to) options.version = args.to; 83 | else if (args.major) options.inc = 'major'; 84 | else if (args.minor) options.inc = 'minor'; 85 | else if (args.premajor) options.inc = 'premajor'; 86 | else if (args.preminor) options.inc = 'preminor'; 87 | else if (args.prepatch) options.inc = 'prepatch'; 88 | else if (args.prerelease || args.pre) options.inc = 'prerelease'; 89 | else options.inc = 'patch'; 90 | 91 | return options; 92 | } 93 | 94 | /** 95 | * ask(): 96 | * (private) thanks https://coderwall.com/p/v16yja 97 | */ 98 | 99 | function ask (question, fn) { 100 | var r = require('readline').createInterface({ 101 | input: process.stdin, 102 | output: process.stderr}); 103 | 104 | r.question(question, function (answer) { 105 | r.close(); 106 | fn(answer); 107 | }); 108 | } 109 | -------------------------------------------------------------------------------- /test/support/cli.js: -------------------------------------------------------------------------------- 1 | /* jshint expr: true */ 2 | 3 | /*** 4 | * cli: 5 | * Helper for CLI tests. 6 | * 7 | * var cli = require('...'); 8 | * cli.bin = './bin/hello'; 9 | */ 10 | 11 | var exec = require('child_process').exec; 12 | 13 | /** 14 | * result : cli.result 15 | * the result. 16 | * 17 | * describe('help', function () { 18 | * cli.run('--help'); 19 | * 20 | * it('works', function () { 21 | * cli.result.code => 0 22 | * cli.result.error => true/false 23 | * cli.result.out => "..." (stdout output) 24 | * cli.result.stderr => "..." (stderr output) 25 | * }); 26 | * }); 27 | */ 28 | 29 | exports.result = {}; 30 | 31 | 32 | /** 33 | * bin : cli.bin 34 | * the bin to run. 35 | * 36 | * var cli = require('...'); 37 | * cli.bin = './bin/hello'; 38 | */ 39 | 40 | exports.bin = './bin/lol'; 41 | 42 | /** 43 | * run() : cli.run(cmd) 44 | * Runs a given command. 45 | * 46 | * describe('running', function () { 47 | * cli.run('--help'); 48 | * cli.success(); 49 | * }); 50 | */ 51 | 52 | exports.run = function (args) { 53 | before(function (next) { 54 | exec(exports.bin + ' ' + args, function (_exit, _cout, _cerr) { 55 | exports.result.code = _exit && _exit.code || 0; 56 | exports.result.error = _exit; 57 | exports.result.out = _cout; 58 | exports.result.stripped = _cout.replace(/\033\[[^m]*m/g, ''); 59 | exports.result.stderr = _cerr; 60 | next(); 61 | }); 62 | }); 63 | 64 | after(function () { 65 | delete exports.result.code; 66 | delete exports.result.error; 67 | delete exports.result.out; 68 | delete exports.result.stripped; 69 | delete exports.result.stderr; 70 | }); 71 | }; 72 | 73 | /** 74 | * success() : cli.success() 75 | * asserts success 76 | * 77 | * describe('running', function () { 78 | * cli.run('--help'); 79 | * cli.success(); 80 | * }); 81 | */ 82 | 83 | exports.success = function () { 84 | it('is successful', function () { 85 | expect(exports.result.code).eql(0); 86 | expect(exports.result.error).not.ok; 87 | }); 88 | }; 89 | 90 | /** 91 | * pipe() : cli.pipe(input, args) 92 | * runs and pipes things into stdin 93 | * 94 | * describe('pipes', function () { 95 | * cli.pipe('var x = 2', ['--no-pager']) 96 | * cli.success(); 97 | * }); 98 | */ 99 | 100 | exports.pipe = function (input, args) { 101 | before(function (next) { 102 | var spawn = require('child_process').spawn; 103 | var child = spawn(exports.bin, args || [], { stdio: 'pipe' }); 104 | exports.result.out = ''; 105 | exports.result.stderr = ''; 106 | 107 | if (input) { 108 | child.stdin.write(input); 109 | child.stdin.end(); 110 | } 111 | 112 | child.stdout.on('data', function (data) { exports.result.out += data; }); 113 | child.stderr.on('data', function (data) { exports.result.stderr += data; }); 114 | child.on('close', function (code) { 115 | exports.result.code = code; 116 | next(); 117 | }); 118 | }); 119 | 120 | after(function () { 121 | delete exports.result.out; 122 | delete exports.result.stderr; 123 | }); 124 | }; 125 | -------------------------------------------------------------------------------- /test/cli.js: -------------------------------------------------------------------------------- 1 | require('./setup'); 2 | var cli = require('./support/cli'); 3 | cli.bin = './bin/bump'; 4 | var fs = require('fs'); 5 | var res = cli.result; 6 | 7 | function tempfile() { 8 | return '/tmp/tmp' + Math.random(); 9 | } 10 | 11 | describe('CLI: --help', function () { 12 | cli.run('--help'); 13 | cli.success(); 14 | 15 | it('prints the command name', function () { 16 | expect(res.out).match(/bump FILES/); 17 | }); 18 | 19 | it('prints the command name', function () { 20 | expect(res.out).match(/bump FILES/); 21 | }); 22 | }); 23 | 24 | describe('CLI: --version', function () { 25 | cli.run('--version'); 26 | cli.success(); 27 | 28 | it('prints out the version', function () { 29 | expect(res.out).include(require('../package.json').version); 30 | }); 31 | }); 32 | 33 | // NB: this is sequential! 34 | describe('working with files', function () { 35 | var fname = tempfile(); 36 | 37 | before(function (next) { 38 | fs.writeFile(fname, 'VERSION = "1.0.0"\n', 'utf-8', next); 39 | }); 40 | 41 | after(function (next) { 42 | fs.unlink(fname, next); 43 | }); 44 | 45 | describe('invoking with -v', function () { 46 | cli.pipe('\n', [fname, '-v', '2.2.0']); 47 | cli.success(); 48 | 49 | it('works', function () { 50 | var str = fs.readFileSync(fname, 'utf-8'); 51 | expect(str).eql('VERSION = "2.2.0"\n'); 52 | }); 53 | 54 | it('produced preview output', function () { 55 | expect(res.stderr).match(/done!/); 56 | expect(res.stderr).include('2.2.0'); 57 | expect(res.stderr).include('was 1.0.0'); 58 | expect(res.stderr).match(/VERSION = .*2\.2\.0.*/); 59 | }); 60 | }); 61 | 62 | describe('invoking with --yes', function () { 63 | cli.run(fname + ' -y'); 64 | cli.success(); 65 | 66 | it('works', function () { 67 | var str = fs.readFileSync(fname, 'utf-8'); 68 | expect(str).eql('VERSION = "2.2.1"\n'); 69 | }); 70 | }); 71 | 72 | describe('invoking by default', function () { 73 | cli.pipe('\n', [fname]); 74 | cli.success(); 75 | 76 | it('prints a preview', function () { 77 | expect(res.stderr).match(/done!/); 78 | expect(res.stderr).include('2.2.2'); 79 | expect(res.stderr).include('was 2.2.1'); 80 | expect(res.stderr).match(/VERSION = .*2\.2\.2.*/); 81 | }); 82 | 83 | it('updates the version', function () { 84 | var str = fs.readFileSync(fname, 'utf-8'); 85 | expect(str).eql('VERSION = "2.2.2"\n'); 86 | }); 87 | }); 88 | 89 | describe('aborting with "n"', function () { 90 | cli.pipe('n\n', [fname]); 91 | 92 | it('produces a non-zero exit', function () { 93 | expect(res.code).gt(0); 94 | }); 95 | 96 | it('prints an aborted message', function () { 97 | expect(res.stderr).match(/cancelled/); 98 | }); 99 | 100 | it('doesnt do anything', function () { 101 | var str = fs.readFileSync(fname, 'utf-8'); 102 | expect(str).eql('VERSION = "2.2.2"\n'); 103 | }); 104 | }); 105 | 106 | describe('invoking with --minor', function () { 107 | cli.run(fname + ' -m -y'); 108 | cli.success(); 109 | 110 | it('works', function () { 111 | var str = fs.readFileSync(fname, 'utf-8'); 112 | expect(str).eql('VERSION = "2.3.0"\n'); 113 | }); 114 | }); 115 | 116 | describe('invoking with --quiet', function () { 117 | cli.run(fname + ' -q -v 2.2.0'); 118 | cli.success(); 119 | 120 | it('works', function () { 121 | var str = fs.readFileSync(fname, 'utf-8'); 122 | expect(str).eql('VERSION = "2.2.0"\n'); 123 | }); 124 | 125 | it('produces no stderr', function () { 126 | expect(res.stderr).eql(""); 127 | }); 128 | }); 129 | 130 | describe('invoking with a file without a version', function () { 131 | cli.run('bin/bump'); 132 | 133 | it('produces a non-zero exit', function () { 134 | expect(res.code).gt(0); 135 | }); 136 | 137 | it('produces stderr', function () { 138 | expect(res.stderr).match(/no version found/); 139 | }); 140 | }); 141 | 142 | describe('invoking with an invalid file', function () { 143 | cli.run('trololololol'); 144 | 145 | it('produces a non-zero exit', function () { 146 | expect(res.code).gt(0); 147 | }); 148 | 149 | it('produces stderr', function () { 150 | expect(res.stderr).match(/no such file/); 151 | }); 152 | }); 153 | }); 154 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | require('./setup'); 2 | 3 | var ctx, src; 4 | var Context = require('../index').Context; 5 | 6 | describe('using with a multi-line gemspec', function () { 7 | beforeEach(function () { 8 | src = [ 9 | "require 'rubygems'", 10 | "", 11 | "Gem.specification do |s|", 12 | " s.version = '2.2.0'", 13 | "end" 14 | ].join('\n'); 15 | ctx = new Context(src, "foo.gemspec"); 16 | }); 17 | 18 | it('finds the version', function () { 19 | expect(ctx.version).eql('2.2.0'); 20 | }); 21 | 22 | it('sets the new version', function () { 23 | expect(ctx.newVersion).eql('2.2.1'); 24 | }); 25 | 26 | it('gets the line before and after', function () { 27 | expect(ctx.lineBefore).eql(" s.version = '"); 28 | expect(ctx.lineAfter).eql("'"); 29 | }); 30 | 31 | it('gets the before and after', function () { 32 | expect(ctx.before).eql("require 'rubygems'\n\nGem.specification do |s|\n"); 33 | expect(ctx.after).eql("\nend"); 34 | }); 35 | 36 | it('reconstructs using toString()', function () { 37 | expect(ctx.toString()).eql(src.replace(/2.2.0/, '2.2.1')); 38 | }); 39 | 40 | it('preview', function () { 41 | expect(ctx.preview()).have.length.gt(10); 42 | }); 43 | 44 | it('finds source line', function () { 45 | expect(ctx.line).eql(4); 46 | }); 47 | }); 48 | 49 | describe('having the version on the first line', function () { 50 | beforeEach(function () { 51 | src = [ 52 | "s.version = '2.2.0'", 53 | "end" 54 | ].join('\n'); 55 | ctx = new Context(src); 56 | }); 57 | 58 | it('finds the version', function () { 59 | expect(ctx.version).eql('2.2.0'); 60 | }); 61 | 62 | it('gets the line before and after', function () { 63 | expect(ctx.lineBefore).eql("s.version = '"); 64 | expect(ctx.lineAfter).eql("'"); 65 | }); 66 | 67 | it('gets the before and after', function () { 68 | expect(ctx.before).eql(""); 69 | expect(ctx.after).eql("\nend"); 70 | }); 71 | 72 | it('finds source line', function () { 73 | expect(ctx.line).eql(1); 74 | }); 75 | }); 76 | 77 | describe('having the version as the only line', function () { 78 | beforeEach(function () { 79 | src = [ 80 | "" 81 | ].join('\n'); 82 | ctx = new Context(src); 83 | }); 84 | 85 | it('finds the version', function () { 86 | expect(ctx.version).eql('2.2.0'); 87 | }); 88 | 89 | it('gets the line before and after', function () { 90 | expect(ctx.lineBefore).eql(""); 92 | }); 93 | 94 | it('gets the before and after', function () { 95 | expect(ctx.before).eql(""); 96 | expect(ctx.after).eql(""); 97 | }); 98 | 99 | it('finds source line', function () { 100 | expect(ctx.line).eql(1); 101 | }); 102 | }); 103 | 104 | describe('using different version schemes', function () { 105 | it('works with basic semver-style versions', function () { 106 | ctx = new Context("version=2.2.5"); 107 | expect(ctx.version).eql('2.2.5'); 108 | }); 109 | 110 | it('works with prereleases', function () { 111 | ctx = new Context("version=2.2.5-pre3"); 112 | expect(ctx.version).eql('2.2.5-pre3'); 113 | }); 114 | 115 | it('works with build IDs', function () { 116 | ctx = new Context("version=2.2.5+20140404"); 117 | expect(ctx.version).eql('2.2.5+20140404'); 118 | }); 119 | 120 | it('works with prereleases and build IDs', function () { 121 | ctx = new Context("version=2.2.5-pre3+20140404"); 122 | expect(ctx.version).eql('2.2.5-pre3+20140404'); 123 | }); 124 | }); 125 | 126 | describe('xml', function () { 127 | it('ignores xml version strings', function () { 128 | ctx = new Context("\n"); 129 | expect(ctx.version).eql('2.0.4'); 130 | }); 131 | }); 132 | 133 | describe('using with invalid files', function () { 134 | it('ignores invalid files', function () { 135 | ctx = new Context("holla"); 136 | expect(ctx.valid).eql(false); 137 | }); 138 | }); 139 | 140 | describe('specifying an increment', function () { 141 | it('defaults to patch', function () { 142 | ctx = new Context("version=2.2.5"); 143 | expect(ctx.newVersion).eql('2.2.6'); 144 | }); 145 | 146 | it('works with "minor"', function () { 147 | ctx = new Context("version=2.2.5", '', { inc: 'minor' }); 148 | expect(ctx.newVersion).eql('2.3.0'); 149 | }); 150 | 151 | it('works with "preminor"', function () { 152 | ctx = new Context("version=2.2.5", '', { inc: 'preminor' }); 153 | expect(ctx.newVersion).eql('2.3.0-0'); 154 | }); 155 | 156 | it('works with setting an explicit version', function () { 157 | ctx = new Context("version=2.2.5", '', { version: 'pancakes' }); 158 | expect(ctx.newVersion).eql('pancakes'); 159 | expect(ctx.toString()).eql('version=pancakes'); 160 | }); 161 | }); 162 | 163 | describe("upper-case VERSION", function () { 164 | it('parsed by Context', function () { 165 | ctx = new Context("VERSION=2.2.5"); 166 | expect(ctx.valid).eql(true); 167 | expect(ctx.version).eql('2.2.5'); 168 | }); 169 | }); 170 | --------------------------------------------------------------------------------