From e5a2dd5ae3361ff5ddc9cbbefccb3cea40ba30d0 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Thu, 7 Dec 2017 02:04:46 +0100 Subject: [PATCH 01/12] Add sub-directory option for CLI --- lib/cli.js | 3 ++- lib/index.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cli.js b/lib/cli.js index cbb4216..7225bfe 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -17,4 +17,5 @@ module.exports = CLI .option('-t, --tag ', 'generate from specific tag or range (e.g. v1.2.3 or v1.2.3..v1.2.4)') .option('-x, --exclude ', 'exclude selected commit types (comma separated)', list) .option('-f, --file [file]', 'file to write to, defaults to ./CHANGELOG.md, use - for stdout', './CHANGELOG.md') - .option('-u, --repo-url [url]', 'specify the repo URL for commit links, defaults to checking the package.json'); + .option('-u, --repo-url [url]', 'specify the repo URL for commit links, defaults to checking the package.json') + .option('-s, --sub-directory ', 'specify an explicit relatvie path to a sub-directory'); diff --git a/lib/index.js b/lib/index.js index e799a4b..15f39f0 100644 --- a/lib/index.js +++ b/lib/index.js @@ -14,6 +14,7 @@ var Writer = require('./writer'); * @param {Boolean} options.major - whether it should be a major changelog * @param {String} options.repoUrl - repo URL that will be used when linking commits * @param {Array} options.exclude - exclude listed commit types (e.g. ['chore', 'style', 'refactor']) + * @param {String} options.subDirectory - specify an explicit relatvie path to a sub-directory * @returns {Promise} the \n separated changelog string */ exports.generate = function (options) { From 6c6a7f822d6fbebd305b3b1a3436923755bd8cf8 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Thu, 7 Dec 2017 02:05:58 +0100 Subject: [PATCH 02/12] Add git log command filtering when sub-directory is specified --- lib/git.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/git.js b/lib/git.js index 17d7c32..20d1933 100644 --- a/lib/git.js +++ b/lib/git.js @@ -33,8 +33,14 @@ exports.getCommits = function (options) { revisions = tag ? tag + '..HEAD' : ''; } + var gitLogCommand = 'git log -E --format=' + FORMAT + ' ' + revisions; + + if (options.subDirectory) { + gitLogCommand += ' -- ' + options.subDirectory; + } + return CP.execAsync( - 'git log -E --format=' + FORMAT + ' ' + revisions, + gitLogCommand, { maxBuffer: Number.MAX_SAFE_INTEGER } From c5a6f07a2465c340ac3efda57a82916fd8ab2a64 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Thu, 7 Dec 2017 02:08:00 +0100 Subject: [PATCH 03/12] Add output file path normalization when sub-directory option is used --- lib/file.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/file.js b/lib/file.js index c927c65..afbc9ba 100644 --- a/lib/file.js +++ b/lib/file.js @@ -2,6 +2,7 @@ var Bluebird = require('bluebird'); var Fs = Bluebird.promisifyAll(require('fs')); +var Path = Bluebird.promisifyAll(require('path')); var STDOUT_PATH = '-'; @@ -42,3 +43,26 @@ exports.writeToFile = function (path, data) { } }); }; + +/** + * Normalize the input/output file path according to a sub-directory if needed + * @param {String} file - path of the input/ouput file + * @param {String|null} subDirectory - an explicit path to a sub-directory if given + * @returns {Promise} + */ +exports.normalizeFilePath = function (file, subDirectory) { + return Bluebird.resolve() + .then(function () { + if (!subDirectory) { + return file; + } + + file = Path.normalize(file); + + if (Path.dirname(file) === '.') { + return Path.join(subDirectory, file); + } + + return file; + }); +}; From f241a2d8e163ead405b24e73f713b6bd052d9b5d Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Thu, 7 Dec 2017 02:08:54 +0100 Subject: [PATCH 04/12] Add path normalization as prior step to changelog generation --- bin/generate | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/bin/generate b/bin/generate index 78fe7b5..570b77f 100755 --- a/bin/generate +++ b/bin/generate @@ -9,10 +9,15 @@ var File = require('../lib/file'); CLI.parse(process.argv); -return Bluebird.all([ - Changelog.generate(CLI), - File.readIfExists(CLI.file) -]) +return File.normalizeFilePath(CLI.file, CLI.subDirectory) +.then(function (normalizedPath) { + CLI.file = normalizedPath; + + return Bluebird.all([ + Changelog.generate(CLI), + File.readIfExists(CLI.file) + ]); +}) .spread(function (newLogs, oldLogs) { return File.writeToFile(CLI.file, newLogs + oldLogs); }) From d052541680621565719eb66f419f38e9b31b9955 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Thu, 7 Dec 2017 02:09:16 +0100 Subject: [PATCH 05/12] Add tests to cover new functionalities --- test/file.test.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++ test/git.test.js | 26 ++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/test/file.test.js b/test/file.test.js index fe6845b..5e42f4b 100644 --- a/test/file.test.js +++ b/test/file.test.js @@ -7,6 +7,7 @@ var Sinon = require('sinon'); var File = require('../lib/file'); +var DEFAULT_FILE = './CHANGELOG.md'; var NONEXISTENT = Path.resolve(__dirname, '../fake-file.txt'); var README = Path.resolve(__dirname, '../README.md'); var STDOUT_FD = 1; @@ -79,4 +80,71 @@ describe('file', function () { }); + describe('normalizePath', function () { + + it('default output, no sub-directory given => CHANGELOG.md in current directory', function () { + return File.normalizeFilePath(DEFAULT_FILE) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(DEFAULT_FILE); + }); + }); + + it('default name, with sub-directory given => CHANGELOG.md in sub directory', function () { + var subDirectory = 'subdirectory'; + + return File.normalizeFilePath(DEFAULT_FILE, subDirectory) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(Path.join(subDirectory, DEFAULT_FILE)); + }); + }); + + it('explicit name, no sub-directory given => explicit name in current directory', function () { + var someFile = 'SOMEFILE.md'; + + return File.normalizeFilePath(someFile) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(someFile); + }); + }); + + it('explicit name, with sub-directory given => explicit name in sub directory', function () { + var subDirectory = 'subdirectory'; + var someFile = 'SOMEFILE.md'; + + return File.normalizeFilePath(someFile, subDirectory) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(Path.join(subDirectory, someFile)); + }); + }); + + it('default name, with deep-sub-directory given => CHANGELOG.md in deep-sub directory', function () { + var subDirectory = Path.join('path', 'to', 'subdirectory'); + + return File.normalizeFilePath(DEFAULT_FILE, subDirectory) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(Path.join(subDirectory, DEFAULT_FILE)); + }); + }); + + it('explicit output path, without sub-directory given => explicit output path', function () { + var explicitPath = Path.join('path', 'to', DEFAULT_FILE); + + return File.normalizeFilePath(explicitPath) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(explicitPath); + }); + }); + + it('explicit output path, with sub-directory given => explicit output path', function () { + var explicitPath = Path.join('path', 'to', DEFAULT_FILE); + var subDirectory = Path.join('some', 'other', 'directory'); + + return File.normalizeFilePath(explicitPath, subDirectory) + .then(function (normalizedPath) { + Expect(normalizedPath).to.eql(explicitPath); + }); + }); + + }); + }); diff --git a/test/git.test.js b/test/git.test.js index 42be2b0..d8d4e69 100644 --- a/test/git.test.js +++ b/test/git.test.js @@ -108,6 +108,32 @@ describe('git', function () { }); }); + it('uses subDirectory for filtering git log command when `-s` / `--sub-directory` option was used', function () { + Sinon.stub(CP, 'execAsync') + .onFirstCall().returns(Bluebird.resolve('1.2.3.4')) + .onSecondCall().returns(Bluebird.resolve(VALID_COMMITS)); + + var subDirectory = 'subdirectory'; + + return Git.getCommits({ subDirectory: subDirectory }) + .then(function () { + CP.execAsync.secondCall.calledWithMatch(new RegExp('-- ' + subDirectory + '$')); + CP.execAsync.restore(); + }); + }); + + it('git log command does not filter path when `-s` / `--sub-directory` option was not used', function () { + Sinon.stub(CP, 'execAsync') + .onFirstCall().returns(Bluebird.resolve('1.2.3.4')) + .onSecondCall().returns(Bluebird.resolve(VALID_COMMITS)); + + return Git.getCommits() + .then(function () { + CP.execAsync.secondCall.notCalledWithMatch(/-- /); + CP.execAsync.restore(); + }); + }); + }); }); From 6237ca591f9287b0fd9316f81c5c98be8e3b86a8 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Thu, 7 Dec 2017 02:09:35 +0100 Subject: [PATCH 06/12] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 880feb0..0cec411 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ $ changelog -h -x, --exclude exclude selected commit types (comma separated) -f, --file [file] file to write to, defaults to ./CHANGELOG.md, use - for stdout -u, --repo-url [url] specify the repo URL for commit links, defaults to checking the package.json + -s, --sub-directory specify an explicit relatvie path to a sub-directory ``` From ce1e23a741616e6c51ea696834d3b75cd2ac609d Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Sun, 17 Dec 2017 23:36:15 +0100 Subject: [PATCH 07/12] Update argument text and add defaulting to current folder ('.') --- lib/cli.js | 2 +- lib/index.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index 7225bfe..aa5f561 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -18,4 +18,4 @@ module.exports = CLI .option('-x, --exclude ', 'exclude selected commit types (comma separated)', list) .option('-f, --file [file]', 'file to write to, defaults to ./CHANGELOG.md, use - for stdout', './CHANGELOG.md') .option('-u, --repo-url [url]', 'specify the repo URL for commit links, defaults to checking the package.json') - .option('-s, --sub-directory ', 'specify an explicit relatvie path to a sub-directory'); + .option('-s, --sub-directory ', 'specify a path to be passed into git log', '.'); diff --git a/lib/index.js b/lib/index.js index 15f39f0..e799a4b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -14,7 +14,6 @@ var Writer = require('./writer'); * @param {Boolean} options.major - whether it should be a major changelog * @param {String} options.repoUrl - repo URL that will be used when linking commits * @param {Array} options.exclude - exclude listed commit types (e.g. ['chore', 'style', 'refactor']) - * @param {String} options.subDirectory - specify an explicit relatvie path to a sub-directory * @returns {Promise} the \n separated changelog string */ exports.generate = function (options) { From bebb8c8176017373e397de14c64bae24a5af2bb1 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Sun, 17 Dec 2017 23:38:51 +0100 Subject: [PATCH 08/12] Exchange path normalization with simple `Path.join(...)` call --- bin/generate | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/bin/generate b/bin/generate index 570b77f..6ccb222 100755 --- a/bin/generate +++ b/bin/generate @@ -2,6 +2,7 @@ 'use strict'; var Bluebird = require('bluebird'); +var Path = require('path'); var CLI = require('../lib/cli'); var Changelog = require('../lib'); @@ -9,17 +10,14 @@ var File = require('../lib/file'); CLI.parse(process.argv); -return File.normalizeFilePath(CLI.file, CLI.subDirectory) -.then(function (normalizedPath) { - CLI.file = normalizedPath; +var filePath = Path.join(CLI.subDirectory, CLI.file); - return Bluebird.all([ - Changelog.generate(CLI), - File.readIfExists(CLI.file) - ]); -}) +return Bluebird.all([ + Changelog.generate(CLI), + File.readIfExists(filePath) +]) .spread(function (newLogs, oldLogs) { - return File.writeToFile(CLI.file, newLogs + oldLogs); + return File.writeToFile(filePath, newLogs + oldLogs); }) .catch(function (err) { console.error(err); From 0aec59f2ef47e850d5fee8893747fd21033f0912 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Sun, 17 Dec 2017 23:39:37 +0100 Subject: [PATCH 09/12] Clean up all `normalizeFilePath` function and its tests --- lib/file.js | 24 ----------------- test/file.test.js | 68 ----------------------------------------------- 2 files changed, 92 deletions(-) diff --git a/lib/file.js b/lib/file.js index afbc9ba..c927c65 100644 --- a/lib/file.js +++ b/lib/file.js @@ -2,7 +2,6 @@ var Bluebird = require('bluebird'); var Fs = Bluebird.promisifyAll(require('fs')); -var Path = Bluebird.promisifyAll(require('path')); var STDOUT_PATH = '-'; @@ -43,26 +42,3 @@ exports.writeToFile = function (path, data) { } }); }; - -/** - * Normalize the input/output file path according to a sub-directory if needed - * @param {String} file - path of the input/ouput file - * @param {String|null} subDirectory - an explicit path to a sub-directory if given - * @returns {Promise} - */ -exports.normalizeFilePath = function (file, subDirectory) { - return Bluebird.resolve() - .then(function () { - if (!subDirectory) { - return file; - } - - file = Path.normalize(file); - - if (Path.dirname(file) === '.') { - return Path.join(subDirectory, file); - } - - return file; - }); -}; diff --git a/test/file.test.js b/test/file.test.js index 5e42f4b..fe6845b 100644 --- a/test/file.test.js +++ b/test/file.test.js @@ -7,7 +7,6 @@ var Sinon = require('sinon'); var File = require('../lib/file'); -var DEFAULT_FILE = './CHANGELOG.md'; var NONEXISTENT = Path.resolve(__dirname, '../fake-file.txt'); var README = Path.resolve(__dirname, '../README.md'); var STDOUT_FD = 1; @@ -80,71 +79,4 @@ describe('file', function () { }); - describe('normalizePath', function () { - - it('default output, no sub-directory given => CHANGELOG.md in current directory', function () { - return File.normalizeFilePath(DEFAULT_FILE) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(DEFAULT_FILE); - }); - }); - - it('default name, with sub-directory given => CHANGELOG.md in sub directory', function () { - var subDirectory = 'subdirectory'; - - return File.normalizeFilePath(DEFAULT_FILE, subDirectory) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(Path.join(subDirectory, DEFAULT_FILE)); - }); - }); - - it('explicit name, no sub-directory given => explicit name in current directory', function () { - var someFile = 'SOMEFILE.md'; - - return File.normalizeFilePath(someFile) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(someFile); - }); - }); - - it('explicit name, with sub-directory given => explicit name in sub directory', function () { - var subDirectory = 'subdirectory'; - var someFile = 'SOMEFILE.md'; - - return File.normalizeFilePath(someFile, subDirectory) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(Path.join(subDirectory, someFile)); - }); - }); - - it('default name, with deep-sub-directory given => CHANGELOG.md in deep-sub directory', function () { - var subDirectory = Path.join('path', 'to', 'subdirectory'); - - return File.normalizeFilePath(DEFAULT_FILE, subDirectory) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(Path.join(subDirectory, DEFAULT_FILE)); - }); - }); - - it('explicit output path, without sub-directory given => explicit output path', function () { - var explicitPath = Path.join('path', 'to', DEFAULT_FILE); - - return File.normalizeFilePath(explicitPath) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(explicitPath); - }); - }); - - it('explicit output path, with sub-directory given => explicit output path', function () { - var explicitPath = Path.join('path', 'to', DEFAULT_FILE); - var subDirectory = Path.join('some', 'other', 'directory'); - - return File.normalizeFilePath(explicitPath, subDirectory) - .then(function (normalizedPath) { - Expect(normalizedPath).to.eql(explicitPath); - }); - }); - - }); - }); From a82d581056f5ce16c74eba482f2bee2ba7655a4f Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Sun, 17 Dec 2017 23:40:45 +0100 Subject: [PATCH 10/12] Simplify the git log command generation logic and remove redundant test --- lib/git.js | 6 +----- test/git.test.js | 12 ------------ 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/lib/git.js b/lib/git.js index 20d1933..fa2a493 100644 --- a/lib/git.js +++ b/lib/git.js @@ -33,11 +33,7 @@ exports.getCommits = function (options) { revisions = tag ? tag + '..HEAD' : ''; } - var gitLogCommand = 'git log -E --format=' + FORMAT + ' ' + revisions; - - if (options.subDirectory) { - gitLogCommand += ' -- ' + options.subDirectory; - } + var gitLogCommand = 'git log -E --format=' + FORMAT + ' ' + revisions + ' -- ' + options.subDirectory; return CP.execAsync( gitLogCommand, diff --git a/test/git.test.js b/test/git.test.js index d8d4e69..efcbfb3 100644 --- a/test/git.test.js +++ b/test/git.test.js @@ -122,18 +122,6 @@ describe('git', function () { }); }); - it('git log command does not filter path when `-s` / `--sub-directory` option was not used', function () { - Sinon.stub(CP, 'execAsync') - .onFirstCall().returns(Bluebird.resolve('1.2.3.4')) - .onSecondCall().returns(Bluebird.resolve(VALID_COMMITS)); - - return Git.getCommits() - .then(function () { - CP.execAsync.secondCall.notCalledWithMatch(/-- /); - CP.execAsync.restore(); - }); - }); - }); }); From 4899221ce956b5a15e500649606fde9e168216d7 Mon Sep 17 00:00:00 2001 From: "Jakob (Koby) Shimony" Date: Mon, 18 Dec 2017 00:01:07 +0100 Subject: [PATCH 11/12] Update README file: - update ouput of help command - add section to clarify sub-directory flag's usage nuances --- README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0cec411..c8e0285 100644 --- a/README.md +++ b/README.md @@ -51,18 +51,19 @@ $ changelog -h Generate a changelog from git commits. + Options: - -h, --help output usage information - -V, --version output the version number - -p, --patch create a patch changelog - -m, --minor create a minor changelog - -M, --major create a major changelog - -t, --tag generate from specific tag or range (e.g. v1.2.3 or v1.2.3..v1.2.4) - -x, --exclude exclude selected commit types (comma separated) - -f, --file [file] file to write to, defaults to ./CHANGELOG.md, use - for stdout - -u, --repo-url [url] specify the repo URL for commit links, defaults to checking the package.json - -s, --sub-directory specify an explicit relatvie path to a sub-directory + -V, --version output the version number + -p, --patch create a patch changelog + -m, --minor create a minor changelog + -M, --major create a major changelog + -t, --tag generate from specific tag or range (e.g. v1.2.3 or v1.2.3..v1.2.4) + -x, --exclude exclude selected commit types (comma separated) + -f, --file [file] file to write to, defaults to ./CHANGELOG.md, use - for stdout + -u, --repo-url [url] specify the repo URL for commit links, defaults to checking the package.json + -s, --sub-directory specify a path to be passed into git log + -h, --help output usage information ``` @@ -88,6 +89,11 @@ The way that I would recommend using this module would be the way it's being use "release:patch": "changelog -p && git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md' && npm version patch && git push origin && git push origin --tags", ``` +### Sub-directory + +Setting up the `--sub-directory` flag will run the `git log` command under the specified path. +When combined with the `--file` flag, the input/output file would be ***relative to the sub-directory*** specified in the previous flag. + ## Testing To run the test suite, just clone the repository and run the following: From 5cb6344ec126ffbbce081cbd37b6451ba8dc4635 Mon Sep 17 00:00:00 2001 From: Fabio Picheli Date: Wed, 7 Nov 2018 10:59:32 +0100 Subject: [PATCH 12/12] fix(sub-directory): check file before join paths --- bin/generate | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/generate b/bin/generate index 6ccb222..c122138 100755 --- a/bin/generate +++ b/bin/generate @@ -10,7 +10,7 @@ var File = require('../lib/file'); CLI.parse(process.argv); -var filePath = Path.join(CLI.subDirectory, CLI.file); +var filePath = CLI.file !== '-' ? Path.join(CLI.subDirectory, CLI.file) : CLI.file; return Bluebird.all([ Changelog.generate(CLI),