Files
hermes-sync/sync.sh
2026-04-14 07:21:33 +09:00

152 lines
4.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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