Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy Data set bug + DeferredPromise format fix #2413

Merged
merged 28 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a3f4678
implementation and unit tests
pujal0909 Jan 16, 2025
62eab1d
update snapshots
pujal0909 Jan 16, 2025
d0f6291
merge conflicts fix
pujal0909 Jan 16, 2025
484775d
Updated changelog
pujal0909 Jan 16, 2025
af98302
unused import fix
pujal0909 Jan 16, 2025
981bdc1
Delete packages/zosfiles/__tests__/__system__/methods/invoke/DeleteVS…
pujal0909 Jan 16, 2025
85db2c4
Delete packages/zosfiles/__tests__/__system__/methods/invoke/DefineVS…
pujal0909 Jan 16, 2025
d45ef6c
fixed en.ts error
pujal0909 Jan 16, 2025
37c02a5
updated snapshots
pujal0909 Jan 16, 2025
f18a8d6
updated handler
pujal0909 Jan 17, 2025
0f41919
deferred promise format fix
pujal0909 Jan 17, 2025
6f70fd0
imperative changelog update
pujal0909 Jan 17, 2025
61ae685
removed promptFn from ICrossLparCopyDataSetOptions.ts
pujal0909 Jan 17, 2025
fa51517
merged master
pujal0909 Jan 17, 2025
b6a671a
updated changelogs
pujal0909 Jan 17, 2025
98cdedb
updated changelogs
pujal0909 Jan 17, 2025
7bbb5c5
updated code coverage for handler
pujal0909 Jan 21, 2025
12827c9
updated handler unit test
pujal0909 Jan 21, 2025
cd2f078
merged master
pujal0909 Jan 22, 2025
3fc5fb5
data set copy aborted message fix - PR comment
pujal0909 Jan 29, 2025
b034a3e
Merge branch 'master' into copy-ds-bug
pujal0909 Jan 29, 2025
da4fe15
Update packages/cli/CHANGELOG.md
pujal0909 Jan 29, 2025
f21d2ea
Update packages/zosfiles/CHANGELOG.md
pujal0909 Jan 29, 2025
68b2efb
updated snapshot
pujal0909 Jan 29, 2025
956f3a5
updated --sr alias
pujal0909 Jan 29, 2025
2f15736
updated system tests
pujal0909 Jan 29, 2025
6591bee
integration snapshots
pujal0909 Jan 30, 2025
cdf4915
Merge branch 'master' into copy-ds-bug
zFernand0 Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Change Log
All notable changes to the Zowe CLI package will be documented in this file.


## Recent Changes

