feat: sap-cli skill v2.1.0 — self-contained distributable package

- 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
This commit is contained in:
2026-06-13 20:52:24 +08:00
commit 1e39b6da88
49 changed files with 7172 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
"""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)})")