From 60d823d319f27d9a3980a4f526f2c1034022ad2e Mon Sep 17 00:00:00 2001 From: Ian Grant Date: Thu, 13 Jul 2023 20:09:32 +0000 Subject: [PATCH 1/3] feat: add consumeWholeFile option for output file --- index.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index af767fb..dbe0f78 100644 --- a/index.js +++ b/index.js @@ -35,7 +35,8 @@ const parseFileOption = option => { const file = isString(option) ? option : option.file; const mimeType = typeof option !== 'string' ? option.type : null; const path = (typeof option !== 'string' && option.path) || 'version'; - return { file, mimeType, path }; + const consumeWholeFile = typeof option !== 'string' ? option.consumeWholeFile : false; + return { file, mimeType, path, consumeWholeFile }; }; const getFileType = (file, mimeType) => { @@ -63,7 +64,7 @@ class Bumper extends Plugin { async getLatestVersion() { const { in: option } = this.options; if (!option) return; - const { file, mimeType, path } = parseFileOption(option); + const { file, mimeType, path, consumeWholeFile } = parseFileOption(option); if (file) { const type = getFileType(file, mimeType); let data; @@ -109,7 +110,7 @@ class Bumper extends Plugin { return Promise.all( options.map(async out => { - const { file, mimeType, path } = parseFileOption(out); + const { file, mimeType, path, consumeWholeFile } = parseFileOption(out); this.log.exec(`Writing version to ${file}`, isDryRun); if (isDryRun) return noop; @@ -141,7 +142,7 @@ class Bumper extends Plugin { return writeFileSync(file, ini.encode(parsed)); default: const versionMatch = new RegExp(latestVersion || '', 'g'); - const write = parsed ? parsed.replace(versionMatch, version) : version + EOL; + const write = (parsed && !consumeWholeFile) ? parsed.replace(versionMatch, version) : version + EOL; return writeFileSync(file, write); } }) From 68797b8bb9dc0f04829d5016f81f00977cf14b6d Mon Sep 17 00:00:00 2001 From: Ian Grant Date: Thu, 13 Jul 2023 20:10:07 +0000 Subject: [PATCH 2/3] test: add tests for consumeWholeFile output option --- test.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/test.js b/test.js index 43d878b..f0fab7c 100644 --- a/test.js +++ b/test.js @@ -17,6 +17,8 @@ mock({ './foo.toml': `[tool.test]${EOL}version = "1.0.0"${EOL}`, './foo.ini': `path.version=1.0.0${EOL}path.name=fake${EOL}`, './VERSION': `v1.0.0${EOL}`, + './VERSION-OLD': `v0.9.0${EOL}`, + './VERSION-OLD2': `v0.9.0${EOL}`, './README.md': `Release v1.0.0${EOL}`, './foo.yaml': `version: v1.0.0${EOL}`, './invalid.toml': `/# -*- some invalid toml -*-${EOL}version = "1.0.0"${EOL}` @@ -257,3 +259,68 @@ test('should give precedence to mime type over file extension', async () => { await runTasks(plugin); assert.equal(readFile('./invalid.toml'), `/# -*- some invalid toml -*-${EOL}version = "1.0.1"${EOL}`); }); + +test('should read from plain text file, overwrite out-of-date plain version text file, completely', async () => { + const options = { + [namespace]: { + in: { file: 'VERSION', type: 'text/plain' }, + out: [ + { + file: './VERSION-OLD', + type: 'text/plain', + consumeWholeFile: true + }, + { + file: './VERSION', + type: 'text/plain' + } + ] } + }; + const plugin = factory(Bumper, { namespace, options }); + await runTasks(plugin); + assert.equal(readFile('./VERSION'), `v1.0.1${EOL}`); + assert.equal(readFile('./VERSION-OLD'), `1.0.1${EOL}`); +}); + +test('should read from plain text file, not update out-of-date plain version text file', async () => { + const options = { + [namespace]: { + in: { file: 'VERSION', type: 'text/plain' }, + out: [ + { + file: './VERSION-OLD2', + type: 'text/plain', + consumeWholeFile: false + }, + { + file: './VERSION', + type: 'text/plain' + } + ] } + }; + const plugin = factory(Bumper, { namespace, options }); + await runTasks(plugin); + assert.equal(readFile('./VERSION'), `v1.0.1${EOL}`); + assert.equal(readFile('./VERSION-OLD2'), `v0.9.0${EOL}`); +}); + +test('should read from plain text file, not update out-of-date plain version text file (default implied)', async () => { + const options = { + [namespace]: { + in: { file: 'VERSION', type: 'text/plain' }, + out: [ + { + file: './VERSION-OLD2', + type: 'text/plain' + }, + { + file: './VERSION', + type: 'text/plain' + } + ] } + }; + const plugin = factory(Bumper, { namespace, options }); + await runTasks(plugin); + assert.equal(readFile('./VERSION'), `v1.0.1${EOL}`); + assert.equal(readFile('./VERSION-OLD2'), `v0.9.0${EOL}`); +}); From 28513a2a569236cc5e828e7764c689be4446a4b9 Mon Sep 17 00:00:00 2001 From: Ian Grant Date: Thu, 13 Jul 2023 20:10:34 +0000 Subject: [PATCH 3/3] docs: describe the use of consumeWholeFile output option --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index dc06d67..a263a57 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,26 @@ To replace all occurences of the current version with the new version in any tex } ``` +:warning: the operation is a search-and-replace; if the current version is not found in the file, the new version cannot be written out. + +To instead always consume the entire file, that is, the whole and only content of the file is the version number, set `consumeWholeFile: true` for the `out` option: + +```json +"plugins": { + "@release-it/bumper": { + "out": { + "file": "VERSION", + "type": "text/plain", + "consumeWholeFile": true + } + } +} +``` + +The version number is then written to the output file, overwriting it completely instead of a search-and-replace. + +:bulb: Setting `consumeWholeFile: true` precludes the use of prefixes, such as `v1.0.1` in the output file. + The `out` option can also be an array of files: ```json