From 49774009be512a0e2dc4ae1298f3076dc259d16d Mon Sep 17 00:00:00 2001 From: Mixer Date: Tue, 14 Apr 2026 07:21:33 +0900 Subject: [PATCH] Initial hermes sync setup --- .gitignore | 13 +++++ sync.sh | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 .gitignore create mode 100755 sync.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4868cd3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Ignore everything by default +* + +# But explicitly track these directories +!memories/ +!skills/ +!sync.sh +!.gitignore + +# Ignore lock files and logs +memories/*.lock +skills/*.lock +*.log diff --git a/sync.sh b/sync.sh new file mode 100755 index 0000000..e6c9536 --- /dev/null +++ b/sync.sh @@ -0,0 +1,151 @@ +#!/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