From a85763f677902d92418ceafed82ca57698018143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 26 Mar 2014 14:21:39 -0400 Subject: [PATCH 1/4] Util: Allow an error to be passed to Release.abort() When generating a new stack trace, don't include Release.abort(). --- lib/util.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/util.js b/lib/util.js index b7338c6..3adf5df 100644 --- a/lib/util.js +++ b/lib/util.js @@ -29,12 +29,17 @@ Release.define({ process.chdir( directory ); }, - abort: function( msg ) { - var error = new Error(); - Error.captureStackTrace( error ); + abort: function( msg, error ) { + if ( !error ) { + error = new Error( msg ); + Error.captureStackTrace( error, Release.abort ); + } + console.log( msg.red ); console.log( "Aborting.".red ); + console.log(); console.log( error.stack ); + process.exit( 1 ); }, From bea68ad27876d9ed9a6705beb2dc8e0d0aab1688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 26 Mar 2014 09:43:22 -0400 Subject: [PATCH 2/4] Changelog: Use changelogplease for git parsing Fixes gh-7 --- lib/changelog.js | 66 ++- node_modules/changelogplease/.npmignore | 1 + node_modules/changelogplease/.travis.yml | 5 + node_modules/changelogplease/LICENSE.txt | 20 + node_modules/changelogplease/README.md | 60 +++ node_modules/changelogplease/index.js | 107 +++++ .../node_modules/git-tools/.jshintrc | 12 + .../node_modules/git-tools/.npmignore | 2 + .../node_modules/git-tools/Gruntfile.js | 26 ++ .../node_modules/git-tools/LICENSE-MIT.txt | 20 + .../node_modules/git-tools/README.md | 265 ++++++++++++ .../node_modules/git-tools/git-tools.js | 396 ++++++++++++++++++ .../node_modules/git-tools/package.json | 36 ++ .../node_modules/git-tools/test/test.js | 43 ++ node_modules/changelogplease/package.json | 37 ++ .../changelogplease/tests/changelog.js | 183 ++++++++ .../changelogplease/tests/fixtures/commits.js | 15 + .../tests/fixtures/commits.txt | 43 ++ package.json | 1 + 19 files changed, 1298 insertions(+), 40 deletions(-) create mode 100644 node_modules/changelogplease/.npmignore create mode 100644 node_modules/changelogplease/.travis.yml create mode 100644 node_modules/changelogplease/LICENSE.txt create mode 100644 node_modules/changelogplease/README.md create mode 100644 node_modules/changelogplease/index.js create mode 100644 node_modules/changelogplease/node_modules/git-tools/.jshintrc create mode 100644 node_modules/changelogplease/node_modules/git-tools/.npmignore create mode 100644 node_modules/changelogplease/node_modules/git-tools/Gruntfile.js create mode 100644 node_modules/changelogplease/node_modules/git-tools/LICENSE-MIT.txt create mode 100644 node_modules/changelogplease/node_modules/git-tools/README.md create mode 100644 node_modules/changelogplease/node_modules/git-tools/git-tools.js create mode 100644 node_modules/changelogplease/node_modules/git-tools/package.json create mode 100644 node_modules/changelogplease/node_modules/git-tools/test/test.js create mode 100644 node_modules/changelogplease/package.json create mode 100644 node_modules/changelogplease/tests/changelog.js create mode 100644 node_modules/changelogplease/tests/fixtures/commits.js create mode 100644 node_modules/changelogplease/tests/fixtures/commits.txt diff --git a/lib/changelog.js b/lib/changelog.js index 6d29e53..cd1dba3 100644 --- a/lib/changelog.js +++ b/lib/changelog.js @@ -1,16 +1,20 @@ -var fs = require( "fs" ); +var fs = require( "fs" ), + changelogplease = require( "changelogplease" ); module.exports = function( Release ) { Release.define({ - _generateChangelog: function() { - var changelogPath = Release.dir.base + "/changelog", - changelog = Release.changelogShell() + - Release._generateCommitChangelog() + - Release._generateIssueChangelog(); - - fs.writeFileSync( changelogPath, changelog ); - console.log( "Stored changelog in " + changelogPath.cyan + "." ); + _generateChangelog: function( callback ) { + Release._generateCommitChangelog(function( commitChangelog ) { + var changelogPath = Release.dir.base + "/changelog", + changelog = Release.changelogShell() + + commitChangelog + + Release._generateIssueChangelog(); + + fs.writeFileSync( changelogPath, changelog ); + console.log( "Stored changelog in " + changelogPath.cyan + "." ); + callback(); + }); }, changelogShell: function() { @@ -21,39 +25,21 @@ Release.define({ return Release.newVersion; }, - _generateCommitChangelog: function() { - var commits, - commitRef = "[%h](" + Release._repositoryUrl() + "/commit/%H)", - fullFormat = "* %s (TICKETREF, " + commitRef + ")", - ticketUrl = Release._ticketUrl(); - + _generateCommitChangelog: function( callback ) { console.log( "Adding commits..." ); - Release.chdir( Release.dir.repo ); - commits = Release.gitLog( fullFormat ); - - console.log( "Adding links to tickets..." ); - return commits - - // Add ticket references - .map(function( commit ) { - var tickets = []; - - commit.replace( /Fix(?:e[sd])? #(\d+)/g, function( match, ticket ) { - tickets.push( ticket ); - }); - - return tickets.length ? - commit.replace( "TICKETREF", tickets.map(function( ticket ) { - return "[#" + ticket + "](" + ticketUrl + ticket + ")"; - }).join( ", " ) ) : - - // Leave TICKETREF token in place so it's easy to find commits without tickets - commit; - }) - // Sort commits so that they're grouped by component - .sort() - .join( "\n" ) + "\n"; + changelogplease({ + ticketUrl: Release._ticketUrl() + "{id}", + commitUrl: Release._repositoryUrl() + "/commit/{id}", + repo: Release.dir.repo, + committish: Release.prevVersion + ".." + Release.newVersion + }, function( error, log ) { + if ( error ) { + Release.abort( "Error generating commit changelog.", error ); + } + + callback( log ); + }); }, _generateIssueChangelog: function() { diff --git a/node_modules/changelogplease/.npmignore b/node_modules/changelogplease/.npmignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/node_modules/changelogplease/.npmignore @@ -0,0 +1 @@ +/node_modules/ diff --git a/node_modules/changelogplease/.travis.yml b/node_modules/changelogplease/.travis.yml new file mode 100644 index 0000000..4a83e22 --- /dev/null +++ b/node_modules/changelogplease/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.11" + - "0.10" + - "0.8" diff --git a/node_modules/changelogplease/LICENSE.txt b/node_modules/changelogplease/LICENSE.txt new file mode 100644 index 0000000..2354819 --- /dev/null +++ b/node_modules/changelogplease/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2014 Scott González http://scottgonzalez.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/changelogplease/README.md b/node_modules/changelogplease/README.md new file mode 100644 index 0000000..b69685b --- /dev/null +++ b/node_modules/changelogplease/README.md @@ -0,0 +1,60 @@ +# Changelog, please + +Generate changelogs from git commit messages using node.js. The generated changelogs are written in markdown. + +Support this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/). + +## Installation + +``` +npm install changelogplease +``` + +## Usage + +```javascript +var changelog = require( "changelogplease" ); +var parsed = changelog({ + ticketUrl: "https://github.com/scottgonzalez/changelogplease/issues/{id}", + commitUrl: "https://github.com/scottgonzalez/changelogplease/commit/{id}", + repo: "/path/to/repo", + committish: "1.2.3..1.2.4" +}); +``` + +## API + +### changelog( options, callback ) + +* `options` (Object): Options for creating the changelog. + * `ticketUrl` (String): Template for ticket/issue URLs; `{id}` will be replaced with the ticket id. + * `commitUrl (String)`: Template for commit URLs; `{id}` will be replaced with the commit hash. + * `repo` (String): Path to the repository. + * `committish` (String): The range of commits for the changelog. +* `callback` (Function; `function( error, log )`): Function to invoke after generating the changelog. + * `log` (String): Generated changelog, written in markdown. + +### Changelog + +`changelog( options, callback )` is a shorthand for the following: + +```js +var Changelog = require( "changelogplease" ).Changelog; +var instance = new Changelog( options ); +instance.parse( callback ); +``` + +Changelog generation is tailored to a specific format based on the needs of the various jQuery +projects. However, the `Changelog` constructor and prototype are exposed to allow flexibility. +Be aware that these methods are not currently documented because they may change. Feel free to +submit [feature requests](https://github.com/scottgonzalez/changelogplease/issues/new) if you don't +feel comfortable hacking in your own changes (or even if you do). + + +## License + +Copyright 2014 Scott González. Released under the terms of the MIT license. + +--- + +Support this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/). diff --git a/node_modules/changelogplease/index.js b/node_modules/changelogplease/index.js new file mode 100644 index 0000000..1cbf0b3 --- /dev/null +++ b/node_modules/changelogplease/index.js @@ -0,0 +1,107 @@ +var Repo = require( "git-tools" ); + +exports = module.exports = changelog; +exports.Changelog = Changelog; + +function changelog( options, callback ) { + var instance = new Changelog( options ); + + if ( callback ) { + instance.parse( callback ); + } + + return instance; +} + +function Changelog( options ) { + this.options = options; + this.repo = new Repo( this.options.repo ); + + // Bind all methods to the instance + for ( var method in this ) { + if ( typeof this[ method ] === "function" ) { + this[ method ] = this[ method ].bind( this ); + } + } +} + +Changelog.prototype.parse = function( callback ) { + this.getLog(function( error, log ) { + if ( error ) { + return callback( error ); + } + + callback( null, this.parseCommits( log ) ); + }.bind( this )); +}; + +Changelog.prototype.ticketUrl = function( id ) { + return this.options.ticketUrl.replace( "{id}", id ); +}; + +Changelog.prototype.getLog = function( callback ) { + var commitUrl = this.options.commitUrl.replace( "{id}", "%H" ); + + this.repo.exec( "log", + "--format=" + + "__COMMIT__%n" + + "%s (__TICKETREF__, [%h](" + commitUrl + "))%n" + + "%b", + this.options.committish, + callback ); +}; + +Changelog.prototype.parseCommits = function( commits ) { + commits = commits.split( "__COMMIT__\n" ); + commits.shift(); + + return commits + + // Parse each individual commit + .map( this.parseCommit ) + + // Sort commits so that they're grouped by component + .sort() + .join( "\n" ) + "\n"; +}; + +Changelog.prototype.parseCommit = function( commit ) { + var ticketUrl = this.ticketUrl; + var tickets = []; + + // Sane global exec with iteration over matches + commit.replace( + /Fix(?:e[sd])? ((?:[a-zA-Z0-9_-]{1,39}\/[a-zA-Z0-9_-]{1,100}#)|#|gh-)(\d+)/g, + function( match, refType, ticketId ) { + var ticketRef = { + url: ticketUrl( ticketId ), + label: "#" + ticketId + }; + + // If the refType has anything before the #, assume it's a GitHub ref + if ( /.#$/.test( refType ) ) { + refType = refType.replace( /#$/, "" ); + ticketRef.url = "https://github.com/" + refType + "/issues/" + ticketId; + ticketRef.label = refType + ticketRef.label; + } + + tickets.push( ticketRef ); + } + ); + + // Only keep the summary for the changelog; drop the body + var parsed = "* " + commit.split( /\r?\n/ )[ 0 ]; + + // Add in ticket references + // Leave __TICKETREF__ token in place so it's easy to find commits without tickets + if ( tickets.length ) { + parsed = parsed.replace( "__TICKETREF__", tickets.map(function( ticket ) { + return "[" + ticket.label + "](" + ticket.url + ")"; + }).join( ", " ) ); + } + + // Remove cherry pick references + parsed = parsed.replace( / \(cherry picked from commit [^)]+\)/, "" ); + + return parsed; +}; diff --git a/node_modules/changelogplease/node_modules/git-tools/.jshintrc b/node_modules/changelogplease/node_modules/git-tools/.jshintrc new file mode 100644 index 0000000..872f201 --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/.jshintrc @@ -0,0 +1,12 @@ +{ + "curly": true, + "eqnull": true, + "eqeqeq": true, + "expr": true, + "noarg": true, + "node": true, + "strict": false, + "trailing": true, + "undef": true, + "unused": true +} diff --git a/node_modules/changelogplease/node_modules/git-tools/.npmignore b/node_modules/changelogplease/node_modules/git-tools/.npmignore new file mode 100644 index 0000000..177acc9 --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/.npmignore @@ -0,0 +1,2 @@ +node_modules +test/repo diff --git a/node_modules/changelogplease/node_modules/git-tools/Gruntfile.js b/node_modules/changelogplease/node_modules/git-tools/Gruntfile.js new file mode 100644 index 0000000..ff669fb --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/Gruntfile.js @@ -0,0 +1,26 @@ +var grunt = require( "grunt" ); + +grunt.loadNpmTasks( "grunt-contrib-jshint" ); +grunt.loadNpmTasks( "grunt-contrib-nodeunit" ); + +grunt.initConfig({ + jshint: { + src: { + options: { + jshintrc: ".jshintrc" + }, + src: [ "git-tools.js" ] + }, + test: { + options: { + jshintrc: ".jshintrc" + }, + src: [ "test/**.js" ] + } + }, + nodeunit: { + all: [ "test/**/*.js" ] + } +}); + +grunt.registerTask( "default", [ "jshint", "nodeunit" ] ); diff --git a/node_modules/changelogplease/node_modules/git-tools/LICENSE-MIT.txt b/node_modules/changelogplease/node_modules/git-tools/LICENSE-MIT.txt new file mode 100644 index 0000000..b99c1ea --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/LICENSE-MIT.txt @@ -0,0 +1,20 @@ +Copyright 2013 Scott González http://scottgonzalez.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/changelogplease/node_modules/git-tools/README.md b/node_modules/changelogplease/node_modules/git-tools/README.md new file mode 100644 index 0000000..ad92887 --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/README.md @@ -0,0 +1,265 @@ +# node-git-tools + +Tools for parsing data out of git repositories. + +Support this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/). + +## About + +The goal of node-git-tools is to provide a set of tools that can be used to +easily write custom git commands or other scripts that are tightly integrated +with git. + +I expect the API to grow over time and will happily entertain any feature +requests. If there is anything you'd like added, just file an issue. + +## Installation + +```sh +npm install git-tools +``` + +## Usage + +```js +var Repo = require( "git-tools" ); +var repo = new Repo( "path/to/repo" ); +repo.authors(function( error, authors ) { + console.log( authors ); +}); +``` + + + +## API + +### Repo.clone( options, callback ) + +Clones a repository and returns the new `Repo` instance. + +* `options` (Object): Options for cloning the repository. + * `repo` (String): The repository to clone from. + * `path` (String): The path to clone into. + * extra: Additional options can be provided, as documented below. +* `callback` (Function; `function( error, repo )`): Function to invoke after cloning the repository. + * `repo` (Object): A new `Repo` instance for the cloned repository. + +This function accepts arbitrary options to pass to `git clone`. +For example, to create a bare repository: + +```js +Repo.clone({ + repo: "git://github.com/scottgonzalez/node-git-tools.git", + dir: "/tmp/git-tools", + bare: true +}); +``` + +Or to create a repo with limited history: + +```js +Repo.clone({ + repo: "git://github.com/scottgonzalez/node-git-tools.git", + dir: "/tmp/git-tools", + depth: 5 +}); +``` + + + +### Repo.isRepo( path, callback ) + +Determines if the specified path is a git repository. + +* `path` (String): The path to check. +* `callback` (Function; `function( error, isRepo )`): Function to invoke after determining if the path is a git repository. + * `isRepo` (Boolean): Whether the path is a git repository. + +*Note: This is equivalent to creating a `Repo` instance with `path` and calling `isRepo()` on the instance.* + + + +### activeDays( [committish], callback ) + +Gets the number of active days (unique days of authorship). Includes activity +by day, month, year, and the entire history. + +* `committish` (String; default: `"master"`): Committish range to analyze. +* `callback` (Function; `function( error, activeDays )`): Function to invoke after getting active days. + * `activeDays` (Object): Summary of active days. + +The `activeDays` object has the following form: + +```js +{ + activeDays: Number, + commits: Number, + dates: { + "YYYY-MM-DD": Number( commits ), + ... + }, + years: { + "YYYY": { + activeDays: Number, + commits: Number, + months: { + "M": { + activeDays: Number, + commits: Number, + days: { + "D": { + commits: Number + }, + ... + } + }, + ... + } + }, + ... + } +} +``` + + + +### age( callback ) + +Gets the age of the repository. + +* `callback` (Function; `function( error, age )`): Function to invoke after getting the age. + * `age` (String): The age of the repository. + + + +### authors( [committish], callback ) + +Gets all authors, sorted by number of commits. + +* `committish` (String; default: `"master"`): Committish range to analyze. +* `callback` (Function; `function( error, authors )`): Function to invoke after getting authors. + * `authors` (Array): All authors, sorted by number of commits. + +Each author object contains the following properties: + +* `email` (String): Author's email address. +* `name` (String): Author's name. +* `commits` (Number): Number of commits. +* `commitsPercent` (Number): Percentage of commits. + + + +### blame( options, callback ) + +Determine what revision and author last modified each line of a file. + +* `options` (Object): Options for the blame. + * `path` (String): The path to the file to run the blame for. + * `committish` (String; default: `"HEAD"`): Revision or range to blame against. +* `callback` (Function; `function( error, blame )`): Function to invoke after blaming the file. + * `blame` (Array): Commit information for each line. + +Each blame item contains the following properties: + +* `commit`: SHA of commit that most recently modified the line. +* `path`: Path to the file at the time of the most recent modification to the line. +* `lineNumber`: Line number within the file. +* `content`: Contents of the line. + + + +### branches( callback ) + +Gets all branches in order of most recent commit. + +* `callback` (Function; `function( error, branches )`): Function to invoke after getting branches. + * `branches` (Array): All branches, sorted by most recent commit date. + +Each branch object contains the following properties: + +* `name` (String): Branch name. +* `sha` (String): SHA-1 of most recent commit. +* `date` (Date): Author date of most recent commit. +* `subject` (String): Subject (first line) of most recent commit. +* `author` (Object): Author of most recent commit. + * `email` (String): Author's email address. + * `name` (String): Author's name. + + + +### config( name, callback ) + +Gets the value of a configuration option. + +* `name` (String): The name of the configuration option. +* `callback` (Function; `function( error, value )`): Function to invoke after getting the configuration option. + * `value` (String|null): The value for the configuration option, or `null` if no value is set. + + + +### currentBranch( callback ) + +Gets the name of the currently checked out branch, if any. + +* `callback` (Function; `function( error, branch )`): Function to invoke after getting the branch. + * `branch` (String|null): Branch name, or `null` if in detached HEAD state. + + + +### isRepo( callback ) + +Determines if the specified path is a git repository. + +* `callback` (Function; `function( error, isRepo )`): Function to invoke after determining if the path is a git repository. + * `isRepo` (Boolean): Whether the path is a git repository. + + + +### remotes( callback ) + +Gets all remote repositories. + +* `callback` (Function; `function( error, remotes )`): Function to invoke after getting the remotes. + * `remotes` (Array): All remote repositories. + +Each remote object contains the following properties: + +* `name` (String): Remote name. +* `url` (String): URL for the remote repository. + + + +### resolveCommittish( committish, callback ) + +Resolves a committish to a SHA1. + +* `committish` (String): Any committish to resolve. +* `callback` (Function; `function( error, sha )`): Function to invoke after resolving the comittish. + * `sha`: SHA1 of the resolved committish. + + + +### tags( callback ) + +Gets all tags in reverse chronological order. + +Lightweight tags are sorted by author date and annotated tags are sorted by tagger date. + +* `callback` (Function; `function( error, tags )`): Function to invoke after getting tags. + * `tags` (Array): All tags, sorted by date. + +Each tag object contains the following properties: + +* `name` (String): Tag name. +* `sha` (String): SHA-1 for the tag. For lightweight tags, this is the SHA-1 of the commit. +* `date` (Date): Author date for ligthweight tags, tagger date for annotated tags. + + + +## License + +Copyright 2013 Scott González. Released under the terms of the MIT license. + +--- + +Support this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/). diff --git a/node_modules/changelogplease/node_modules/git-tools/git-tools.js b/node_modules/changelogplease/node_modules/git-tools/git-tools.js new file mode 100644 index 0000000..541ce59 --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/git-tools.js @@ -0,0 +1,396 @@ +var spawn = require( "child_process" ).spawn; + +function extend( a, b ) { + for ( var prop in b ) { + a[ prop ] = b[ prop ]; + } + + return a; +} + +function copy( obj ) { + return extend( {}, obj ); +} + +function Repo( path ) { + this.path = path; +} + +Repo.parsePerson = (function() { + var rPerson = /^(\S+)\s(.+)$/; + return function( person ) { + var matches = rPerson.exec( person ); + return { + email: matches[ 1 ], + name: matches[ 2 ] + }; + }; +})(); + +Repo.clone = function( options, callback ) { + var dir = options.dir; + var args = [ "clone", options.repo, dir ]; + options = copy( options ); + delete options.repo; + delete options.dir; + + Object.keys( options ).forEach(function( option ) { + args.push( "--" + option ); + + var value = options[ option ]; + if ( value !== true ) { + args.push( value ); + } + }); + + args.push(function( error ) { + if ( error ) { + return callback( error ); + } + + callback( null, new Repo( dir ) ); + }); + + var repo = new Repo( process.cwd() ); + repo.exec.apply( repo, args ); +}; + +Repo.isRepo = function( path, callback ) { + var repo = new Repo( path ); + repo.isRepo( callback ); +}; + +Repo.prototype.exec = function() { + var args = [].slice.call( arguments ); + var callback = args.pop(); + var stdout = ""; + var stderr = ""; + var child = spawn( "git", args, { cwd: this.path } ); + var hadError = false; + child.on( "error", function( error ) { + hadError = true; + callback( error ); + }); + child.stdout.on( "data", function( data ) { + stdout += data; + }); + child.stderr.on( "data", function( data ) { + stderr += data; + }); + child.on( "close", function( code ) { + if ( hadError ) { + return; + } + + var error; + if ( code ) { + error = new Error( stderr ); + error.code = code; + return callback( error ); + } + + callback( null, stdout.trimRight() ); + }); +}; + +Repo.prototype.activeDays = function( committish, callback ) { + if ( !callback ) { + callback = committish; + committish = "master"; + } + + this.exec( "log", "--format=%at", committish, function( error, dates ) { + if ( error ) { + return callback( error ); + } + + var dateMap = { + activeDays: 0, + commits: 0, + dates: {}, + years: {} + }; + + dates.split( "\n" ).sort().forEach(function( timestamp ) { + var date = new Date( timestamp * 1000 ); + var year = date.getFullYear(); + var month = date.getMonth() + 1; + var day = date.getDate(); + + date = year + "-" + + (month < 10 ? "0" : "") + month + "-" + + (day < 10 ? "0" : "") + day; + + if ( !dateMap.dates[ date ] ) { + dateMap.dates[ date ] = 0; + } + dateMap.commits++; + dateMap.dates[ date ]++; + + if ( !dateMap.years[ year ] ) { + dateMap.years[ year ] = { + activeDays: 0, + commits: 0, + months: {} + }; + } + dateMap.years[ year ].commits++; + + if ( !dateMap.years[ year ].months[ month ] ) { + dateMap.years[ year ].months[ month ] = { + activeDays: 0, + commits: 0, + days: {} + }; + } + dateMap.years[ year ].months[ month ].commits++; + + if ( !dateMap.years[ year ].months[ month ].days[ day ] ) { + dateMap.years[ year ].months[ month ].days[ day ] = { + commits: 0 + }; + dateMap.activeDays++; + dateMap.years[ year ].activeDays++; + dateMap.years[ year ].months[ month ].activeDays++; + } + dateMap.years[ year ].months[ month ].days[ day ].commits++; + }); + + callback( null, dateMap ); + }); +}; + +Repo.prototype.age = function( callback ) { + this.exec( "log", "--reverse", "--format=%cr", function( error, stdout ) { + if ( error ) { + return callback( error ); + } + + callback( null, stdout.split( "\n" )[ 0 ].replace( /\sago/, "" ) ); + }); +}; + +Repo.prototype.authors = function( committish, callback ) { + if ( !callback ) { + callback = committish; + committish = "master"; + } + + this.exec( "log", "--format=%aE %aN", committish, function( error, data ) { + if ( error ) { + return callback( error ); + } + + var authors = data.split( "\n" ); + var authorMap = {}; + var totalCommits = 0; + + authors.forEach(function( author ) { + if ( !authorMap[ author ] ) { + authorMap[ author ] = 0; + } + + authorMap[ author ]++; + totalCommits++; + }); + + authors = Object.keys( authorMap ).map(function( author ) { + var commits = authorMap[ author ]; + return extend( Repo.parsePerson( author ), { + commits: commits, + commitsPercent: (commits * 100 / totalCommits).toFixed( 1 ) + }); + }).sort(function( a, b ) { + return b.commits - a.commits; + }); + + callback( null, authors ); + }); +}; + +Repo.prototype.blame = function( options, callback ) { + var args = [ "blame", "-s" ]; + + if ( options.committish ) { + args.push( options.committish ); + } + + args.push( "--", options.path ); + + var rBlame = /^(\w+)(\s(\S+))?\s+(\d+)\)\s(.*)$/; + + args.push(function( error, blame ) { + if ( error ) { + return callback( error ); + } + + var lines = blame.split( /\r?\n/ ); + lines = lines.map(function( line ) { + var matches = rBlame.exec( line ); + + return { + commit: matches[ 1 ], + path: matches[ 3 ] || options.path, + lineNumber: parseInt( matches[ 4 ], 10 ), + content: matches[ 5 ] + }; + }); + + callback( null, lines ); + }); + + this.exec.apply( this, args ); +}; + +Repo.prototype.branches = function( callback ) { + this.exec( "for-each-ref", + "--format=" + + "%(refname:short)%0a" + + "%(authordate:rfc2822)%0a" + + "%(authoremail) %(authorname)%0a" + + "%(subject)%0a" + + "%(objectname)%0a", + "refs/heads", + function( error, data ) { + if ( error ) { + return callback( error ); + } + + var branches = data.split( "\n\n" ).map(function( branch ) { + var lines = branch.split( "\n" ); + var name = lines[ 0 ]; + var date = new Date( lines[ 1 ] ); + var author = Repo.parsePerson( lines[ 2 ] ); + var subject = lines[ 3 ]; + var sha = lines[ 4 ]; + + return { + name: name, + sha: sha, + date: date, + subject: subject, + author: author + }; + }).sort(function( a, b ) { + return b.date - a.date; + }); + + callback( null, branches ); + }); +}; + +Repo.prototype.config = function( name, callback ) { + this.exec( "config --get " + name, function( error, stdout ) { + if ( error ) { + if ( /^Command failed:\s+$/.test( error.message ) ) { + return callback( null, null ); + } + + return callback( error ); + } + + callback( null, stdout.trim() ); + }); +}; + +Repo.prototype.currentBranch = function( callback ) { + this.exec( "rev-parse", "--abbrev-ref", "HEAD", function( error, data ) { + if ( error ) { + return callback( error ); + } + + var branch = data === "HEAD" ? null : data; + callback( null, branch ); + }); +}; + +Repo.prototype.isRepo = function( callback ) { + this.exec( "rev-parse", "--git-dir", function( error ) { + if ( error ) { + if ( error.message.indexOf( "Not a git repository" ) ) { + return callback( null, false ); + } + + // If the path doesn't exist, don't return an error + if ( error.code === "ENOENT" ) { + return callback( null, false ); + } + + return callback( error ); + } + + callback( null, true ); + }); +}; + +Repo.prototype.remotes = function( callback ) { + this.exec( "remote", "-v", function( error, data ) { + if ( error ) { + return callback( error ); + } + + var remotes = data.split( "\n" ); + var rRemote = /^(\S+)\s(\S+)/; + var remoteMap = {}; + + remotes.forEach(function( remote ) { + var matches = rRemote.exec( remote ); + + // New repositories with no remotes will have `origin` but no URL + if ( !matches ) { + return; + } + + var name = matches[ 1 ]; + var url = matches[ 2 ]; + + remoteMap[ name ] = url; + }); + + remotes = Object.keys( remoteMap ).map(function( remote ) { + return { + name: remote, + url: remoteMap[ remote ] + }; + }); + + callback( null, remotes ); + }); +}; + +Repo.prototype.resolveCommittish = function( committish, callback ) { + this.exec( "rev-parse", committish, callback ); +}; + +Repo.prototype.tags = function( callback ) { + this.exec( "for-each-ref", + "--format=" + + "%(refname:short)%0a" + + "%(authordate)%(taggerdate)%0a" + + "%(objectname)%0a", + "refs/tags", + function( error, data ) { + if ( error ) { + return callback( error ); + } + + var tags = data.split( "\n\n" ).map(function( tag ) { + var lines = tag.split( "\n" ); + var name = lines[ 0 ]; + var date = new Date( lines[ 1 ] ); + var sha = lines[ 2 ]; + + return { + name: name, + sha: sha, + date: date + }; + }).sort(function( a, b ) { + return b.date - a.date; + }); + + callback( null, tags ); + }); +}; + +module.exports = Repo; diff --git a/node_modules/changelogplease/node_modules/git-tools/package.json b/node_modules/changelogplease/node_modules/git-tools/package.json new file mode 100644 index 0000000..030e1cc --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/package.json @@ -0,0 +1,36 @@ +{ + "name": "git-tools", + "version": "0.0.8", + "description": "Tools for parsing data out of git repositories.", + "keywords": [ + "git" + ], + "homepage": "https://github.com/scottgonzalez/node-git-tools", + "bugs": { + "url": "https://github.com/scottgonzalez/node-git-tools/issues" + }, + "author": { + "name": "Scott González", + "email": "scott.gonzalez@gmail.com", + "url": "http://scottgonzalez.com" + }, + "main": "git-tools.js", + "repository": { + "type": "git", + "url": "git://github.com/scottgonzalez/node-git-tools.git" + }, + "devDependencies": { + "grunt": "~0.4.0", + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-nodeunit": "~0.1.2", + "rimraf": "~2.1.4" + }, + "readme": "# node-git-tools\n\nTools for parsing data out of git repositories.\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n\n## About\n\nThe goal of node-git-tools is to provide a set of tools that can be used to\neasily write custom git commands or other scripts that are tightly integrated\nwith git.\n\nI expect the API to grow over time and will happily entertain any feature\nrequests. If there is anything you'd like added, just file an issue.\n\n## Installation\n\n```sh\nnpm install git-tools\n```\n\n## Usage\n\n```js\nvar Repo = require( \"git-tools\" );\nvar repo = new Repo( \"path/to/repo\" );\nrepo.authors(function( error, authors ) {\n\tconsole.log( authors );\n});\n```\n\n\n\n## API\n\n### Repo.clone( options, callback )\n\nClones a repository and returns the new `Repo` instance.\n\n* `options` (Object): Options for cloning the repository.\n * `repo` (String): The repository to clone from.\n * `path` (String): The path to clone into.\n * extra: Additional options can be provided, as documented below.\n* `callback` (Function; `function( error, repo )`): Function to invoke after cloning the repository.\n * `repo` (Object): A new `Repo` instance for the cloned repository.\n\nThis function accepts arbitrary options to pass to `git clone`.\nFor example, to create a bare repository:\n\n```js\nRepo.clone({\n\trepo: \"git://github.com/scottgonzalez/node-git-tools.git\",\n\tdir: \"/tmp/git-tools\",\n\tbare: true\n});\n```\n\nOr to create a repo with limited history:\n\n```js\nRepo.clone({\n\trepo: \"git://github.com/scottgonzalez/node-git-tools.git\",\n\tdir: \"/tmp/git-tools\",\n\tdepth: 5\n});\n```\n\n\n\n### Repo.isRepo( path, callback )\n\nDetermines if the specified path is a git repository.\n\n* `path` (String): The path to check.\n* `callback` (Function; `function( error, isRepo )`): Function to invoke after determining if the path is a git repository.\n * `isRepo` (Boolean): Whether the path is a git repository.\n\n*Note: This is equivalent to creating a `Repo` instance with `path` and calling `isRepo()` on the instance.*\n\n\n\n### activeDays( [committish], callback )\n\nGets the number of active days (unique days of authorship). Includes activity\nby day, month, year, and the entire history.\n\n* `committish` (String; default: `\"master\"`): Committish range to analyze.\n* `callback` (Function; `function( error, activeDays )`): Function to invoke after getting active days.\n * `activeDays` (Object): Summary of active days.\n\nThe `activeDays` object has the following form:\n\n```js\n{\n\tactiveDays: Number,\n\tcommits: Number,\n\tdates: {\n\t\t\"YYYY-MM-DD\": Number( commits ),\n\t\t...\n\t},\n\tyears: {\n\t\t\"YYYY\": {\n\t\t\tactiveDays: Number,\n\t\t\tcommits: Number,\n\t\t\tmonths: {\n\t\t\t\t\"M\": {\n\t\t\t\t\tactiveDays: Number,\n\t\t\t\t\tcommits: Number,\n\t\t\t\t\tdays: {\n\t\t\t\t\t\t\"D\": {\n\t\t\t\t\t\t\tcommits: Number\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t...\n\t\t\t}\n\t\t},\n\t\t...\n\t}\n}\n```\n\n\n\n### age( callback )\n\nGets the age of the repository.\n\n* `callback` (Function; `function( error, age )`): Function to invoke after getting the age.\n * `age` (String): The age of the repository.\n\n\n\n### authors( [committish], callback )\n\nGets all authors, sorted by number of commits.\n\n* `committish` (String; default: `\"master\"`): Committish range to analyze.\n* `callback` (Function; `function( error, authors )`): Function to invoke after getting authors.\n * `authors` (Array): All authors, sorted by number of commits.\n\nEach author object contains the following properties:\n\n* `email` (String): Author's email address.\n* `name` (String): Author's name.\n* `commits` (Number): Number of commits.\n* `commitsPercent` (Number): Percentage of commits.\n\n\n\n### blame( options, callback )\n\nDetermine what revision and author last modified each line of a file.\n\n* `options` (Object): Options for the blame.\n * `path` (String): The path to the file to run the blame for.\n * `committish` (String; default: `\"HEAD\"`): Revision or range to blame against.\n* `callback` (Function; `function( error, blame )`): Function to invoke after blaming the file.\n * `blame` (Array): Commit information for each line.\n\nEach blame item contains the following properties:\n\n* `commit`: SHA of commit that most recently modified the line.\n* `path`: Path to the file at the time of the most recent modification to the line.\n* `lineNumber`: Line number within the file.\n* `content`: Contents of the line.\n\n\n\n### branches( callback )\n\nGets all branches in order of most recent commit.\n\n* `callback` (Function; `function( error, branches )`): Function to invoke after getting branches.\n * `branches` (Array): All branches, sorted by most recent commit date.\n\nEach branch object contains the following properties:\n\n* `name` (String): Branch name.\n* `sha` (String): SHA-1 of most recent commit.\n* `date` (Date): Author date of most recent commit.\n* `subject` (String): Subject (first line) of most recent commit.\n* `author` (Object): Author of most recent commit.\n * `email` (String): Author's email address.\n * `name` (String): Author's name.\n\n\n\n### config( name, callback )\n\nGets the value of a configuration option.\n\n* `name` (String): The name of the configuration option.\n* `callback` (Function; `function( error, value )`): Function to invoke after getting the configuration option.\n * `value` (String|null): The value for the configuration option, or `null` if no value is set.\n\n\n\n### currentBranch( callback )\n\nGets the name of the currently checked out branch, if any.\n\n* `callback` (Function; `function( error, branch )`): Function to invoke after getting the branch.\n * `branch` (String|null): Branch name, or `null` if in detached HEAD state.\n\n\n\n### isRepo( callback )\n\nDetermines if the specified path is a git repository.\n\n* `callback` (Function; `function( error, isRepo )`): Function to invoke after determining if the path is a git repository.\n * `isRepo` (Boolean): Whether the path is a git repository.\n\n\n\n### remotes( callback )\n\nGets all remote repositories.\n\n* `callback` (Function; `function( error, remotes )`): Function to invoke after getting the remotes.\n * `remotes` (Array): All remote repositories.\n\nEach remote object contains the following properties:\n\n* `name` (String): Remote name.\n* `url` (String): URL for the remote repository.\n\n\n\n### resolveCommittish( committish, callback )\n\nResolves a committish to a SHA1.\n\n* `committish` (String): Any committish to resolve.\n* `callback` (Function; `function( error, sha )`): Function to invoke after resolving the comittish.\n * `sha`: SHA1 of the resolved committish.\n\n\n\n### tags( callback )\n\nGets all tags in reverse chronological order.\n\nLightweight tags are sorted by author date and annotated tags are sorted by tagger date.\n\n* `callback` (Function; `function( error, tags )`): Function to invoke after getting tags.\n * `tags` (Array): All tags, sorted by date.\n\nEach tag object contains the following properties:\n\n* `name` (String): Tag name.\n* `sha` (String): SHA-1 for the tag. For lightweight tags, this is the SHA-1 of the commit.\n* `date` (Date): Author date for ligthweight tags, tagger date for annotated tags.\n\n\n\n## License\n\nCopyright 2013 Scott González. Released under the terms of the MIT license.\n\n---\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n", + "readmeFilename": "README.md", + "_id": "git-tools@0.0.8", + "dist": { + "shasum": "2b54771f2224f1e1f7af2142ba2a180bbc689cd7" + }, + "_from": "git-tools@0.0.8", + "_resolved": "https://registry.npmjs.org/git-tools/-/git-tools-0.0.8.tgz" +} diff --git a/node_modules/changelogplease/node_modules/git-tools/test/test.js b/node_modules/changelogplease/node_modules/git-tools/test/test.js new file mode 100644 index 0000000..95a2d80 --- /dev/null +++ b/node_modules/changelogplease/node_modules/git-tools/test/test.js @@ -0,0 +1,43 @@ +var fs = require( "fs" ); +var rimraf = require( "rimraf" ); +var path = __dirname + "/repo"; +var Repo = require( "../git-tools" ); +var testRepo = new Repo( path ); + +function createRepo( callback ) { + rimraf.sync( path ); + fs.mkdirSync( path ); + testRepo.exec( "init", function( error ) { + if ( error ) { + throw error; + } + + testRepo.exec( "commit", "--allow-empty", + "--author=John Doe ", "-m first commit", + callback ); + }); +} + +exports.authors = { + "one commit": function( test ) { + createRepo(function( error ) { + if ( error ) { + throw error; + } + + testRepo.authors(function( error, authors ) { + test.ifError( error ); + + test.deepEqual( authors, [ + { + email: "john.doe@example.com", + name: "John Doe", + commits: 1, + commitsPercent: 100 + } + ], "one author" ); + test.done(); + }); + }); + } +}; diff --git a/node_modules/changelogplease/package.json b/node_modules/changelogplease/package.json new file mode 100644 index 0000000..aee8126 --- /dev/null +++ b/node_modules/changelogplease/package.json @@ -0,0 +1,37 @@ +{ + "name": "changelogplease", + "version": "1.0.0", + "description": "Generate changelogs from git commit messages", + "author": { + "name": "Scott González", + "email": "scott.gonzalez@gmail.com", + "url": "http://scottgonzalez.com" + }, + "license": "MIT", + "main": "index.js", + "homepage": "https://github.com/scottgonzalez/changelogplease", + "repository": { + "type": "git", + "url": "git://github.com/scottgonzalez/changelogplease.git" + }, + "bugs": { + "url": "https://github.com/scottgonzalez/changelogplease/issues" + }, + "keywords": [ + "changelog", + "release" + ], + "scripts": { + "test": "nodeunit tests" + }, + "dependencies": { + "git-tools": "0.0.8" + }, + "devDependencies": { + "nodeunit": "0.8.6" + }, + "readme": "# Changelog, please\n\nGenerate changelogs from git commit messages using node.js. The generated changelogs are written in markdown.\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n\n## Installation\n\n```\nnpm install changelogplease\n```\n\n## Usage\n\n```javascript\nvar changelog = require( \"changelogplease\" );\nvar parsed = changelog({\n\tticketUrl: \"https://github.com/scottgonzalez/changelogplease/issues/{id}\",\n\tcommitUrl: \"https://github.com/scottgonzalez/changelogplease/commit/{id}\",\n\trepo: \"/path/to/repo\",\n\tcommittish: \"1.2.3..1.2.4\"\n});\n```\n\n## API\n\n### changelog( options, callback )\n\n* `options` (Object): Options for creating the changelog.\n * `ticketUrl` (String): Template for ticket/issue URLs; `{id}` will be replaced with the ticket id.\n * `commitUrl (String)`: Template for commit URLs; `{id}` will be replaced with the commit hash.\n * `repo` (String): Path to the repository.\n * `committish` (String): The range of commits for the changelog.\n* `callback` (Function; `function( error, log )`): Function to invoke after generating the changelog.\n * `log` (String): Generated changelog, written in markdown.\n\n### Changelog\n\n`changelog( options, callback )` is a shorthand for the following:\n\n```js\nvar Changelog = require( \"changelogplease\" ).Changelog;\nvar instance = new Changelog( options );\ninstance.parse( callback );\n```\n\nChangelog generation is tailored to a specific format based on the needs of the various jQuery\nprojects. However, the `Changelog` constructor and prototype are exposed to allow flexibility.\nBe aware that these methods are not currently documented because they may change. Feel free to\nsubmit [feature requests](https://github.com/scottgonzalez/changelogplease/issues/new) if you don't\nfeel comfortable hacking in your own changes (or even if you do).\n\n\n## License\n\nCopyright 2014 Scott González. Released under the terms of the MIT license.\n\n---\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n", + "readmeFilename": "README.md", + "_id": "changelogplease@1.0.0", + "_from": "changelogplease@" +} diff --git a/node_modules/changelogplease/tests/changelog.js b/node_modules/changelogplease/tests/changelog.js new file mode 100644 index 0000000..6b17870 --- /dev/null +++ b/node_modules/changelogplease/tests/changelog.js @@ -0,0 +1,183 @@ +var fs = require( "fs" ), + Changelog = require( ".." ).Changelog, + fixtures = require( "./fixtures/commits" ); + +exports.ticketUrl = { + setUp: function( done ) { + this.changelog = new Changelog({ + ticketUrl: "http://example.com/ticket/{id}/" + }); + done(); + }, + + replacement: function( test ) { + test.expect( 1 ); + + var url = this.changelog.ticketUrl( 37 ); + test.strictEqual( url, "http://example.com/ticket/37/", + "Ticket id should be inserted." ); + test.done(); + } +}; + +exports.getLog = { + setUp: function( done ) { + this.changelog = new Changelog({ + commitUrl: "http://example.com/commit/{id}/", + committish: "alpha..omega" + }); + done(); + }, + + error: function( test ) { + test.expect( 1 ); + + var providedError = new Error(); + + this.changelog.repo.exec = function() { + var callback = arguments[ arguments.length - 1 ]; + process.nextTick(function() { + callback( providedError ); + }); + }; + + this.changelog.getLog(function( error ) { + test.strictEqual( error, providedError, "Should pass error." ); + test.done(); + }); + }, + + success: function( test ) { + test.expect( 5 ); + + var providedLog = {}; + + this.changelog.repo.exec = function( command, format, committish, callback ) { + test.strictEqual( command, "log", "Should invoke git log." ); + test.strictEqual( format, + "--format=" + + "__COMMIT__%n" + + "%s (__TICKETREF__, [%h](http://example.com/commit/%H/))%n" + + "%b", + "Should pass format with proper commit URL." ); + test.strictEqual( committish, "alpha..omega", "Should pass committish." ); + + process.nextTick(function() { + callback( null, providedLog ); + }); + }; + + this.changelog.getLog(function( error, log ) { + test.strictEqual( error, null, "Should not pass an error." ); + test.strictEqual( log, providedLog, "Should pass log." ); + test.done(); + }); + } +}; + +exports.parseCommit = { + setUp: function( done ) { + this.changelog = new Changelog({ + ticketUrl: "TICKET-URL/{id}", + commitUrl: "COMMIT-URL/{id}" + }); + done(); + }, + + commits: function( test ) { + test.expect( 6 ); + + Object.keys( fixtures ).forEach(function( name ) { + test.strictEqual( + this.changelog.parseCommit( fixtures[ name ].input ), + fixtures[ name ].output, + name + ); + }.bind( this )); + + test.done(); + } +}; + +exports.parseCommits = { + setUp: function( done ) { + this.changelog = new Changelog({}); + done(); + }, + + commits: function( test ) { + test.expect( 4 ); + + var providedCommits = [ "a", "c", "b" ]; + var parsedCommits = [ "a", "c", "b" ]; + var providedCommitsLog = "__COMMIT__\n" + + providedCommits.join( "__COMMIT__\n" ); + var callCount = 0; + + this.changelog.parseCommit = function( commit ) { + test.strictEqual( commit, providedCommits[ callCount ], + "Should pass commit" ); + + var parsedCommit = parsedCommits[ callCount ]; + + callCount++; + + return parsedCommit; + }; + + test.strictEqual( + this.changelog.parseCommits( providedCommitsLog ), + "a\nb\nc\n", + "Should parse and sort commits." + ); + test.done(); + } +}; + +exports.parse = { + setUp: function( done ) { + this.changelog = new Changelog({}); + done(); + }, + + "getLog error": function( test ) { + test.expect( 1 ); + + var providedError = new Error(); + + this.changelog.getLog = function( callback ) { + process.nextTick(function() { + callback( providedError ); + }); + }; + + this.changelog.parse(function( error ) { + test.strictEqual( error, providedError, "Should pass error." ); + test.done(); + }); + }, + + success: function( test ) { + test.expect( 3 ); + + var providedLog = {}; + var providedParsedLog = {}; + + this.changelog.getLog = function( callback ) { + process.nextTick(function() { + callback( null, providedLog ); + }); + }; + + this.changelog.parseCommits = function( log ) { + test.strictEqual( log, providedLog, "Should pass log." ); + return providedParsedLog; + }; + + this.changelog.parse(function( error, log ) { + test.strictEqual( error, null, "Should not pass an error." ); + test.strictEqual( log, providedParsedLog, "Should pass parsed log." ); + test.done(); + }); + } +}; diff --git a/node_modules/changelogplease/tests/fixtures/commits.js b/node_modules/changelogplease/tests/fixtures/commits.js new file mode 100644 index 0000000..1b3e6b3 --- /dev/null +++ b/node_modules/changelogplease/tests/fixtures/commits.js @@ -0,0 +1,15 @@ +var fs = require( "fs" ); + +var commits = {}; +module.exports = commits; + +fs.readFileSync( __dirname + "/commits.txt", "utf8" ) + .trim() + .split( "\n=====\n") + .forEach(function( raw ) { + var parts = raw.split( "\n*****\n" ); + commits[ parts[ 0 ] ] = { + input: parts[ 1 ], + output: parts[ 2 ] + }; + }); diff --git a/node_modules/changelogplease/tests/fixtures/commits.txt b/node_modules/changelogplease/tests/fixtures/commits.txt new file mode 100644 index 0000000..ae1cc44 --- /dev/null +++ b/node_modules/changelogplease/tests/fixtures/commits.txt @@ -0,0 +1,43 @@ +noRef +***** +Alpha: Fixed something without a ticket! (__TICKETREF__, [aaa1111](COMMIT-URL/aaa1111000000000000000000000000000000000)) +***** +* Alpha: Fixed something without a ticket! (__TICKETREF__, [aaa1111](COMMIT-URL/aaa1111000000000000000000000000000000000)) +===== +fixesHash +***** +Alpha: Did stuff (__TICKETREF__, [abc123](COMMIT-URL/abc1234000000000000000000000000000000000)) +Fixes #123 +***** +* Alpha: Did stuff ([#123](TICKET-URL/123), [abc123](COMMIT-URL/abc1234000000000000000000000000000000000)) +===== +fixGh +***** +Beta: Make the baz properly qux (__TICKETREF__, [bbb2222](COMMIT-URL/bbb2222000000000000000000000000000000000)) +Fix gh-239 +***** +* Beta: Make the baz properly qux ([#239](TICKET-URL/239), [bbb2222](COMMIT-URL/bbb2222000000000000000000000000000000000)) +===== +otherGithub +***** +Alpha: Cross-project bugs are fun (__TICKETREF__, [ddd1234](COMMIT-URL/ddd1234000000000000000000000000000000000)) +Fixed other/project#123 +***** +* Alpha: Cross-project bugs are fun ([other/project#123](https://github.com/other/project/issues/123), [ddd1234](COMMIT-URL/ddd1234000000000000000000000000000000000)) +===== +multiRef +***** +Omega: Fix all the things (__TICKETREF__, [000deb7](COMMIT-URL/000deb7000000000000000000000000000000000)) +Fixes #12 +Fixes #34 +Fixes other/project#3456 +Closes gh-2000 +***** +* Omega: Fix all the things ([#12](TICKET-URL/12), [#34](TICKET-URL/34), [other/project#3456](https://github.com/other/project/issues/3456), [000deb7](COMMIT-URL/000deb7000000000000000000000000000000000)) +===== +cherryPick +***** +Beta: Fix something (cherry picked from commit 9999999000000000000000000000000000000000) (__TICKETREF__, [fff1234](COMMIT-URL/fff1234000000000000000000000000000000000)) +Fixes #55 +***** +* Beta: Fix something ([#55](TICKET-URL/55), [fff1234](COMMIT-URL/fff1234000000000000000000000000000000000)) diff --git a/package.json b/package.json index 0926c46..9d82114 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "changelogplease": "1.0.0", "colors": "0.6.2", "semver": "2.2.1", "shelljs": "0.2.6", From d9e1fdb647779ccad2e5760fe23a34ec95e3cb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 26 Mar 2014 14:25:32 -0400 Subject: [PATCH 3/4] [squash]: abort docs --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5b22db3..e8fefa4 100644 --- a/README.md +++ b/README.md @@ -141,9 +141,10 @@ need to install dependencies which are only necessary for the release. Defines new properties and methods to add to the `Release` object. -#### abort( msg ) +#### abort( msg [, error ] ) -Aborts the release and prints the message. +Aborts the release and prints the message. If an error object is provided, it is +used for the stack trace, otherwise the current call stack is used. #### exec( command, options ) From a02118e56b9e0981509af01c326ac3736266a581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Scott=20Gonz=C3=A1lez?= Date: Wed, 26 Mar 2014 15:03:26 -0400 Subject: [PATCH 4/4] [squash] changelogplease 1.0.1 --- node_modules/changelogplease/.npmignore | 3 + node_modules/changelogplease/.travis.yml | 5 - .../node_modules/git-tools/.jshintrc | 12 -- .../node_modules/git-tools/.npmignore | 5 +- .../node_modules/git-tools/Gruntfile.js | 26 --- .../node_modules/git-tools/package.json | 10 +- .../node_modules/git-tools/test/test.js | 43 ---- node_modules/changelogplease/package.json | 12 +- .../changelogplease/tests/changelog.js | 183 ------------------ .../changelogplease/tests/fixtures/commits.js | 15 -- .../tests/fixtures/commits.txt | 43 ---- package.json | 2 +- 12 files changed, 18 insertions(+), 341 deletions(-) delete mode 100644 node_modules/changelogplease/.travis.yml delete mode 100644 node_modules/changelogplease/node_modules/git-tools/.jshintrc delete mode 100644 node_modules/changelogplease/node_modules/git-tools/Gruntfile.js delete mode 100644 node_modules/changelogplease/node_modules/git-tools/test/test.js delete mode 100644 node_modules/changelogplease/tests/changelog.js delete mode 100644 node_modules/changelogplease/tests/fixtures/commits.js delete mode 100644 node_modules/changelogplease/tests/fixtures/commits.txt diff --git a/node_modules/changelogplease/.npmignore b/node_modules/changelogplease/.npmignore index 2ccbe46..36f30bb 100644 --- a/node_modules/changelogplease/.npmignore +++ b/node_modules/changelogplease/.npmignore @@ -1 +1,4 @@ /node_modules/ +/tests/ +.travis.yml +Gruntfile.js diff --git a/node_modules/changelogplease/.travis.yml b/node_modules/changelogplease/.travis.yml deleted file mode 100644 index 4a83e22..0000000 --- a/node_modules/changelogplease/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.11" - - "0.10" - - "0.8" diff --git a/node_modules/changelogplease/node_modules/git-tools/.jshintrc b/node_modules/changelogplease/node_modules/git-tools/.jshintrc deleted file mode 100644 index 872f201..0000000 --- a/node_modules/changelogplease/node_modules/git-tools/.jshintrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "curly": true, - "eqnull": true, - "eqeqeq": true, - "expr": true, - "noarg": true, - "node": true, - "strict": false, - "trailing": true, - "undef": true, - "unused": true -} diff --git a/node_modules/changelogplease/node_modules/git-tools/.npmignore b/node_modules/changelogplease/node_modules/git-tools/.npmignore index 177acc9..3a4259c 100644 --- a/node_modules/changelogplease/node_modules/git-tools/.npmignore +++ b/node_modules/changelogplease/node_modules/git-tools/.npmignore @@ -1,2 +1,3 @@ -node_modules -test/repo +/test/ +.jshintrc +Gruntfile.js diff --git a/node_modules/changelogplease/node_modules/git-tools/Gruntfile.js b/node_modules/changelogplease/node_modules/git-tools/Gruntfile.js deleted file mode 100644 index ff669fb..0000000 --- a/node_modules/changelogplease/node_modules/git-tools/Gruntfile.js +++ /dev/null @@ -1,26 +0,0 @@ -var grunt = require( "grunt" ); - -grunt.loadNpmTasks( "grunt-contrib-jshint" ); -grunt.loadNpmTasks( "grunt-contrib-nodeunit" ); - -grunt.initConfig({ - jshint: { - src: { - options: { - jshintrc: ".jshintrc" - }, - src: [ "git-tools.js" ] - }, - test: { - options: { - jshintrc: ".jshintrc" - }, - src: [ "test/**.js" ] - } - }, - nodeunit: { - all: [ "test/**/*.js" ] - } -}); - -grunt.registerTask( "default", [ "jshint", "nodeunit" ] ); diff --git a/node_modules/changelogplease/node_modules/git-tools/package.json b/node_modules/changelogplease/node_modules/git-tools/package.json index 030e1cc..a24419f 100644 --- a/node_modules/changelogplease/node_modules/git-tools/package.json +++ b/node_modules/changelogplease/node_modules/git-tools/package.json @@ -1,6 +1,6 @@ { "name": "git-tools", - "version": "0.0.8", + "version": "0.1.0", "description": "Tools for parsing data out of git repositories.", "keywords": [ "git" @@ -27,10 +27,6 @@ }, "readme": "# node-git-tools\n\nTools for parsing data out of git repositories.\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n\n## About\n\nThe goal of node-git-tools is to provide a set of tools that can be used to\neasily write custom git commands or other scripts that are tightly integrated\nwith git.\n\nI expect the API to grow over time and will happily entertain any feature\nrequests. If there is anything you'd like added, just file an issue.\n\n## Installation\n\n```sh\nnpm install git-tools\n```\n\n## Usage\n\n```js\nvar Repo = require( \"git-tools\" );\nvar repo = new Repo( \"path/to/repo\" );\nrepo.authors(function( error, authors ) {\n\tconsole.log( authors );\n});\n```\n\n\n\n## API\n\n### Repo.clone( options, callback )\n\nClones a repository and returns the new `Repo` instance.\n\n* `options` (Object): Options for cloning the repository.\n * `repo` (String): The repository to clone from.\n * `path` (String): The path to clone into.\n * extra: Additional options can be provided, as documented below.\n* `callback` (Function; `function( error, repo )`): Function to invoke after cloning the repository.\n * `repo` (Object): A new `Repo` instance for the cloned repository.\n\nThis function accepts arbitrary options to pass to `git clone`.\nFor example, to create a bare repository:\n\n```js\nRepo.clone({\n\trepo: \"git://github.com/scottgonzalez/node-git-tools.git\",\n\tdir: \"/tmp/git-tools\",\n\tbare: true\n});\n```\n\nOr to create a repo with limited history:\n\n```js\nRepo.clone({\n\trepo: \"git://github.com/scottgonzalez/node-git-tools.git\",\n\tdir: \"/tmp/git-tools\",\n\tdepth: 5\n});\n```\n\n\n\n### Repo.isRepo( path, callback )\n\nDetermines if the specified path is a git repository.\n\n* `path` (String): The path to check.\n* `callback` (Function; `function( error, isRepo )`): Function to invoke after determining if the path is a git repository.\n * `isRepo` (Boolean): Whether the path is a git repository.\n\n*Note: This is equivalent to creating a `Repo` instance with `path` and calling `isRepo()` on the instance.*\n\n\n\n### activeDays( [committish], callback )\n\nGets the number of active days (unique days of authorship). Includes activity\nby day, month, year, and the entire history.\n\n* `committish` (String; default: `\"master\"`): Committish range to analyze.\n* `callback` (Function; `function( error, activeDays )`): Function to invoke after getting active days.\n * `activeDays` (Object): Summary of active days.\n\nThe `activeDays` object has the following form:\n\n```js\n{\n\tactiveDays: Number,\n\tcommits: Number,\n\tdates: {\n\t\t\"YYYY-MM-DD\": Number( commits ),\n\t\t...\n\t},\n\tyears: {\n\t\t\"YYYY\": {\n\t\t\tactiveDays: Number,\n\t\t\tcommits: Number,\n\t\t\tmonths: {\n\t\t\t\t\"M\": {\n\t\t\t\t\tactiveDays: Number,\n\t\t\t\t\tcommits: Number,\n\t\t\t\t\tdays: {\n\t\t\t\t\t\t\"D\": {\n\t\t\t\t\t\t\tcommits: Number\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t...\n\t\t\t}\n\t\t},\n\t\t...\n\t}\n}\n```\n\n\n\n### age( callback )\n\nGets the age of the repository.\n\n* `callback` (Function; `function( error, age )`): Function to invoke after getting the age.\n * `age` (String): The age of the repository.\n\n\n\n### authors( [committish], callback )\n\nGets all authors, sorted by number of commits.\n\n* `committish` (String; default: `\"master\"`): Committish range to analyze.\n* `callback` (Function; `function( error, authors )`): Function to invoke after getting authors.\n * `authors` (Array): All authors, sorted by number of commits.\n\nEach author object contains the following properties:\n\n* `email` (String): Author's email address.\n* `name` (String): Author's name.\n* `commits` (Number): Number of commits.\n* `commitsPercent` (Number): Percentage of commits.\n\n\n\n### blame( options, callback )\n\nDetermine what revision and author last modified each line of a file.\n\n* `options` (Object): Options for the blame.\n * `path` (String): The path to the file to run the blame for.\n * `committish` (String; default: `\"HEAD\"`): Revision or range to blame against.\n* `callback` (Function; `function( error, blame )`): Function to invoke after blaming the file.\n * `blame` (Array): Commit information for each line.\n\nEach blame item contains the following properties:\n\n* `commit`: SHA of commit that most recently modified the line.\n* `path`: Path to the file at the time of the most recent modification to the line.\n* `lineNumber`: Line number within the file.\n* `content`: Contents of the line.\n\n\n\n### branches( callback )\n\nGets all branches in order of most recent commit.\n\n* `callback` (Function; `function( error, branches )`): Function to invoke after getting branches.\n * `branches` (Array): All branches, sorted by most recent commit date.\n\nEach branch object contains the following properties:\n\n* `name` (String): Branch name.\n* `sha` (String): SHA-1 of most recent commit.\n* `date` (Date): Author date of most recent commit.\n* `subject` (String): Subject (first line) of most recent commit.\n* `author` (Object): Author of most recent commit.\n * `email` (String): Author's email address.\n * `name` (String): Author's name.\n\n\n\n### config( name, callback )\n\nGets the value of a configuration option.\n\n* `name` (String): The name of the configuration option.\n* `callback` (Function; `function( error, value )`): Function to invoke after getting the configuration option.\n * `value` (String|null): The value for the configuration option, or `null` if no value is set.\n\n\n\n### currentBranch( callback )\n\nGets the name of the currently checked out branch, if any.\n\n* `callback` (Function; `function( error, branch )`): Function to invoke after getting the branch.\n * `branch` (String|null): Branch name, or `null` if in detached HEAD state.\n\n\n\n### isRepo( callback )\n\nDetermines if the specified path is a git repository.\n\n* `callback` (Function; `function( error, isRepo )`): Function to invoke after determining if the path is a git repository.\n * `isRepo` (Boolean): Whether the path is a git repository.\n\n\n\n### remotes( callback )\n\nGets all remote repositories.\n\n* `callback` (Function; `function( error, remotes )`): Function to invoke after getting the remotes.\n * `remotes` (Array): All remote repositories.\n\nEach remote object contains the following properties:\n\n* `name` (String): Remote name.\n* `url` (String): URL for the remote repository.\n\n\n\n### resolveCommittish( committish, callback )\n\nResolves a committish to a SHA1.\n\n* `committish` (String): Any committish to resolve.\n* `callback` (Function; `function( error, sha )`): Function to invoke after resolving the comittish.\n * `sha`: SHA1 of the resolved committish.\n\n\n\n### tags( callback )\n\nGets all tags in reverse chronological order.\n\nLightweight tags are sorted by author date and annotated tags are sorted by tagger date.\n\n* `callback` (Function; `function( error, tags )`): Function to invoke after getting tags.\n * `tags` (Array): All tags, sorted by date.\n\nEach tag object contains the following properties:\n\n* `name` (String): Tag name.\n* `sha` (String): SHA-1 for the tag. For lightweight tags, this is the SHA-1 of the commit.\n* `date` (Date): Author date for ligthweight tags, tagger date for annotated tags.\n\n\n\n## License\n\nCopyright 2013 Scott González. Released under the terms of the MIT license.\n\n---\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n", "readmeFilename": "README.md", - "_id": "git-tools@0.0.8", - "dist": { - "shasum": "2b54771f2224f1e1f7af2142ba2a180bbc689cd7" - }, - "_from": "git-tools@0.0.8", - "_resolved": "https://registry.npmjs.org/git-tools/-/git-tools-0.0.8.tgz" + "_id": "git-tools@0.1.0", + "_from": "git-tools@0.1.0" } diff --git a/node_modules/changelogplease/node_modules/git-tools/test/test.js b/node_modules/changelogplease/node_modules/git-tools/test/test.js deleted file mode 100644 index 95a2d80..0000000 --- a/node_modules/changelogplease/node_modules/git-tools/test/test.js +++ /dev/null @@ -1,43 +0,0 @@ -var fs = require( "fs" ); -var rimraf = require( "rimraf" ); -var path = __dirname + "/repo"; -var Repo = require( "../git-tools" ); -var testRepo = new Repo( path ); - -function createRepo( callback ) { - rimraf.sync( path ); - fs.mkdirSync( path ); - testRepo.exec( "init", function( error ) { - if ( error ) { - throw error; - } - - testRepo.exec( "commit", "--allow-empty", - "--author=John Doe ", "-m first commit", - callback ); - }); -} - -exports.authors = { - "one commit": function( test ) { - createRepo(function( error ) { - if ( error ) { - throw error; - } - - testRepo.authors(function( error, authors ) { - test.ifError( error ); - - test.deepEqual( authors, [ - { - email: "john.doe@example.com", - name: "John Doe", - commits: 1, - commitsPercent: 100 - } - ], "one author" ); - test.done(); - }); - }); - } -}; diff --git a/node_modules/changelogplease/package.json b/node_modules/changelogplease/package.json index aee8126..cd018ba 100644 --- a/node_modules/changelogplease/package.json +++ b/node_modules/changelogplease/package.json @@ -1,6 +1,6 @@ { "name": "changelogplease", - "version": "1.0.0", + "version": "1.0.1", "description": "Generate changelogs from git commit messages", "author": { "name": "Scott González", @@ -25,13 +25,17 @@ "test": "nodeunit tests" }, "dependencies": { - "git-tools": "0.0.8" + "git-tools": "0.1.0" }, "devDependencies": { "nodeunit": "0.8.6" }, "readme": "# Changelog, please\n\nGenerate changelogs from git commit messages using node.js. The generated changelogs are written in markdown.\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n\n## Installation\n\n```\nnpm install changelogplease\n```\n\n## Usage\n\n```javascript\nvar changelog = require( \"changelogplease\" );\nvar parsed = changelog({\n\tticketUrl: \"https://github.com/scottgonzalez/changelogplease/issues/{id}\",\n\tcommitUrl: \"https://github.com/scottgonzalez/changelogplease/commit/{id}\",\n\trepo: \"/path/to/repo\",\n\tcommittish: \"1.2.3..1.2.4\"\n});\n```\n\n## API\n\n### changelog( options, callback )\n\n* `options` (Object): Options for creating the changelog.\n * `ticketUrl` (String): Template for ticket/issue URLs; `{id}` will be replaced with the ticket id.\n * `commitUrl (String)`: Template for commit URLs; `{id}` will be replaced with the commit hash.\n * `repo` (String): Path to the repository.\n * `committish` (String): The range of commits for the changelog.\n* `callback` (Function; `function( error, log )`): Function to invoke after generating the changelog.\n * `log` (String): Generated changelog, written in markdown.\n\n### Changelog\n\n`changelog( options, callback )` is a shorthand for the following:\n\n```js\nvar Changelog = require( \"changelogplease\" ).Changelog;\nvar instance = new Changelog( options );\ninstance.parse( callback );\n```\n\nChangelog generation is tailored to a specific format based on the needs of the various jQuery\nprojects. However, the `Changelog` constructor and prototype are exposed to allow flexibility.\nBe aware that these methods are not currently documented because they may change. Feel free to\nsubmit [feature requests](https://github.com/scottgonzalez/changelogplease/issues/new) if you don't\nfeel comfortable hacking in your own changes (or even if you do).\n\n\n## License\n\nCopyright 2014 Scott González. Released under the terms of the MIT license.\n\n---\n\nSupport this project by [donating on Gittip](https://www.gittip.com/scottgonzalez/).\n", "readmeFilename": "README.md", - "_id": "changelogplease@1.0.0", - "_from": "changelogplease@" + "_id": "changelogplease@1.0.1", + "dist": { + "shasum": "2953e41245f475cd0a3d66b2861e3344166d6c30" + }, + "_from": "changelogplease@1.0.1", + "_resolved": "https://registry.npmjs.org/changelogplease/-/changelogplease-1.0.1.tgz" } diff --git a/node_modules/changelogplease/tests/changelog.js b/node_modules/changelogplease/tests/changelog.js deleted file mode 100644 index 6b17870..0000000 --- a/node_modules/changelogplease/tests/changelog.js +++ /dev/null @@ -1,183 +0,0 @@ -var fs = require( "fs" ), - Changelog = require( ".." ).Changelog, - fixtures = require( "./fixtures/commits" ); - -exports.ticketUrl = { - setUp: function( done ) { - this.changelog = new Changelog({ - ticketUrl: "http://example.com/ticket/{id}/" - }); - done(); - }, - - replacement: function( test ) { - test.expect( 1 ); - - var url = this.changelog.ticketUrl( 37 ); - test.strictEqual( url, "http://example.com/ticket/37/", - "Ticket id should be inserted." ); - test.done(); - } -}; - -exports.getLog = { - setUp: function( done ) { - this.changelog = new Changelog({ - commitUrl: "http://example.com/commit/{id}/", - committish: "alpha..omega" - }); - done(); - }, - - error: function( test ) { - test.expect( 1 ); - - var providedError = new Error(); - - this.changelog.repo.exec = function() { - var callback = arguments[ arguments.length - 1 ]; - process.nextTick(function() { - callback( providedError ); - }); - }; - - this.changelog.getLog(function( error ) { - test.strictEqual( error, providedError, "Should pass error." ); - test.done(); - }); - }, - - success: function( test ) { - test.expect( 5 ); - - var providedLog = {}; - - this.changelog.repo.exec = function( command, format, committish, callback ) { - test.strictEqual( command, "log", "Should invoke git log." ); - test.strictEqual( format, - "--format=" + - "__COMMIT__%n" + - "%s (__TICKETREF__, [%h](http://example.com/commit/%H/))%n" + - "%b", - "Should pass format with proper commit URL." ); - test.strictEqual( committish, "alpha..omega", "Should pass committish." ); - - process.nextTick(function() { - callback( null, providedLog ); - }); - }; - - this.changelog.getLog(function( error, log ) { - test.strictEqual( error, null, "Should not pass an error." ); - test.strictEqual( log, providedLog, "Should pass log." ); - test.done(); - }); - } -}; - -exports.parseCommit = { - setUp: function( done ) { - this.changelog = new Changelog({ - ticketUrl: "TICKET-URL/{id}", - commitUrl: "COMMIT-URL/{id}" - }); - done(); - }, - - commits: function( test ) { - test.expect( 6 ); - - Object.keys( fixtures ).forEach(function( name ) { - test.strictEqual( - this.changelog.parseCommit( fixtures[ name ].input ), - fixtures[ name ].output, - name - ); - }.bind( this )); - - test.done(); - } -}; - -exports.parseCommits = { - setUp: function( done ) { - this.changelog = new Changelog({}); - done(); - }, - - commits: function( test ) { - test.expect( 4 ); - - var providedCommits = [ "a", "c", "b" ]; - var parsedCommits = [ "a", "c", "b" ]; - var providedCommitsLog = "__COMMIT__\n" + - providedCommits.join( "__COMMIT__\n" ); - var callCount = 0; - - this.changelog.parseCommit = function( commit ) { - test.strictEqual( commit, providedCommits[ callCount ], - "Should pass commit" ); - - var parsedCommit = parsedCommits[ callCount ]; - - callCount++; - - return parsedCommit; - }; - - test.strictEqual( - this.changelog.parseCommits( providedCommitsLog ), - "a\nb\nc\n", - "Should parse and sort commits." - ); - test.done(); - } -}; - -exports.parse = { - setUp: function( done ) { - this.changelog = new Changelog({}); - done(); - }, - - "getLog error": function( test ) { - test.expect( 1 ); - - var providedError = new Error(); - - this.changelog.getLog = function( callback ) { - process.nextTick(function() { - callback( providedError ); - }); - }; - - this.changelog.parse(function( error ) { - test.strictEqual( error, providedError, "Should pass error." ); - test.done(); - }); - }, - - success: function( test ) { - test.expect( 3 ); - - var providedLog = {}; - var providedParsedLog = {}; - - this.changelog.getLog = function( callback ) { - process.nextTick(function() { - callback( null, providedLog ); - }); - }; - - this.changelog.parseCommits = function( log ) { - test.strictEqual( log, providedLog, "Should pass log." ); - return providedParsedLog; - }; - - this.changelog.parse(function( error, log ) { - test.strictEqual( error, null, "Should not pass an error." ); - test.strictEqual( log, providedParsedLog, "Should pass parsed log." ); - test.done(); - }); - } -}; diff --git a/node_modules/changelogplease/tests/fixtures/commits.js b/node_modules/changelogplease/tests/fixtures/commits.js deleted file mode 100644 index 1b3e6b3..0000000 --- a/node_modules/changelogplease/tests/fixtures/commits.js +++ /dev/null @@ -1,15 +0,0 @@ -var fs = require( "fs" ); - -var commits = {}; -module.exports = commits; - -fs.readFileSync( __dirname + "/commits.txt", "utf8" ) - .trim() - .split( "\n=====\n") - .forEach(function( raw ) { - var parts = raw.split( "\n*****\n" ); - commits[ parts[ 0 ] ] = { - input: parts[ 1 ], - output: parts[ 2 ] - }; - }); diff --git a/node_modules/changelogplease/tests/fixtures/commits.txt b/node_modules/changelogplease/tests/fixtures/commits.txt deleted file mode 100644 index ae1cc44..0000000 --- a/node_modules/changelogplease/tests/fixtures/commits.txt +++ /dev/null @@ -1,43 +0,0 @@ -noRef -***** -Alpha: Fixed something without a ticket! (__TICKETREF__, [aaa1111](COMMIT-URL/aaa1111000000000000000000000000000000000)) -***** -* Alpha: Fixed something without a ticket! (__TICKETREF__, [aaa1111](COMMIT-URL/aaa1111000000000000000000000000000000000)) -===== -fixesHash -***** -Alpha: Did stuff (__TICKETREF__, [abc123](COMMIT-URL/abc1234000000000000000000000000000000000)) -Fixes #123 -***** -* Alpha: Did stuff ([#123](TICKET-URL/123), [abc123](COMMIT-URL/abc1234000000000000000000000000000000000)) -===== -fixGh -***** -Beta: Make the baz properly qux (__TICKETREF__, [bbb2222](COMMIT-URL/bbb2222000000000000000000000000000000000)) -Fix gh-239 -***** -* Beta: Make the baz properly qux ([#239](TICKET-URL/239), [bbb2222](COMMIT-URL/bbb2222000000000000000000000000000000000)) -===== -otherGithub -***** -Alpha: Cross-project bugs are fun (__TICKETREF__, [ddd1234](COMMIT-URL/ddd1234000000000000000000000000000000000)) -Fixed other/project#123 -***** -* Alpha: Cross-project bugs are fun ([other/project#123](https://github.com/other/project/issues/123), [ddd1234](COMMIT-URL/ddd1234000000000000000000000000000000000)) -===== -multiRef -***** -Omega: Fix all the things (__TICKETREF__, [000deb7](COMMIT-URL/000deb7000000000000000000000000000000000)) -Fixes #12 -Fixes #34 -Fixes other/project#3456 -Closes gh-2000 -***** -* Omega: Fix all the things ([#12](TICKET-URL/12), [#34](TICKET-URL/34), [other/project#3456](https://github.com/other/project/issues/3456), [000deb7](COMMIT-URL/000deb7000000000000000000000000000000000)) -===== -cherryPick -***** -Beta: Fix something (cherry picked from commit 9999999000000000000000000000000000000000) (__TICKETREF__, [fff1234](COMMIT-URL/fff1234000000000000000000000000000000000)) -Fixes #55 -***** -* Beta: Fix something ([#55](TICKET-URL/55), [fff1234](COMMIT-URL/fff1234000000000000000000000000000000000)) diff --git a/package.json b/package.json index 9d82114..000ec82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "changelogplease": "1.0.0", + "changelogplease": "1.0.1", "colors": "0.6.2", "semver": "2.2.1", "shelljs": "0.2.6",