diff --git a/lib/cli/index.js b/lib/cli/index.js index 3c44bbe5bd..b24f32b3d0 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -3957,20 +3957,39 @@ export async function createDartBom(path, options) { `${options.multiProject ? "**/" : ""}pubspec.yaml`, options, ); + let dependencies = []; let pkgList = []; + const parentComponent = determineParentComponent(options); if (pubFiles.length) { for (const f of pubFiles) { if (DEBUG_MODE) { console.log(`Parsing ${f}`); } const pubLockData = readFileSync(f, { encoding: "utf-8" }); - const dlist = await parsePubLockData(pubLockData); - if (dlist?.length) { - pkgList = pkgList.concat(dlist); + const retMap = await parsePubLockData(pubLockData); + if (retMap.pkgList?.length) { + pkgList = pkgList.concat(retMap.pkgList); + } + if (retMap?.rootList?.length) { + const thisParentDependsOn = [ + { + ref: parentComponent["bom-ref"], + dependsOn: [ + ...new Set(retMap.rootList.map((c) => c["bom-ref"])), + ].sort(), + }, + ]; + dependencies = mergeDependencies( + dependencies, + thisParentDependsOn, + parentComponent, + ); } } return buildBomNSData(options, pkgList, "pub", { src: path, + dependencies, + parentComponent, filename: pubFiles.join(", "), }); } diff --git a/lib/helpers/utils.js b/lib/helpers/utils.js index eb9555f594..4f28340f3e 100644 --- a/lib/helpers/utils.js +++ b/lib/helpers/utils.js @@ -7415,42 +7415,43 @@ export async function parseCargoAuditableData(cargoData) { } export async function parsePubLockData(pubLockData) { - const pkgList = []; if (!pubLockData) { - return pkgList; + return []; } - let pkg = null; - pubLockData.split("\n").forEach((l) => { - let key = null; - let value = null; - l = l.replace("\r", ""); - if (!pkg && (l.startsWith("sdks:") || !l.startsWith(" "))) { - return; - } - if (l.startsWith(" ") && !l.startsWith(" ")) { - pkg = { - name: l.trim().replace(":", ""), - }; + let pkgList = []; + const rootList = []; + const data = _load(pubLockData); + const packages = data.packages; + + for (const [packageName, packageData] of Object.entries(packages)) { + const pkg = { name: packageName, version: packageData.version }; + // older dart versions don't have sha256 + if (packageData.description?.sha256) { + pkg._integrity = `sha256-${packageData.description?.sha256}`; } - if (l.startsWith(" ")) { - const tmpA = l.split(":"); - key = tmpA[0].trim(); - value = tmpA[1].trim().replace(/"/g, ""); - switch (key) { - case "version": - pkg.version = value; - if (pkg.name) { - pkgList.push(pkg); - } - pkg = {}; - break; - } + + const purlString = new PackageURL("dart", "", pkg.name, pkg.version) + .toString() + .replace(/%2F/g, "/"); + pkg["bom-ref"] = decodeURIComponent(purlString); + + if (packageData.dependency === "direct main") { + pkg.scope = "required"; + rootList.push(pkg); + } else if (packageData.dependency === "transitive") { + pkg.scope = "required"; + } else if (packageData.dependency === "direct dev") { + pkg.scope = "optional"; } - }); + + pkgList.push(pkg); + } + if (shouldFetchLicense()) { - return await getDartMetadata(pkgList); + pkgList = await getDartMetadata(pkgList); } - return pkgList; + + return { rootList, pkgList }; } export function parsePubYamlData(pubYamlData) { diff --git a/lib/helpers/utils.test.js b/lib/helpers/utils.test.js index abafaa4435..307ab7d339 100644 --- a/lib/helpers/utils.test.js +++ b/lib/helpers/utils.test.js @@ -2075,13 +2075,28 @@ test("get crates metadata", async () => { test("parse pub lock", async () => { expect(await parsePubLockData(null)).toEqual([]); - let dep_list = await parsePubLockData( + const ret_val = await parsePubLockData( readFileSync("./test/data/pubspec.lock", { encoding: "utf-8" }), ); - expect(dep_list.length).toEqual(26); + const root_list = ret_val.rootList; + let dep_list = ret_val.pkgList; + expect(dep_list.length).toEqual(28); expect(dep_list[0]).toEqual({ name: "async", - version: "2.8.2", + version: "2.11.0", + _integrity: + "sha256-947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c", + "bom-ref": "pkg:dart/async@2.11.0", + scope: "required", + }); + expect(root_list.length).toEqual(3); + expect(root_list[0]).toEqual({ + name: "flare_flutter", + version: "3.0.2", + _integrity: + "sha256-99d63c60f00fac81249ce6410ee015d7b125c63d8278a30da81edf3317a1f6a0", + "bom-ref": "pkg:dart/flare_flutter@3.0.2", + scope: "required", }); dep_list = parsePubYamlData( readFileSync("./test/data/pubspec.yaml", { encoding: "utf-8" }), diff --git a/test/data/pubspec.lock b/test/data/pubspec.lock index e1857ee01c..25fb048785 100644 --- a/test/data/pubspec.lock +++ b/test/data/pubspec.lock @@ -5,56 +5,56 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.18.0" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.1" flare_flutter: dependency: "direct main" description: name: flare_flutter - url: "https://pub.dartlang.org" + sha256: "99d63c60f00fac81249ce6410ee015d7b125c63d8278a30da81edf3317a1f6a0" + url: "https://pub.dev" source: hosted version: "3.0.2" flutter: @@ -66,7 +66,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" source: hosted version: "1.0.4" flutter_test: @@ -74,46 +75,76 @@ packages: description: flutter source: sdk version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" source: hosted version: "1.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.8.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.11.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.0" simple_animations: dependency: "direct main" description: name: simple_animations - url: "https://pub.dartlang.org" + sha256: "79acf025f196001d4680280f67b4d77ca828459b23498606d2fb130a4961046e" + url: "https://pub.dev" source: hosted version: "4.0.1" sky_engine: @@ -125,57 +156,65 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" source: hosted - version: "0.4.8" - typed_data: + version: "0.6.1" + vector_math: dependency: transitive description: - name: typed_data - url: "https://pub.dartlang.org" + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "1.3.0" - vector_math: + version: "2.1.4" + vm_service: dependency: transitive description: - name: vector_math - url: "https://pub.dartlang.org" + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "13.0.0" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=3.2.0-0 <4.0.0"