]> acesimba.cloud Git - studybase.git/commitdiff
自动同步:代码/数据/Media 更新(2026-09-21 02:00:02)
authorroot <root@localhost.localdomain>
Sun, 20 Sep 2026 18:00:02 +0000 (02:00 +0800)
committerroot <root@localhost.localdomain>
Sun, 20 Sep 2026 18:00:02 +0000 (02:00 +0800)
代码变更:
  - 修改 auto_sync.sh (+7 -8)
  - 修改 auto_sync_msg.py (+52 -1)
新增题目ID:无
新增试卷ID:无
反馈结果:无

auto_sync.sh
auto_sync_msg.py

index 67f41e1bc6c0a069d5b7f5035ef14ad1dafa0e51..79e03b1c7b03dcbc47d63c8c5b07dde4fd6abcab 100644 (file)
@@ -27,7 +27,13 @@ if [ -z "$(git status --porcelain)" ]; then
   exit 0
 fi
 
-# 生成提交说明(对比 HEAD 中的上次数据库快照)
+git add -A || { echo "git add 失败,本次终止"; exit 1; }
+if [ -z "$(git status --porcelain)" ]; then
+  echo "无实质变更,无需提交"
+  exit 0
+fi
+
+# 生成提交说明(对比 HEAD 中的上次数据库快照 + 暂存区代码差异)
 MSGFILE=$(mktemp) || MSGFILE=""
 PREVDB=$(mktemp) || PREVDB=""
 if [ -n "$MSGFILE" ] && [ -n "$PREVDB" ] && git show HEAD:s/studybase.db > "$PREVDB" 2>/dev/null; then
@@ -40,13 +46,6 @@ else
   : > "$MSGFILE"
 fi
 
-git add -A || { echo "git add 失败,本次终止"; rm -f "$PREVDB" "$MSGFILE"; exit 1; }
-if [ -z "$(git status --porcelain)" ]; then
-  echo "无实质变更,无需提交"
-  rm -f "$PREVDB" "$MSGFILE"
-  exit 0
-fi
-
 if [ -s "$MSGFILE" ]; then
   git commit -F "$MSGFILE" || { echo "git commit 失败,本次终止"; rm -f "$PREVDB" "$MSGFILE"; exit 1; }
 else
index ee51020fa519d373ffb1568c9373ce8809d84ff6..8b95d339a4034f7fc04f79f5691fcadf8f06dc2e 100644 (file)
 - 新增试卷ID
 - 反馈结果的试卷ID(判定行 result_type 有变化的试卷,附当前统计)
 """
-import sqlite3, sys, tempfile, os
+import sqlite3, sys, tempfile, os, subprocess
 from datetime import datetime
 
 prev_path, msg_path = sys.argv[1], sys.argv[2]
 cur_override = sys.argv[3] if len(sys.argv) > 3 else None
 LIVE = 's/studybase.db'
+REPO = os.path.dirname(os.path.abspath(__file__))
+
+
+def git(*args):
+    return subprocess.run(['git'] + list(args), cwd=REPO,
+                          capture_output=True, text=True).stdout
+
+
+def code_and_media_changes():
+    """读取已暂存(index)相对 HEAD 的变更,分离代码文件与 Media。
+    返回 (code_list, media_count),code_list 元素为 (status, path, added, deleted)。"""
+    code, media = [], 0
+    out = git('diff', '--cached', '--name-status', 'HEAD')
+    for line in out.splitlines():
+        if not line.strip():
+            continue
+        fields = line.split('\t')
+        st = fields[0][0]
+        path = fields[-1]
+        if path == LIVE or path.startswith('Media/'):
+            if path.startswith('Media/'):
+                media += 1
+            continue
+        ns = git('diff', '--cached', '--numstat', 'HEAD', '--', path).splitlines()
+        a = d = '-'
+        if ns:
+            a, d, _ = ns[0].split('\t')
+        if st == 'R':
+            code.append(('R', '%s -> %s' % (fields[1], fields[2]), a, d))
+        else:
+            code.append((st, path, a, d))
+    return code, media
 
 
 def backup_live():
@@ -91,13 +123,32 @@ def fb_detail(pid):
     return "%d/%d题:正确%d、错误%d、部分错误%d" % (n1 + n2 + n3, total, n1, n3, n2)
 
 
+code_changes, media_count = code_and_media_changes()
+
 lines = ["自动同步:代码/数据/Media 更新(%s)" % datetime.now().strftime('%Y-%m-%d %H:%M:%S')]
+if code_changes:
+    lines.append("代码变更:")
+    for st, p, a, d in code_changes:
+        if st == 'A':
+            lines.append("  - 新增 %s (+%s)" % (p, a))
+        elif st == 'M':
+            lines.append("  - 修改 %s (+%s -%s)" % (p, a, d))
+        elif st == 'D':
+            lines.append("  - 删除 %s" % p)
+        elif st == 'R':
+            lines.append("  - 重命名 %s" % p)
+        else:
+            lines.append("  - %s %s" % (st, p))
+else:
+    lines.append("代码变更:无")
 lines.append("新增题目ID:%s%s" % (ranges(new_q), "(共%d题)" % len(new_q) if new_q else ""))
 lines.append("新增试卷ID:%s%s" % (ranges(new_p), "(共%d份)" % len(new_p) if new_p else ""))
 if fb:
     lines.append("反馈结果:" + "、".join("试卷%d(%s)" % (pid, fb_detail(pid)) for pid in sorted(fb)))
 else:
     lines.append("反馈结果:无")
+if media_count:
+    lines.append("Media:更新 %d 个文件" % media_count)
 
 with open(msg_path, 'w', encoding='utf-8') as f:
     f.write("\n".join(lines) + "\n")