diff --git a/README.md b/README.md
index 1cdeba5a02..96ffb1047c 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
-# **Zowe CLI**
+# Zowe CLI
+
[![codecov](https://codecov.io/gh/zowe/zowe-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/zowe/zowe-cli)
[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7204/badge)](https://bestpractices.coreinfrastructure.org/projects/7204)
@@ -8,49 +9,56 @@ This repository also contains the Zowe Node Client SDK. The SDK lets you leverag
-## **Contents**
+## Content
+
- [Documentation](#documentation)
- - [Contribution Guidelines](#contribution-guidelines)
- - [Building Zowe CLI From Source](#building-zowe-cli-from-source)
- - [Installing Zowe CLI From Source](#installing-zowe-cli-from-source)
+ - [Contribution guidelines](#contribution-guidelines)
+ - [Building Zowe CLI from source](#building-zowe-cli-from-source)
+ - [Installing Zowe CLI from source](#installing-zowe-cli-from-source)
- [Uninstalling Zowe CLI](#uninstalling-zowe-cli)
- [Configuring Zowe CLI](#configuring-zowe-cli)
- [Zowe Node Client SDK](#zowe-node-client-sdk)
- - [Running System Tests](#running-system-tests)
+ - [Running system tests](#running-system-tests)
- [FAQs](#frequently-asked-questions)
- - [Project Structure and Governance](#project-structure-and-governance)
+ - [Project structure and governance](#project-structure-and-governance)
-## **Documentation**
-For information about how to install, configure, and use Zowe CLI, see [Zowe CLI Quick Start Documentation](https://docs.zowe.org/stable/getting-started/cli-getting-started/). For more detailed instructions, see [Zowe CLI Documentation](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/), which also includes examples and tutorials for how to contribute to Zowe CLI and develop CLI plug-ins.
+## Documentation
+
+For information about how to install, configure, and use Zowe CLI, see [Zowe CLI Quick Start](https://docs.zowe.org/stable/getting-started/cli-getting-started/) documentation. For more detailed instructions, see [Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/) documentation, which also includes examples and tutorials for how to contribute to Zowe CLI and develop CLI plug-ins.
-Engineering design documentation is contained in the 'docs' directory in this repository. To view the Web Help for all Zowe CLI commands and contributed plug-ins, see the [Zowe CLI Web Help](https://docs.zowe.org/stable/web_help/index.html). To view all locally accessible commands, run `zowe --help-web`. For more use cases and tutorials visit [Medium.com/zowe](https://medium.com/zowe).
+Engineering design documentation is contained in the `docs` directory in this repository. To view the Web Help for all Zowe CLI commands and contributed plug-ins, see the [Zowe CLI Web Help](https://docs.zowe.org/stable/web_help/index.html). To view all locally accessible commands, run `zowe --help-web`. For more use cases and tutorials visit [Medium.com/zowe](https://medium.com/zowe).
-## **Contribution Guidelines**
+## Contribution guidelines
+
The following information is critical to working with the code, running/writing/maintaining automated tests, developing consistent syntax in your plug-in, and ensuring that your plug-in integrates with Zowe CLI properly:
-| For more information about ... | See: |
+| For more information about | Go to |
| ------------------------------ | ----- |
-| General guidelines that apply to contributing to Zowe CLI and Plug-ins | [Contribution Guidelines](./CONTRIBUTING.md) |
-| Conventions and best practices for creating packages and plug-ins for Zowe CLI | [Package and Plug-in Guidelines](./docs/PackagesAndPluginGuidelines.md)|
-Guidelines for contributing to Zowe SDKs| [SDK Guidelines](./docs/SDKGuidelines.md) |
-| Guidelines for running tests on Zowe CLI | [Testing Guidelines](./docs/TESTING.md) |
-| Guidelines for running tests on the plug-ins that you build| [Plug-in Testing Guidelines](./docs/PluginTESTINGGuidelines.md) |
+| General guidelines that apply to contributing to Zowe CLI and Plug-ins | [Contribution guidelines](./CONTRIBUTING.md) |
+| Conventions and best practices for creating packages and plug-ins for Zowe CLI | [Package and plug-in guidelines](./docs/PackagesAndPluginGuidelines.md)|
+Guidelines for contributing to Zowe SDKs| [SDK guidelines](./docs/SDKGuidelines.md) |
+| Guidelines for running tests on Zowe CLI | [Testing guidelines](./docs/TESTING.md) |
+| Guidelines for running tests on the plug-ins that you build| [Plug-in testing guidelines](./docs/PluginTESTINGGuidelines.md) |
| Documentation that describes the features of the Imperative CLI Framework | [About Imperative CLI Framework](https://github.com/zowe/imperative/wiki) |
-| Naming CLI commands and developing syntax | [Command Format Standards](./docs/CommandFormatStandards.md) |
-Versioning conventions for Zowe CLI and Plug-ins| [Versioning Guidelines](./docs/MaintainerVersioning.md) |
-| Miscellaneous tips for development | [Development Tips](./docs/DevelopmentTips.md)
+| Naming CLI commands and developing syntax | [Command format standards](./docs/CommandFormatStandards.md) |
+Versioning conventions for Zowe CLI and Plug-ins| [Versioning guidelines](./docs/MaintainerVersioning.md) |
+| Miscellaneous tips for development | [Development tips](./docs/DevelopmentTips.md)
-**Tip:**
-- Visit our [Sample Plug-in repository](https://github.com/zowe/zowe-cli-sample-plugin) for example plug-in code. You can follow developer tutorials [here](https://docs.zowe.org/stable/extend/extend-cli/cli-devTutorials.html).
+**Tip:** Visit our [Sample plug-in repository](https://github.com/zowe/zowe-cli-sample-plugin) for example plug-in code. Follow the [developer tutorials](https://docs.zowe.org/stable/extend/extend-cli/cli-devTutorials.html) for more tips.
-## **Building Zowe CLI From Source**
-Zowe CLI requires NPM version 8 and Cargo version 1.72.0 (or newer) to build from source. Before proceeding, check your NPM version with `npm --version` and if it's older than 8.x, update with `npm install -g npm`. To check your version of Cargo, run `cargo --version`. Cargo can be installed using rustup: [https://rustup.rs/](https://rustup.rs/). To update Cargo, run the `rustup update` command.
+## Building Zowe CLI from source
+
+Zowe CLI requires the NPM version bundled with the active LTS versions of NodeJS and Cargo version 1.72.0 (or newer) to build from source.
+
+Check your NPM version with `npm --version` and if it's older than 8.x, update with `npm install -g npm`.
+
+Check your Cargo version with `cargo --version`. Cargo can be installed using [rustup](https://rustup.rs/). To update Cargo, run the `rustup update` command.
For developers using Linux, the following packages are required to build Zowe CLI from source:
@@ -80,26 +88,28 @@ When you update `package.json` to include new dependencies, or when you pull cha
npm update
```
-**Tip:**
-- When necessary, you can run the install command again to update dependencies changed in `package.json`.
+**Tip:** When necessary, run the install command again to update dependencies changed in `package.json`.
-## **Installing Zowe CLI From Source**
-From your copy of this repository, after a build, navigate to the `packages/cli` directory, then issue the following command to install Zowe CLI from source:
+## Installing Zowe CLI from source
+
+From your copy of this repository, after a build, navigate to the `packages/cli` directory, then install Zowe CLI from source:
```
npm install -g
```
-**Notes:**
+**Notes:**
+
- Depending on how you configured npm on Linux or Mac, you might need to prefix the `npm install -g` command or the `npm uninstall -g` command with `sudo` to let npm have write access to the installation directory.
- On Windows, the `npm install -g` command might fail several times due to an `EPERM` error. This appears to be a bug that npm documented in their GitHub issues. This behaviour does not appear to be specific to installing the Zowe CLI package. Unfortunately, the only solution that we know of is to issue the `npm cache clean` command and the `npm install -g` command repeatedly until it works.
-## **Uninstalling Zowe CLI**
-From your local copy of this repository, issue the following command to uninstall Zowe CLI:
+## Uninstalling Zowe CLI
+
+From your local copy of this repository, to uninstall Zowe CLI:
```
npm uninstall --global @zowe/cli
@@ -107,49 +117,55 @@ npm uninstall --global @zowe/cli
-## **Configuring Zowe CLI**
-
-Zowe CLI configuration is made up of different **profiles**. The profiles contain the information that Zowe CLI needs to communicate with the mainframe system. For example, credentials and z/OSMF host name. If you try to use Zowe CLI functionality and you get an error message that Zowe CLI failed to load any profiles, see the `zowe profiles create --help` command for the group of commands that you are trying to use (if any) to initialize your configuration.
+## Configuring Zowe CLI
-The most fundamental Zowe CLI profile is a `zosmf` profile. Issue the following command to understand how to create a `zosmf` profile in Zowe CLI:
+Zowe CLI team configuration is made up of different **profiles**. Each profile contains the information that Zowe CLI needs to communicate with the mainframe system, such as credentials and host name.
-```
-zowe profiles create zosmf-profile --help
-```
+The most fundamental Zowe CLI profile is a `zosmf` profile, and it is included when Zowe CLI initializes your team configuration. However, you must still add your specific connection information to complete the `zosmf` profile. To do so, update your `~/.zowe/zowe.config.json` configuration file with a text editor or an IDE (such as Visual Studio Code) on your computer.
-After you create your profile, you can confirm that the properties of your profile can connect to and communicate with your mainframe system successfully by issuing the following command:
+After you create and/or finalize your profile, confirm that the properties of your profile can connect to and communicate with your mainframe system successfully:
```
zowe zosmf check status
```
-For detailed information about creating service profiles, creating base profiles, or integrating with Zowe API ML, see [Using Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/).
+For detailed information about creating profiles, or integrating with Zowe API ML, see the documentation in the [Using Zowe CLI](https://docs.zowe.org/stable/user-guide/cli-using-usingcli/) section of Zowe Docs.
-**Tip:**
-- When you confirm that your profile connects to and communicates with your mainframe system successfully, you can issue the same command at any time to verify the availability and status of the z/OSMF subsystem on your mainframe.
+**Tip:** When you confirm that your profile connects to and communicates with your mainframe system successfully, issue the same command at any time to verify the availability and status of the z/OSMF subsystem on your mainframe.
-## **Zowe Node Client SDK**
+## Troubleshooting Zowe CLI
+
+If you try to use Zowe CLI functionality and you get an error message that Zowe CLI failed to load any profiles, try issuing the following commands:
+
+- `zowe config report-env` to generate a report on the status of the key areas in your working environment. Address any problems indicated in the report.
+- `zowe config edit` to open your `~/.zowe/zowe.config.json` configuration file in your system's default text editor. Fix any properties with incorrect values.
+- `zowe config secure` to have Zowe CLI prompt for your secure configuration properties in case your secure values are incorrect in your configuration.
+
+**Note:** For these commands, use the `--global-config` option to update your global configuration or `--user-config` for your user configuration.
+
+## Zowe Node Client SDK
The Zowe Node Client SDK consists of APIs that enable you to build client applications that interface with the mainframe. Use the APIs to build your own client applications or automation scripts, independent of Zowe CLI.
-For information about downloading and getting started with the SDK, see the [Zowe Docs](https://docs.zowe.org/stable/user-guide/sdks-using). To view the Zowe Node.js SDK doc, see [Zowe SDK Docs](https://docs.zowe.org/stable/typedoc/index.html).
+For information about downloading and getting started with the SDK, see the [Zowe Docs](https://docs.zowe.org/stable/user-guide/sdks-using). To view the Zowe Node.js SDK doc, see [Using Zowe SDKs](https://docs.zowe.org/stable/typedoc/index.html).
-**Tip:**
-- Alternatively, you can import Zowe CLI into your project to call the Node APIs. However, importing all of Zowe CLI will increase the size of your project. For example, use the following statement to import packages from Zowe CLI:
+Alternatively, import Zowe CLI into your project to call the Node APIs. However, importing all of Zowe CLI increases the size of your project. For example, use the following statement to import packages from Zowe CLI:
```
import { } from @zowe/cli
```
- Where `` is the name of an interface that you populate (i.e. `IIssueParms`) or a function that submits requests (i.e `IssueCommand`).
+ ``
+
+ - Name of an interface that you populate (i.e. `IIssueParms`), or a function that submits requests (i.e `IssueCommand`)
-### Example API Usage
+### Example API usage
-For example usage syntax, see the readme for each API package in this repository:
+For example usage syntax, see the README for each API package in this repository:
- [Provisioning](https://github.com/zowe/zowe-cli/tree/master/packages/provisioning): Provision middleware and resources such as IBM CICS, IBM Db2, IBM MQ, and more.
- [z/OS Console](https://github.com/zowe/zowe-cli/tree/master/packages/zosconsole): Perform z/OS console operations.
@@ -163,9 +179,11 @@ For example usage syntax, see the readme for each API package in this repository
-## **Running System Tests**
+## Running system tests
+
+In addition to Node.js, you must have a means to execute `.sh` (bash) scripts, which are required for running integration tests.
-In addition to Node.js, you must have a means to execute `.sh` (bash) scripts, which are required for running integration tests. On Windows, you can install "Git Bash" (bundled with the standard [Git](https://git-scm.com/downloads) installation - check "Use Git and Unix Tools from Windows Command Prompt" installation option).
+On Windows, install "Git Bash", which is bundled with the standard [Git](https://git-scm.com/downloads) installation. Select the installation option **Use Git and Unix Tools from Windows Command Prompt**.
After downloading/installing the prerequisites, ensure that you can execute the following commands and receive success responses:
@@ -175,11 +193,11 @@ After downloading/installing the prerequisites, ensure that you can execute the
3. On Windows: `where sh`
```
-To run Zowe CLI system tests, you need a configured properties file with proper system information present.
+To run Zowe CLI system tests, you need a configured properties file populated with proper system information.
-A dummy properties file is present in the `__tests__/__resources__/properties folder`, `default_properties.yaml`. Using this file as a template, you should create a `custom_properties.yaml` file within the same directory. Git is configured to ignore all properties files in the properties folder, except for the `default_properties.yaml` file. If the `custom_properties.yaml` file cannot be found or loaded, an error with relevant details will be thrown when attempting to run tests.
+A dummy properties file is available in the `default_properties.yaml` file in the `__tests__/__resources__/properties` folder. Using this file as a template, you should create a `custom_properties.yaml` file within the same directory. Git is configured to ignore all properties files in the properties folder, except for the `default_properties.yaml` file. If the `custom_properties.yaml` file cannot be found or loaded, an error with relevant details displays when attempting to run tests.
-You can then run the system tests by issuing the following command:
+Run the system tests:
```
npm run test:system
@@ -187,34 +205,39 @@ npm run test:system
-**IMPORTANT!** Do not commit configured properties files because they contain security principles and other critical information.
+**IMPORTANT!** Do not commit configured properties files to this repository because they contain security principles and other critical information.
-## **Frequently Asked Questions**
+## Frequently asked questions
-**How can I install Zowe CLI as a root user on Mac/Linux?**
+### How can I install Zowe CLI as a root user on Mac/Linux?
- - You can install the CLI as root so that all users can access the CLI without installing it individually on their user account. As the root user on Mac/Linux, issue the following command:
+ - Install the CLI as root so that all users can access the CLI without installing it individually on their user account. As the root user on Mac/Linux, issue the following command:
```
npm i -g @zowe/cli@latest --ignore-scripts
```
+
**WARNING!** If you use this method, plug-ins that are installed as root can only be accessed as root. Users must install plug-ins on their user account or share all profiles/plugins/settings/logs with root. You also might encounter npm errors if you install as root. We recommend that Linux administrators implement a user/group environment where permissions can be more carefully controlled.
-**What is the difference between V1 and V2?**
+### What is the difference between Zowe V2 and V3?
- - V2 uses **team profiles** and **deprecates the Secure Credential Store** (SCS) plug-in.
+ - V2 introduces **team profiles** and **deprecates the Secure Credential Store** (SCS) plug-in used in Zowe V1.
- Connection details can be managed efficiently within one file, promoting a global configuration that can be shared across teams and mainframe services. For more information on how to use profiles, visit [Zowe Docs](https://docs.zowe.org/stable/user-guide/cli-using-using-team-profiles/).
+ - Connection details can be managed efficiently within one file, promoting a global configuration that can be shared across teams and mainframe services. For more information on how to use profiles, see [Team configurations](https://docs.zowe.org/stable/user-guide/cli-using-using-team-profiles/) in Zowe Docs.
- Secure credential encryption is included in the core CLI.
+ - Secure credential encryption is included in the core CLI.
+
+ - V3 includes the preceding features. Additionally, removes support for Zowe V1 profiles.
+
+ - To upgrade from an older Zowe release, see [Migrating from Zowe Vx to Zowe V3](https://docs.zowe.org/stable/whats-new/zowe-v3-migratio3).
Don't see what you're looking for? Browse questions from the community or ask your own in the [Q&A section](https://github.com/zowe/zowe-cli/discussions/categories/q-a) of our repo.
-## **Project Structure and Governance**
+## Project structure and governance
Zowe CLI is a component of the Zowe Open Mainframe Project, part of the Linux Foundation.
diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md
index 3e2a7e9c9d..979fb828ea 100644
--- a/packages/cli/CHANGELOG.md
+++ b/packages/cli/CHANGELOG.md
@@ -1,9 +1,11 @@
# Change Log
All notable changes to the Zowe CLI package will be documented in this file.
-## `8.9.0`
+## Recent Changes
+-Enhancement: The `zowe zos-files copy data-set` command now copies members from a source partitioned data set to an existing target partitioned data set.[#2386](https://github.com/zowe/zowe-cli/pull/2386)
--Enhancement: Added new command zowe zos-files download all-members-matching, (zowe files dl amm), to download members matching specified pattern(s). The success message for the Download.allMembers API was changed from originally "Data set downloaded successfully" to "Member(s) downloaded successfully." The change also alters the commandResponse when using the --rfj flag. [#2359](https://github.com/zowe/zowe-cli/pull/2359)
+## `8.9.0`
+- Enhancement: Added new command zowe zos-files download all-members-matching, (zowe files dl amm), to download members matching specified pattern(s). The success message for the Download.allMembers API was changed from originally "Data set downloaded successfully" to "Member(s) downloaded successfully." The change also alters the commandResponse when using the --rfj flag. [#2359](https://github.com/zowe/zowe-cli/pull/2359)
## `8.8.0`
diff --git a/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap b/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap
index abf6986543..6a4e1020b7 100644
--- a/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap
+++ b/packages/cli/__tests__/zosfiles/__integration__/copy/ds/__snapshots__/cli.files.copy.ds.integration.test.ts.snap
@@ -11,7 +11,7 @@ exports[`Copy Data Set should display the help 1`] = `
DESCRIPTION
-----------
- Copy a data set to another data set.
+ Copy a data set/partitioned data set to another data set/partitioned data set.
USAGE
-----
@@ -171,8 +171,8 @@ exports[`Copy Data Set should display the help in json format 1`] = `
\\"success\\": true,
\\"exitCode\\": 0,
\\"message\\": \\"The help was constructed for command: data-set.\\",
- \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target data set\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\",
+ \\"stdout\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set/partitioned data set to another data set/partitioned data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target data set\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\",
\\"stderr\\": \\"\\",
- \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set to another data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target data set\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\"
+ \\"data\\": \\"\\\\n COMMAND NAME\\\\n ------------\\\\n\\\\n data-set | ds\\\\n\\\\n DESCRIPTION\\\\n -----------\\\\n\\\\n Copy a data set/partitioned data set to another data set/partitioned data set.\\\\n\\\\n USAGE\\\\n -----\\\\n\\\\n zowe zos-files copy data-set [options]\\\\n\\\\n POSITIONAL ARGUMENTS\\\\n --------------------\\\\n\\\\n fromDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy from\\\\n\\\\n toDataSetName\\\\t\\\\t (string)\\\\n\\\\n The name of the data set that you want to copy to (data set must be\\\\n preallocated)\\\\n\\\\n OPTIONS\\\\n -------\\\\n\\\\n --replace | --rep (boolean)\\\\n\\\\n Specify this option as true if you wish to replace like-named members in the\\\\n target data set\\\\n\\\\n --response-timeout | --rto (number)\\\\n\\\\n The maximum amount of time in seconds the z/OSMF Files TSO servlet should run\\\\n before returning a response. Any request exceeding this amount of time will be\\\\n terminated and return an error. Allowed values: 5 - 600\\\\n\\\\n ZOSMF CONNECTION OPTIONS\\\\n ------------------------\\\\n\\\\n --host | -H (string)\\\\n\\\\n The z/OSMF server host name.\\\\n\\\\n --port | -P (number)\\\\n\\\\n The z/OSMF server port.\\\\n\\\\n Default value: 443\\\\n\\\\n --user | -u (string)\\\\n\\\\n Mainframe (z/OSMF) user name, which can be the same as your TSO login.\\\\n\\\\n --password | --pass | --pw (string)\\\\n\\\\n Mainframe (z/OSMF) password, which can be the same as your TSO password.\\\\n\\\\n --reject-unauthorized | --ru (boolean)\\\\n\\\\n Reject self-signed certificates.\\\\n\\\\n Default value: true\\\\n\\\\n --base-path | --bp (string)\\\\n\\\\n The base path for your API mediation layer instance. Specify this option to\\\\n prepend the base path to all z/OSMF resources when making REST requests. Do not\\\\n specify this option if you are not using an API mediation layer.\\\\n\\\\n --protocol (string)\\\\n\\\\n The protocol used (HTTP or HTTPS)\\\\n\\\\n Default value: https\\\\n Allowed values: http, https\\\\n\\\\n --cert-file (local file path)\\\\n\\\\n The file path to a certificate file to use for authentication\\\\n\\\\n --cert-key-file (local file path)\\\\n\\\\n The file path to a certificate key file to use for authentication\\\\n\\\\n PROFILE OPTIONS\\\\n ---------------\\\\n\\\\n --zosmf-profile | --zosmf-p (string)\\\\n\\\\n The name of a (zosmf) profile to load for this command execution.\\\\n\\\\n --base-profile | --base-p (string)\\\\n\\\\n The name of a (base) profile to load for this command execution.\\\\n\\\\n BASE CONNECTION OPTIONS\\\\n -----------------------\\\\n\\\\n --token-type | --tt (string)\\\\n\\\\n The type of token to get and use for the API. Omit this option to use the\\\\n default token type, which is provided by 'zowe auth login'.\\\\n\\\\n --token-value | --tv (string)\\\\n\\\\n The value of the token to pass to the API.\\\\n\\\\n GLOBAL OPTIONS\\\\n --------------\\\\n\\\\n --show-inputs-only (boolean)\\\\n\\\\n Show command inputs and do not run the command\\\\n\\\\n --response-format-json | --rfj (boolean)\\\\n\\\\n Produce JSON formatted data from a command\\\\n\\\\n --help | -h (boolean)\\\\n\\\\n Display help text\\\\n\\\\n --help-web | --hw (boolean)\\\\n\\\\n Display HTML help in browser\\\\n\\\\n EXAMPLES\\\\n --------\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n member named 'USER.TO.SET(MEM2)':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET(mem2)\\\\\\"\\\\n\\\\n - Copy the data set member named 'USER.FROM.SET(MEM1)' to the\\\\n data set named 'USER.TO.SET':\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET(mem1)\\\\\\" \\\\\\"USER.TO.SET\\\\\\"\\\\n\\\\n - Copy the data set named 'USER.FROM.SET' to the data set\\\\n named 'USER.TO.SET' and replace like-named members:\\\\n\\\\n $ zowe zos-files copy data-set \\\\\\"USER.FROM.SET\\\\\\" \\\\\\"USER.TO.SET\\\\\\" --replace\\\\n\\\\n\\"
}"
`;
diff --git a/packages/cli/src/zosfiles/-strings-/en.ts b/packages/cli/src/zosfiles/-strings-/en.ts
index bd65b59d95..803eb27554 100644
--- a/packages/cli/src/zosfiles/-strings-/en.ts
+++ b/packages/cli/src/zosfiles/-strings-/en.ts
@@ -188,8 +188,8 @@ export default {
DESCRIPTION: "Copy a data set.",
ACTIONS: {
DATA_SET: {
- SUMMARY: "Copy a data set to another data set",
- DESCRIPTION: "Copy a data set to another data set.",
+ SUMMARY: "Copy a data set/partitioned data set to another data set/partitioned data set",
+ DESCRIPTION: "Copy a data set/partitioned data set to another data set/partitioned data set.",
POSITIONALS: {
FROMDSNAME: "The name of the data set that you want to copy from",
TODSNAME: "The name of the data set that you want to copy to (data set must be preallocated)"
@@ -202,7 +202,8 @@ export default {
EX2: "Copy the data set member named 'USER.FROM.SET(MEM1)' to the data set member named 'USER.TO.SET(MEM2)'",
EX3: "Copy the data set named 'USER.FROM.SET' to the data set member named 'USER.TO.SET(MEM2)'",
EX4: "Copy the data set member named 'USER.FROM.SET(MEM1)' to the data set named 'USER.TO.SET'",
- EX5: "Copy the data set named 'USER.FROM.SET' to the data set named 'USER.TO.SET' and replace like-named members"
+ EX5: "Copy the data set named 'USER.FROM.SET' to the data set named 'USER.TO.SET' and replace like-named members",
+ EX6: "Copy the partitioned data set named 'TEST.PDS1' to the partitioned data set named 'TEST.PDS2'"
}
},
DATA_SET_CROSS_LPAR: {
diff --git a/packages/zosfiles/CHANGELOG.md b/packages/zosfiles/CHANGELOG.md
index 3d8b3f6d79..50a6326d17 100644
--- a/packages/zosfiles/CHANGELOG.md
+++ b/packages/zosfiles/CHANGELOG.md
@@ -2,13 +2,15 @@
All notable changes to the Zowe z/OS files SDK package will be documented in this file.
+## Recent Changes
+- Enhancement: The `Copy.dataset` method now recognizes partitioned data sets and can copy members of a source PDS into an existing target PDS. [#2386](https://github.com/zowe/zowe-cli/pull/2386)
+
## `8.9.1`
- BugFix: Corrected the `apiResponse` response value from `streamToDataSet()`,`streamToUss()`,`bufferToUss()` and `bufferToDataSet()` on the Upload SDK. [#2381](https://github.com/zowe/zowe-cli/pull/2381)
- BugFix: Corrected the `Upload.BufferToUssFile()` SDK function to properly tag uploaded files. [#2378](https://github.com/zowe/zowe-cli/pull/2378)
## `8.9.0`
-
- Enhancement: Added a `List.membersMatchingPattern` method to download all members that match a specific pattern.[#2359](https://github.com/zowe/zowe-cli/pull/2359)
## `8.8.4`
diff --git a/packages/zosfiles/__tests__/__system__/methods/copy/Copy.system.test.ts b/packages/zosfiles/__tests__/__system__/methods/copy/Copy.system.test.ts
index 312fd5dd0b..893b40f268 100644
--- a/packages/zosfiles/__tests__/__system__/methods/copy/Copy.system.test.ts
+++ b/packages/zosfiles/__tests__/__system__/methods/copy/Copy.system.test.ts
@@ -10,14 +10,18 @@
*/
import { Create, Upload, Delete, CreateDataSetTypeEnum, Copy, ZosFilesMessages, Get, IDataSet,
- ICrossLparCopyDatasetOptions, IGetOptions, IZosFilesResponse } from "../../../../src";
-import { Imperative, Session } from "@zowe/imperative";
+ ICrossLparCopyDatasetOptions, IGetOptions, IZosFilesResponse,
+ ZosFilesUtils} from "../../../../src";
+import { Imperative, IO, Session } from "@zowe/imperative";
import { inspect } from "util";
import { TestEnvironment } from "../../../../../../__tests__/__src__/environment/TestEnvironment";
import { ITestPropertiesSchema } from "../../../../../../__tests__/__src__/properties/ITestPropertiesSchema";
import { join } from "path";
import { readFileSync } from "fs";
import { ITestEnvironment } from "../../../../../../__tests__/__src__/environment/ITestEnvironment";
+import { tmpdir } from "os";
+import path = require("path");
+import * as fs from "fs";
let REAL_SESSION: Session;
let REAL_TARGET_SESSION: Session;
@@ -98,6 +102,60 @@ describe("Copy", () => {
expect(contents1.toString()).toEqual(contents2.toString());
});
});
+ describe("Partioned > Partioned", () => {
+ let downloadDir: string;
+ beforeEach(async () => {
+ try {
+ downloadDir = path.join(tmpdir(), fromDataSetName);
+ fs.mkdirSync(downloadDir, { recursive: true });
+ const mockFile = path.join(downloadDir, "mockFile.txt");
+ fs.writeFileSync(mockFile, "test file content");
+
+ const uploadFileList: string[] = ZosFilesUtils.getFileListFromPath(downloadDir);
+ const stream = IO.createReadStream(uploadFileList[0]);
+ await Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, fromDataSetName);
+ await Create.dataSet(REAL_SESSION, CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, toDataSetName);
+ await Upload.streamToDataSet(REAL_SESSION, stream, fromDataSetName);
+ } catch (err) {
+ Imperative.console.info(`Error: ${inspect(err)}`);
+ }
+ });
+ it("Should copy a partitioned data set", async () => {
+ let error;
+ let response;
+ let contents1;
+ let contents2;
+
+ try {
+ response = await Copy.dataSet(
+ REAL_SESSION,
+ {dsn: toDataSetName},
+ {"from-dataset": {
+ dsn:fromDataSetName
+ }}
+ );
+ contents1 = await Get.dataSet(REAL_SESSION, fromDataSetName);
+ contents2 = await Get.dataSet(REAL_SESSION, toDataSetName);
+ Imperative.console.info(`Response: ${inspect(response)}`);
+ } catch (err) {
+ error = err;
+ Imperative.console.info(`Error: ${inspect(err)}`);
+ }
+
+ expect(error).toBeFalsy();
+
+ expect(response).toBeTruthy();
+ expect(response.success).toBe(true);
+ expect(response.commandResponse).toContain(ZosFilesMessages.datasetCopiedSuccessfully.message);
+
+ expect(contents1).toBeTruthy();
+ expect(contents2).toBeTruthy();
+ expect(contents1.toString()).toEqual(contents2.toString());
+ });
+ afterEach(() => {
+ fs.rmSync(downloadDir, { recursive: true, force: true });
+ });
+ });
describe("Member > Member", () => {
beforeEach(async () => {
try {
diff --git a/packages/zosfiles/__tests__/__unit__/methods/copy/Copy.unit.test.ts b/packages/zosfiles/__tests__/__unit__/methods/copy/Copy.unit.test.ts
index d3413f7860..767b66a118 100644
--- a/packages/zosfiles/__tests__/__unit__/methods/copy/Copy.unit.test.ts
+++ b/packages/zosfiles/__tests__/__unit__/methods/copy/Copy.unit.test.ts
@@ -9,12 +9,12 @@
*
*/
-import { Session, ImperativeError } from "@zowe/imperative";
+import { Session, ImperativeError, IO } from "@zowe/imperative";
import { posix } from "path";
-
+import * as fs from "fs";
import { error } from "console";
-import { Copy, Create, Get, List, Upload, ZosFilesConstants, ZosFilesMessages, IZosFilesResponse } from "../../../../src";
+import { Copy, Create, Get, List, Upload, ZosFilesConstants, ZosFilesMessages, IZosFilesResponse, Download, ZosFilesUtils } from "../../../../src";
import { ZosmfHeaders, ZosmfRestClient } from "@zowe/core-for-zowe-sdk";
describe("Copy", () => {
@@ -33,14 +33,18 @@ describe("Copy", () => {
const fromMemberName = "mem1";
const toDataSetName = "USER.DATA.TO";
const toMemberName = "mem2";
+ let isPDSSpy: jest.SpyInstance;
beforeEach(() => {
copyExpectStringSpy.mockClear();
copyExpectStringSpy.mockImplementation(async () => {
return "";
});
+ isPDSSpy = jest.spyOn(Copy as any, "isPDS").mockResolvedValue(false);
+ });
+ afterAll(() => {
+ isPDSSpy.mockRestore();
});
-
describe("Success Scenarios", () => {
describe("Sequential > Sequential", () => {
it("should send a request", async () => {
@@ -438,6 +442,40 @@ describe("Copy", () => {
expect(lastArgumentOfCall).toHaveProperty("replace", false);
});
});
+ describe("Partitioned > Partitioned", () => {
+ let copyPDSSpy = jest.spyOn(Copy, "copyPDS");
+ beforeEach(() => {
+ copyPDSSpy.mockClear();
+ copyPDSSpy = jest.spyOn(Copy, "copyPDS").mockResolvedValue({
+ success:true,
+ commandResponse: ZosFilesMessages.datasetCopiedSuccessfully.message,
+ });
+ isPDSSpy = jest.spyOn(Copy as any, "isPDS").mockResolvedValue(true);
+ });
+ afterAll(() => {
+ copyPDSSpy.mockRestore();
+ isPDSSpy.mockRestore();
+ });
+ it("should call copyPDS to copy members of source PDS to target PDS", async () => {
+ const response = await Copy.dataSet(
+ dummySession,
+ {dsn: toDataSetName},
+ {"from-dataset": {
+ dsn:fromDataSetName
+ }}
+ );
+ expect(isPDSSpy).toHaveBeenNthCalledWith(1, dummySession, fromDataSetName);
+ expect(isPDSSpy).toHaveBeenNthCalledWith(2, dummySession, toDataSetName);
+
+ expect(copyPDSSpy).toHaveBeenCalledTimes(1);
+ expect(copyPDSSpy).toHaveBeenCalledWith(dummySession, fromDataSetName, toDataSetName);
+
+ expect(response).toEqual({
+ success: true,
+ commandResponse: ZosFilesMessages.datasetCopiedSuccessfully.message
+ });
+ });
+ });
});
describe("Failure Scenarios", () => {
it("should fail if the zOSMF REST client fails", async () => {
@@ -515,6 +553,107 @@ describe("Copy", () => {
});
});
+ describe("Copy Partitioned Data Set", () => {
+ const listAllMembersSpy = jest.spyOn(List, "allMembers");
+ const downloadAllMembersSpy = jest.spyOn(Download, "allMembers");
+ const uploadSpy = jest.spyOn(Upload, "streamToDataSet");
+ const fileListPathSpy = jest.spyOn(ZosFilesUtils, "getFileListFromPath");
+ const generateMemName = jest.spyOn(ZosFilesUtils, "generateMemberName");
+ const fromDataSetName = "USER.DATA.FROM";
+ const toDataSetName = "USER.DATA.TO";
+ const readStream = jest.spyOn(IO, "createReadStream");
+ const rmSync = jest.spyOn(fs, "rmSync");
+ const listDatasetSpy = jest.spyOn(List, "dataSet");
+
+ const dsPO = {
+ dsname: fromDataSetName,
+ dsorg: "PO",
+ };
+ const dsPS = {
+ dsname: fromDataSetName,
+ dsorg: "PS",
+ };
+
+ it("should detect PDS datasets correctly during copy", async () => {
+ let caughtError;
+ let response;
+ listDatasetSpy.mockImplementation(async (): Promise => {
+ return {
+ apiResponse: {
+ items: [dsPO]
+ }
+ };
+ });
+ try {
+ response = await Copy.isPDS(dummySession, dsPO.dsname);
+ }
+ catch(e) {
+ caughtError = e;
+ }
+ expect(response).toEqual(true);
+ expect(listDatasetSpy).toHaveBeenCalledWith(dummySession, dsPO.dsname, { attributes: true });
+ });
+
+ it("should return false if the data set is not partitioned", async () => {
+ let response;
+ let caughtError;
+ listDatasetSpy.mockImplementation(async (): Promise => {
+ return {
+ apiResponse: {
+ items: [dsPS]
+ }
+ };
+ });
+ try {
+ response = await Copy.isPDS(dummySession, dsPS.dsname);
+ }
+ catch(e) {
+ caughtError = e;
+ }
+ expect(response).toEqual(false);
+ expect(listDatasetSpy).toHaveBeenCalledWith(dummySession, dsPS.dsname, { attributes: true });
+ });
+
+ it("should successfully copy members from source to target PDS", async () => {
+ let caughtError;
+ let response;
+ const sourceResponse = {
+ apiResponse: {
+ items: [
+ { member: "mem1" },
+ { member: "mem2" },
+ ]
+ }
+ };
+ const fileList = ["mem1", "mem2"];
+
+ listAllMembersSpy.mockImplementation(async (): Promise => sourceResponse);
+ downloadAllMembersSpy.mockImplementation(async (): Promise => undefined);
+ fileListPathSpy.mockReturnValue(fileList);
+ generateMemName.mockReturnValue("mem1");
+ readStream.mockReturnValue("test" as any);
+ uploadSpy.mockResolvedValue(undefined);
+ rmSync.mockImplementation(jest.fn());
+
+
+ try{
+ response = await Copy.copyPDS(dummySession, fromDataSetName, toDataSetName);
+ }
+ catch(e) {
+ caughtError = e;
+ }
+ expect(listAllMembersSpy).toHaveBeenCalledWith(dummySession, fromDataSetName);
+ expect(downloadAllMembersSpy).toHaveBeenCalledWith(dummySession, fromDataSetName, expect.any(Object));
+ expect(fileListPathSpy).toHaveBeenCalled();
+ expect(uploadSpy).toHaveBeenCalledTimes(fileList.length);
+ expect(rmSync).toHaveBeenCalled();
+ expect(response).toEqual({
+ success: true,
+ commandResponse: ZosFilesMessages.datasetCopiedSuccessfully.message,
+ });
+ });
+ });
+
describe("Data Set Cross LPAR", () => {
const getDatasetSpy = jest.spyOn(Get, "dataSet");
const listDatasetSpy = jest.spyOn(List, "dataSet");
diff --git a/packages/zosfiles/src/methods/copy/Copy.ts b/packages/zosfiles/src/methods/copy/Copy.ts
index 2f29a329c0..fc419ca27e 100644
--- a/packages/zosfiles/src/methods/copy/Copy.ts
+++ b/packages/zosfiles/src/methods/copy/Copy.ts
@@ -9,10 +9,10 @@
*
*/
-import { AbstractSession, ImperativeError, ImperativeExpect, ITaskWithStatus, Logger, Headers,
- IHeaderContent, TaskStage } from "@zowe/imperative";
+import { AbstractSession, ImperativeError, ImperativeExpect, ITaskWithStatus,
+ Logger, Headers, IHeaderContent, TaskStage, IO} from "@zowe/imperative";
import { posix } from "path";
-
+import * as fs from "fs";
import { Create, CreateDataSetTypeEnum, ICreateDataSetOptions } from "../create";
import { Get } from "../get";
import { Upload } from "../upload";
@@ -26,6 +26,10 @@ import { IZosmfListResponse } from "../list/doc/IZosmfListResponse";
import { IDataSet } from "../../doc/IDataSet";
import { ICopyDatasetOptions } from "./doc/ICopyDatasetOptions";
import { ICrossLparCopyDatasetOptions } from "./doc/ICrossLparCopyDatasetOptions";
+import { Download } from "../download";
+import { ZosFilesUtils } from "../../utils/ZosFilesUtils";
+import { tmpdir } from "os";
+import path = require("path");
/**
* This class holds helper functions that are used to copy the contents of datasets through the
* z/OSMF APIs.
@@ -53,6 +57,12 @@ export class Copy {
ImperativeExpect.toBeDefinedAndNonBlank(options["from-dataset"].dsn, "fromDataSetName");
ImperativeExpect.toBeDefinedAndNonBlank(toDataSetName, "toDataSetName");
+ const sourceIsPds = await this.isPDS(session, options["from-dataset"].dsn);
+ const targetIsPds = await this.isPDS(session, toDataSetName);
+ if (sourceIsPds && targetIsPds) {
+ return await this.copyPDS(session, options["from-dataset"].dsn, toDataSetName);
+ }
+
const endpoint: string = posix.join(
ZosFilesConstants.RESOURCE,
ZosFilesConstants.RES_DS_FILES,
@@ -93,6 +103,75 @@ export class Copy {
}
}
+ /**
+ * Private function that checks if a dataset is type PDS
+ **/
+ public static async isPDS(
+ session: AbstractSession,
+ dataSetName: string
+ ): Promise {
+ try {
+ const response = await List.dataSet(session, dataSetName, {attributes: true});
+ const dsorg = response.apiResponse.items[0].dsorg;
+ return dsorg.startsWith("PO");
+ }
+ catch(error) {
+ Logger.getAppLogger().error(error);
+ throw error;
+ }
+ }
+
+ /**
+ * Copy the members of a Partitioned dataset into another Partitioned dataset
+ *
+ * @param {AbstractSession} session - z/OSMF connection info
+ * @param {IDataSet} toDataSet - The data set to copy to
+ * @param {IDataSetOptions} options - Options
+ *
+ * @returns {Promise} A response indicating the status of the copying
+ *
+ * @throws {ImperativeError} Data set name must be specified as a non-empty string
+ * @throws {Error} When the {@link ZosmfRestClient} throws an error
+ *
+ * @see https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.izua700/IZUHPINFO_API_PutDataSetMemberUtilities.htm
+ */
+
+ public static async copyPDS (
+ session: AbstractSession,
+ fromPds: string,
+ toPds: string
+ ): Promise {
+ try {
+ const sourceResponse = await List.allMembers(session, fromPds);
+ const sourceMemberList: Array<{ member: string }> = sourceResponse.apiResponse.items;
+
+ if(sourceMemberList.length == 0) {
+ return {
+ success: true,
+ commandResponse: `Source dataset (${fromPds}) - ` + ZosFilesMessages.noMembersFound.message
+ };
+ }
+
+ const downloadDir = path.join(tmpdir(), fromPds);
+ await Download.allMembers(session, fromPds, {directory:downloadDir});
+ const uploadFileList: string[] = ZosFilesUtils.getFileListFromPath(downloadDir);
+
+ for (const file of uploadFileList) {
+ const uploadingDsn = `${toPds}(${ZosFilesUtils.generateMemberName(file)})`;
+ const uploadStream = IO.createReadStream(file);
+ await Upload.streamToDataSet(session, uploadStream, uploadingDsn);
+ }
+ fs.rmSync(downloadDir, {recursive: true});
+ return {
+ success:true,
+ commandResponse: ZosFilesMessages.datasetCopiedSuccessfully.message
+ };
+ }
+ catch (error) {
+ Logger.getAppLogger().error(error);
+ throw error;
+ }
+ }
/**
* Copy the contents of a dataset from one LPAR to another LPAR