Files
sap-cli-skill/assets/sapcli/commands/upload.py
T

105 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""upload 命令 — 仅上传源代码到 SAP(锁定→写入→解锁,不检查不激活)。"""
from __future__ import annotations
import argparse
import logging
import os
from sapcli.client import ADTClient
from sapcli.commands.crud import _select_transport_request
from sapcli.exceptions import (
ConfigError,
InvalidNameError,
LockError,
ObjectNotFoundError,
)
from sapcli.types import get_type_config, parse_object_name
logger = logging.getLogger("sapcli.commands.upload")
def cmd_upload(args: argparse.Namespace, client: ADTClient) -> None:
"""上传本地源代码到 SAP(仅锁定→写入→解锁,不检查不激活)。
与 sync 的区别:
- 不自动创建对象(对象必须已存在,否则报 ObjectNotFoundError
- 不执行语法检查
- 不执行激活
适用于自动化测试场景:修改代码后先安全写入 SAP,避开 activate 的
锁定冲突,稍后再单独 activate。
"""
name: str = args.name
obj_type: str = args.type
file_path: str = args.path
corr_nr: str | None = getattr(args, "corr_nr", None)
parsed = parse_object_name(name, obj_type)
type_label = get_type_config(obj_type).label
if parsed.src_uri is None:
print(f"\n{type_label}没有源代码,不支持 upload 操作")
print(f" functiongroup 等是容器对象,不包含可编辑的源代码文件")
raise InvalidNameError(f"{type_label}没有源代码,不支持 upload 操作")
if not os.path.isfile(file_path):
print(f"\n ✗ 文件不存在: {file_path}")
raise ConfigError(f"文件不存在: {file_path}")
with open(file_path, "r", encoding="utf-8") as f:
source = f.read()
print("=" * 60)
print(" SAP ADT 源代码上传(不检查不激活)")
print("=" * 60)
print(f" 对象类型: {type_label}")
print(f" 对象名称: {parsed.display_name}")
print(f" 本地文件: {file_path}")
print(f" 源代码: {len(source)} 字符, {len(source.splitlines())} 行")
print(f" 流程: 检查 → 锁定 → 写入 → 解锁")
# 检查对象是否存在(upload 不自动创建,区别于 sync)
print(f"\n → 检查对象是否存在...")
if not client.object_exists(parsed.obj_uri):
print(f" ✗ 对象不存在: {parsed.display_name}")
print(f" upload 不会自动创建对象,请先用 create 或 sync 创建")
raise ObjectNotFoundError(parsed.display_name, obj_type)
print(" ✓ 对象存在")
# ── 锁定 → 写入 → 解锁(提取自 crud._sync_single,不含检查/激活)──
print("\n ── 锁定 → 写入 → 解锁 ──")
lock_handle: str
if corr_nr:
lock_handle, _ = client.lock(parsed.obj_uri, corr_nr)
print(f" ✓ 锁定成功(传输请求: {corr_nr}")
else:
try:
lock_handle, detected_corr_nr = client.lock(parsed.obj_uri)
if detected_corr_nr:
corr_nr = detected_corr_nr
print(f" ✓ 锁定成功(对象已绑定传输请求: {corr_nr}")
else:
print(f" ✓ 锁定成功(本地对象,无需传输请求)")
except LockError:
print(" ℹ 对象需要传输请求号")
corr_nr = _select_transport_request(client)
if not corr_nr:
print(" ✗ 锁定失败: 无法获取传输请求号")
raise LockError("锁定失败: 无法获取传输请求号", obj_uri=parsed.obj_uri)
lock_handle, _ = client.lock(parsed.obj_uri, corr_nr)
print(f" ✓ 锁定成功(传输请求: {corr_nr}")
try:
client.set_source(parsed.src_uri, source, lock_handle, corr_nr)
print(f" ✓ 源代码写入成功")
finally:
client.unlock(parsed.obj_uri, lock_handle)
print(f" ✓ 解锁成功")
print(f"\n {'=' * 60}")
print(f" ✓ {parsed.display_name} 源代码已上传")
print(f" 文件: {file_path}")
print(f" 源代码: {len(source)} 字符, {len(source.splitlines())} 行")
print(f" 注意: 未执行语法检查和激活,请按需单独执行 syntax-check / activate")
print(f" {'=' * 60}")