@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
JavaScript
"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