Skip to content

Commit

Permalink
fix: use transform on all found copyright notices in a file (#337)
Browse files Browse the repository at this point in the history
Closes #333
  • Loading branch information
FantasticFiasco authored Mar 29, 2023
1 parent 5d720e8 commit 66d9f99
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 94 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

## [Unreleased]

### :syringe: Fixed

- [#333](https://github.com/FantasticFiasco/action-update-license-year/issues/333) [BREAKING CHANGE] Update all licenses in a file, not only the first found (discovered by [@glimchb](https://github.com/glimchb)).

**Migration guide**

Custom RegExp transforms where previously written to execute with the `mi` flags ("multiline" and "ignore case"). With this new major version the transform also needs to respect the `g` flag ("global"). I.e. please verify that your custom transform behaves as expected when used with the `gmi` flags.

## [2.3.0] - 2023-01-06

### :zap: Added
Expand Down
85 changes: 37 additions & 48 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1244,16 +1244,18 @@ exports.create = create;
* Computes the sha256 hash of a glob
*
* @param patterns Patterns separated by newlines
* @param currentWorkspace Workspace used when matching files
* @param options Glob options
* @param verbose Enables verbose logging
*/
function hashFiles(patterns, options, verbose = false) {
function hashFiles(patterns, currentWorkspace = '', options, verbose = false) {
return __awaiter(this, void 0, void 0, function* () {
let followSymbolicLinks = true;
if (options && typeof options.followSymbolicLinks === 'boolean') {
followSymbolicLinks = options.followSymbolicLinks;
}
const globber = yield create(patterns, { followSymbolicLinks });
return internal_hash_files_1.hashFiles(globber, verbose);
return internal_hash_files_1.hashFiles(globber, currentWorkspace, verbose);
});
}
exports.hashFiles = hashFiles;
Expand Down Expand Up @@ -1613,13 +1615,15 @@ const fs = __importStar(__nccwpck_require__(7147));
const stream = __importStar(__nccwpck_require__(2781));
const util = __importStar(__nccwpck_require__(3837));
const path = __importStar(__nccwpck_require__(1017));
function hashFiles(globber, verbose = false) {
function hashFiles(globber, currentWorkspace, verbose = false) {
var e_1, _a;
var _b;
return __awaiter(this, void 0, void 0, function* () {
const writeDelegate = verbose ? core.info : core.debug;
let hasMatch = false;
const githubWorkspace = (_b = process.env['GITHUB_WORKSPACE']) !== null && _b !== void 0 ? _b : process.cwd();
const githubWorkspace = currentWorkspace
? currentWorkspace
: (_b = process.env['GITHUB_WORKSPACE']) !== null && _b !== void 0 ? _b : process.cwd();
const result = crypto.createHash('sha256');
let count = 0;
try {
Expand Down Expand Up @@ -16932,69 +16936,46 @@ module.exports = Repository
// Regular expressions capable of transforming the following license files:
// - GNU Affero General Public License v3.0 only (AGPL-3.0-only)
// prettier-ignore
const AGPL_3_ONLY_YEAR_RANGE = new RegExp(
const AGPL_3_ONLY = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (C) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'-\\d{4}' + // '-YYYY'
'(-\\d{4})?' + // '(-YYYY)?'
'(?!\\s+free\\s+software\\s+foundation)', // ' Free Software Foundation' negative lookahead
'im' // Multi-line/Insensitive
);
// prettier-ignore
const AGPL_3_ONLY_SINGLE_YEAR = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (C) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'(?!\\s+free software foundation)', // ' Free Software Foundation' negative lookahead
'im' // Multi-line/Insensitive
'gmi' // Global/Multi-line/Insensitive
);

// Regular expressions capable of transforming the following license files:
// - Apache 2.0 (Apache-2.0)
// - MIT (MIT)
// prettier-ignore
const APACHE_2_MIT_YEAR_RANGE = new RegExp(
const APACHE_2_MIT = new RegExp(
'(?<=copyright\\s+)' + // 'Copyright ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'-\\d{4}', // '-YYYY'
'im' // Multi-line/Insensitive
);
// prettier-ignore
const APACHE_2_MIT_SINGLE_YEAR = new RegExp(
'(?<=copyright\\s+)' + // 'Copyright ' positive lookbehind
'(?<from>\\d{4})', // 'YYYY' group named 'from'
'im' // Multi-line/Insensitive
'(-\\d{4})?', // '(-YYYY)?'
'gmi' // Global/Multi-line/Insensitive
);

// Regular expressions capable of transforming the following license files:
// - BSD 2-clause "Simplified" (BSD-2-Clause)
// - BSD 3-clause "New" or "Revised" (BSD-3-Clause)
// prettier-ignore
const BSD_YEAR_RANGE = new RegExp(
const BSD = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (c) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'-\\d{4}' + // '-YYYY'
'(-\\d{4})?' + // '(-YYYY)?'
'(?=,)', // ',' positive lookahead
'im' // Multi-line/Insensitive
'gmi' // Global/Multi-line/Insensitive
)
// prettier-ignore
const BSD_SINGLE_YEAR = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (c) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'(?=,)', // ',' positive lookahead
'im' // Multi-line/Insensitive
);

/**
* @typedef LicenseTransform
* @property {string} name
* @property {RegExp} transform
*/
const DEFAULT_LICENSE_TRANSFORMS = [
{ name: 'AGPL-3.0-only', transform: AGPL_3_ONLY_YEAR_RANGE },
{ name: 'AGPL-3.0-only', transform: AGPL_3_ONLY_SINGLE_YEAR },
{ name: 'Apache-2.0', transform: APACHE_2_MIT_YEAR_RANGE },
{ name: 'Apache-2.0', transform: APACHE_2_MIT_SINGLE_YEAR },
{ name: 'BSD-2-Clause/BSD-3-Clause/MIT', transform: BSD_YEAR_RANGE },
{ name: 'BSD-2-Clause/BSD-3-Clause/MIT', transform: BSD_SINGLE_YEAR },
{ name: 'AGPL-3.0-only', transform: AGPL_3_ONLY },
{ name: 'Apache-2.0', transform: APACHE_2_MIT },
{ name: 'BSD-2-Clause/BSD-3-Clause/MIT', transform: BSD },
]

/**
Expand Down Expand Up @@ -17033,7 +17014,7 @@ const applyDefaultTransform = (license, currentYear, fileName) => {
const applyCustomTransform = (transform, license, currentYear, fileName) => {
const licenseTransform = {
name: 'Custom',
transform: new RegExp(transform, 'im'),
transform: new RegExp(transform, 'gmi'),
}

if (!canApplyLicenseTransform(licenseTransform, license)) {
Expand All @@ -17057,16 +17038,24 @@ const canApplyLicenseTransform = (licenseTransform, license) => {
* @param {number} currentYear
*/
const applyLicenseTransform = (licenseTransform, license, currentYear) => {
const match = licenseTransform.transform.exec(license)
if (match === null || match.groups === undefined) {
throw new Error(`Transforming ${licenseTransform.name} license failed`)
}
license = license.replace(licenseTransform.transform, (match, ...args) => {
// The last argument is the groups object
const groups = args[args.length - 1]

if (Number(match.groups['from']) === currentYear) {
return license
}
if (groups === undefined) {
throw new Error(`Transforming ${licenseTransform.name} license failed`)
}

const from = groups['from']

if (Number(from) === currentYear) {
return from
}

return `${from}-${currentYear}`
})

return license.replace(licenseTransform.transform, `$<from>-${currentYear}`)
return license
}

module.exports = {
Expand Down
73 changes: 29 additions & 44 deletions src/transforms.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,46 @@
// Regular expressions capable of transforming the following license files:
// - GNU Affero General Public License v3.0 only (AGPL-3.0-only)
// prettier-ignore
const AGPL_3_ONLY_YEAR_RANGE = new RegExp(
const AGPL_3_ONLY = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (C) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'-\\d{4}' + // '-YYYY'
'(-\\d{4})?' + // '(-YYYY)?'
'(?!\\s+free\\s+software\\s+foundation)', // ' Free Software Foundation' negative lookahead
'im' // Multi-line/Insensitive
);
// prettier-ignore
const AGPL_3_ONLY_SINGLE_YEAR = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (C) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'(?!\\s+free software foundation)', // ' Free Software Foundation' negative lookahead
'im' // Multi-line/Insensitive
'gmi' // Global/Multi-line/Insensitive
);

// Regular expressions capable of transforming the following license files:
// - Apache 2.0 (Apache-2.0)
// - MIT (MIT)
// prettier-ignore
const APACHE_2_MIT_YEAR_RANGE = new RegExp(
const APACHE_2_MIT = new RegExp(
'(?<=copyright\\s+)' + // 'Copyright ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'-\\d{4}', // '-YYYY'
'im' // Multi-line/Insensitive
);
// prettier-ignore
const APACHE_2_MIT_SINGLE_YEAR = new RegExp(
'(?<=copyright\\s+)' + // 'Copyright ' positive lookbehind
'(?<from>\\d{4})', // 'YYYY' group named 'from'
'im' // Multi-line/Insensitive
'(-\\d{4})?', // '(-YYYY)?'
'gmi' // Global/Multi-line/Insensitive
);

// Regular expressions capable of transforming the following license files:
// - BSD 2-clause "Simplified" (BSD-2-Clause)
// - BSD 3-clause "New" or "Revised" (BSD-3-Clause)
// prettier-ignore
const BSD_YEAR_RANGE = new RegExp(
const BSD = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (c) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'-\\d{4}' + // '-YYYY'
'(-\\d{4})?' + // '(-YYYY)?'
'(?=,)', // ',' positive lookahead
'im' // Multi-line/Insensitive
'gmi' // Global/Multi-line/Insensitive
)
// prettier-ignore
const BSD_SINGLE_YEAR = new RegExp(
'(?<=copyright\\s+\\(c\\)\\s+)' + // 'Copyright (c) ' positive lookbehind
'(?<from>\\d{4})' + // 'YYYY' group named 'from'
'(?=,)', // ',' positive lookahead
'im' // Multi-line/Insensitive
);

/**
* @typedef LicenseTransform
* @property {string} name
* @property {RegExp} transform
*/
const DEFAULT_LICENSE_TRANSFORMS = [
{ name: 'AGPL-3.0-only', transform: AGPL_3_ONLY_YEAR_RANGE },
{ name: 'AGPL-3.0-only', transform: AGPL_3_ONLY_SINGLE_YEAR },
{ name: 'Apache-2.0', transform: APACHE_2_MIT_YEAR_RANGE },
{ name: 'Apache-2.0', transform: APACHE_2_MIT_SINGLE_YEAR },
{ name: 'BSD-2-Clause/BSD-3-Clause/MIT', transform: BSD_YEAR_RANGE },
{ name: 'BSD-2-Clause/BSD-3-Clause/MIT', transform: BSD_SINGLE_YEAR },
{ name: 'AGPL-3.0-only', transform: AGPL_3_ONLY },
{ name: 'Apache-2.0', transform: APACHE_2_MIT },
{ name: 'BSD-2-Clause/BSD-3-Clause/MIT', transform: BSD },
]

/**
Expand Down Expand Up @@ -102,7 +79,7 @@ const applyDefaultTransform = (license, currentYear, fileName) => {
const applyCustomTransform = (transform, license, currentYear, fileName) => {
const licenseTransform = {
name: 'Custom',
transform: new RegExp(transform, 'im'),
transform: new RegExp(transform, 'gmi'),
}

if (!canApplyLicenseTransform(licenseTransform, license)) {
Expand All @@ -126,16 +103,24 @@ const canApplyLicenseTransform = (licenseTransform, license) => {
* @param {number} currentYear
*/
const applyLicenseTransform = (licenseTransform, license, currentYear) => {
const match = licenseTransform.transform.exec(license)
if (match === null || match.groups === undefined) {
throw new Error(`Transforming ${licenseTransform.name} license failed`)
}
license = license.replace(licenseTransform.transform, (match, ...args) => {
// The last argument is the groups object
const groups = args[args.length - 1]

if (Number(match.groups['from']) === currentYear) {
return license
}
if (groups === undefined) {
throw new Error(`Transforming ${licenseTransform.name} license failed`)
}

const from = groups['from']

if (Number(from) === currentYear) {
return from
}

return `${from}-${currentYear}`
})

return license.replace(licenseTransform.transform, `$<from>-${currentYear}`)
return license
}

module.exports = {
Expand Down
Loading

0 comments on commit 66d9f99

Please sign in to comment.