Skip to content
Open
2 changes: 1 addition & 1 deletion native/c/commands/ds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ int handle_data_set_write(InvocationContext &context)
// Handle truncation warning
if (RTNCD_WARNING == rc && ZDS_RSNCD_TRUNCATION_WARNING == zds.diag.detail_rc)
{
context.error_stream() << "Warning: " << zds.diag.e_msg << endl;
context.error_stream() << "\nWarning: " << zds.diag.e_msg << endl;
result->set("truncationWarning", str(zds.diag.e_msg));
// Continues w/ logic below to output success RC - operation succeeded with warning
}
Expand Down
1 change: 1 addition & 0 deletions packages/vsce/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how

- Added the functionality for the **Rename Member** option. [#765] (https://github.com/zowe/zowe-native-proto/pull/765).
- Added the `multivolume` (`mvol`) property when displaying data set attributes. [#782](https://github.com/zowe/zowe-native-proto/pull/782)
- Fixed an issue where using the "Upload Member" option with an SSH profile in Zowe Explorer caused an error. Now, the member name is provided to the back end for each member that is uploaded.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to add a PR or issue link to this?


## `0.2.3`

Expand Down
69 changes: 68 additions & 1 deletion packages/vsce/src/api/SshMvsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*/

import { createReadStream, createWriteStream } from "node:fs";
import * as path from "node:path";
import type * as zosfiles from "@zowe/zos-files-for-zowe-sdk";
import {
type AttributeEntryInfo,
Expand Down Expand Up @@ -172,15 +173,81 @@ export class SshMvsApi extends SshCommonApi implements MainframeInteraction.IMvs
dataSetName: string,
options?: zosfiles.IUploadOptions,
): Promise<zosfiles.IZosFilesResponse> {
// Determine if we need to generate a member name for PDS uploads
const dsname = await this.resolveDataSetName(inputFilePath, dataSetName);

const response = await (await this.client).ds.writeDataset({
dsname: dataSetName,
dsname,
encoding: options?.encoding,
stream: createReadStream(inputFilePath),
etag: options?.etag,
});
return this.buildZosFilesResponse({ etag: response.etag });
}

/**
* Resolves the full data set name, including member name if uploading to a PDS.
* When uploading a file to a PDS without specifying a member name, the member name
* is generated from the input file path (similar to z/OSMF's pathToDataSet behavior).
*
* @param inputFilePath - The local file path being uploaded
* @param dataSetName - The target data set name (may or may not include member)
* @returns The resolved data set name with member if applicable
*/
private async resolveDataSetName(inputFilePath: string, dataSetName: string): Promise<string> {
const openParens = dataSetName.indexOf("(");

// If member name is already specified, use it as-is
if (openParens > 0) {
return dataSetName;
}

// Check if the target is a PDS by fetching data set attributes
const dsInfo = await (await this.client).ds.listDatasets({
pattern: dataSetName,
attributes: true,
});

const dsorg = dsInfo.items[0]?.dsorg;
const isPds = dsorg?.startsWith("PO");

if (isPds) {
// Generate member name from the input file path
const memberName = this.generateMemberName(inputFilePath);
return `${dataSetName}(${memberName})`;
}

return dataSetName;
}

/**
* Generates a valid z/OS member name from a file path.
* Member names must be 1-8 characters, start with a letter or national character,
* and contain only letters, numbers, or national characters (@, #, $).
*
* @param filePath - The file path to generate a member name from
* @returns A valid z/OS member name
*/
private generateMemberName(filePath: string): string {
// Get the base filename without extension
const baseName = path.basename(filePath, path.extname(filePath));

// Convert to uppercase and remove invalid characters
let memberName = baseName.toUpperCase().replaceAll(/[^A-Z0-9@#$]/g, "");

memberName = memberName.replaceAll(/^\d*/, "");

// Truncate to 8 characters max
memberName = memberName.substring(0, 8);

// If empty, use a default
if (memberName.length === 0) {
memberName = "MEMBER";
}

return memberName;
}

public async createDataSet(
_dataSetType: zosfiles.CreateDataSetTypeEnum,
dataSetName: string,
Expand Down
17 changes: 5 additions & 12 deletions packages/vsce/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2020",
"lib": [
"es2020"
],
"target": "es2022",
"lib": ["es2022"],
"outDir": "out",
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"rootDir": "src"
},
"exclude": [
"node_modules",
".vscode-test"
],
"include": [
"./src"
],
"exclude": ["node_modules", ".vscode-test"],
"include": ["./src"],
"references": [
{
"path": "../sdk"
}
]
}
}
Loading