#!/usr/bin/env python3 # git_auto_commit.py - 自动提交指定目录到 Gitea # 用法: python git_auto_commit.py [目录路径] import os import sys import shutil import subprocess import tempfile from datetime import datetime from pathlib import Path from urllib.parse import urlparse # 配置 REPO_URL = "https://gittea.dev/popiskill/skills.git" BRANCH = "master" DEFAULT_SOURCE_DIR = "C:/ai/openclaw" # Windows 路径格式 # 排除的文件/目录 EXCLUDE_PATTERNS = ['.git', '.openclaw'] def load_config(): """从配置文件读取凭证""" script_dir = Path(__file__).parent config_file = script_dir / "git_config.env" if not config_file.exists(): print(f"错误: 配置文件不存在: {config_file}") print("请创建配置文件并设置 GIT_USERNAME 和 GIT_TOKEN") sys.exit(1) config = {} with open(config_file, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if line and not line.startswith('#') and '=' in line: key, value = line.split('=', 1) config[key.strip()] = value.strip().strip('"\'') if not config.get('GIT_USERNAME') or not config.get('GIT_TOKEN'): print("错误: 请在配置文件中设置 GIT_USERNAME 和 GIT_TOKEN") sys.exit(1) return config['GIT_USERNAME'], config['GIT_TOKEN'] def build_auth_url(repo_url, username, token): """构建带凭证的 URL""" parsed = urlparse(repo_url) return f"{parsed.scheme}://{username}:{token}@{parsed.netloc}{parsed.path}" def copy_directory(src, dst, exclude=None): """复制目录,排除指定文件""" if exclude is None: exclude = [] src_path = Path(src) dst_path = Path(dst) for item in src_path.rglob('*'): # 检查是否在排除列表中 rel_path = item.relative_to(src_path) if any(part in exclude for part in rel_path.parts): continue if item.is_file(): target = dst_path / rel_path target.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(item, target) def run_git_command(args, cwd=None, check=True): """运行 git 命令""" result = subprocess.run( ['git'] + args, cwd=cwd, capture_output=True, text=True, encoding='utf-8' ) if check and result.returncode != 0: print(f"Git 错误: {result.stderr}") raise subprocess.CalledProcessError(result.returncode, ['git'] + args) return result def main(): # 获取源目录 if len(sys.argv) < 2: source_dir = DEFAULT_SOURCE_DIR print(f"未指定目录,使用默认: {source_dir}") else: source_dir = sys.argv[1] source_path = Path(source_dir) if not source_path.exists(): print(f"错误: 目录不存在: {source_dir}") sys.exit(1) # 加载配置 username, token = load_config() # 创建临时工作目录 work_dir = tempfile.mkdtemp(prefix='git_auto_commit_') print(f"工作目录: {work_dir}") print(f"源目录: {source_dir}") try: # 构建带凭证的 URL auth_url = build_auth_url(REPO_URL, username, token) # 尝试克隆现有仓库 try: run_git_command(['clone', auth_url, '.'], cwd=work_dir) print("已克隆现有仓库") except subprocess.CalledProcessError: print("初始化新仓库...") run_git_command(['init'], cwd=work_dir) run_git_command(['remote', 'add', 'origin', auth_url], cwd=work_dir) # 复制文件到仓库 print("复制文件...") copy_directory(source_dir, work_dir, exclude=EXCLUDE_PATTERNS) # 配置 git run_git_command(['config', 'user.email', 'auto@commit.local'], cwd=work_dir) run_git_command(['config', 'user.name', 'Auto Commit'], cwd=work_dir) # 添加所有更改 run_git_command(['add', '-A'], cwd=work_dir) # 检查是否有更改要提交 status_result = run_git_command(['diff', '--cached', '--quiet'], cwd=work_dir, check=False) if status_result.returncode == 0: print("没有更改需要提交") return # 提交并推送 commit_msg = f"Auto commit: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" run_git_command(['commit', '-m', commit_msg], cwd=work_dir) run_git_command(['push', 'origin', BRANCH], cwd=work_dir) print(f"✓ 成功提交到 {REPO_URL}") finally: # 清理临时目录 shutil.rmtree(work_dir, ignore_errors=True) if __name__ == '__main__': main()