- BugFix: The `zowe zos-files copy data-set` command overwrites the contents of the target data set without user confirmation. A `--safe-replace` option was added which prompts the user to confirm before overwriting the contents of the target data set. [#2369] (https://github.com/zowe/zowe-cli/issues/2369)
pujal0909 marked this conversation as resolved.
Show resolved Hide resolved

## `8.12.0`

- Enhancement: The `zowe zos-files copy data-set` command no longer requires the target data set to be preallocated. [##2349] (https://github.com/zowe/zowe-cli/issues/2349)

## `8.10.4`
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,24 @@ describe("DsHandler", () => {

const fromDataSetName = "ABCD";
const toDataSetName = "EFGH";
const enq = "SHR";
const replace = true;
const safeReplace = true;
const responseTimeout: any = undefined;


const commandParameters: any = {
arguments: {
fromDataSetName,
toDataSetName
toDataSetName,
enq,
replace,
safeReplace,
responseTimeout

},
response: {
console: { promptFn: jest.fn() }
}
};

Expand All @@ -49,7 +62,14 @@ describe("DsHandler", () => {
expect(copyDatasetSpy).toHaveBeenLastCalledWith(
dummySession,
{ dsn: commandParameters.arguments.toDataSetName },
{ "from-dataset": { dsn: commandParameters.arguments.fromDataSetName } }
{
"from-dataset": { dsn: commandParameters.arguments.fromDataSetName },
"enq": commandParameters.arguments.enq,
"replace": commandParameters.arguments.replace,
"responseTimeout": commandParameters.arguments.responseTimeout,
"safeReplace": commandParameters.arguments.safeReplace,
"promptFn": expect.any(Function)
}
);
expect(response).toBe(defaultReturn);
});
Expand All @@ -63,11 +83,22 @@ describe("DsHandler", () => {
const fromMemberName = "mem1";
const toDataSetName = "EFGH";
const toMemberName = "mem2";
const enq = "SHR";
const replace = true;
const safeReplace = true;
const responseTimeout: any = undefined;

const commandParameters: any = {
arguments: {
fromDataSetName: `${fromDataSetName}(${fromMemberName})`,
toDataSetName: `${toDataSetName}(${toMemberName})`
toDataSetName: `${toDataSetName}(${toMemberName})`,
enq,
replace,
safeReplace,
responseTimeout
},
response: {
console: { promptFn: jest.fn() }
}
};

Expand All @@ -79,7 +110,14 @@ describe("DsHandler", () => {
expect(copyDatasetSpy).toHaveBeenLastCalledWith(
dummySession,
{ dsn: toDataSetName, member: toMemberName },
{ "from-dataset": { dsn: fromDataSetName, member: fromMemberName } }
{
"from-dataset": { dsn: fromDataSetName, member: fromMemberName },
"enq": commandParameters.arguments.enq,
"replace": commandParameters.arguments.replace,
"responseTimeout": commandParameters.arguments.responseTimeout,
"safeReplace": commandParameters.arguments.safeReplace,
"promptFn": expect.any(Function)
}
);
expect(response).toBe(defaultReturn);
});
Expand All @@ -93,13 +131,20 @@ describe("DsHandler", () => {
const toDataSetName = "EFGH";
const enq = "SHR";
const replace = true;
const safeReplace = true;
const responseTimeout: any = undefined;

const commandParameters: any = {
arguments: {
fromDataSetName,
toDataSetName,
enq,
replace
replace,
safeReplace,
responseTimeout
},
response: {
console: { promptFn: jest.fn() }
}
};

Expand All @@ -114,9 +159,84 @@ describe("DsHandler", () => {
{
"from-dataset": { dsn: commandParameters.arguments.fromDataSetName },
"enq": commandParameters.arguments.enq,
"replace": commandParameters.arguments.replace
"replace": commandParameters.arguments.replace,
"responseTimeout": commandParameters.arguments.responseTimeout,
"safeReplace": commandParameters.arguments.safeReplace,
"promptFn": expect.any(Function)
}
);
expect(response).toBe(defaultReturn);
});
it("should prompt the user and return true when input is 'y'", async () => {
const handler = new DsHandler();

expect(handler).toBeInstanceOf(ZosFilesBaseHandler);
const fromDataSetName = "ABCD";
const toDataSetName = "EFGH";
const enq = "SHR";
const replace = true;
const safeReplace = true;
const responseTimeout: any = undefined;

const commandParameters: any = {
arguments: {
fromDataSetName,
toDataSetName,
enq,
replace,
safeReplace,
responseTimeout
},
response: {
console: { promptFn: jest.fn() }
}
};
const promptMock = jest.fn();
promptMock.mockResolvedValue("y");

const promptFn = (handler as any)["promptForSafeReplace"]({ prompt: promptMock });
const result = await promptFn(commandParameters.arguments.toDataSetName);

expect(promptMock).toHaveBeenCalledWith(
`The dataset '${toDataSetName}' exists on the target system. This copy will result in data loss.` +
` Are you sure you want to continue? [y/N]: `
);
expect(result).toBe(true);
});
it("should prompt the user and return true when input is 'N'", async () => {
const handler = new DsHandler();

expect(handler).toBeInstanceOf(ZosFilesBaseHandler);
const fromDataSetName = "ABCD";
const toDataSetName = "EFGH";
const enq = "SHR";
const replace = true;
const safeReplace = true;
const responseTimeout: any = undefined;

const commandParameters: any = {
arguments: {
fromDataSetName,
toDataSetName,
enq,
replace,
safeReplace,
responseTimeout
},
response: {
console: { promptFn: jest.fn() }
}
};
const promptMock = jest.fn();
promptMock.mockResolvedValue("N");

const promptFn = (handler as any)["promptForSafeReplace"]({ prompt: promptMock });
const result = await promptFn(commandParameters.arguments.toDataSetName);

expect(promptMock).toHaveBeenCalledWith(
`The dataset '${toDataSetName}' exists on the target system. This copy will result in data loss.` +
` Are you sure you want to continue? [y/N]: `
);
expect(result).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ Array [
"name": "replace",
"type": "boolean",
},
Object {
"aliases": Array [
"safe-rep",
],
"description": "Specify this option as true if you wish to replace like-named members or the content of the target data set. This option will prompt to confirm.",
"name": "safe-replace",
"type": "boolean",
},
]
`;

Expand All @@ -35,5 +43,9 @@ Array [
"description": "Copy the data set named 'USER.FROM.SET' to the data set named 'USER.TO.SET' and replace like-named members",
"options": "\\"USER.FROM.SET\\" \\"USER.TO.SET\\" --replace",
},
Object {
"description": "Copy the partitioned data set named 'TEST.PDS1' to the partitioned data set named 'TEST.PDS2'",
"options": "\\"USER.FROM.SET\\" \\"USER.TO.SET\\" --safe-replace",
},
]
`;
6 changes: 4 additions & 2 deletions packages/cli/src/zosfiles/-strings-/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@ export default {
TODSNAME: "The name of the data set that you want to copy to"
},
OPTIONS: {
REPLACE: "Specify this option as true if you wish to replace like-named members in the target data set"
REPLACE: "Specify this option as true if you wish to replace like-named members in the target data set",
SAFE_REPLACE: "Specify this option as true if you wish to replace like-named members or the content of the target data set. " +
"This option will prompt to confirm."
},
EXAMPLES: {
EX1: "Copy the data set named 'USER.FROM.SET' to the data set named 'USER.TO.SET'",
Expand All @@ -204,7 +206,7 @@ export default {
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",
EX6: "Copy the partitioned data set named 'TEST.PDS1' to the partitioned data set named 'TEST.PDS2'",
EX7: "Copy the partionted data set named 'EXISTING.PDS' to a non-existent target 'NEW.PDS'"
EX7: "Copy the partitioned data set named 'EXISTING.PDS' to a non-existent target 'NEW.PDS'"
}
},
DATA_SET_CROSS_LPAR: {
Expand Down
10 changes: 10 additions & 0 deletions packages/cli/src/zosfiles/copy/ds/Ds.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ export const DsDefinition: ICommandDefinition = {
aliases: ["rep"],
description: strings.OPTIONS.REPLACE,
type: "boolean"
},
{
name: "safe-replace",
aliases: ["safe-rep"],
description: strings.OPTIONS.SAFE_REPLACE,
type: "boolean",
}
] as ICommandOptionDefinition[]).sort((a, b) =>
a.name.localeCompare(b.name)
Expand All @@ -77,6 +83,10 @@ export const DsDefinition: ICommandDefinition = {
{
description: strings.EXAMPLES.EX5,
options: `"USER.FROM.SET" "USER.TO.SET" --replace`
},
{
description: strings.EXAMPLES.EX6,
options: `"USER.FROM.SET" "USER.TO.SET" --safe-replace`
}
]
};
16 changes: 14 additions & 2 deletions packages/cli/src/zosfiles/copy/ds/Ds.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
*/

import { AbstractSession, IHandlerParameters } from "@zowe/imperative";
import { AbstractSession, IHandlerParameters, IHandlerResponseConsoleApi } from "@zowe/imperative";
import { Copy, IZosFilesResponse, IDataSet, ICopyDatasetOptions, ZosFilesUtils } from "@zowe/zos-files-for-zowe-sdk";
import { ZosFilesBaseHandler } from "../../ZosFilesBase.handler";

Expand All @@ -24,9 +24,21 @@ export default class DsHandler extends ZosFilesBaseHandler {
"from-dataset": fromDataSet,
enq: commandParameters.arguments.enq,
replace: commandParameters.arguments.replace,
responseTimeout: commandParameters.arguments.responseTimeout
responseTimeout: commandParameters.arguments.responseTimeout,
safeReplace: commandParameters.arguments.safeReplace,
promptFn: this.promptForSafeReplace(commandParameters.response.console)
};

return Copy.dataSet(session, toDataSet, options);
}

private promptForSafeReplace(console: IHandlerResponseConsoleApi) {
return async (targetDSN: string) => {
const answer: string = await console.prompt(
`The dataset '${targetDSN}' exists on the target system. This copy will result in data loss.` +
` Are you sure you want to continue? [y/N]: `
);
return answer != null && (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
};
}
}
3 changes: 3 additions & 0 deletions packages/imperative/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

All notable changes to the Imperative package will be documented in this file.

## Recent Changes
- Format fix: `DeferredPromise` and `DeferredPromise.unit.test` comment format changed to match standard.

## `8.11.0`

- Enhancement: Added `DeferredPromise` class to Imperative to provide utilities for data synchronization. [#2405](https://github.com/zowe/zowe-cli/pull/2405)
Expand Down
pujal0909 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* 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.
*
*/
/*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Copyright Contributors to the Zowe Project.
*
*/

import { DeferredPromise, DeferredPromiseStatus } from "../src/DeferredPromise";

Expand Down
20 changes: 10 additions & 10 deletions packages/imperative/src/utilities/src/DeferredPromise.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* 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.
*
*/
/*
* 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.
*
*/

/* Status of the deferred promise */
export enum DeferredPromiseStatus {
Expand Down
5 changes: 4 additions & 1 deletion packages/zosfiles/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

All notable changes to the Zowe z/OS files SDK package will be documented in this file.

## `8.12.0`
## Recent Changes

- Bug Fix: The `Copy.data.set` function now prompts the user to confirm before overwriting the contents of the target data set with the addition of the `--safe-replace` option. [#2369] (https://github.com/zowe/zowe-cli/issues/2369)

## `8.12.0`
- Enhancement: The `Copy.dataset` function now creates a new data set if the entered target data set does not exist. [#2349](https://github.com/zowe/zowe-cli/issues/2349)
- Enhancement: Added the `maxLength` option to List SDK functions (`allMembers`, `dataSetsMatchingPattern`, `membersMatchingPattern`) to specify the maximum number of items to return. [#2409](https://github.com/zowe/zowe-cli/pull/2409)
- Enhancement: Added the `start` option to List SDK functions (`allMembers`, `dataSetsMatchingPattern`, `membersMatchingPattern`) to specify the first data set/member name to return in the response. [#2409](https://github.com/zowe/zowe-cli/pull/2409)
Expand Down
Loading
Loading