From 7bc4e1026c79984cd6fd8f8e9553a3927e34588e Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Wed, 12 Jul 2023 21:09:37 +0200 Subject: [PATCH 1/2] [FIX] Application: Fallback to manifest.appdescr_variant if manifest.json is not found This fixes a regression presumably present since ui5-projevt 3.0.0, which prevented proper fallback to manifest.appdescr_variant in case no manifest.json is found in the project. --- lib/specifications/types/Application.js | 12 ++++++++---- test/lib/specifications/types/Application.js | 13 ++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/specifications/types/Application.js b/lib/specifications/types/Application.js index f153e5176..693531827 100644 --- a/lib/specifications/types/Application.js +++ b/lib/specifications/types/Application.js @@ -124,7 +124,7 @@ class Application extends ComponentProject { try { return await this._getNamespaceFromManifestJson(); } catch (manifestJsonError) { - if (manifestJsonError.code !== "ENOENT") { + if (manifestJsonError.cause?.code !== "ENOENT") { throw manifestJsonError; } // No manifest.json present @@ -132,7 +132,7 @@ class Application extends ComponentProject { try { return await this._getNamespaceFromManifestAppDescVariant(); } catch (appDescVarError) { - if (appDescVarError.code === "ENOENT") { + if (appDescVarError.cause?.code === "ENOENT") { // Fallback not possible: No manifest.appdescr_variant present // => Throw error indicating missing manifest.json // (do not mention manifest.appdescr_variant since it is only @@ -214,14 +214,18 @@ class Application extends ComponentProject { return this._pManifests[filePath] = this._getRawSourceReader().byPath(filePath) .then(async (resource) => { if (!resource) { - throw new Error( + const error = new Error( `Could not find resource ${filePath} in project ${this.getName()}`); + error.code = "ENOENT"; // "File or directory does not exist" + throw error; } return JSON.parse(await resource.getString()); }).catch((err) => { throw new Error( `Failed to read ${filePath} for project ` + - `${this.getName()}: ${err.message}`); + `${this.getName()}: ${err.message}`, { + cause: err + }); }); } } diff --git a/test/lib/specifications/types/Application.js b/test/lib/specifications/types/Application.js index 19b9054a3..94d355ffe 100644 --- a/test/lib/specifications/types/Application.js +++ b/test/lib/specifications/types/Application.js @@ -9,6 +9,8 @@ import Application from "../../../../lib/specifications/types/Application.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const applicationAPath = path.join(__dirname, "..", "..", "..", "fixtures", "application.a"); const applicationHPath = path.join(__dirname, "..", "..", "..", "fixtures", "application.h"); +const ENOENT_ERROR = new Error(); +ENOENT_ERROR.code = "ENOENT"; test.beforeEach((t) => { t.context.sinon = sinonGlobal.createSandbox(); @@ -489,7 +491,7 @@ test("_getNamespace: Correct fallback to manifest.appdescr_variant if manifest.j const {projectInput, sinon} = t.context; const project = await Specification.create(projectInput); const _getManifestStub = sinon.stub(project, "_getManifest") - .onFirstCall().rejects({code: "ENOENT"}) + .onFirstCall().rejects(new Error("", {cause: ENOENT_ERROR})) .onSecondCall().resolves({id: "my.id"}); const namespace = await project._getNamespace(); @@ -504,7 +506,7 @@ test("_getNamespace: Correct error message if fallback to manifest.appdescr_vari const {projectInput, sinon} = t.context; const project = await Specification.create(projectInput); const _getManifestStub = sinon.stub(project, "_getManifest") - .onFirstCall().rejects({code: "ENOENT"}) + .onFirstCall().rejects(new Error("", {cause: ENOENT_ERROR})) .onSecondCall().rejects(new Error("EPON: Pony Error")); const error = await t.throwsAsync(project._getNamespace()); @@ -520,8 +522,8 @@ test("_getNamespace: Correct error message if fallback to manifest.appdescr_vari const {projectInput, sinon} = t.context; const project = await Specification.create(projectInput); const _getManifestStub = sinon.stub(project, "_getManifest") - .onFirstCall().rejects({message: "No such stable or directory: manifest.json", code: "ENOENT"}) - .onSecondCall().rejects({code: "ENOENT"}); // both files are missing + .onFirstCall().rejects(new Error("No such stable or directory: manifest.json", {cause: ENOENT_ERROR})) + .onSecondCall().rejects(new Error("", {cause: ENOENT_ERROR})); // both files are missing const error = await t.throwsAsync(project._getNamespace()); t.deepEqual(error.message, @@ -583,10 +585,11 @@ test.serial("_getManifest: File does not exist", async (t) => { const project = await Specification.create(projectInput); const error = await t.throwsAsync(project._getManifest("/does-not-exist.json")); - t.deepEqual(error.message, + t.is(error.message, "Failed to read /does-not-exist.json for project application.a: " + "Could not find resource /does-not-exist.json in project application.a", "Rejected with correct error message"); + t.is(error.cause.code, "ENOENT"); }); test.serial("_getManifest: result is cached", async (t) => { From f57ddbd862fba351e8f28bc425b4720e0f743fb6 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Thu, 13 Jul 2023 08:42:55 +0200 Subject: [PATCH 2/2] [INTERNAL] Application: Re-throw ENOENT error as-is --- lib/specifications/types/Application.js | 11 ++++++----- test/lib/specifications/types/Application.js | 13 +++++-------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/specifications/types/Application.js b/lib/specifications/types/Application.js index 693531827..05303eb92 100644 --- a/lib/specifications/types/Application.js +++ b/lib/specifications/types/Application.js @@ -124,7 +124,7 @@ class Application extends ComponentProject { try { return await this._getNamespaceFromManifestJson(); } catch (manifestJsonError) { - if (manifestJsonError.cause?.code !== "ENOENT") { + if (manifestJsonError.code !== "ENOENT") { throw manifestJsonError; } // No manifest.json present @@ -132,7 +132,7 @@ class Application extends ComponentProject { try { return await this._getNamespaceFromManifestAppDescVariant(); } catch (appDescVarError) { - if (appDescVarError.cause?.code === "ENOENT") { + if (appDescVarError.code === "ENOENT") { // Fallback not possible: No manifest.appdescr_variant present // => Throw error indicating missing manifest.json // (do not mention manifest.appdescr_variant since it is only @@ -221,11 +221,12 @@ class Application extends ComponentProject { } return JSON.parse(await resource.getString()); }).catch((err) => { + if (err.code === "ENOENT") { + throw err; + } throw new Error( `Failed to read ${filePath} for project ` + - `${this.getName()}: ${err.message}`, { - cause: err - }); + `${this.getName()}: ${err.message}`); }); } } diff --git a/test/lib/specifications/types/Application.js b/test/lib/specifications/types/Application.js index 94d355ffe..38699c4a3 100644 --- a/test/lib/specifications/types/Application.js +++ b/test/lib/specifications/types/Application.js @@ -9,8 +9,6 @@ import Application from "../../../../lib/specifications/types/Application.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const applicationAPath = path.join(__dirname, "..", "..", "..", "fixtures", "application.a"); const applicationHPath = path.join(__dirname, "..", "..", "..", "fixtures", "application.h"); -const ENOENT_ERROR = new Error(); -ENOENT_ERROR.code = "ENOENT"; test.beforeEach((t) => { t.context.sinon = sinonGlobal.createSandbox(); @@ -491,7 +489,7 @@ test("_getNamespace: Correct fallback to manifest.appdescr_variant if manifest.j const {projectInput, sinon} = t.context; const project = await Specification.create(projectInput); const _getManifestStub = sinon.stub(project, "_getManifest") - .onFirstCall().rejects(new Error("", {cause: ENOENT_ERROR})) + .onFirstCall().rejects({code: "ENOENT"}) .onSecondCall().resolves({id: "my.id"}); const namespace = await project._getNamespace(); @@ -506,7 +504,7 @@ test("_getNamespace: Correct error message if fallback to manifest.appdescr_vari const {projectInput, sinon} = t.context; const project = await Specification.create(projectInput); const _getManifestStub = sinon.stub(project, "_getManifest") - .onFirstCall().rejects(new Error("", {cause: ENOENT_ERROR})) + .onFirstCall().rejects({code: "ENOENT"}) .onSecondCall().rejects(new Error("EPON: Pony Error")); const error = await t.throwsAsync(project._getNamespace()); @@ -522,8 +520,8 @@ test("_getNamespace: Correct error message if fallback to manifest.appdescr_vari const {projectInput, sinon} = t.context; const project = await Specification.create(projectInput); const _getManifestStub = sinon.stub(project, "_getManifest") - .onFirstCall().rejects(new Error("No such stable or directory: manifest.json", {cause: ENOENT_ERROR})) - .onSecondCall().rejects(new Error("", {cause: ENOENT_ERROR})); // both files are missing + .onFirstCall().rejects({message: "No such stable or directory: manifest.json", code: "ENOENT"}) + .onSecondCall().rejects({code: "ENOENT"}); // both files are missing const error = await t.throwsAsync(project._getNamespace()); t.deepEqual(error.message, @@ -586,10 +584,9 @@ test.serial("_getManifest: File does not exist", async (t) => { const error = await t.throwsAsync(project._getManifest("/does-not-exist.json")); t.is(error.message, - "Failed to read /does-not-exist.json for project application.a: " + "Could not find resource /does-not-exist.json in project application.a", "Rejected with correct error message"); - t.is(error.cause.code, "ENOENT"); + t.is(error.code, "ENOENT"); }); test.serial("_getManifest: result is cached", async (t) => {