- assets/: sap-cli source (v2.1.0, 26 commands, 16 object types) - references/: tool constraints + error handling (self-contained) - scripts/setup.py: one-click install/config/verify - SKILL.md: full command reference + dual-platform install guide - VERSION: 2.1.0 Built from D:/Codespace/sap-cli via scripts/pack_skill.py
123 lines
3.7 KiB
Python
123 lines
3.7 KiB
Python
"""activate 命令 — 单独激活 SAP 对象(无需重新 sync)。"""
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import logging
|
||
|
||
from sapcli.client import ADTClient
|
||
from sapcli.types import get_type_config, parse_object_name
|
||
|
||
logger = logging.getLogger("sapcli.commands.activate")
|
||
|
||
|
||
def cmd_activate(args: argparse.Namespace, client: ADTClient) -> None:
|
||
"""单独激活一个 SAP 对象。
|
||
|
||
支持 --name / --type 激活单个对象,
|
||
也支持 --names / --types 批量激活多个对象。
|
||
可选 --corr_nr 传入传输请求号。
|
||
"""
|
||
corr_nr: str | None = getattr(args, "corr_nr", None)
|
||
|
||
# 批量模式:--names ZCLS1,ZCLS2 --types class,class
|
||
names_raw: str | None = getattr(args, "names", None)
|
||
types_raw: str | None = getattr(args, "types", None)
|
||
|
||
if names_raw and types_raw:
|
||
names = [n.strip() for n in names_raw.split(",") if n.strip()]
|
||
types = [t.strip() for t in types_raw.split(",") if t.strip()]
|
||
if len(names) != len(types):
|
||
print(" ✗ --names 和 --types 的数量不匹配")
|
||
return
|
||
_activate_batch(client, names, types, corr_nr)
|
||
return
|
||
|
||
# 单对象模式:--name / --type
|
||
name: str = args.name
|
||
obj_type: str = args.type
|
||
|
||
parsed = parse_object_name(name, obj_type)
|
||
type_label = get_type_config(obj_type).label
|
||
|
||
print("=" * 60)
|
||
print(" SAP ADT 对象激活")
|
||
print("=" * 60)
|
||
print(f" 对象名称: {parsed.display_name}")
|
||
print(f" 对象类型: {type_label}")
|
||
if corr_nr:
|
||
print(f" 传输请求: {corr_nr}")
|
||
|
||
_activate_single(client, name, parsed.obj_uri, corr_nr, type_label)
|
||
|
||
|
||
def _activate_single(
|
||
client: ADTClient,
|
||
name: str,
|
||
obj_uri: str,
|
||
corr_nr: str | None,
|
||
type_label: str = "",
|
||
) -> bool:
|
||
"""激活单个对象,返回是否成功。"""
|
||
label = type_label or name
|
||
print(f"\n → 正在激活 {name}...")
|
||
|
||
try:
|
||
success, messages = client.activate(name, obj_uri, corr_nr)
|
||
except Exception as e:
|
||
print(f" ✗ 激活失败: {e}")
|
||
return False
|
||
|
||
errors = [m for m in messages if m["type"] == "E"]
|
||
warnings = [m for m in messages if m["type"] == "W"]
|
||
infos = [m for m in messages if m["type"] == "I"]
|
||
|
||
if success:
|
||
print(f" ✓ {name} 激活成功!")
|
||
else:
|
||
print(f" ✗ {name} 激活失败! {len(errors)} 个错误, {len(warnings)} 个警告")
|
||
|
||
for msg in messages:
|
||
icon = {"E": "✗", "W": "⚠", "I": "ℹ", "S": "✓"}.get(msg["type"], "?")
|
||
line = msg.get("line", "?")
|
||
text = msg.get("text", "")
|
||
print(f" {icon} [{msg['type']}] 行 {line}: {text}")
|
||
|
||
return success
|
||
|
||
|
||
def _activate_batch(
|
||
client: ADTClient,
|
||
names: list[str],
|
||
types: list[str],
|
||
corr_nr: str | None,
|
||
) -> None:
|
||
"""批量激活多个对象。"""
|
||
print("=" * 60)
|
||
print(" SAP ADT 批量激活")
|
||
print("=" * 60)
|
||
print(f" 对象数量: {len(names)}")
|
||
if corr_nr:
|
||
print(f" 传输请求: {corr_nr}")
|
||
|
||
results: list[tuple[str, bool]] = []
|
||
for name, obj_type in zip(names, types):
|
||
parsed = parse_object_name(name, obj_type)
|
||
ok = _activate_single(client, name, parsed.obj_uri, corr_nr)
|
||
results.append((name, ok))
|
||
|
||
# 汇总
|
||
print()
|
||
print("─" * 60)
|
||
print(" 激活结果汇总:")
|
||
print("─" * 60)
|
||
ok_count = sum(1 for _, ok in results if ok)
|
||
fail_count = len(results) - ok_count
|
||
for name, ok in results:
|
||
icon = "✓" if ok else "✗"
|
||
print(f" {icon} {name}")
|
||
print()
|
||
if fail_count == 0:
|
||
print(f" ✓ 全部激活成功 ({ok_count}/{len(results)})")
|
||
else:
|
||
print(f" ⚠ 成功 {ok_count}, 失败 {fail_count} (共 {len(results)})")
|