UNPKG

@zowe/cli

Version:

Zowe CLI is a command line interface (CLI) that provides a simple and streamlined way to interact with IBM z/OS.

816 lines 42.3 kB
"use strict"; /* * 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. * */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const imperative_1 = require("@zowe/imperative"); const fs = require("fs"); const path = require("path"); const rest_1 = require("../../../../../rest"); const ZosFiles_constants_1 = require("../../constants/ZosFiles.constants"); const ZosFiles_messages_1 = require("../../constants/ZosFiles.messages"); const ZosFilesUtils_1 = require("../../utils/ZosFilesUtils"); const list_1 = require("../list"); const create_1 = require("../create"); const utils_1 = require("../../../../../utils"); const ZosFilesAttributes_1 = require("../../utils/ZosFilesAttributes"); const utilities_1 = require("../utilities"); class Upload { /** * Upload content from file to data set * @param {AbstractSession} session - z/OS connection info * @param {string} inputFile - path to a file * @param {string} dataSetName - Name of the data set to write to * @param {IUploadOptions} [options={}] - Uploading options * * @return {Promise<IZosFilesResponse>} A response indicating the out come * * @throws {ImperativeError} When encounter error scenarios. * */ static fileToDataset(session, inputFile, dataSetName, options = {}) { return __awaiter(this, void 0, void 0, function* () { this.log.info(`Uploading file ${inputFile} to ${dataSetName}`); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(inputFile, ZosFiles_messages_1.ZosFilesMessages.missingInputFile.message); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(dataSetName, ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); imperative_1.ImperativeExpect.toNotBeEqual(dataSetName, "", ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); const promise = new Promise((resolve, reject) => { fs.lstat(inputFile, (err, stats) => { if (err == null && stats.isFile()) { resolve(true); } else if (err == null) { reject(new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.missingInputFile.message })); } else { reject(new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.nodeJsFsError.message, additionalDetails: err.toString(), causeErrors: err })); } }); }); yield promise; return this.pathToDataSet(session, inputFile, dataSetName, options); }); } /** * Upload content from a directory to a PDS * @param {AbstractSession} session - z/OS connection info * @param {string} inputDir - path to a file * @param {string} dataSetName - Name of the data set to write to * @param {IUploadOptions} [options={}] - Uploading options * * @return {Promise<IZosFilesResponse>} A response indicating the out come * * @throws {ImperativeError} When encounter error scenarios. * */ static dirToPds(session, inputDir, dataSetName, options = {}) { return __awaiter(this, void 0, void 0, function* () { this.log.info(`Uploading directory ${inputDir} to ${dataSetName}`); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(inputDir, ZosFiles_messages_1.ZosFilesMessages.missingInputDir.message); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(dataSetName, ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); imperative_1.ImperativeExpect.toNotBeEqual(dataSetName, "", ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); const promise = new Promise((resolve, reject) => { fs.lstat(inputDir, (err, stats) => { if (err == null && !stats.isFile()) { resolve(true); } else if (err == null) { reject(new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.pathIsNotDirectory.message })); } else { reject(new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.nodeJsFsError.message, additionalDetails: err.toString(), causeErrors: err })); } }); }); yield promise; if (!imperative_1.IO.isDir(inputDir)) { throw new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.missingInputDir.message }); } return this.pathToDataSet(session, inputDir, dataSetName, options); }); } /** * Writting data buffer to a data set. * @param {AbstractSession} session - z/OS connection info * @param {Buffer} fileBuffer - Data buffer to be written * @param {string} dataSetName - Name of the data set to write to * @param {IUploadOptions} [options={}] - Uploading options * * @return {Promise<IZosFilesResponse>} A response indicating the out come * * @throws {ImperativeError} When encounter error scenarios. */ static bufferToDataSet(session, fileBuffer, dataSetName, options = {}) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(dataSetName, ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); try { // Construct zOSMF REST endpoint. let endpoint = path.posix.join(ZosFiles_constants_1.ZosFilesConstants.RESOURCE, ZosFiles_constants_1.ZosFilesConstants.RES_DS_FILES); if (options.volume) { endpoint = path.posix.join(endpoint, `-(${options.volume})`); } endpoint = path.posix.join(endpoint, dataSetName); // Construct request header parameters const reqHeader = []; if (options.binary) { reqHeader.push(rest_1.ZosmfHeaders.X_IBM_BINARY); } else { reqHeader.push(rest_1.ZosmfHeaders.X_IBM_TEXT); fileBuffer = ZosFilesUtils_1.ZosFilesUtils.normalizeNewline(fileBuffer); } // Migrated recall options if (options.recall) { switch (options.recall.toLowerCase()) { case "wait": reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_WAIT); break; case "nowait": reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_NO_WAIT); break; case "error": reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_ERROR); break; default: reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_NO_WAIT); break; } } yield rest_1.ZosmfRestClient.putExpectString(session, endpoint, reqHeader, fileBuffer); return { success: true, commandResponse: ZosFiles_messages_1.ZosFilesMessages.dataSetUploadedSuccessfully.message }; } catch (error) { throw error; } }); } /** * Writting data buffer to a data set. * @param {AbstractSession} session - z/OS connection info * @param {Buffer} fileBuffer - Data buffer to be written * @param {string} dataSetName - Name of the data set to write to * @param {IUploadOptions} [options={}] - Uploading options * * @return {Promise<IZosFilesResponse>} A response indicating the out come * * @throws {ImperativeError} When encounter error scenarios. */ static streamToDataSet(session, fileStream, dataSetName, options = {}) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(dataSetName, ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); try { // Construct zOSMF REST endpoint. let endpoint = path.posix.join(ZosFiles_constants_1.ZosFilesConstants.RESOURCE, ZosFiles_constants_1.ZosFilesConstants.RES_DS_FILES); if (options.volume) { endpoint = path.posix.join(endpoint, `-(${options.volume})`); } endpoint = path.posix.join(endpoint, dataSetName); // Construct request header parameters const reqHeader = []; if (options.binary) { reqHeader.push(rest_1.ZosmfHeaders.X_IBM_BINARY); } else { reqHeader.push(rest_1.ZosmfHeaders.X_IBM_TEXT); } // Migrated recall options if (options.recall) { switch (options.recall.toLowerCase()) { case "wait": reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_WAIT); break; case "nowait": reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_NO_WAIT); break; case "error": reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_ERROR); break; default: reqHeader.push(rest_1.ZosmfHeaders.X_IBM_MIGRATED_RECALL_NO_WAIT); break; } } yield rest_1.ZosmfRestClient.putStreamedRequestOnly(session, endpoint, reqHeader, fileStream, !options.binary /* only normalize newlines if we are not uploading in binary*/, options.task); return { success: true, commandResponse: ZosFiles_messages_1.ZosFilesMessages.dataSetUploadedSuccessfully.message }; } catch (error) { throw error; } }); } /** * Upload content from input path to dataSet or PDS members * @param {AbstractSession} session - z/OS connection info * @param {string} inputPath - User input path to file or directory * @param {string} dataSetName - Name of the data set to write to * @param {IUploadOptions} [options={}] - Uploading options * * @param task - use this to be updated on the current status of the upload operation * @return {Promise<IZosFilesResponse>} A response indicating the out come * * @throws {ImperativeError} When encounter error scenarios. * * @example pathToDataSet(session, "file.txt", "ps.name") * @example pathToDataset(session, "file.txt", "psd.name(member)") * @example pathToDataSet(session, "directory", "pds.name") * @example pathToDataset(session, "/full/path/file.txt", "ps.name") * * Note: * This method does everything needed to do from checking if path is file or directory * and if data set is sequential file or PDS to determind what name to be used when * upload content to data set. All you have to specify is a directory and a dsname. */ static pathToDataSet(session, inputPath, dataSetName, options = {}) { return __awaiter(this, void 0, void 0, function* () { this.log.info(`Uploading path ${inputPath} to ${dataSetName}`); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(dataSetName, ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); imperative_1.ImperativeExpect.toNotBeEqual(dataSetName, "", ZosFiles_messages_1.ZosFilesMessages.missingDatasetName.message); let memberName = ""; let uploadingFile = ""; let uploadingDsn = ""; let uploadFileList; let isUploadToPds = false; const results = []; // Check and make sure that data set name does not contain any masking character (%*). if (ZosFilesUtils_1.ZosFilesUtils.isDataSetNameContainMasking(dataSetName)) { throw new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.unsupportedMaskingInDataSetName.message }); } // From the input path, retrieve the list of all files that we are trying to upload. // If input is a file, the return is an array of 1 element, // If input is a directory, the return will be an array of all of it files. uploadFileList = ZosFilesUtils_1.ZosFilesUtils.getFileListFromPath(inputPath); // Check if data set name is actually a PDS member. // if it is, then we have to make sure that we do not try to upload a directory // to a PDS member. if (dataSetName.endsWith(")")) { if (imperative_1.IO.isDir(inputPath)) { throw new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.uploadDirectoryToDatasetMember.message }); } memberName = dataSetName.substr(dataSetName.indexOf("(")).replace(/[()]/g, ""); dataSetName = dataSetName.substr(0, dataSetName.indexOf("(")); } // Retrieve the information on the input data set name to determine if it is a // sequential data set or PDS. const listResponse = yield list_1.List.dataSet(session, dataSetName, { attributes: true, maxLength: 1, start: dataSetName, recall: "wait" }); if (listResponse.apiResponse != null && listResponse.apiResponse.returnedRows != null && listResponse.apiResponse.items != null) { // Look for the index of the data set in the response from the List API const dsnameIndex = listResponse.apiResponse.returnedRows === 0 ? -1 : listResponse.apiResponse.items.findIndex((ds) => ds.dsname.toUpperCase() === dataSetName.toUpperCase()); if (dsnameIndex !== -1) { // If dsnameIndex === -1, it means we could not find the given data set. // We will attempt the upload anyways so that we can forward/throw the proper error from z/OS MF const dsInfo = listResponse.apiResponse.items[dsnameIndex]; switch (dsInfo.dsorg) { case "PO": case "PO-E": isUploadToPds = true; break; default: // if loading to a physical sequential data set and multiple files found then error if (uploadFileList.length > 1) { throw new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.uploadDirectoryToPhysicalSequentialDataSet.message }); } break; } } } // Loop through the array of upload file and perform upload one file at a time. // The reason we can not perform this task in parallel is because the Enqueueing on a PDS. It will // result will random errors when trying to upload to multiple member of the same PDS at the same time. // This also allow us to break out as soon as the first error is encounter instead of wait until the // entire list is processed. try { let uploadError; let uploadsInitiated = 0; for (const file of uploadFileList) { uploadingFile = file; uploadingDsn = dataSetName; if (isUploadToPds) { if (memberName.length === 0) { uploadingDsn = `${uploadingDsn}(${ZosFilesUtils_1.ZosFilesUtils.generateMemberName(uploadingFile)})`; } else { uploadingDsn = `${uploadingDsn}(${memberName})`; } } uploadingDsn = uploadingDsn.toUpperCase(); if (options.task != null) { // update the progress bar if any const LAST_FIFTEEN_CHARS = -15; const abbreviatedFile = uploadingFile.slice(LAST_FIFTEEN_CHARS); options.task.statusMessage = "Uploading ..." + abbreviatedFile; options.task.percentComplete = Math.floor(imperative_1.TaskProgress.ONE_HUNDRED_PERCENT * (uploadsInitiated / uploadFileList.length)); uploadsInitiated++; } if (uploadError === undefined) { try { // read payload from file const uploadStream = imperative_1.IO.createReadStream(uploadingFile); const streamUploadOptions = JSON.parse(JSON.stringify(options)); // copy the options if (uploadFileList.length > 1) { // don't update the progress bar in the streamToDataSet function if we // are uploading more than one file because we already update it with the member name delete streamUploadOptions.task; } const result = yield this.streamToDataSet(session, uploadStream, uploadingDsn, streamUploadOptions); this.log.info(`Success Uploaded data From ${uploadingFile} To ${uploadingDsn}`); results.push({ success: result.success, from: uploadingFile, to: uploadingDsn }); } catch (err) { this.log.error(`Failure Uploading data From ${uploadingFile} To ${uploadingDsn}`); results.push({ success: false, from: uploadingFile, to: uploadingDsn, error: err }); uploadError = err; } } else { results.push({ success: undefined, from: uploadingFile, to: uploadingDsn, }); } } if (uploadError) { throw uploadError; } return { success: true, commandResponse: ZosFiles_messages_1.ZosFilesMessages.dataSetUploadedSuccessfully.message, apiResponse: results }; } catch (error) { return { success: false, commandResponse: error.message, apiResponse: results }; } }); } /** * Upload content to USS file * @param {AbstractSession} session - z/OS connection info * @param {string} ussname - Name of the USS file to write to * @param {Buffer} buffer - Data to be written * @param {boolean} binary - The indicator to upload the file in binary mode * @returns {Promise<object>} */ static bufferToUSSFile(session, ussname, buffer, binary = false, localEncoding) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFiles_messages_1.ZosFilesMessages.missingUSSFileName.message); ussname = ZosFilesUtils_1.ZosFilesUtils.sanitizeUssPathForRestCall(ussname); const parameters = ZosFiles_constants_1.ZosFilesConstants.RES_USS_FILES + "/" + ussname; const headers = []; if (binary) { headers.push(rest_1.ZosmfHeaders.OCTET_STREAM); headers.push(rest_1.ZosmfHeaders.X_IBM_BINARY); } else if (localEncoding) { headers.push({ "Content-Type": localEncoding }); headers.push(rest_1.ZosmfHeaders.X_IBM_TEXT); } else { headers.push(rest_1.ZosmfHeaders.TEXT_PLAIN); } return rest_1.ZosmfRestClient.putExpectString(session, ZosFiles_constants_1.ZosFilesConstants.RESOURCE + parameters, headers, buffer); }); } /** * Upload content to USS file * @param {AbstractSession} session - z/OS connection info * @param {string} ussname - Name of the USS file to write to * @param {Buffer} uploadStream - Data to be written * @param {boolean} binary - The indicator to upload the file in binary mode * @returns {Promise<object>} */ static streamToUSSFile(session, ussname, uploadStream, binary = false, localEncoding, task) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFiles_messages_1.ZosFilesMessages.missingUSSFileName.message); ussname = path.posix.normalize(ussname); ussname = ZosFilesUtils_1.ZosFilesUtils.formatUnixFilepath(ussname); ussname = encodeURIComponent(ussname); const parameters = ZosFiles_constants_1.ZosFilesConstants.RES_USS_FILES + "/" + ussname; const headers = []; if (binary) { headers.push(rest_1.ZosmfHeaders.OCTET_STREAM); headers.push(rest_1.ZosmfHeaders.X_IBM_BINARY); } else if (localEncoding) { headers.push({ "Content-Type": localEncoding }); headers.push(rest_1.ZosmfHeaders.X_IBM_TEXT); } else { headers.push(rest_1.ZosmfHeaders.TEXT_PLAIN); } yield rest_1.ZosmfRestClient.putStreamedRequestOnly(session, ZosFiles_constants_1.ZosFilesConstants.RESOURCE + parameters, headers, uploadStream, !binary /* only normalize newlines if we are not in binary mode*/, task); }); } static fileToUSSFile(session, inputFile, ussname, binary = false, localEncoding, task) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(inputFile, ZosFiles_messages_1.ZosFilesMessages.missingInputFile.message); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFiles_messages_1.ZosFilesMessages.missingUSSFileName.message); imperative_1.ImperativeExpect.toNotBeEqual(ussname, "", ZosFiles_messages_1.ZosFilesMessages.missingUSSFileName.message); const promise = new Promise((resolve, reject) => { fs.lstat(inputFile, (err, stats) => { if (err == null && stats.isFile()) { resolve(true); } else if (err == null) { reject(new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.missingInputFile.message })); } else { reject(new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.nodeJsFsError.message, additionalDetails: err.toString(), causeErrors: err })); } }); }); yield promise; let result; // read payload from file const uploadStream = imperative_1.IO.createReadStream(inputFile); yield this.streamToUSSFile(session, ussname, uploadStream, binary, localEncoding, task); result = { success: true, from: inputFile, to: ussname }; return { success: true, commandResponse: ZosFiles_messages_1.ZosFilesMessages.ussFileUploadedSuccessfully.message, apiResponse: result }; }); } /** * Upload local directory to USS directory * @param {AbstractSession} session - z/OS connection info * @param {string} inputDirectory - the path of local directory * @param {string} ussname - the name of uss folder * @param {IUploadOptions} [options={}] - Uploading options * @returns {Promise<IZosFilesResponse>} */ static dirToUSSDir(session, inputDirectory, ussname, options = {}) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(inputDirectory, ZosFiles_messages_1.ZosFilesMessages.missingInputDirectory.message); imperative_1.ImperativeExpect.toNotBeEqual(inputDirectory, "", ZosFiles_messages_1.ZosFilesMessages.missingInputDirectory.message); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFiles_messages_1.ZosFilesMessages.missingUSSDirectoryName.message); imperative_1.ImperativeExpect.toNotBeEqual(ussname, "", ZosFiles_messages_1.ZosFilesMessages.missingUSSDirectoryName.message); // Set default values for options options.binary = options.binary == null ? false : options.binary; options.recursive = options.recursive == null ? false : options.recursive; const maxConcurrentRequests = options.maxConcurrentRequests == null ? 1 : options.maxConcurrentRequests; try { // Check if inputDirectory is directory if (!imperative_1.IO.isDir(inputDirectory)) { throw new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.missingInputDirectory.message }); } // Check if provided unix directory exists const isDirectoryExist = yield this.isDirectoryExist(session, ussname); if (!isDirectoryExist) { yield create_1.Create.uss(session, ussname, "directory"); } // initialize array for the files to be uploaded const filesArray = []; // getting list of files from directory const files = ZosFilesUtils_1.ZosFilesUtils.getFileListFromPath(inputDirectory, false); // building list of files with full path and transfer mode files.forEach((file) => { let tempBinary = options.binary; // check if filesMap is specified, and verify if file is in the list if (options.filesMap) { if (options.filesMap.fileNames.indexOf(file) > -1) { // if file is in list, assign binary mode from mapping tempBinary = options.filesMap.binary; } } // update the array filesArray.push({ binary: tempBinary, fileName: file }); }); let uploadsInitiated = 0; const createFileUploadPromise = (file) => { // update the progress bar if any if (options.task != null) { options.task.statusMessage = "Uploading ..." + this.formatStringForDisplay(file.fileName); options.task.percentComplete = Math.floor(imperative_1.TaskProgress.ONE_HUNDRED_PERCENT * (uploadsInitiated / filesArray.length)); uploadsInitiated++; } const fileName = path.normalize(path.join(inputDirectory, file.fileName)); const ussFilePath = path.posix.join(ussname, file.fileName); return this.uploadFile(fileName, ussFilePath, session, options); }; if (maxConcurrentRequests === 0) { yield Promise.all(filesArray.map(createFileUploadPromise)); } else { yield utils_1.asyncPool(maxConcurrentRequests, filesArray, createFileUploadPromise); } const result = { success: true, from: inputDirectory, to: ussname }; return { success: true, commandResponse: ZosFiles_messages_1.ZosFilesMessages.ussDirUploadedSuccessfully.message, apiResponse: result }; } catch (error) { imperative_1.Logger.getAppLogger().error(error); throw error; } }); } /** * Check if USS directory exists * @param {AbstractSession} session - z/OS connection info * @param {string} ussname - the name of uss folder * @return {Promise<boolean>} */ static isDirectoryExist(session, ussname) { return __awaiter(this, void 0, void 0, function* () { ussname = path.posix.normalize(ussname); ussname = encodeURIComponent(ussname); const parameters = `${ZosFiles_constants_1.ZosFilesConstants.RES_USS_FILES}?path=${ussname}`; try { const response = yield rest_1.ZosmfRestClient.getExpectJSON(session, ZosFiles_constants_1.ZosFilesConstants.RESOURCE + parameters); if (response.items) { return true; } } catch (err) { if (err) { return false; } } return false; }); } /** * Upload directory to USS recursively * @param {AbstractSession} session - z/OS connection info * @param {string} inputDirectory - the path of local directory * @param {string} ussname - the name of uss folder * @param {IUploadOptions} [options={}] - Uploading options * @return {null} */ static dirToUSSDirRecursive(session, inputDirectory, ussname, options = {}) { return __awaiter(this, void 0, void 0, function* () { imperative_1.ImperativeExpect.toNotBeNullOrUndefined(inputDirectory, ZosFiles_messages_1.ZosFilesMessages.missingInputDirectory.message); imperative_1.ImperativeExpect.toNotBeEqual(inputDirectory, "", ZosFiles_messages_1.ZosFilesMessages.missingInputDirectory.message); imperative_1.ImperativeExpect.toNotBeNullOrUndefined(ussname, ZosFiles_messages_1.ZosFilesMessages.missingUSSDirectoryName.message); imperative_1.ImperativeExpect.toNotBeEqual(ussname, "", ZosFiles_messages_1.ZosFilesMessages.missingUSSDirectoryName.message); // Set default values options.binary = options.binary == null ? false : options.binary; const maxConcurrentRequests = options.maxConcurrentRequests == null ? 1 : options.maxConcurrentRequests; // initialize arrays for the files and directories to be uploaded const filesArray = []; let directoriesArray = []; // Check if inputDirectory is directory if (!imperative_1.IO.isDir(inputDirectory)) { throw new imperative_1.ImperativeError({ msg: ZosFiles_messages_1.ZosFilesMessages.missingInputDirectory.message }); } // Check if provided unix directory exists const isDirectoryExist = yield this.isDirectoryExist(session, ussname); if (!isDirectoryExist) { yield create_1.Create.uss(session, ussname, "directory"); } // getting list of files and sub-directories directoriesArray = Upload.getDirs(inputDirectory); if (options.attributes) { directoriesArray = directoriesArray.filter((dir) => { return options.attributes.fileShouldBeUploaded(dir.fullPath); }); } const files = ZosFilesUtils_1.ZosFilesUtils.getFileListFromPath(inputDirectory, false); files.forEach((file) => __awaiter(this, void 0, void 0, function* () { let tempBinary = options.binary; // check if filesMap is specified, and verify if file is in the list if (options.filesMap) { if (options.filesMap.fileNames.indexOf(file) > -1) { // if file is in list, assign binary mode from mapping tempBinary = options.filesMap.binary; } } // update the array filesArray.push({ binary: tempBinary, fileName: file }); })); // create the directories if (directoriesArray.length > 0) { const createDirUploadPromise = (dir) => __awaiter(this, void 0, void 0, function* () { const tempUssname = path.posix.join(ussname, dir.dirName); const isDirectoryExists = yield this.isDirectoryExist(session, tempUssname); if (!isDirectoryExists) { return create_1.Create.uss(session, tempUssname, "directory"); } }); if (maxConcurrentRequests === 0) { yield Promise.all(directoriesArray.map(createDirUploadPromise)); } else { yield utils_1.asyncPool(maxConcurrentRequests, directoriesArray, createDirUploadPromise); } } for (const elem of directoriesArray) { yield this.dirToUSSDirRecursive(session, elem.fullPath, path.posix.join(ussname, elem.dirName), options); } // upload the files if (filesArray.length > 0) { let uploadsInitiated = 0; const createUploadPromise = (file) => { // update the progress bar if any if (options.task != null) { options.task.statusMessage = "Uploading ..." + this.formatStringForDisplay(file.fileName); options.task.percentComplete = Math.floor(imperative_1.TaskProgress.ONE_HUNDRED_PERCENT * (uploadsInitiated / filesArray.length)); uploadsInitiated++; } const filePath = path.normalize(path.join(inputDirectory, file.fileName)); const ussFilePath = path.posix.join(ussname, file.fileName); return this.uploadFile(filePath, ussFilePath, session, options); }; if (maxConcurrentRequests === 0) { yield Promise.all(filesArray.map(createUploadPromise)); } else { yield utils_1.asyncPool(maxConcurrentRequests, filesArray, createUploadPromise); } } const result = { success: true, from: inputDirectory, to: ussname }; return { success: true, commandResponse: ZosFiles_messages_1.ZosFilesMessages.ussDirUploadedSuccessfully.message, apiResponse: result }; }); } static uploadFile(localPath, ussPath, session, options) { return __awaiter(this, void 0, void 0, function* () { let tempBinary; if (options.attributes) { yield this.uploadFileAndTagBasedOnAttributes(localPath, ussPath, session, options.attributes); } else { if (options.filesMap) { if (options.filesMap.fileNames.indexOf(path.basename(localPath)) > -1) { tempBinary = options.filesMap.binary; } else { tempBinary = options.binary; } } else { tempBinary = options.binary; } yield this.fileToUSSFile(session, localPath, ussPath, tempBinary); } }); } static uploadFileAndTagBasedOnAttributes(localPath, ussPath, session, attributes) { return __awaiter(this, void 0, void 0, function* () { if (attributes.fileShouldBeUploaded(localPath)) { const binary = attributes.getFileTransferMode(localPath) === ZosFilesAttributes_1.TransferMode.BINARY; if (binary) { yield this.fileToUSSFile(session, localPath, ussPath, binary); } else { yield this.fileToUSSFile(session, localPath, ussPath, binary, attributes.getLocalEncoding(localPath)); } const tag = attributes.getRemoteEncoding(localPath); if (tag === utilities_1.Tag.BINARY.valueOf()) { yield utilities_1.Utilities.chtag(session, ussPath, utilities_1.Tag.BINARY); } else { yield utilities_1.Utilities.chtag(session, ussPath, utilities_1.Tag.TEXT, tag); } } }); } /** * Get Log * @returns {Logger} applicationLogger. */ static get log() { return imperative_1.Logger.getAppLogger(); // return Logger.getConsoleLogger(); } /** * Checks if a given directory has sub-directories or not * @param {string} dirPath full-path for the directory to check */ static hasDirs(dirPath) { const directories = fs.readdirSync(dirPath).filter((file) => imperative_1.IO.isDir(path.normalize(path.join(dirPath, file)))); // directories = directories.filter((file) => IO.isDir(path.normalize(path.join(dirPath, file)))); if (directories.length === 0) { return false; } else { return true; } } /** * Returns an array of sub-directories objects, containing directory name, and full path specification * @param dirPath full-path for the directory to check */ static getDirs(dirPath) { const response = []; if (Upload.hasDirs(dirPath)) { const directories = fs.readdirSync(dirPath).filter((file) => imperative_1.IO.isDir(path.normalize(path.join(dirPath, file)))); // directories = directories.filter((file) => IO.isDir(path.normalize(path.join(dirPath, file)))); // tslint:disable-next-line:prefer-for-of for (let index = 0; index < directories.length; index++) { const dirFullPath = path.normalize(path.join(dirPath, directories[index])); response.push({ dirName: directories[index], fullPath: dirFullPath }); } } return response; } /** * helper function to prepare file names for display on progress bar * @param stringInput string input to be formated */ static formatStringForDisplay(stringInput) { const LAST_FIFTEEN_CHARS = -15; const stringToDisplay = stringInput.split(path.sep).splice(-1, 1).toString().slice(LAST_FIFTEEN_CHARS); const result = stringToDisplay === "" ? "all files" : stringToDisplay; return result; } } exports.Upload = Upload; //# sourceMappingURL=Upload.js.map