diff --git a/example-files/opossum_input.json b/example-files/opossum_input.json index 3abc252b5..2bb9c5f08 100644 --- a/example-files/opossum_input.json +++ b/example-files/opossum_input.json @@ -233,7 +233,8 @@ "licenseName": "The MIT License (MIT)", "copyright": "Copyright (c) 2013-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2013-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.", - "originId": "1eb75f3b-fc84-e781-ad9d-d46d6d61abf2" + "originId": "1eb75f3b-fc84-e781-ad9d-d46d6d61abf2", + "wasPreferred": true }, "5f1948d6-63fa-4f7e-b02b-7799083511fc": { "source": { diff --git a/src/ElectronBackend/input/OpossumInputFileSchema.json b/src/ElectronBackend/input/OpossumInputFileSchema.json index c909d240b..5250917c0 100644 --- a/src/ElectronBackend/input/OpossumInputFileSchema.json +++ b/src/ElectronBackend/input/OpossumInputFileSchema.json @@ -160,6 +160,10 @@ "items": { "type": "string" } + }, + "wasPreferred":{ + "type": "boolean", + "description": "Indicates that the attribution had previously been marked as preferred." } }, "required": ["source"], diff --git a/src/ElectronBackend/input/OpossumOutputFileSchema.json b/src/ElectronBackend/input/OpossumOutputFileSchema.json index 13426e21a..739b6d176 100644 --- a/src/ElectronBackend/input/OpossumOutputFileSchema.json +++ b/src/ElectronBackend/input/OpossumOutputFileSchema.json @@ -120,6 +120,10 @@ "items": { "type": "string" } + }, + "wasPreferred":{ + "type": "boolean", + "description": "Indicates that the attribution had previously been marked as preferred." } }, "required": [], diff --git a/src/ElectronBackend/input/__tests__/importFromFile.test.ts b/src/ElectronBackend/input/__tests__/importFromFile.test.ts index 7686ffee8..a1a419d71 100644 --- a/src/ElectronBackend/input/__tests__/importFromFile.test.ts +++ b/src/ElectronBackend/input/__tests__/importFromFile.test.ts @@ -94,6 +94,7 @@ const inputFileContent: ParsedOpossumInputFile = { criticality: Criticality.High, preferred: true, preferredOverOriginIds: ['test-id'], + wasPreferred: true, }, }, frequentLicenses: [ @@ -142,6 +143,7 @@ const expectedFileContent: ParsedFileContent = { criticality: Criticality.High, preferred: true, preferredOverOriginIds: ['test-id'], + wasPreferred: true, }, }, resourcesToAttributions: { diff --git a/src/ElectronBackend/output/__tests__/writeCsvToFile.test.ts b/src/ElectronBackend/output/__tests__/writeCsvToFile.test.ts index f1f639ff1..ccc8dc4bf 100644 --- a/src/ElectronBackend/output/__tests__/writeCsvToFile.test.ts +++ b/src/ElectronBackend/output/__tests__/writeCsvToFile.test.ts @@ -19,7 +19,7 @@ import { createTempFolder, deleteFolder } from '../../test-helpers'; const testCsvHeader = '"Index";"Confidence";"Comment";"Package Name";"Package Version";"Package Namespace";' + '"Package Type";"PURL Appendix";"URL";"Copyright";"License Name";"License Text (truncated)";"Source";"First Party";' + - '"Follow-up";"Origin Attribution IDs";"pre-selected";"exclude-from-notice";"criticality";"needs-review";"preferred";"preferred-over-origin-ids";"Resources"'; + '"Follow-up";"Origin Attribution IDs";"pre-selected";"exclude-from-notice";"criticality";"needs-review";"preferred";"preferred-over-origin-ids";"was-preferred";"Resources"'; describe('writeCsvToFile', () => { it('writeCsvToFile short', async () => { @@ -46,13 +46,13 @@ describe('writeCsvToFile', () => { const content = await fs.promises.readFile(csvPath, 'utf8'); expect(content).toContain(testCsvHeader); expect(content).toContain( - '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"/test.file"', + '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"";"/test.file"', ); expect(content).toContain( - '"2";"";"";"Fancy name,: tt";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/c/bla.mm"', + '"2";"";"";"Fancy name,: tt";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/c/bla.mm"', ); expect(content).toContain( - '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/b"', + '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/b"', ); deleteFolder(temporaryPath); }); @@ -117,10 +117,10 @@ describe('writeCsvToFile', () => { const content = await fs.promises.readFile(csvPath, 'utf8'); expect(content).toContain(testCsvHeader); expect(content).toContain( - '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"/test.file"', + '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"";"/test.file"', ); expect(content).toContain( - '"2";"";"";"Fancy name,: tt";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/c/bla.mm\n' + + '"2";"";"";"Fancy name,: tt";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/c/bla.mm\n' + '/b"', ); deleteFolder(temporaryPath); @@ -163,10 +163,10 @@ describe('writeCsvToFile', () => { const content = await fs.promises.readFile(csvPath, 'utf8'); expect(content).toContain(testCsvHeader); expect(content).toContain( - '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"/test.file"', + '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"";"/test.file"', ); expect(content).toContain( - `"2";"";"";"Fancy name,: tt";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"${expectedResources}"`, + `"2";"";"";"Fancy name,: tt";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"${expectedResources}"`, ); deleteFolder(temporaryPath); }); @@ -453,25 +453,25 @@ describe('writeCsvToFile', () => { const content = await fs.promises.readFile(csvPath, 'utf8'); expect(content).toContain(testCsvHeader); expect(content).toContain( - '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"/test.file"', + '"1";"";"";"";"";"";"";"";"";"";"";"license text, with; commas";"";"true";"";"";"";"";"";"";"";"";"";"/test.file"', ); expect(content).toContain( - `"2";"";"";"Fancy name with long license";"";"";"";"";"";"";"";"${expectedLicenseText}";"";"";"";"";"";"";"";"";"";"";"/a"`, + `"2";"";"";"Fancy name with long license";"";"";"";"";"";"";"";"${expectedLicenseText}";"";"";"";"";"";"";"";"";"";"";"";"/a"`, ); expect(content).toContain( - '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b"', + '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b"', ); expect(content).toContain( - '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b/c"', + '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b/c"', ); expect(content).toContain( - '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b/c/testi.bla"', + '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b/c/testi.bla"', ); expect(content).toContain( - '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b/c/testi.blub"', + '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/a/b/c/testi.blub"', ); expect(content).toContain( - '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/other"', + '"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"/other"', ); deleteFolder(temporaryPath); }); diff --git a/src/ElectronBackend/output/writeCsvToFile.ts b/src/ElectronBackend/output/writeCsvToFile.ts index 7cc091957..d0e86ba81 100644 --- a/src/ElectronBackend/output/writeCsvToFile.ts +++ b/src/ElectronBackend/output/writeCsvToFile.ts @@ -93,6 +93,7 @@ export function getHeadersFromColumns(columns: Array): { needsReview: 'needs-review', preferred: 'preferred', preferredOverOriginIds: 'preferred-over-origin-ids', + wasPreferred: 'was-preferred', }; const headers: { [key: string]: string } = {}; diff --git a/src/ElectronBackend/types/types.ts b/src/ElectronBackend/types/types.ts index 56f4f2587..90faf0411 100644 --- a/src/ElectronBackend/types/types.ts +++ b/src/ElectronBackend/types/types.ts @@ -63,6 +63,7 @@ interface RawPackageInfo { needsReview?: boolean; preferred?: boolean; preferredOverOriginIds?: Array; + wasPreferred?: boolean; } export interface RawAttributions { diff --git a/src/Frontend/Components/ReportTableItem/report-table-item-helpers.ts b/src/Frontend/Components/ReportTableItem/report-table-item-helpers.ts index aa0510780..685ae30c8 100644 --- a/src/Frontend/Components/ReportTableItem/report-table-item-helpers.ts +++ b/src/Frontend/Components/ReportTableItem/report-table-item-helpers.ts @@ -31,6 +31,7 @@ export function getFormattedCellData( case 'needsReview': case 'excludeFromNotice': case 'preferred': + case 'wasPreferred': cellData = attributionInfo[config.attributionProperty] ? 'Yes' : 'No'; break; case 'icons': diff --git a/src/Frontend/util/__tests__/convert-package-info.test.ts b/src/Frontend/util/__tests__/convert-package-info.test.ts index 200da5be8..0e6b9e4b6 100644 --- a/src/Frontend/util/__tests__/convert-package-info.test.ts +++ b/src/Frontend/util/__tests__/convert-package-info.test.ts @@ -55,6 +55,7 @@ describe('convertPackageInfoToDisplayPackageInfo', () => { 'needsReview', 'preferred', 'preferredOverOriginIds', + 'wasPreferred', ]; expect(testKeysOfPackageInfo).toEqual(expectedKeysOfPackageInfo); }); @@ -137,6 +138,7 @@ describe('convertDisplayPackageInfoToPackageInfo', () => { 'attributionIds', 'preferred', 'preferredOverOriginIds', + 'wasPreferred', ]; expect(testKeysOfDisplayPackageInfo).toEqual( expectedKeysOfDisplayPackageInfo, diff --git a/src/Frontend/util/get-display-package-info-keys.ts b/src/Frontend/util/get-display-package-info-keys.ts index fa632ab13..db8270941 100644 --- a/src/Frontend/util/get-display-package-info-keys.ts +++ b/src/Frontend/util/get-display-package-info-keys.ts @@ -31,6 +31,7 @@ export function getDisplayPackageInfoKeys(): Array { attributionIds: true, preferred: true, preferredOverOriginIds: true, + wasPreferred: true, }; return Object.keys( displayPackageInfoKeysObject, diff --git a/src/shared/shared-types.ts b/src/shared/shared-types.ts index 7e733e5ea..b19b1b60c 100644 --- a/src/shared/shared-types.ts +++ b/src/shared/shared-types.ts @@ -57,6 +57,7 @@ interface PackageInfoCore { needsReview?: boolean; preferred?: boolean; preferredOverOriginIds?: Array; + wasPreferred?: boolean; } export interface PackageInfo extends PackageInfoCore { diff --git a/src/shared/shared-util.ts b/src/shared/shared-util.ts index 01fd62cb0..3030301dd 100644 --- a/src/shared/shared-util.ts +++ b/src/shared/shared-util.ts @@ -30,6 +30,7 @@ export function getPackageInfoKeys(): Array { needsReview: true, preferred: true, preferredOverOriginIds: true, + wasPreferred: true, }; return Object.keys(packageInfoKeysObject) as Array; }