sin601/claude-code
0
1#!/bin/bash2# Git 双向同步服务3 4set -e5 6CONFIG_DIR="${CONFIG_DIR:-/config}"7WORK_DIR="${WORK_DIR:-/workspace}"8HOME="${HOME:-/root}"9 10# 加载配置11if [ -f "${CONFIG_DIR}/config.env" ]; then12 set -a13 source "${CONFIG_DIR}/config.env"14 set +a15fi16 17# 默认值18GIT_SYNC_INTERVAL="${GIT_SYNC_INTERVAL:-300}"19GIT_BRANCH="${GIT_BRANCH:-main}"20SYNC_EXCLUDE="${SYNC_EXCLUDE:-node_modules .git __pycache__ *.pyc .env *.log .cache tmp}"21COMMIT_PREFIX="${COMMIT_PREFIX:-[HF-Space]}"22 23# 日志函数24log() {25 echo "[$(date '+%Y-%m-%d %H:%M:%S')] [git-sync] $1"26}27 28# 错误处理29error() {30 echo "[$(date '+%Y-%m-%d %H:%M:%S')] [git-sync] ERROR: $1" >&231}32 33# 检查 Git 配置34check_git_config() {35 if [ -z "${GIT_REPO_URL}" ]; then36 log "GIT_REPO_URL not configured. Git sync disabled."37 return 138 fi39 40 if [ -z "${GIT_TOKEN}" ]; then41 log "GIT_TOKEN not configured. Git sync disabled."42 return 143 fi44 45 return 046}47 48# 配置 Git 远程仓库49setup_remote() {50 cd "${WORK_DIR}"51 52 # 构建带认证的 URL53 if [[ "${GIT_REPO_URL}" == https://github.com/* ]]; then54 AUTH_URL="https://${GIT_TOKEN}@github.com/${GIT_REPO_URL#https://github.com/}"55 elif [[ "${GIT_REPO_URL}" == https://gitlab.com/* ]]; then56 AUTH_URL="https://oauth2:${GIT_TOKEN}@gitlab.com/${GIT_REPO_URL#https://gitlab.com/}"57 elif [[ "${GIT_REPO_URL}" == https://huggingface.co/* ]]; then58 AUTH_URL="https://user:${GIT_TOKEN}@huggingface.co/${GIT_REPO_URL#https://huggingface.co/}"59 else60 AUTH_URL="${GIT_REPO_URL}"61 fi62 63 # 检查是否已有远程仓库64 if git remote | grep -q "^origin$"; then65 git remote set-url origin "${AUTH_URL}"66 else67 git remote add origin "${AUTH_URL}"68 fi69 70 log "Git remote configured"71}72 73# 初始拉取74initial_pull() {75 cd "${WORK_DIR}"76 77 # 检查是否有提交78 if ! git rev-parse HEAD >/dev/null 2>&1; then79 log "No commits in local repo. Pulling from remote..."80 81 # 备份本地文件82 if [ "$(ls -A . 2>/dev/null | grep -v '^.git$')" ]; then83 log "Backing up local files..."84 mkdir -p /tmp/workspace-backup85 find . -maxdepth 1 ! -name '.git' ! -name '.' -exec cp -r {} /tmp/workspace-backup/ \;86 fi87 88 # 拉取远程89 git fetch origin "${GIT_BRANCH}" || true90 git checkout -b "${GIT_BRANCH}" || git checkout "${GIT_BRANCH}"91 git reset --hard "origin/${GIT_BRANCH}" 2>/dev/null || true92 93 # 恢复备份文件(如果有冲突,保留远程版本)94 if [ -d /tmp/workspace-backup ] && [ "$(ls -A /tmp/workspace-backup 2>/dev/null)" ]; then95 log "Restoring local files..."96 cp -r /tmp/workspace-backup/* . 2>/dev/null || true97 rm -rf /tmp/workspace-backup98 fi99 fi100}101 102# 推送变更103push_changes() {104 cd "${WORK_DIR}"105 106 # 检查是否有变更107 if [ -z "$(git status --porcelain)" ]; then108 log "No changes to push"109 return 0110 fi111 112 log "Pushing changes to remote..."113 114 # 添加所有变更115 git add -A116 117 # 排除敏感文件118 for pattern in ${SYNC_EXCLUDE}; do119 git reset HEAD "${pattern}" 2>/dev/null || true120 done121 122 # 生成提交信息123 CHANGES=$(git status --porcelain | head -20)124 COMMIT_MSG="${COMMIT_PREFIX} Auto-sync $(date '+%Y-%m-%d %H:%M:%S')125 126Changes:127${CHANGES}"128 129 # 提交130 git commit -m "${COMMIT_MSG}" || {131 log "Nothing to commit"132 return 0133 }134 135 # 拉取远程变更(rebase)136 git fetch origin "${GIT_BRANCH}" || true137 git rebase "origin/${GIT_BRANCH}" 2>/dev/null || {138 log "Rebase conflict detected. Creating backup and forcing push..."139 # 创建冲突备份140 git stash push -m "conflict-backup-$(date +%s)" 2>/dev/null || true141 git rebase --abort 2>/dev/null || true142 git reset --hard "origin/${GIT_BRANCH}"143 git stash pop 2>/dev/null || true144 }145 146 # 推送147 git push origin "${GIT_BRANCH}" || {148 error "Failed to push changes"149 return 1150 }151 152 log "Changes pushed successfully"153}154 155# 拉取变更156pull_changes() {157 cd "${WORK_DIR}"158 159 log "Pulling changes from remote..."160 161 # 获取远程变更162 git fetch origin "${GIT_BRANCH}" || return 1163 164 # 检查是否有新变更165 LOCAL=$(git rev-parse HEAD 2>/dev/null || echo "")166 REMOTE=$(git rev-parse "origin/${GIT_BRANCH}" 2>/dev/null || echo "")167 168 if [ "$LOCAL" = "$REMOTE" ]; then169 log "Remote is up to date"170 return 0171 fi172 173 # 保存本地变更174 if [ -n "$(git status --porcelain)" ]; then175 log "Stashing local changes..."176 git stash push -m "auto-stash-$(date +%s)"177 fi178 179 # 拉取180 git pull --rebase origin "${GIT_BRANCH}" || {181 error "Pull conflict detected"182 git rebase --abort 2>/dev/null || true183 return 1184 }185 186 # 恢复本地变更187 git stash pop 2>/dev/null || true188 189 log "Changes pulled successfully"190}191 192# 同步状态193sync_status() {194 cd "${WORK_DIR}"195 196 echo "=== Git Sync Status ==="197 echo "Repository: ${GIT_REPO_URL:-Not configured}"198 echo "Branch: ${GIT_BRANCH}"199 echo "Interval: ${GIT_SYNC_INTERVAL}s"200 echo ""201 202 if [ -d ".git" ]; then203 echo "Local commits:"204 git log --oneline -5 2>/dev/null || echo "No commits yet"205 echo ""206 echo "Working directory status:"207 git status --short 2>/dev/null || echo "Clean"208 else209 echo "Not a git repository"210 fi211}212 213# 主同步循环214main_loop() {215 log "Starting Git sync service..."216 log "Repository: ${GIT_REPO_URL}"217 log "Branch: ${GIT_BRANCH}"218 log "Interval: ${GIT_SYNC_INTERVAL}s"219 220 # 初始设置221 setup_remote222 initial_pull223 224 # 同步循环225 while true; do226 sleep "${GIT_SYNC_INTERVAL}"227 228 # 先拉取再推送229 pull_changes || true230 push_changes || true231 done232}233 234# 命令行接口235case "${1:-}" in236 push)237 check_git_config || exit 1238 setup_remote239 push_changes240 ;;241 pull)242 check_git_config || exit 1243 setup_remote244 pull_changes245 ;;246 status)247 sync_status248 ;;249 init)250 check_git_config || exit 1251 setup_remote252 initial_pull253 ;;254 *)255 if check_git_config; then256 main_loop257 else258 log "Git sync service not started due to missing configuration"259 # 保持进程运行但不执行同步260 tail -f /dev/null261 fi262 ;;263esac264 