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
: > "$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
- 新增试卷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():
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")