#!/bin/bash # Hermes Sync Script - 同步记忆和技能到 Gitea # 用法: ./sync.sh [local|pull|push|status] set -e HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}" SYNC_DIR="/root/hermes-sync-tmp" BRANCH_NAME="$(hostname)" GITEA_REMOTE="origin" COMMIT_MSG="Sync $(date '+%Y-%m-%d %H:%M')" # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; } warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; } error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; } # 同步函数 - 从远程拉取最新记忆和技能 pull_changes() { log "Pulling latest changes from remote..." cd "$SYNC_DIR" git fetch "$GITEA_REMOTE" 2>/dev/null || warn "Fetch failed (may be empty repo)" # 尝试合并远程更改 if git rev-parse "$GITEA_REMOTE/$BRANCH_NAME" >/dev/null 2>&1; then if git show-ref --quiet -- HEAD 2>/dev/null && ! git diff --quiet "$GITEA_REMOTE/$BRANCH_NAME" HEAD 2>/dev/null; then log "Merging remote changes..." git merge "$GITEA_REMOTE/$BRANCH_NAME" --no-edit || { warn "Merge conflict detected, attempting auto-resolve..." # 自动解决:ours 优先(保留本地记忆) git checkout --ours memories/ skills/ 2>/dev/null || true git add memories/ skills/ git commit -m "Auto-resolved merge conflict at $(date)" } else log "Already up to date" fi fi # 如果本地分支不存在,基于远程创建 if ! git rev-parse "$BRANCH_NAME" >/dev/null 2>&1; then if git rev-parse "$GITEA_REMOTE/$BRANCH_NAME" >/dev/null 2>&1; then git checkout -b "$BRANCH_NAME" "$GITEA_REMOTE/$BRANCH_NAME" fi fi # 复制到 hermes 目录 rsync -a --delete "$SYNC_DIR/memories/" "$HERMES_HOME/memories/" 2>/dev/null || { mkdir -p "$HERMES_HOME/memories/" cp -r "$SYNC_DIR/memories/"* "$HERMES_HOME/memories/" 2>/dev/null || true } # 技能目录用 rsync 合并(不删除本地独有的) rsync -a --delete "$SYNC_DIR/skills/" "$HERMES_HOME/skills/" 2>/dev/null || { cp -r "$SYNC_DIR/skills/"* "$HERMES_HOME/skills/" 2>/dev/null || true } log "Pull complete. Memories and skills updated." } # 推送本地更改到远程 push_changes() { log "Pushing local changes to remote..." cd "$SYNC_DIR" # 确保分支存在 if ! git rev-parse "$BRANCH_NAME" >/dev/null 2>&1; then git checkout -b "$BRANCH_NAME" fi # 复制 hermes 内容到同步目录 mkdir -p "$SYNC_DIR/memories" "$SYNC_DIR/skills" rsync -a "$HERMES_HOME/memories/" "$SYNC_DIR/memories/" 2>/dev/null || true rsync -a "$HERMES_HOME/skills/" "$SYNC_DIR/skills/" 2>/dev/null || true # 检查是否有更改 if git diff --quiet && git diff --cached --quiet; then log "No changes to push" return 0 fi git add -A git commit -m "$COMMIT_MSG" git push "$GITEA_REMOTE" "$BRANCH_NAME" --force || { error "Push failed! Check credentials and network." return 1 } log "Push complete. Your changes are now synced." } # 双向同步 sync_bidirectional() { log "Starting bidirectional sync..." pull_changes push_changes } # 查看状态 show_status() { cd "$SYNC_DIR" echo "=== Hermes Sync Status ===" echo "Branch: $BRANCH_NAME" echo "" echo "Local changes:" git status -s 2>/dev/null || echo " (clean)" echo "" echo "Remote changes:" git fetch "$GITEA_REMOTE" 2>/dev/null if git rev-parse "$GITEA_REMOTE/$BRANCH_NAME" >/dev/null 2>&1; then BEHIND=$(git rev-list --count "$BRANCH_NAME..$GITEA_REMOTE/$BRANCH_NAME" 2>/dev/null || echo "?") AHEAD=$(git rev-list --count "$GITEA_REMOTE/$BRANCH_NAME..$BRANCH_NAME" 2>/dev/null || echo "?") echo " Behind remote: $BEHIND commits" echo " Ahead of remote: $AHEAD commits" else echo " No remote branch yet" fi echo "" echo "Last sync:" git log -1 --format="%cr (%s)" 2>/dev/null || echo " Never committed" } # 主逻辑 case "${1:-status}" in pull) pull_changes ;; push) push_changes ;; sync|bidirectional) sync_bidirectional ;; status) show_status ;; *) echo "Usage: $0 {pull|push|sync|status}" echo " pull - Pull from remote to local" echo " push - Push local to remote" echo " sync - Pull then push (bidirectional)" echo " status - Show sync status" exit 1 ;; esac