Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow specifying ranges in clarifications file and add strict usage checking for them #110

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 98 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,79 @@
- [Debugging](#debugging)
- [How Licenses are Found](#how-licenses-are-found)
- [Related information sources on the internet](#related-information-sources-on-the-internet)

<<< clarifications-semver
326

`version` can either be an exact version or a semver range, multiple ranges are supported for a single package, for example:
327

328

```json5
329

{
330

"package_name@^1": {
331

// Any field available in customFormat can be clarified
332

"licenses": "GPL",
333

// ... other fields, see above
334

},
335

"package_name@^2": {
336

// Any field available in customFormat can be clarified
337

"licenses": "MIT",
338

// ... other fields, see above
339

},
340

}
341

```
342

343

For overlapping ranges, the first matching entry is used.
344

345

The `--clarificationsMatchAll` option, when enabled, raises an error if not all specified clarifications were used, it is off by default.
346

347

<a name="custom_format"></a>
348

349

#
## <a id="a-message-from-the-maintainer"></a>A message from the maintainer

Folks, I love and honor open software (the latter not as much as I should), and therefore I am a little ashamed of the lack of regular care I give to this project. My family (two still young kids and a wife working full-time just as me) plus my hobbies (reading - currently I read the great book "Coders at work" and plan to work my way through "Structure and interpretation of computer programs", a book many great and experienced coders say is kind of a must-read - and homebrewing) take their toll. And then there's the time I need for procrastination as well. You get the picture.
Expand Down Expand Up @@ -249,6 +321,7 @@ before.

- `--angularCli` is just a synonym for `--plainVertical`
- `--clarificationsFile [filepath]` A file that describe the license clarifications for each package, see clarificationExample.json, any field available to the customFormat option can be clarified. The clarifications file can also be used to specify a subregion of a package's license file (instead reading the entire file)
- `--clarificationsMatchAll [boolean]` This optional new feature is still lacking a description - to be done
- `--csv` output in csv format
- `--csvComponentPrefix` prefix column for component in csv format
- `--customPath` to add a custom Format file in JSON
Expand Down Expand Up @@ -322,7 +395,30 @@ The `--clarificationsFile` option can be used to provide custom processing instr
}
```

## <a id="custom_format"></a>Custom format
`version` can either be an exact version or a semver range, multiple ranges are supported for a single package, for example:

```json5
{
"package_name@^1": {
// Any field available in customFormat can be clarified
"licenses": "GPL",
// ... other fields, see above
},
"package_name@^2": {
// Any field available in customFormat can be clarified
"licenses": "MIT",
// ... other fields, see above
},
}
```

For overlapping ranges, the first matching entry is used.

The `--clarificationsMatchAll` option, when enabled, raises an error if not all specified clarifications were used, it is off by default.

<a name="custom_format"></a>

## Custom format

The `--customPath` option can be used with CSV to specify the columns. Note that
the first column, `module_name`, will always be used.
Expand Down
3 changes: 2 additions & 1 deletion lib/args.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import path from 'node:path';

const knownOptions = {
angularCli: Boolean,
clarificationsFile: path,
clarificationsFile: path,clarificationsMatchAll
clarificationsMatchAll: Boolean,
color: Boolean,
csv: Boolean,
csvComponentPrefix: String,
Expand Down
45 changes: 40 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import spdxCorrect from 'spdx-correct';
import spdxSatisfies from 'spdx-satisfies';
import treeify from 'treeify';
import { createHash } from 'crypto';
import semver from 'semver';

import * as licenseCheckerHelpers from './licenseCheckerHelpers.js';
import { getLicenseTitle } from './getLicenseTitle.js';
Expand All @@ -45,8 +46,13 @@ const recursivelyCollectAllDependencies = (options) => {
let licenseData;
let licenseFile;
let noticeFiles = [];
let clarification = options.clarifications?.[currentPackageNameAndVersion];
const clarification = options.clarifications[currentExtendedPackageJson.name]?.find((clarification) =>
currentExtendedPackageJson.version == clarification.semverRange || semver.satisfies(currentExtendedPackageJson.version, clarification.semverRange)
);
let passedClarificationCheck = clarification?.checksum ? false : true;
if (clarification) {
clarification.used = true;
}

if (
// If we have processed this currentPackageNameAndVersion already, just return the data object.
Expand Down Expand Up @@ -133,7 +139,7 @@ const recursivelyCollectAllDependencies = (options) => {
);

if (licenseData) {
// License information has been collected from either the clarifiation file or from the package.json file
// License information has been collected from either the clarification file or from the package.json file
/*istanbul ignore else*/
if (Array.isArray(licenseData) && licenseData.length > 0) {
moduleInfo.licenses = licenseData.map((moduleLicense) => {
Expand Down Expand Up @@ -393,10 +399,21 @@ const init = (args, callback) => {
pusher = toCheckforFailOn;
}

// An object mapping from Package name -> What contents it should have
// An object mapping from Package name -> list of what contents it should have, including a semver range for each entry
let clarifications = {};
if (args.clarificationsFile) {
clarifications = parseJson(args.clarificationsFile);
const clarificationsFromFile = parseJson(args.clarificationsFile);

for (const [versionString, clarification] of Object.entries(clarificationsFromFile)) {
const versionSplit = versionString.lastIndexOf('@');
if (versionSplit !== -1) {
const name = versionString.slice(0, versionSplit);
const semverRange = versionString.slice(versionSplit + 1);
clarifications[name] ??= [];
// keep track for each clarification if it was used, optionally error when not
clarifications[name].push({...clarification, semverRange, used: false});
}
}
}

if (checker && pusher) {
Expand Down Expand Up @@ -432,7 +449,25 @@ const init = (args, callback) => {
unknown: args.unknown,
currentRecursionDepth: 0,
clarifications,
});
})

if (args.clarificationsMatchAll) {
const unusedClarifications = []
for (const [package, entries] of Object.entries(clarifications)) {
for (const clarification of entries) {
if (!clarification.used) {
unusedClarifications.push(`${package}@${clarification.semverRange}`);
}
}
}
if (unusedClarifications.length) {
console.error(
`Some clarifications (${unusedClarifications.join(', ')}) were unused and --clarificationsMatchAll was specified. Exiting.`,
);

process.exit(1);
}
}

const colorize = args.color;
const sorted = {}; // 'sorted' will store the same items as allWantedDepthDependenciesWithVersions, but sorted by package name and version
Expand Down
Loading