docs: 按照开发规范重构项目,完成七个环节文档整理与.xagent流程搭建
This commit is contained in:
107
.xagent/check-dirty.py
Normal file
107
.xagent/check-dirty.py
Normal file
@@ -0,0 +1,107 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
# Force stdout to be UTF-8 for Windows terminals
|
||||
if hasattr(sys.stdout, 'reconfigure'):
|
||||
sys.stdout.reconfigure(encoding='utf-8')
|
||||
|
||||
NOW = time.time()
|
||||
|
||||
def get_git_timestamp(filepath):
|
||||
# Normalize paths to use forward slashes for git compatibility
|
||||
git_path = filepath.replace('\\', '/')
|
||||
|
||||
# 1. Check if the file exists on disk.
|
||||
if not os.path.exists(filepath):
|
||||
return 0
|
||||
|
||||
# 2. Check for local modifications (staged or unstaged)
|
||||
try:
|
||||
status_proc = subprocess.run(
|
||||
['git', 'status', '--porcelain', '--', git_path],
|
||||
capture_output=True, text=True, check=True
|
||||
)
|
||||
if status_proc.stdout.strip():
|
||||
# Locally modified files are considered "edited just now"
|
||||
return NOW
|
||||
except subprocess.SubprocessError:
|
||||
pass
|
||||
|
||||
# 3. Get the last commit timestamp
|
||||
try:
|
||||
log_proc = subprocess.run(
|
||||
['git', 'log', '-1', '--format=%ct', '--', git_path],
|
||||
capture_output=True, text=True, check=True
|
||||
)
|
||||
output = log_proc.stdout.strip()
|
||||
if output.isdigit():
|
||||
return int(output)
|
||||
except subprocess.SubprocessError:
|
||||
pass
|
||||
|
||||
# 4. Fallback to OS modification time if file exists but has no git commits yet
|
||||
try:
|
||||
return os.path.getmtime(filepath)
|
||||
except OSError:
|
||||
return 0
|
||||
|
||||
def check_dirty():
|
||||
graph_path = os.path.join(os.path.dirname(__file__), 'graph.json')
|
||||
if not os.path.exists(graph_path):
|
||||
print(f"Error: graph.json not found at {graph_path}")
|
||||
sys.exit(1)
|
||||
|
||||
with open(graph_path, 'r', encoding='utf-8') as f:
|
||||
graph = json.load(f)
|
||||
|
||||
files_dict = graph.get('files', {})
|
||||
timestamps = {}
|
||||
|
||||
# Calculate timestamps for all files
|
||||
for filepath in files_dict.keys():
|
||||
timestamps[filepath] = get_git_timestamp(filepath)
|
||||
|
||||
dirty_files = {}
|
||||
|
||||
# Check dependencies
|
||||
for filepath, info in files_dict.items():
|
||||
depends_on = info.get('depends_on', [])
|
||||
file_ts = timestamps[filepath]
|
||||
|
||||
# If the file itself doesn't exist, it's not "dirty" in the sense of being out of date,
|
||||
# but it is missing. However, to keep it clean, if it doesn't exist, we can skip or flag it.
|
||||
# Let's say if a file exists, we check if its dependencies are newer.
|
||||
if file_ts == 0:
|
||||
# File is missing on disk
|
||||
continue
|
||||
|
||||
file_dirty_deps = []
|
||||
for dep in depends_on:
|
||||
dep_ts = get_git_timestamp(dep)
|
||||
if dep_ts > file_ts:
|
||||
file_dirty_deps.append((dep, dep_ts, file_ts))
|
||||
|
||||
if file_dirty_deps:
|
||||
dirty_files[filepath] = file_dirty_deps
|
||||
|
||||
if dirty_files:
|
||||
print("\n[DIRTY] 发现以下下游文件落后于其上游依赖:")
|
||||
for filepath, deps in dirty_files.items():
|
||||
print(f"\n* {filepath}")
|
||||
for dep, dep_ts, file_ts in deps:
|
||||
dep_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(dep_ts))
|
||||
file_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(file_ts))
|
||||
print(f" [依赖于] {dep}")
|
||||
print(f" (上游最后提交: {dep_time} > 下游最后提交: {file_time})")
|
||||
print("\n请跟进并更新上述下游文件,重新 commit 即可刷新基线并自动消脏。\n")
|
||||
return False
|
||||
else:
|
||||
print("\n[CLEAN] 所有文件均已与依赖同步,无脏文件。\n")
|
||||
return True
|
||||
|
||||
if __name__ == '__main__':
|
||||
success = check_dirty()
|
||||
sys.exit(0 if success else 1)
|
||||
Reference in New Issue
Block a user