Skip to content

adding copy to zrs backend#750

Merged
ATorrise merged 101 commits intomainfrom
copy
Feb 19, 2026
Merged

adding copy to zrs backend#750
ATorrise merged 101 commits intomainfrom
copy

Conversation

@ATorrise
Copy link
Contributor

@ATorrise ATorrise commented Jan 16, 2026

Add Data Set Copy Command (zowex ds copy)

This PR introduces the zowex ds copy command for data sets and members, featuring overwrite protection via --replace and --delete-target-members optional flags.

What It Does

Backend copy functionality supporting the following operations:

Scenario With no optional flags With -r With -d
PDS → PDS Skip existing members Replace existing members Delete all target members first, then copy (exact mirror)
PS → PS Fail if target exists Overwrite target N/A (only for PDS)
Member → Member Fail if target member exists Overwrite target member N/A (only for PDS)
  • --replace (-r): Overwrites matching members but keeps target members not in source.
  • --delete-target-members (-d): Deletes ALL target members first ->target becomes an exact mirror of source. (PDS-to-PDS only)

Manual Test Commands for zowex ds copy

Copy paste these commands into a new file and substitute USERID with your chosen HLQ :) (also you don't need to test this way I just want to help make reviewing easier and faster because there are many branches of this copy pr) Pay attention to expected replacement/overrides when executing these commands. Working through these setup and copy commands then verifying should take 10-15 minutes

Initial Setup

# Create source sequential data set
zowex ds create "USERID.SEQ.SRC" --dsorg PS --dirblk 0 --primary 1 --secondary 1
echo "SOURCE-SEQ-DATA-12345" | zowex ds write "USERID.SEQ.SRC"

# Create target sequential data set with different content
zowex ds create "USERID.SEQ.TGT" --dsorg PS --dirblk 0 --primary 1 --secondary 1
echo "TARGET-SEQ-ORIGINAL-99999" | zowex ds write "USERID.SEQ.TGT"

# Create source PDS with members
zowex ds create "USERID.PDS.SRC" --dsorg PO --dirblk 2
zowex ds create-member "USERID.PDS.SRC(MEM1)"
zowex ds create-member "USERID.PDS.SRC(MEM2)"
echo "SRC-MEM1-CONTENT-AAA" | zowex ds write "USERID.PDS.SRC(MEM1)"
echo "SRC-MEM2-CONTENT-BBB" | zowex ds write "USERID.PDS.SRC(MEM2)"

# Create target PDS with one overlapping member (MEM1) and one unique member (ONLY)
zowex ds create "USERID.PDS.TGT" --dsorg PO --dirblk 2
zowex ds create-member "USERID.PDS.TGT(MEM1)"
zowex ds create-member "USERID.PDS.TGT(ONLY)"
echo "TGT-MEM1-ORIGINAL-XXX" | zowex ds write "USERID.PDS.TGT(MEM1)"
echo "TGT-ONLY-CONTENT-ZZZ" | zowex ds write "USERID.PDS.TGT(ONLY)"

PS

# Copy to Non-Existent Target (creates new)
zowex ds copy "USERID.SEQ.SRC" "USERID.SEQ.NEW"
# Expected: New data set 'USERID.SEQ.NEW' created and copied from 'USERID.SEQ.SRC'
zowex ds view "USERID.SEQ.NEW"
# => SOURCE-SEQ-DATA-12345

# Copy to Existing Target Without Flag (fails)
zowex ds copy "USERID.SEQ.SRC" "USERID.SEQ.TGT"
# Expected: Error containing "already exists" and "Use --replace to overwrite"

# Copy with --replace (overwrites)
zowex ds copy "USERID.SEQ.SRC" "USERID.SEQ.TGT" --replace
# Expected: Data set 'USERID.SEQ.TGT' has been updated with contents of 'USERID.SEQ.SRC'
zowex ds view "USERID.SEQ.TGT"
# => SOURCE-SEQ-DATA-12345

PDS

# Copy to Non-Existent Target (creates new)
zowex ds copy "USERID.PDS.SRC" "USERID.PDS.NEW"
# Expected: New data set 'USERID.PDS.NEW' created and copied from 'USERID.PDS.SRC'
zowex ds list-members "USERID.PDS.NEW"
# => MEM1, MEM2

# Copy Without --replace (skips existing members)
echo "TGT-MEM1-ORIGINAL-XXX" | zowex ds write "USERID.PDS.TGT(MEM1)"  # Reset first
zowex ds copy "USERID.PDS.SRC" "USERID.PDS.TGT"
zowex ds list-members "USERID.PDS.TGT"
# => MEM1, MEM2, ONLY (MEM2 added, MEM1 skipped, ONLY kept)
zowex ds view "USERID.PDS.TGT(MEM1)"
# => TGT-MEM1-ORIGINAL-XXX (NOT replaced)

# Copy with --replace (replaces matching, keeps unique)
zowex ds copy "USERID.PDS.SRC" "USERID.PDS.TGT" --replace
zowex ds list-members "USERID.PDS.TGT"
# => MEM1, MEM2, ONLY (ONLY preserved)
zowex ds view "USERID.PDS.TGT(MEM1)"
# => SRC-MEM1-CONTENT-AAA (REPLACED!)

# Copy with --delete-target-members (exact mirror)
zowex ds create-member "USERID.PDS.TGT(ONLY)"
echo "TGT-ONLY-CONTENT-ZZZ" | zowex ds write "USERID.PDS.TGT(ONLY)"
zowex ds copy "USERID.PDS.SRC" "USERID.PDS.TGT" --delete-target-members
zowex ds list-members "USERID.PDS.TGT"
# => MEM1, MEM2 (ONLY is GONE - exact mirror of source)

Member

# Copy to New Member
zowex ds copy "USERID.PDS.SRC(MEM1)" "USERID.PDS.TGT(NEWMEM)"
zowex ds view "USERID.PDS.TGT(NEWMEM)"
# => SRC-MEM1-CONTENT-AAA

# Copy to Existing Member Without Flag (fails)
zowex ds copy "USERID.PDS.SRC(MEM2)" "USERID.PDS.TGT(MEM1)"
# Expected: Error containing "already exists"

# Copy with --replace (overwrites)
zowex ds copy "USERID.PDS.SRC(MEM2)" "USERID.PDS.TGT(MEM1)" --replace
zowex ds view "USERID.PDS.TGT(MEM1)"
# => SRC-MEM2-CONTENT-BBB (REPLACED!)

Cleanup

zowex ds delete "USERID.SEQ.SRC"
zowex ds delete "USERID.SEQ.TGT"
zowex ds delete "USERID.SEQ.NEW"
zowex ds delete "USERID.PDS.SRC"
zowex ds delete "USERID.PDS.TGT"
zowex ds delete "USERID.PDS.NEW"

Review Checklist

I certify that I have:

  • tested my changes
  • added/updated automated tests
  • updated the changelog
  • followed the contribution guidelines

Additional Comments

Development Notes: Why This PR Took Longer Than Expected

This PR encountered several z/OS-specific challenges that required significant investigation and architectural decisions:

  1. Copy Implementation Approach
    Copy uses member-by-member binary I/O (fopen/fread/fwrite) rather than IEBCOPY. This approach was chosen despite initial advice to leverage compress code because:
    • It provides granular control for --replace semantics (skip/overwrite individual members)
    • It handles all record formats (F/FB/V/VB) natively
    • It avoids the complexity of IEBCOPY control statement generation for selective member copying (occasional soc4 errors)
    • The compress command continues to use IEBCOPY via the existing zut_run() path since compress requires IEBCOPY (no alternative).
  2. BLKSIZE
    When creating target data sets, z/OS's System-Determined Block Size (SDFS) can round BLKSIZE for track efficiency. The target BLKSIZE may be larger than the source (ie 800 -> 6080) depending on SMS Data Class settings. This is expected z/OS behavior, but I didn't anticipate it initially, so debugging why tests were failing with "mismatched BLKSIZE" took some time to understand and handle correctly.
  3. PDS vs PDSE Detection
    Some z/OS systems override DSNTYPE(PDS) requests via SMS, creating PDSEs instead. This is handled by:
    • Using fldata() to verify actual data set type at runtime
    • Allowing tests to pass on systems that honor or override DSNTYPE requests
  4. --replace, --overwrite vs --delete-target-members
    The original --overwrite flag was renamed to --delete-target-members for clarity and to align with its actual behavior.
    This naming makes the destructive nature of the flag explicit and avoids confusion despite veering from the original semantics of the Zowe CLI. Pujal and Dan both suggested something less confusing be done with the overwrite flag naming.

🤠

Signed-off-by: Amber <amber.torrise@broadcom.com>
@github-project-automation github-project-automation bot moved this to New Issues in Zowe CLI Squad Jan 16, 2026
@ATorrise ATorrise requested a review from dkelosky January 16, 2026 16:49
@zowe-robot zowe-robot moved this from New Issues to In Progress in Zowe CLI Squad Jan 16, 2026
@github-actions
Copy link

github-actions bot commented Jan 16, 2026

Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
@github-actions
Copy link

github-actions bot commented Jan 16, 2026

Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
@ATorrise ATorrise marked this pull request as ready for review January 20, 2026 16:15
@zowe-robot zowe-robot moved this from In Progress to Review/QA in Zowe CLI Squad Jan 20, 2026
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
@dkelosky
Copy link
Collaborator

Does the existing copy ability in Zowe Explorer support masking / wildcarding? For example, can I copy all members that match IEF* into a target data set ?

Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Copy link
Member

@zFernand0 zFernand0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 😋

I do see a few commits trickling in, so I'll wait for those two slow down before approving, but overall LGTM! 😋

traeok
traeok previously requested changes Feb 12, 2026
Copy link
Member

@traeok traeok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Amber, working on testing the functionality now. I left a couple requests for changes, mostly surrounding the dsorg check. Left a suggestion about reducing parameter count for the newly-exposed zds API.

ATorrise and others added 4 commits February 13, 2026 10:35
Signed-off-by: Amber Torrise <112635587+ATorrise@users.noreply.github.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
Signed-off-by: Amber <amber.torrise@broadcom.com>
@traeok traeok dismissed their stale review February 13, 2026 16:01

Requested changes have been addressed, thanks

Signed-off-by: Amber <amber.torrise@broadcom.com>
@ATorrise ATorrise requested review from traeok and zFernand0 and removed request for zFernand0 February 13, 2026 16:20
Signed-off-by: Amber <amber.torrise@broadcom.com>
Copy link
Member

@traeok traeok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Amber, latest changes make sense to me. All tests are passing on the internal zVDT.
LGTM

Copy link
Member

@zFernand0 zFernand0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍰🍰🍰 LGTM! 🍰🍰🍰

Thanks for adapting to all the upcoming feedback 🙏
Very well done! 👍

Copy link
Contributor

@pujal0909 pujal0909 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying from a PDS to PS returns a success message, but it should fail.
Data set 'pujal.test.pds1' copied to 'pujal.ps.test13'

ATorrise and others added 2 commits February 18, 2026 10:29
Signed-off-by: Amber <amber.torrise@broadcom.com>
@sonarqubecloud
Copy link

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

@ATorrise ATorrise requested a review from pujal0909 February 18, 2026 15:37
@ATorrise
Copy link
Contributor Author

requesting to merge:
image

all test cases pass including the edge case pujal brought up 🤠

@ATorrise ATorrise dismissed stale reviews from pujal0909, jace-roell, and t1m0thyj February 19, 2026 16:13

addressed

@ATorrise ATorrise merged commit 260d20b into main Feb 19, 2026
14 of 23 checks passed
@ATorrise ATorrise deleted the copy branch February 19, 2026 16:13
@github-project-automation github-project-automation bot moved this from Review/QA to Closed in Zowe CLI Squad Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Closed

Development

Successfully merging this pull request may close these issues.

7 participants