自检修复: reflog读git + threaded=True + TODO误判修正
- Git: 从.git/logs/HEAD读取提交历史,不依赖git二进制 - Flask: threaded=True防止单线程阻塞 - TODO: 'already running'→completed而非failed - E元成长: 改用reflog行数计算commit数
This commit is contained in:
@@ -562,22 +562,45 @@ def api_kanban():
|
||||
# ════════════════════════════════════════════════════════════
|
||||
@app.route("/api/git")
|
||||
def api_git():
|
||||
"""最近 git 提交历史 + 分支状态"""
|
||||
"""最近 git 提交历史 + 分支状态(从 .git 直接读取,不依赖 git 命令)"""
|
||||
try:
|
||||
git_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")
|
||||
git_dir = os.path.normpath(git_dir) # → AgentsMeeting/
|
||||
if not os.path.exists(os.path.join(git_dir, ".git")):
|
||||
# 如果 _PROJECT_OVERRIDE 设置了,用它
|
||||
git_dir = os.environ.get("AGENTSMEETING_ROOT", "")
|
||||
if not git_dir or not os.path.exists(os.path.join(git_dir, ".git")):
|
||||
return jsonify({"ok": False, "log": [".git not found at " + git_dir], "dirty": False})
|
||||
r = subprocess.run(["git", "log", "--oneline", "-10"],
|
||||
cwd=git_dir, capture_output=True, text=True, timeout=5)
|
||||
log_lines = r.stdout.strip().split("\n") if r.returncode == 0 else ["git not available"]
|
||||
r2 = subprocess.run(["git", "status", "--short"],
|
||||
cwd=git_dir, capture_output=True, text=True, timeout=5)
|
||||
dirty = r2.stdout.strip() != "" if r2.returncode == 0 else False
|
||||
return jsonify({"ok": True, "log": log_lines if log_lines != [""] else [], "dirty": dirty, "branch": "master"})
|
||||
git_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".."))
|
||||
dot_git = os.path.join(git_dir, ".git")
|
||||
if not os.path.exists(dot_git):
|
||||
alt = os.environ.get("AGENTSMEETING_ROOT", "")
|
||||
if alt and os.path.exists(os.path.join(alt, ".git")):
|
||||
git_dir = alt
|
||||
dot_git = os.path.join(alt, ".git")
|
||||
else:
|
||||
return jsonify({"ok": True, "log": [], "dirty": False, "note": "no .git"})
|
||||
# 从 .git/logs/HEAD 读取最近提交
|
||||
reflog = os.path.join(dot_git, "logs", "HEAD")
|
||||
log_lines = []
|
||||
if os.path.exists(reflog):
|
||||
with open(reflog, "r", encoding="utf-8", errors="replace") as f:
|
||||
lines = f.readlines()
|
||||
# 取最后 10 行非空行,格式: "hash hash user ... msg"
|
||||
for line in reversed(lines):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
parts = line.split("\t")
|
||||
msg = parts[-1] if len(parts) > 1 else line
|
||||
# 取前 7 位 hash
|
||||
hash_part = line.split()[1][:7] if len(line.split()) > 1 else "?"
|
||||
log_lines.append(f"{hash_part} {msg}")
|
||||
if len(log_lines) >= 10:
|
||||
break
|
||||
# 检查是否有未提交的改动:比较 .git/index 的 mtime 与 HEAD
|
||||
dirty = False
|
||||
head_file = os.path.join(dot_git, "HEAD")
|
||||
index_file = os.path.join(dot_git, "index")
|
||||
if os.path.exists(head_file) and os.path.exists(index_file):
|
||||
try:
|
||||
dirty = os.path.getmtime(index_file) > os.path.getmtime(head_file)
|
||||
except:
|
||||
pass
|
||||
return jsonify({"ok": True, "log": log_lines, "dirty": dirty, "branch": "master", "source": "reflog"})
|
||||
except Exception as e:
|
||||
return jsonify({"ok": False, "error": str(e), "log": [], "dirty": False})
|
||||
|
||||
@@ -681,16 +704,16 @@ def api_metagrowth():
|
||||
entry = json.loads(line)
|
||||
if entry.get("status") == "completed":
|
||||
completed_fixes += 1
|
||||
# 统计 git 提交次数(用作开发活动指标)
|
||||
git_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".."))
|
||||
# 统计 git 提交次数(从 reflog 行数计算)
|
||||
git_dir2 = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".."))
|
||||
commit_count = 0
|
||||
try:
|
||||
r = subprocess.run(["git", "rev-list", "--count", "HEAD"],
|
||||
cwd=git_dir, capture_output=True, text=True, timeout=5)
|
||||
if r.returncode == 0:
|
||||
commit_count = int(r.stdout.strip())
|
||||
except:
|
||||
pass
|
||||
reflog = os.path.join(git_dir2, ".git", "logs", "HEAD")
|
||||
if os.path.exists(reflog):
|
||||
try:
|
||||
with open(reflog, "r", encoding="utf-8", errors="replace") as f:
|
||||
commit_count = sum(1 for line in f if line.strip())
|
||||
except:
|
||||
pass
|
||||
return jsonify({
|
||||
"ok": True,
|
||||
"status": "planned", # Phase 3
|
||||
@@ -814,7 +837,7 @@ def main():
|
||||
port = int(os.environ.get("DASHBOARD_PORT", 5803))
|
||||
log.info(f"Dashboard starting on :{port}")
|
||||
print(f"[dashboard] Starting on http://127.0.0.1:{port}")
|
||||
app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False)
|
||||
app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False, threaded=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -162,7 +162,11 @@ def main():
|
||||
log(f"处理: {service} — {issue}")
|
||||
|
||||
success, detail = execute_fix(entry)
|
||||
if success:
|
||||
# "another instance is already running" = 服务已在正常运行,不算失败
|
||||
if not success and "another instance is already running" in detail:
|
||||
mark_todo(entry, "completed", "already_running")
|
||||
log(f" ✅ {service}: 已在运行,无需修复 ({detail[:60]})")
|
||||
elif success:
|
||||
mark_todo(entry, "completed", detail)
|
||||
log(f" ✅ {service}: 修复成功 ({detail})")
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user