diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 4ccde387bf..5c52fac038 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -2,8 +2,11 @@ All notable changes to the Zowe CLI package will be documented in this file. -## `8.0.0-next.202402261705` +## Recent Changes + +- BugFix: Update error handling in zosfiles to resemble that in zosjobs. [#2062](https://github.com/zowe/zowe-cli/pull/2062) +## `8.0.0-next.202402261705` - BugFix: Updated additional dependencies for technical currency. [#2061](https://github.com/zowe/zowe-cli/pull/2061) - BugFix: Updated engine to Node 16.7.0. [#2061](https://github.com/zowe/zowe-cli/pull/2061) @@ -72,7 +75,7 @@ LTS Breaking: Removed the following previously deprecated items: [#1981](https:/ ## `8.0.0-next.202311132045` - Major: First major version bump for V3 - + ## `7.23.3` - BugFix: Fixed race condition in `config convert-profiles` command that may fail to delete secure values for old profiles @@ -88,7 +91,6 @@ LTS Breaking: Removed the following previously deprecated items: [#1981](https:/ ## `7.23.0` - BugFix: Update zos-files copy dsclp system tests to include large mock files. - ## `7.22.0` - Enhancement: Hid the progress bar if `CI` environment variable is set, or if `FORCE_COLOR` environment variable is set to `0`. [#1845](https://github.com/zowe/zowe-cli/issues/1845) diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/cli.files.upload.dtp.integration.test.ts b/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/cli.files.upload.dtp.integration.test.ts index c647e779ec..7440e6a96a 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/cli.files.upload.dtp.integration.test.ts +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/dtp/cli.files.upload.dtp.integration.test.ts @@ -62,7 +62,7 @@ describe("Upload directory to PDS", () => { it("should fail when local directory does not exist", async () => { const shellScript = path.join(__dirname, "__scripts__", "command", "command_upload_dtp.sh"); const response = runCliScript(shellScript, TEST_ENVIRONMENT, ["localDirThatDoesNotExist", "mf.data.set"]); - expect(stripNewLines(response.stderr.toString())).toContain("no such file or directory, lstat"); + expect(stripNewLines(response.stderr.toString())).toContain("no such file or directory"); expect(stripNewLines(response.stderr.toString())).toContain("localDirThatDoesNotExist"); }); diff --git a/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/cli.files.upload.ftds.integration.test.ts b/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/cli.files.upload.ftds.integration.test.ts index 0cff72a34b..1946822813 100644 --- a/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/cli.files.upload.ftds.integration.test.ts +++ b/packages/cli/__tests__/zosfiles/__integration__/upload/ftds/cli.files.upload.ftds.integration.test.ts @@ -50,7 +50,7 @@ describe("Upload file to data set", () => { it("should fail when local file does not exist", async () => { const shellScript = path.join(__dirname, "__scripts__", "command", "command_upload_ftds.sh"); const response = runCliScript(shellScript, TEST_ENVIRONMENT, ["localFileThatDoesNotExist", "data.set.name"]); - expect(stripNewLines(response.stderr.toString())).toContain("no such file or directory, lstat"); + expect(stripNewLines(response.stderr.toString())).toContain("File does not exist or is not accessible"); expect(stripNewLines(response.stderr.toString())).toContain("localFileThatDoesNotExist"); }); diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts index aba9173262..31ff242c42 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/DirToPds.handler.unit.test.ts @@ -11,16 +11,19 @@ import { Upload } from "@zowe/zos-files-for-zowe-sdk"; import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; - +import DirToPdsHandler from "../../../../../src/zosfiles/upload/dtp/DirToPds.handler"; describe("Upload dir-to-pds handler", () => { describe("process method", () => { - it("should upload a directory to a PDS if requested", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/dtp/DirToPds.handler"); - const handler = new handlerReq.default(); - const inputdir = "test-dir"; - const dataSetName = "testing"; + let handler: DirToPdsHandler; + const inputdir = "test-dir"; + const dataSetName = "testing"; + beforeEach(() => { + jest.resetAllMocks(); + handler = new DirToPdsHandler(); + (handler as any).checkDirectoryExistence = jest.fn().mockResolvedValue(undefined); + }); + it("should upload a directory to a PDS if requested", async () => { // Vars populated by the mocked function let error; let apiMessage = ""; @@ -94,12 +97,63 @@ describe("Upload dir-to-pds handler", () => { expect(logMessage).toMatchSnapshot(); }); + it("should not attempt to upload a dir that hasn't been found", async () => { + (handler as any).checkDirectoryExistence = jest.fn().mockRejectedValue(new Error("Failed to access directory")); + // Vars populated by the mocked function + let error; + let apiMessage = ""; + let jsonObj; + let logMessage = ""; + + // Mock the submit JCL function + Upload.dirToPds = jest.fn(); + + try { + // Invoke the handler with a full set of mocked arguments and response functions + await handler.process({ + arguments: { + $0: "fake", + _: ["fake"], + inputdir, + dataSetName, + ...UNIT_TEST_ZOSMF_PROF_OPTS + }, + response: { + data: { + setMessage: jest.fn((setMsgArgs) => { + apiMessage = setMsgArgs; + }), + setObj: jest.fn((setObjArgs) => { + jsonObj = setObjArgs; + }) + }, + console: { + log: jest.fn((logArgs) => { + logMessage += "\n" + logArgs; + }), + error: jest.fn((logArgs) => { + logMessage += "\n" + logArgs; + }) + }, + progress: { + startBar: jest.fn(), + endBar: jest.fn() + } + } + } as any); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toContain("Failed to access directory"); + expect(Upload.dirToPds).toHaveBeenCalledTimes(0); + expect(jsonObj).toMatchSnapshot(); + expect(apiMessage).toMatchSnapshot(); + expect(logMessage).toMatchSnapshot(); + }); + it("should upload a directory to a PDS in binary format if requested", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/dtp/DirToPds.handler"); - const handler = new handlerReq.default(); - const inputdir = "test-dir"; - const dataSetName = "testing"; const binary = true; // Vars populated by the mocked function @@ -178,11 +232,6 @@ describe("Upload dir-to-pds handler", () => { }); it("should upload a directory to a PDS in record format if requested", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/dtp/DirToPds.handler"); - const handler = new handlerReq.default(); - const inputdir = "test-dir"; - const dataSetName = "testing"; const record = true; // Vars populated by the mocked function diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/__snapshots__/DirToPds.handler.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/__snapshots__/DirToPds.handler.unit.test.ts.snap index cde03d8fc2..b751b6f0fc 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/__snapshots__/DirToPds.handler.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/dtp/__snapshots__/DirToPds.handler.unit.test.ts.snap @@ -1,40 +1,103 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Upload dir-to-pds handler process method should upload a directory to a PDS if requested 1`] = `undefined`; +exports[`Upload dir-to-pds handler process method should not attempt to upload a dir that hasn't been found 1`] = `undefined`; -exports[`Upload dir-to-pds handler process method should upload a directory to a PDS if requested 2`] = `""`; +exports[`Upload dir-to-pds handler process method should not attempt to upload a dir that hasn't been found 2`] = `""`; -exports[`Upload dir-to-pds handler process method should upload a directory to a PDS if requested 3`] = ` +exports[`Upload dir-to-pds handler process method should not attempt to upload a dir that hasn't been found 3`] = ` " -success: true -from:  test-dir -to:  testing +Error: Failed to access directory" +`; + +exports[`Upload dir-to-pds handler process method should upload a directory to a PDS if requested 1`] = ` +Object { + "apiResponse": Array [ + Object { + "from": "test-dir", + "success": true, + "to": "testing", + }, + Object { + "from": "testfrom", + "success": false, + "to": "testto", + }, + Object { + "from": "dummy", + "success": undefined, + "to": "nowhere", + }, + ], + "commandResponse": "uploaded", + "success": false, +} +`; + +exports[`Upload dir-to-pds handler process method should upload a directory to a PDS if requested 2`] = `""`; +exports[`Upload dir-to-pds handler process method should upload a directory to a PDS if requested 3`] = ` " +uploaded" `; -exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in binary format if requested 1`] = `undefined`; +exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in binary format if requested 1`] = ` +Object { + "apiResponse": Array [ + Object { + "from": "test-dir", + "success": true, + "to": "testing", + }, + Object { + "from": "testfrom", + "success": false, + "to": "testto", + }, + Object { + "from": "dummy", + "success": undefined, + "to": "nowhere", + }, + ], + "commandResponse": "uploaded", + "success": false, +} +`; exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in binary format if requested 2`] = `""`; exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in binary format if requested 3`] = ` " -success: true -from:  test-dir -to:  testing - -" +uploaded" `; -exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in record format if requested 1`] = `undefined`; +exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in record format if requested 1`] = ` +Object { + "apiResponse": Array [ + Object { + "from": "test-dir", + "success": true, + "to": "testing", + }, + Object { + "from": "testfrom", + "success": false, + "to": "testto", + }, + Object { + "from": "dummy", + "success": undefined, + "to": "nowhere", + }, + ], + "commandResponse": "uploaded", + "success": false, +} +`; exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in record format if requested 2`] = `""`; exports[`Upload dir-to-pds handler process method should upload a directory to a PDS in record format if requested 3`] = ` " -success: true -from:  test-dir -to:  testing - -" +uploaded" `; diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts b/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts index cddbc54373..0c7d993f07 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/FileToDataSet.handler.unit.test.ts @@ -11,16 +11,19 @@ import { Upload } from "@zowe/zos-files-for-zowe-sdk"; import { UNIT_TEST_ZOSMF_PROF_OPTS } from "../../../../../../../__tests__/__src__/mocks/ZosmfProfileMock"; +import FileToDataSet from "../../../../../src/zosfiles/upload/ftds/FileToDataSet.handler"; describe("Upload file-to-data-set handler", () => { describe("process method", () => { + let handler: FileToDataSet; + const inputfile = "test-file"; + const dataSetName = "testing"; + beforeEach(() => { + jest.resetAllMocks(); + handler = new FileToDataSet(); + (handler as any).checkFileExistence = jest.fn().mockResolvedValue(undefined); + }); it("should upload a file to a data set if requested", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/ftds/FileToDataSet.handler"); - const handler = new handlerReq.default(); - const inputfile = "test-file"; - const dataSetName = "testing"; - // Vars populated by the mocked function let error; let apiMessage = ""; @@ -35,7 +38,9 @@ describe("Upload file-to-data-set handler", () => { success: true, commandResponse: "uploaded", apiResponse: [ - {success: true, from: inputfile, to: dataSetName} + {success: true, from: inputfile, to: dataSetName}, + {success: false, from: "testfrom", to: "testto"}, + {success: undefined, from: "dummy", to: "nowhere"} ] }; }); @@ -93,11 +98,6 @@ describe("Upload file-to-data-set handler", () => { }); it("should upload a file to a data set in binary format if requested", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/ftds/FileToDataSet.handler"); - const handler = new handlerReq.default(); - const inputfile = "test-file"; - const dataSetName = "testing"; const binary = true; // Vars populated by the mocked function @@ -174,11 +174,6 @@ describe("Upload file-to-data-set handler", () => { }); it("should upload a file to a data set in record format if requested", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/ftds/FileToDataSet.handler"); - const handler = new handlerReq.default(); - const inputfile = "test-file"; - const dataSetName = "testing"; const record = true; // Vars populated by the mocked function @@ -254,13 +249,7 @@ describe("Upload file-to-data-set handler", () => { expect(logMessage).toMatchSnapshot(); }); - it("should display error when upload file to data set", async () => { - // Require the handler and create a new instance - const handlerReq = require("../../../../../src/zosfiles/upload/ftds/FileToDataSet.handler"); - const handler = new handlerReq.default(); - const inputfile = "test-file"; - const dataSetName = "testing"; - + it("should display error when uploading found file to data set", async () => { // Vars populated by the mocked function let error; let apiMessage = ""; @@ -331,13 +320,63 @@ describe("Upload file-to-data-set handler", () => { }); expect(jsonObj).toMatchSnapshot(); expect(apiMessage).toMatchSnapshot(); - expect(logMessage).toMatch(/success:.*false/); - expect(logMessage).toMatch(/from:.*test-file/); - expect(logMessage).toMatch(/file_to_upload:.*1/); - expect(logMessage).toMatch(/success:.*0/); - expect(logMessage).toMatch(/error:.*1/); - expect(logMessage).toMatch(/skipped:.*0/); - expect(logMessage).toMatch(/uploaded/); + expect(logMessage).toMatchSnapshot(); + }); + + it("should not attempt to upload a file that hasn't been found", async () => { + (handler as any).checkFileExistence = jest.fn().mockRejectedValue(new Error("File does not exist or is not accessible")); + // Vars populated by the mocked function + let error; + let apiMessage = ""; + let jsonObj; + let logMessage = ""; + + // Mock the submit JCL function + Upload.fileToDataset = jest.fn(); + + try { + // Invoke the handler with a full set of mocked arguments and response functions + await handler.process({ + arguments: { + $0: "fake", + _: ["fake"], + inputfile, + dataSetName, + ...UNIT_TEST_ZOSMF_PROF_OPTS + }, + response: { + data: { + setMessage: jest.fn((setMsgArgs) => { + apiMessage = setMsgArgs; + }), + setObj: jest.fn((setObjArgs) => { + jsonObj = setObjArgs; + }) + }, + console: { + log: jest.fn((logArgs) => { + logMessage += "\n" + logArgs; + }), + error: jest.fn((logArgs) => { + logMessage += "\n" + logArgs; + }) + }, + progress: { + startBar: jest.fn(), + endBar: jest.fn() + } + } + } as any); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toContain("File does not exist or is not accessible"); + expect(Upload.fileToDataset).toHaveBeenCalledTimes(0); + expect(jsonObj).toMatchSnapshot(); + expect(apiMessage).toMatchSnapshot(); + expect(logMessage).toMatchSnapshot(); }); }); }); diff --git a/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/__snapshots__/FileToDataSet.handler.unit.test.ts.snap b/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/__snapshots__/FileToDataSet.handler.unit.test.ts.snap index 1cd2b1490a..9aaa562c54 100644 --- a/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/__snapshots__/FileToDataSet.handler.unit.test.ts.snap +++ b/packages/cli/__tests__/zosfiles/__unit__/upload/ftds/__snapshots__/FileToDataSet.handler.unit.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Upload file-to-data-set handler process method should display error when upload file to data set 1`] = ` +exports[`Upload file-to-data-set handler process method should display error when uploading found file to data set 1`] = ` Object { "apiResponse": Array [ Object { @@ -14,7 +14,21 @@ Object { } `; -exports[`Upload file-to-data-set handler process method should display error when upload file to data set 2`] = `""`; +exports[`Upload file-to-data-set handler process method should display error when uploading found file to data set 2`] = `""`; + +exports[`Upload file-to-data-set handler process method should display error when uploading found file to data set 3`] = ` +" +uploaded" +`; + +exports[`Upload file-to-data-set handler process method should not attempt to upload a file that hasn't been found 1`] = `undefined`; + +exports[`Upload file-to-data-set handler process method should not attempt to upload a file that hasn't been found 2`] = `""`; + +exports[`Upload file-to-data-set handler process method should not attempt to upload a file that hasn't been found 3`] = ` +" +Error: File does not exist or is not accessible" +`; exports[`Upload file-to-data-set handler process method should upload a file to a data set if requested 1`] = ` Object { @@ -24,6 +38,16 @@ Object { "success": true, "to": "testing", }, + Object { + "from": "testfrom", + "success": false, + "to": "testto", + }, + Object { + "from": "dummy", + "success": undefined, + "to": "nowhere", + }, ], "commandResponse": "uploaded", "success": true, @@ -34,17 +58,6 @@ exports[`Upload file-to-data-set handler process method should upload a file to exports[`Upload file-to-data-set handler process method should upload a file to a data set if requested 3`] = ` " -success: true -from:  test-file -to:  testing - - -file_to_upload: 1 -success:  1 -error:  0 -skipped:  0 - - uploaded" `; @@ -66,17 +79,6 @@ exports[`Upload file-to-data-set handler process method should upload a file to exports[`Upload file-to-data-set handler process method should upload a file to a data set in binary format if requested 3`] = ` " -success: true -from:  test-file -to:  testing - - -file_to_upload: 1 -success:  1 -error:  0 -skipped:  0 - - uploaded" `; @@ -98,16 +100,5 @@ exports[`Upload file-to-data-set handler process method should upload a file to exports[`Upload file-to-data-set handler process method should upload a file to a data set in record format if requested 3`] = ` " -success: true -from:  test-file -to:  testing - - -file_to_upload: 1 -success:  1 -error:  0 -skipped:  0 - - uploaded" `; diff --git a/packages/cli/src/zosfiles/upload/dtp/DirToPds.handler.ts b/packages/cli/src/zosfiles/upload/dtp/DirToPds.handler.ts index 48297f63d1..f3b2a43e3d 100644 --- a/packages/cli/src/zosfiles/upload/dtp/DirToPds.handler.ts +++ b/packages/cli/src/zosfiles/upload/dtp/DirToPds.handler.ts @@ -1,73 +1,69 @@ -/* -* This program and the accompanying materials are made available under the terms of the -* Eclipse Public License v2.0 which accompanies this distribution, and is available at -* https://www.eclipse.org/legal/epl-v20.html -* -* SPDX-License-Identifier: EPL-2.0 -* -* Copyright Contributors to the Zowe Project. -* -*/ - -import { AbstractSession, IHandlerParameters, ITaskWithStatus, TaskStage, TextUtils } from "@zowe/imperative"; -import { IZosFilesResponse, Upload, IUploadResult } from "@zowe/zos-files-for-zowe-sdk"; +import { AbstractSession, IHandlerParameters, ITaskWithStatus, TaskStage } from "@zowe/imperative"; +import { IZosFilesResponse, Upload } from "@zowe/zos-files-for-zowe-sdk"; import { ZosFilesBaseHandler } from "../../ZosFilesBase.handler"; +import { promises as fs } from 'fs'; /** * Handler to upload content of a directory to a PDS * @export + * */ export default class DirToPdsHandler extends ZosFilesBaseHandler { public async processWithSession(commandParameters: IHandlerParameters, session: AbstractSession): Promise { + const inputDir = commandParameters.arguments.inputdir; + const dataSetName = commandParameters.arguments.dataSetName; const status: ITaskWithStatus = { statusMessage: "Uploading directory to PDS", percentComplete: 0, stageName: TaskStage.IN_PROGRESS }; - commandParameters.response.progress.startBar({task: status}); - const response = await Upload.dirToPds( - session, - commandParameters.arguments.inputdir, - commandParameters.arguments.dataSetName, - { - volume: commandParameters.arguments.volumeSerial, - binary: commandParameters.arguments.binary, - record: commandParameters.arguments.record, - encoding: commandParameters.arguments.encoding, - task: status, - responseTimeout: commandParameters.arguments.responseTimeout - } - ); - if (response.apiResponse) { - let skipCount: number = 0; - let successCount: number = 0; - let errorCount: number = 0; - response.apiResponse.forEach((element: IUploadResult) => { - if (element.success === true) { - const formatMessage = TextUtils.prettyJson(element); - commandParameters.response.console.log(formatMessage); - successCount++; - } else if (element.success === false) { + try { + // Check directory existence and accessibility + await this.checkDirectoryExistence(inputDir); - const formatMessage = TextUtils.prettyJson(element); - commandParameters.response.console.error(TextUtils.chalk.red(formatMessage)); - errorCount++; - } else { - skipCount++; - } - }); + status.statusMessage = "Uploading directory to PDS"; + commandParameters.response.progress.startBar({task: status}); - commandParameters.response.console.log(TextUtils.prettyJson({ - file_to_upload: response.apiResponse.length, - success: successCount, - error: errorCount, - skipped: skipCount - })); + const response = await Upload.dirToPds( + session, + inputDir, + dataSetName, + { + volume: commandParameters.arguments.volumeSerial, + binary: commandParameters.arguments.binary, + record: commandParameters.arguments.record, + encoding: commandParameters.arguments.encoding, + task: status, + responseTimeout: commandParameters.arguments.responseTimeout + } + ); + return response; + } catch (error) { + // Handle errors from directory check or upload + status.statusMessage = "Error during upload"; + commandParameters.response.console.error(`Error: ${error.message}`); + throw new Error(error.message); + } finally { + commandParameters.response.progress.endBar(); } + } - return response; + /** + * Checks if the specified directory exists and is accessible + * @param directoryPath - Path to the directory to check + * @returns Promise + */ + private async checkDirectoryExistence(directoryPath: string): Promise { + try { + const dirStats = await fs.stat(directoryPath); + if (!dirStats.isDirectory()) { + throw new Error(`${directoryPath} is not a directory.`); + } + } catch (error) { + throw new Error(`Failed to access directory: ${error.message}`); + } } } diff --git a/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.handler.ts b/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.handler.ts index 0a590f76eb..89f9f7c510 100644 --- a/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.handler.ts +++ b/packages/cli/src/zosfiles/upload/ftds/FileToDataSet.handler.ts @@ -9,9 +9,10 @@ * */ -import { AbstractSession, IHandlerParameters, ITaskWithStatus, TaskStage, TextUtils } from "@zowe/imperative"; -import { IZosFilesResponse, Upload, IUploadResult } from "@zowe/zos-files-for-zowe-sdk"; +import { AbstractSession, IHandlerParameters, ITaskWithStatus, TaskStage } from "@zowe/imperative"; +import { IZosFilesResponse, Upload } from "@zowe/zos-files-for-zowe-sdk"; import { ZosFilesBaseHandler } from "../../ZosFilesBase.handler"; +import { promises as fs } from 'fs'; /** * Handler to upload content from a file to a data set @@ -21,50 +22,55 @@ export default class FileToDataSetHandler extends ZosFilesBaseHandler { public async processWithSession(commandParameters: IHandlerParameters, session: AbstractSession): Promise { - const task: ITaskWithStatus = { - percentComplete: 0, + const inputFile = commandParameters.arguments.inputfile; + const dataSetName = commandParameters.arguments.dataSetName; + const status: ITaskWithStatus = { statusMessage: "Uploading to data set", + percentComplete: 0, stageName: TaskStage.IN_PROGRESS }; - commandParameters.response.progress.startBar({task}); - const response = await Upload.fileToDataset(session, commandParameters.arguments.inputfile, - commandParameters.arguments.dataSetName, - { - volume: commandParameters.arguments.volumeSerial, - binary: commandParameters.arguments.binary, - record: commandParameters.arguments.record, - encoding: commandParameters.arguments.encoding, - task, - responseTimeout: commandParameters.arguments.responseTimeout - }); - if (response.apiResponse) { - let skipCount: number = 0; - let successCount: number = 0; - let errorCount: number = 0; - response.apiResponse.forEach((element: IUploadResult) => { - if (element.success === true) { - const formatMessage = TextUtils.prettyJson(element); - commandParameters.response.console.log(formatMessage); - successCount++; - } else if (element.success === false) { + try { + // Check for file's existence and accessibility + await this.checkFileExistence(inputFile); - const formatMessage = TextUtils.prettyJson(element); - commandParameters.response.console.error(TextUtils.chalk.red(formatMessage)); - errorCount++; - } else { - skipCount++; - } - }); + commandParameters.response.progress.startBar({task: status}); - commandParameters.response.console.log(TextUtils.prettyJson({ - file_to_upload: response.apiResponse.length, - success: successCount, - error: errorCount, - skipped: skipCount - })); + const response = await Upload.fileToDataset( + session, + inputFile, + dataSetName, + { + volume: commandParameters.arguments.volumeSerial, + binary: commandParameters.arguments.binary, + record: commandParameters.arguments.record, + encoding: commandParameters.arguments.encoding, + task: status, + responseTimeout: commandParameters.arguments.responseTimeout + } + ); + return response; + } catch (error) { + // Handle errors from directory check or upload + status.statusMessage = "Error during upload"; + commandParameters.response.console.error(`Error: ${error.message}`); + throw new Error(error.message); + } finally { + // Clean up + commandParameters.response.progress.endBar(); } + } - return response; + /** + * Checks if the specified file exists and is accessible + * @param filePath - Path to the file to check + * @returns Promise + */ + private async checkFileExistence(filePath: string): Promise { + try { + await fs.access(filePath, fs.constants.F_OK | fs.constants.R_OK); + } catch (error) { + throw new Error(`File does not exist or is not accessible: ${filePath}`); + } } -} +} \ No newline at end of file