Files
karuo-ai/01_卡资(金)/金仓_存储备份/Gitea管理/脚本/自动同步.sh

206 lines
8.1 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
# ============================================
# 卡若AI → Gitea 实时同步局域网优先192.168.110.101:3000日志链接与 gitea_push.conf 一致)
# 规则:超过 1MB 的文件不上传;其余 Skill、功能、文档每日同步
# 推送成功后1) 同步百科 2) 写入 gitea_push_log.md 3) 写入 代码管理.md
# ============================================
REPO_DIR="/Users/karuo/Documents/个人/卡若AI"
REMOTE="gitea"
BRANCH="main"
MAX_SIZE_MB=1
MAX_SIZE_BYTES=$((MAX_SIZE_MB * 1024 * 1024))
LOG_FILE="$REPO_DIR/01_卡资/金仓_存储备份/Gitea管理/sync.log"
PUSH_LOG="$REPO_DIR/运营中枢/工作台/gitea_push_log.md"
CODE_MGMT="$REPO_DIR/运营中枢/工作台/代码管理.md"
GITEA_URL="http://192.168.110.101:3000/fnvtk/karuo-ai"
GITIGNORE="$REPO_DIR/.gitignore"
WIKI_SCRIPT="$REPO_DIR/01_卡资/金仓_存储备份/Gitea管理/脚本/sync_wiki_to_gitea.sh"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"; }
# 限制 sync.log 大小
if [ -f "$LOG_FILE" ] && [ $(stat -f%z "$LOG_FILE" 2>/dev/null || echo 0) -gt 512000 ]; then
tail -100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
fi
cd "$REPO_DIR" || { log "错误:无法进入目录 $REPO_DIR"; exit 1; }
# ============================================
# Step 0: 上传前检查公司 Gitea、仓库完整性和远端现状
# ============================================
if ! git fsck --connectivity-only --no-dangling >/dev/null 2>&1; then
log "错误:本地 Git 对象不完整,停止上传,避免把损坏历史推到公司 Gitea"
exit 2
fi
if ! GIT_TERMINAL_PROMPT=0 git -c http.connectTimeout=5 -c http.lowSpeedLimit=1 -c http.lowSpeedTime=8 \
ls-remote --exit-code --heads "$REMOTE" "$BRANCH" >/dev/null 2>&1; then
log "公司 Gitea 当前不可达或远端分支不存在,停止上传,等待下次重试"
exit 3
fi
if ! GIT_TERMINAL_PROMPT=0 git -c http.connectTimeout=5 -c http.lowSpeedLimit=1 -c http.lowSpeedTime=15 \
fetch --quiet "$REMOTE" "$BRANCH"; then
log "公司 Gitea 拉取检查失败,停止上传"
exit 4
fi
REMOTE_REF="refs/remotes/${REMOTE}/${BRANCH}"
if ! git show-ref --verify --quiet "$REMOTE_REF"; then
log "远端跟踪分支 ${REMOTE}/${BRANCH} 不存在,停止上传"
exit 5
fi
# ============================================
# Step 1: 排除 >1MB 文件(动态写入 .gitignore 区段)
# ============================================
MARKER_START="# === 自动排除:超过${MAX_SIZE_MB}MB的文件脚本自动管理勿手动修改==="
MARKER_END="# === 自动排除结束 ==="
LARGE_FILES=$(find . -type f -size +${MAX_SIZE_MB}M -not -path "./.git/*" 2>/dev/null | sort)
NEW_SECTION="$MARKER_START"
if [ -n "$LARGE_FILES" ]; then
while IFS= read -r file; do
clean_path="${file#./}"
NEW_SECTION="$NEW_SECTION
$clean_path"
done <<< "$LARGE_FILES"
fi
NEW_SECTION="$NEW_SECTION
$MARKER_END"
if grep -q '# === 自动排除:超过.*MB的文件' "$GITIGNORE" 2>/dev/null; then
python3 -c "
import re
with open('$GITIGNORE', 'r') as f:
content = f.read()
pattern = r'(?m)^# === 自动排除:超过[^\n]*MB的文件[^\n]*===\n.*?^# === 自动排除结束 ==='
new_content = re.sub(pattern, '''$NEW_SECTION''', content, flags=re.DOTALL)
with open('$GITIGNORE', 'w') as f:
f.write(new_content)
" 2>/dev/null
else
echo "" >> "$GITIGNORE"
echo "$NEW_SECTION" >> "$GITIGNORE"
fi
LARGE_COUNT=$(echo "$LARGE_FILES" | grep -c '.' 2>/dev/null || echo 0)
log "大文件扫描:$LARGE_COUNT 个 >${MAX_SIZE_MB}MB 已排除"
# ============================================
# Step 2: 检查是否有变更
# ============================================
git add -A 2>/dev/null
# 已被Git跟踪的大文件即使写入.gitignore仍可能被暂存逐项撤出本次提交。
while IFS= read -r -d '' file; do
size=0
if [ -f "$file" ]; then
size=$(stat -f%z "$file" 2>/dev/null || echo 0)
else
size=$(git cat-file -s "HEAD:$file" 2>/dev/null || echo 0)
fi
if [ "$size" -gt "$MAX_SIZE_BYTES" ]; then
git restore --staged -- "$file" 2>/dev/null || git reset -q HEAD -- "$file" 2>/dev/null || true
log "撤出暂存的大文件:$file (${size} bytes)"
fi
done < <(git diff --cached --name-only -z --diff-filter=ACMRD)
if git diff --cached --quiet 2>/dev/null; then
if [ "$(git rev-parse HEAD)" = "$(git rev-parse "$REMOTE_REF")" ]; then
log "本地与公司 Gitea 内容一致,无重复上传"
else
log "无新增文件变更,但本地与远端提交不同;停止并等待历史对账"
fi
exit 0
fi
# ============================================
# Step 3: 提交(提交说明写具体更新内容,不写「变更 N 个文件」)
# ============================================
CHANGED_COUNT=$(git diff --cached --numstat | wc -l | tr -d ' ')
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
SUMMARY_SCRIPT="$REPO_DIR/01_卡资/金仓_存储备份/Gitea管理/脚本/生成同步说明.py"
if [ -f "$SUMMARY_SCRIPT" ]; then
SUMMARY=$(git diff --cached --name-only 2>/dev/null | python3 "$SUMMARY_SCRIPT" 2>/dev/null)
[ -z "$SUMMARY" ] && SUMMARY="多目录更新"
else
SUMMARY="多目录更新"
fi
COMMIT_MSG="🔄 卡若AI 同步 $TIMESTAMP | 更新:$SUMMARY | 排除 >${MAX_SIZE_MB}MB: ${LARGE_COUNT}"
git commit -m "$COMMIT_MSG" --quiet 2>/dev/null
if [ $? -ne 0 ]; then
log "错误:提交失败"
exit 1
fi
log "提交成功:$COMMIT_MSG"
# 提交后再次比较远端:只允许远端是本地祖先时做快进推送。
if [ "$(git rev-parse HEAD)" = "$(git rev-parse "$REMOTE_REF")" ]; then
log "提交已存在于公司 Gitea跳过重复上传"
exit 0
fi
read -r AHEAD BEHIND <<<"$(git rev-list --left-right --count HEAD..."$REMOTE_REF")"
PUSH_MODE="normal"
if [ "${BEHIND:-0}" -gt 0 ]; then
# 用户指定本地为主:先保留远端快照分支,再以 force-with-lease 更新 main。
ARCHIVE_BRANCH="archive/remote-main-$(date '+%Y%m%d-%H%M%S')"
if ! git push "$REMOTE" "$REMOTE_REF:refs/heads/$ARCHIVE_BRANCH" --quiet; then
log "远端快照分支创建失败,停止上传,不直接覆盖"
exit 6
fi
log "已保留远端快照:$ARCHIVE_BRANCH;接下来以本地 main 为主同步"
PUSH_MODE="local-primary"
fi
if [ "${AHEAD:-0}" -eq 0 ]; then
log "没有需要上传的新提交"
exit 0
fi
# ============================================
# Step 4: 推送到 Gitea智能局域网用 IP外网用域名+代理)
# ============================================
PUSH_SCRIPT="$REPO_DIR/01_卡资/金仓_存储备份/Gitea管理/脚本/gitea_push_smart.sh"
if [ -x "$PUSH_SCRIPT" ]; then
bash "$PUSH_SCRIPT" "$REPO_DIR" "$REMOTE" "$BRANCH" "$PUSH_MODE" 2>&1 | tee -a "$LOG_FILE"
PUSH_RESULT=${PIPESTATUS[0]}
else
if [ "$PUSH_MODE" = "local-primary" ]; then
git push --force-with-lease="refs/heads/${BRANCH}:$(git rev-parse "$REMOTE_REF")" "$REMOTE" "${BRANCH}:${BRANCH}" --quiet 2>&1
else
git push "$REMOTE" "$BRANCH" --quiet 2>&1
fi
PUSH_RESULT=$?
fi
if [ $PUSH_RESULT -eq 0 ]; then
log "推送成功 → gitea/$BRANCH"
WIKI_STATUS="未执行"
if [ -x "$WIKI_SCRIPT" ]; then
if bash "$WIKI_SCRIPT" >> "$LOG_FILE" 2>&1; then
WIKI_STATUS="成功"
log "百科同步成功"
else
WIKI_STATUS="失败(百科未初始化或网络)"
log "百科同步失败"
fi
fi
# 建立推送记录
mkdir -p "$(dirname "$PUSH_LOG")"
if [ ! -f "$PUSH_LOG" ]; then
echo -e "# Gitea 推送记录\n\n> 卡若AI 有更新即同步到 ${GITEA_URL}\n\n| 时间 | 提交说明 |\n|:---|:---|" > "$PUSH_LOG"
fi
echo "| $(date '+%Y-%m-%d %H:%M:%S') | $COMMIT_MSG |" >> "$PUSH_LOG"
# 代码管理:写入本次上传(代码+百科+链接)
if [ -f "$CODE_MGMT" ]; then
echo "| $(date '+%Y-%m-%d %H:%M:%S') | 成功 | $WIKI_STATUS | $COMMIT_MSG | [仓库]($GITEA_URL) [百科]($GITEA_URL/wiki) |" >> "$CODE_MGMT"
fi
else
log "推送失败code=$PUSH_RESULT);保留本地提交,等待下次自动重试,不执行强制推送"
exit 1
fi
exit 0