chore: 并入已删除会话的在途成果(防丢失;原会话已删,未做功能验收)
**背景**:这些改动原属本工作区另外几个会话(T01/T02 等),**那些会话已被用户删除** ⇒
工作树里的成果处于"无主"状态,一次错误 checkout / 覆盖即**永久丢失** ⇒ 代入库保全。
口径遵循本项目**先例**(`39a1f2e` / `b617cdb`:**别人的活,代入库并在提交信息里注明**)。
**内容**:档案 101「能力管理」改名 + 页内 tab 分页|档案 102 语言切换搬入「用户设置」|
`07-实例UI分区登记表.md`|`scripts/find-ui*.mjs`(UI 元素定位工具)|`poc/portal-entry/`(0.5.3)|
`src/web/locale-pref.ts` + `home-files.ts`(语言偏好持久化)|`test/locale-pref.test.mjs`|
`package.json`|`BRIEF.md` / `INDEX.md` / `docs-manifest.json` / `03-路线图与待办.md` / 档案 100 增量。
**已做最小健全性检查**(⚠️ **未跑完整构建 / 单测** —— 那是原会话的验收职责,本次只求"不丢"):
- JSON 合法:`package.json` / `poc/business-plugins/package.json` / `docs-manifest.json` ✓
- 4 个 TS 文件 `{}`/`()` 配平 ✓;新增文件均非空 ✓
- 规模:13 文件改动 +340/−210,新增 12 条
**未 push**(按 §4 提交边界:用户说"提交",未说"推送")。
This commit is contained in:
1 parent
03c8363960
commit
3efd68517f
27 files changed
+1712
-206
No files matched your search
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""compare-tree.py —— 把**本地 git 基线**(manifest:mode/type/sha\\tpath)与服务器工作树逐文件比对。
|
||||
|
||||
输出三类(这是"能不能整树覆盖"的唯一判据,不盲覆盖):
|
||||
· 一致 :服务器文件内容 == 本地基线
|
||||
· 不一致 :两边都有但内容不同(**要逐个看是谁的改动**)
|
||||
· 服务器独有:服务器有、基线里没有(**绝不能抹**)
|
||||
再加一类「仅在基线里」:本地有、服务器缺(同步时要补上)。
|
||||
|
||||
用法(在服务器上):python3 scripts/compare-tree.py <manifest> <工作树根>
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
manifest, root = sys.argv[1], sys.argv[2]
|
||||
entries = []
|
||||
for line in open(manifest, encoding='utf-8'):
|
||||
line = line.rstrip('\n')
|
||||
if not line.strip():
|
||||
continue
|
||||
head, path = line.split('\t', 1)
|
||||
mode, typ, sha = head.split()
|
||||
entries.append((path, sha))
|
||||
|
||||
paths = [p for p, _ in entries]
|
||||
present = [p for p in paths if os.path.isfile(os.path.join(root, p))]
|
||||
missing = [p for p in paths if p not in set(present)]
|
||||
|
||||
# 批量算 sha(git hash-object --stdin-paths)
|
||||
hash_out = {}
|
||||
if present:
|
||||
proc = subprocess.run(['git', 'hash-object', '--stdin-paths'], cwd=root,
|
||||
input='\n'.join(present) + '\n', capture_output=True, text=True)
|
||||
for p, h in zip(present, proc.stdout.split('\n')):
|
||||
if h.strip():
|
||||
hash_out[p] = h.strip()
|
||||
|
||||
same, diff = [], []
|
||||
for p, sha in entries:
|
||||
if p in missing:
|
||||
continue
|
||||
if hash_out.get(p) == sha:
|
||||
same.append(p)
|
||||
else:
|
||||
diff.append((p, sha, hash_out.get(p)))
|
||||
|
||||
# 服务器独有:扫同一批顶层目录,取基线里没有的文件
|
||||
tops = sorted({p.split('/')[0] for p, _ in entries})
|
||||
known = set(paths)
|
||||
extra = []
|
||||
for top in tops:
|
||||
base = os.path.join(root, top)
|
||||
if not os.path.isdir(base):
|
||||
continue
|
||||
for dirpath, dirnames, filenames in os.walk(base):
|
||||
dirnames[:] = [d for d in dirnames if d not in ('node_modules', '.git', 'dist')]
|
||||
for fn in filenames:
|
||||
rel = os.path.relpath(os.path.join(dirpath, fn), root).replace(os.sep, '/')
|
||||
if rel not in known:
|
||||
extra.append(rel)
|
||||
|
||||
print('=== 汇总 ===')
|
||||
print(' 基线条目 : %d' % len(entries))
|
||||
print(' 一致 : %d' % len(same))
|
||||
print(' 不一致 : %d' % len(diff))
|
||||
print(' 仅基线有(缺) : %d' % len(missing))
|
||||
print(' 服务器独有 : %d' % len(extra))
|
||||
|
||||
if diff:
|
||||
print('\n=== 不一致(要逐个判断是谁的改动)===')
|
||||
for p, want, got in diff[:60]:
|
||||
print(' %-58s 基线 %s 服务器 %s' % (p, want[:10], (got or '')[:10]))
|
||||
if len(diff) > 60:
|
||||
print(' … 还有 %d 个' % (len(diff) - 60))
|
||||
|
||||
if missing:
|
||||
print('\n=== 仅基线有(服务器缺)===')
|
||||
for p in missing[:40]:
|
||||
print(' ' + p)
|
||||
if len(missing) > 40:
|
||||
print(' … 还有 %d 个' % (len(missing) - 40))
|
||||
|
||||
if extra:
|
||||
print('\n=== 服务器独有(⛔ 覆盖前必须保留/处理)===')
|
||||
for p in extra[:60]:
|
||||
print(' ' + p)
|
||||
if len(extra) > 60:
|
||||
print(' … 还有 %d 个' % (len(extra) - 60))
|
||||
Reference in new issue
Block a user