Skip to content

Commit 0ee4441

Browse files
authored
Improves name identification for yarn v1 lock files with self aliases (#1668)
Signed-off-by: Prabhu Subramanian <[email protected]>
1 parent 205ad38 commit 0ee4441

File tree

7 files changed

+41
-12
lines changed

7 files changed

+41
-12
lines changed

lib/cli/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -6095,6 +6095,9 @@ export async function createCsharpBom(path, options) {
60956095
);
60966096
// Create the slices file if it doesn't exist
60976097
if (!safeExistsSync(slicesFile)) {
6098+
thoughtLog(
6099+
"Alright, the next step is to invoke the dosai command to identify evidence of occurrences for various components.",
6100+
);
60986101
const sliceResult = getDotnetSlices(resolve(path), resolve(slicesFile));
60996102
if (!sliceResult && DEBUG_MODE) {
61006103
console.log(

lib/helpers/logger.js

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export function thoughtLog(s, args) {
3131
if (!s?.endsWith(".") && !s?.endsWith("?") && !s?.endsWith("!")) {
3232
s = `${s}.`;
3333
}
34+
s = s.replaceAll("'.'", "'<project dir>'");
3435
if (args) {
3536
tlogger.log(colorizeText(`${s}`), args);
3637
} else {

lib/helpers/utils.js

+33-8
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,7 @@ export async function parsePkgLock(pkgLockFile, options = {}) {
16381638
}
16391639

16401640
/**
1641-
* Given a lock file this method would return an Object with the identiy as the key and parsed name and value
1641+
* Given a lock file this method would return an Object with the identity as the key and parsed name and value
16421642
* eg: "@actions/core@^1.2.6", "@actions/core@^1.6.0":
16431643
* version "1.6.0"
16441644
* would result in two entries
@@ -1650,7 +1650,7 @@ export function yarnLockToIdentMap(lockData) {
16501650
let currentIdents = [];
16511651
lockData.split("\n").forEach((l) => {
16521652
l = l.replace("\r", "");
1653-
if (l === "\n" || l.startsWith("#")) {
1653+
if (l === "\n" || !l.length || l.startsWith("#")) {
16541654
return;
16551655
}
16561656
// "@actions/core@^1.2.6", "@actions/core@^1.6.0":
@@ -1707,14 +1707,22 @@ export function yarnLockToIdentMap(lockData) {
17071707
function _parseYarnLine(l) {
17081708
let name = "";
17091709
let group = "";
1710-
const prefixAtSymbol = l.startsWith("@");
1710+
let prefixAtSymbol = l.startsWith("@");
17111711
const tmpA = l.split("@");
17121712
// ignore possible leading empty strings
17131713
if (tmpA[0] === "") {
17141714
tmpA.shift();
17151715
}
1716+
let fullName;
17161717
if (tmpA.length >= 2) {
1717-
const fullName = tmpA[0];
1718+
if (tmpA.length === 4) {
1719+
if (tmpA[1] === "npm:") {
1720+
prefixAtSymbol = true;
1721+
}
1722+
fullName = tmpA[2];
1723+
} else {
1724+
fullName = tmpA[0];
1725+
}
17181726
if (fullName.indexOf("/") > -1) {
17191727
const parts = fullName.split("/");
17201728
group = (prefixAtSymbol ? "@" : "") + parts[0];
@@ -1891,16 +1899,26 @@ export async function parseYarnLock(yarnLockFile) {
18911899
if (dgroupname.endsWith(":")) {
18921900
dgroupname = dgroupname.substring(0, dgroupname.length - 1);
18931901
}
1894-
let range = tmpA[1].replace(/["']/g, "");
1902+
let dgroupnameToUse = dgroupname;
1903+
const range = tmpA[1].replace(/["']/g, "");
1904+
let versionRange = range;
18951905
// Deal with range with npm: prefix such as npm:string-width@^4.2.0, npm:@types/ioredis@^4.28.10
18961906
if (range.startsWith("npm:")) {
1897-
range = range.split("@").splice(-1)[0];
1907+
versionRange = range.split("@").splice(-1)[0];
1908+
dgroupnameToUse = range
1909+
.replace("npm:", "")
1910+
.replace(`@${versionRange}`, "");
18981911
}
1899-
const resolvedVersion = identMap[`${dgroupname}|${range}`];
1912+
const resolvedVersion =
1913+
identMap[`${dgroupname}|${versionRange}`] ||
1914+
identMap[`${dgroupnameToUse}|${versionRange}`];
1915+
// Handle case where the dependency name is really an alias.
1916+
// Eg: legacy-swc-helpers "npm:@swc/helpers@=0.4.14". Here the dgroupname=@swc/helpers
1917+
19001918
const depPurlString = new PackageURL(
19011919
"npm",
19021920
null,
1903-
dgroupname,
1921+
dgroupnameToUse,
19041922
resolvedVersion,
19051923
null,
19061924
null,
@@ -14183,6 +14201,9 @@ export function addEvidenceForDotnet(pkgList, slicesFile) {
1418314201
}
1418414202
const slicesData = JSON.parse(readFileSync(slicesFile, "utf-8"));
1418514203
if (slicesData && Object.keys(slicesData)) {
14204+
thoughtLog(
14205+
"Let's thoroughly inspect the dependency slice to identify where and how the components are used.",
14206+
);
1418614207
if (slicesData.Dependencies) {
1418714208
for (const adep of slicesData.Dependencies) {
1418814209
// Case 1: Dependencies slice has the .dll file
@@ -14274,6 +14295,10 @@ export function addEvidenceForDotnet(pkgList, slicesFile) {
1427414295
});
1427514296
}
1427614297
}
14298+
} else if (slicesData?.Dependencies || slicesData?.MethodCalls) {
14299+
thoughtLog(
14300+
"I didn't find any occurrence evidence or detailed imported modules, even though there is good dependency slice data from dosai. This is surprising.",
14301+
);
1427714302
}
1427814303
return pkgList;
1427914304
}

types/lib/cli/index.d.ts.map

+1-1
Original file line numberDiff line numberDiff line change

types/lib/helpers/logger.d.ts.map

+1-1
Original file line numberDiff line numberDiff line change

types/lib/helpers/utils.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export function parsePkgLock(pkgLockFile: string, options?: object): Promise<{
139139
dependenciesList: any;
140140
}>;
141141
/**
142-
* Given a lock file this method would return an Object with the identiy as the key and parsed name and value
142+
* Given a lock file this method would return an Object with the identity as the key and parsed name and value
143143
* eg: "@actions/core@^1.2.6", "@actions/core@^1.6.0":
144144
* version "1.6.0"
145145
* would result in two entries

0 commit comments

Comments
 (0)