novel-doomsday-resurgence/tools/git_version_manager.sh

626 lines
18 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
# 《末日重生》项目Git版本管理脚本
# 提供自动提交、版本标签、定时同步功能
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LOG_FILE="$PROJECT_DIR/logs/git_version.log"
CONFIG_FILE="$PROJECT_DIR/config/version_config.json"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 初始化日志和配置
init() {
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$(dirname "$CONFIG_FILE")"
if [ ! -f "$CONFIG_FILE" ]; then
cat > "$CONFIG_FILE" << EOF
{
"auto_commit": true,
"commit_pattern": "更新: {date} {time}",
"commit_threshold": 3,
"auto_tag": true,
"tag_pattern": "v{version}",
"tag_milestones": [5, 10, 20, 50, 100],
"sync_enabled": true,
"sync_schedule": "*/30 * * * *",
"backup_enabled": true,
"backup_retention": 7,
"notifications": {
"on_success": true,
"on_failure": true
}
}
EOF
fi
}
# 日志函数
log() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
case $level in
"INFO") color=$GREEN ;;
"WARN") color=$YELLOW ;;
"ERROR") color=$RED ;;
*) color=$NC ;;
esac
echo -e "${color}[$timestamp] [$level] $message${NC}"
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
}
# 检查Git状态
check_git_status() {
log "INFO" "检查Git状态..."
cd "$PROJECT_DIR"
# 检查是否有未提交的更改
if [ -n "$(git status --porcelain)" ]; then
changed_files=$(git status --porcelain | wc -l)
log "INFO" "检测到 $changed_files 个未提交的文件"
# 显示更改摘要
echo "📝 更改摘要:"
git status --short
echo ""
return 0 # 有更改
else
log "INFO" "没有未提交的更改"
return 1 # 没有更改
fi
}
# 自动提交更改
auto_commit() {
local message="$1"
if [ -z "$message" ]; then
local current_date=$(date '+%Y年%m月%d日')
local current_time=$(date '+%H:%M:%S')
message="更新: $current_date $current_time"
fi
log "INFO" "自动提交更改: $message"
cd "$PROJECT_DIR"
# 添加所有更改
git add .
# 提交
if git commit -m "$message" > /dev/null 2>&1; then
local commit_hash=$(git rev-parse --short HEAD)
log "INFO" "✅ 提交成功 (commit: $commit_hash)"
echo "提交信息: $message"
echo "提交哈希: $commit_hash"
return 0
else
log "ERROR" "❌ 提交失败"
return 1
fi
}
# 创建版本标签
create_version_tag() {
local tag_name="$1"
local tag_message="$2"
if [ -z "$tag_name" ]; then
# 自动生成标签名
local current_version=$(git tag | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)
if [ -z "$current_version" ]; then
current_version="v0.0.0"
fi
# 递增版本号
local major=$(echo "$current_version" | cut -d. -f1 | tr -d 'v')
local minor=$(echo "$current_version" | cut -d. -f2)
local patch=$(echo "$current_version" | cut -d. -f3)
patch=$((patch + 1))
# 每10个小版本升级一个中版本
if [ $patch -ge 10 ]; then
patch=0
minor=$((minor + 1))
fi
# 每10个中版本升级一个大版本
if [ $minor -ge 10 ]; then
minor=0
major=$((major + 1))
fi
tag_name="v${major}.${minor}.${patch}"
fi
if [ -z "$tag_message" ]; then
local chapter_count=$(find "$PROJECT_DIR/chapters" -name "*.md" | wc -l)
local total_words=0
for chapter in "$PROJECT_DIR/chapters"/*.md; do
if [ -f "$chapter" ]; then
words=$(wc -w < "$chapter" 2>/dev/null || echo 0)
total_words=$((total_words + words))
fi
done
tag_message="版本 ${tag_name} | 章节: ${chapter_count}章 | 字数: ${total_words}"
fi
log "INFO" "创建版本标签: $tag_name"
if git tag -a "$tag_name" -m "$tag_message" > /dev/null 2>&1; then
log "INFO" "✅ 标签创建成功: $tag_name"
echo "标签名称: $tag_name"
echo "标签描述: $tag_message"
return 0
else
log "ERROR" "❌ 标签创建失败"
return 1
fi
}
# 同步到远程仓库
sync_to_remote() {
local force="$1"
log "INFO" "同步到远程仓库..."
cd "$PROJECT_DIR"
# 检查远程仓库
if ! git remote get-url origin > /dev/null 2>&1; then
log "ERROR" "❌ 未配置远程仓库"
return 1
fi
# 获取远程仓库信息
local remote_url=$(git remote get-url origin)
log "INFO" "远程仓库: $(echo $remote_url | sed 's|https://.*@||')"
# 拉取最新更改
log "INFO" "拉取远程更改..."
if ! git pull --rebase origin master 2>&1 | grep -q "Already up to date"; then
log "INFO" "✅ 已更新本地仓库"
fi
# 推送更改
log "INFO" "推送到远程仓库..."
if [ "$force" = "true" ]; then
if git push origin master --tags --force 2>&1; then
log "INFO" "✅ 强制推送成功"
else
log "ERROR" "❌ 推送失败"
return 1
fi
else
if git push origin master --tags 2>&1; then
log "INFO" "✅ 推送成功"
else
log "WARN" "⚠️ 推送失败,尝试强制推送..."
if git push origin master --tags --force 2>&1; then
log "INFO" "✅ 强制推送成功"
else
log "ERROR" "❌ 强制推送失败"
return 1
fi
fi
fi
# 显示同步结果
local current_branch=$(git branch --show-current)
local latest_commit=$(git log -1 --format="%h - %s" 2>/dev/null)
local tag_count=$(git tag | wc -l)
echo ""
echo "📊 同步完成报告"
echo "├─ 分支: $current_branch"
echo "├─ 最新提交: $latest_commit"
echo "├─ 版本标签: $tag_count"
echo "└─ 远程仓库: $(echo $remote_url | sed 's|https://.*@||')"
return 0
}
# 自动备份
create_backup() {
local backup_type="$1"
log "INFO" "创建项目备份..."
local backup_dir="$PROJECT_DIR/backups"
local timestamp=$(date '+%Y%m%d_%H%M%S')
mkdir -p "$backup_dir"
case $backup_type in
"full")
# 完整备份
local backup_file="$backup_dir/full_backup_$timestamp.tar.gz"
tar -czf "$backup_file" -C "$PROJECT_DIR" .
log "INFO" "✅ 完整备份创建: $(basename $backup_file)"
;;
"git")
# Git包备份
local backup_file="$backup_dir/git_bundle_$timestamp.bundle"
git bundle create "$backup_file" --all
log "INFO" "✅ Git包备份创建: $(basename $backup_file)"
;;
"chapters")
# 章节备份
local backup_file="$backup_dir/chapters_$timestamp.tar.gz"
tar -czf "$backup_file" -C "$PROJECT_DIR" chapters/
log "INFO" "✅ 章节备份创建: $(basename $backup_file)"
;;
*)
# 默认备份
local backup_file="$backup_dir/backup_$timestamp.tar.gz"
tar -czf "$backup_file" -C "$PROJECT_DIR" chapters/ outlines/ assets/
log "INFO" "✅ 默认备份创建: $(basename $backup_file)"
;;
esac
# 清理旧备份
local retention_days=7
find "$backup_dir" -name "*.tar.gz" -mtime +$retention_days -delete 2>/dev/null
find "$backup_dir" -name "*.bundle" -mtime +$retention_days -delete 2>/dev/null
echo "备份文件: $backup_file"
echo "备份大小: $(du -h "$backup_file" | cut -f1)"
return 0
}
# 项目状态报告
generate_status_report() {
log "INFO" "生成项目状态报告..."
cd "$PROJECT_DIR"
local report_file="$PROJECT_DIR/progress/status_report_$(date '+%Y%m%d').md"
mkdir -p "$(dirname "$report_file")"
# 收集数据
local chapter_count=$(find chapters -name "*.md" | wc -l)
local total_words=0
local latest_chapter=""
local latest_chapter_time=""
for chapter in chapters/*.md; do
if [ -f "$chapter" ]; then
words=$(wc -w < "$chapter" 2>/dev/null || echo 0)
total_words=$((total_words + words))
# 找到最新章节
chapter_time=$(stat -c %Y "$chapter" 2>/dev/null || echo 0)
if [ -z "$latest_chapter_time" ] || [ $chapter_time -gt $latest_chapter_time ]; then
latest_chapter_time=$chapter_time
latest_chapter=$(basename "$chapter" .md)
fi
fi
done
local commit_count=$(git rev-list --count HEAD 2>/dev/null || echo 0)
local latest_commit=$(git log -1 --format="%h - %s (%ad)" --date=short 2>/dev/null || echo "无")
local tag_count=$(git tag | wc -l)
local latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "无")
# 生成报告
cat > "$report_file" << EOF
# 《末日重生》项目状态报告
## 报告时间
$(date '+%Y年%m月%d日 %H:%M:%S')
## 创作进度
- **总章节**: ${chapter_count} 章
- **总字数**: ${total_words} 字
- **最新章节**: ${latest_chapter}
- **平均每章字数**: $((total_words / chapter_count)) 字
## 版本管理
- **提交次数**: ${commit_count} 次
- **最新提交**: ${latest_commit}
- **版本标签**: ${tag_count} 个
- **最新版本**: ${latest_tag}
## 番茄平台适配
### 字数要求
- 标准章节字数: 2500-3500字
- 当前平均: $((total_words / chapter_count)) 字
- 状态: $(if [ $((total_words / chapter_count)) -ge 2000 ] && [ $((total_words / chapter_count)) -le 3500 ]; then echo "✅ 符合标准"; else echo "⚠️ 需要调整"; fi)
### 更新要求
- 日更全勤要求: 4000字/天
- 当前总字数: ${total_words} 字
- 相当于: $((total_words / 4000)) 天的全勤更新量
## Git状态
\`\`\`bash
$(git status --short 2>/dev/null || echo "无未提交更改")
\`\`\`
## 下一步计划
1. [ ] 继续创作第 $(($chapter_count + 1)) 章
2. [ ] 检查并优化现有章节
3. [ ] 更新项目大纲和设定
4. [ ] 同步到远程仓库
## 健康检查
- [$(if [ $chapter_count -gt 0 ]; then echo "x"; else echo " "; fi)] 章节文件正常
- [$(if [ -d ".git" ]; then echo "x"; else echo " "; fi)] Git仓库正常
- [$(if git remote get-url origin >/dev/null 2>&1; then echo "x"; else echo " "; fi)] 远程仓库配置
- [$(if [ -f "$report_file" ]; then echo "x"; else echo " "; fi)] 报告生成正常
---
*报告自动生成于 $(date '+%Y-%m-%d %H:%M:%S')*
EOF
log "INFO" "✅ 状态报告生成: $(basename $report_file)"
echo "报告文件: $report_file"
return 0
}
# 定时同步任务
setup_cron_job() {
local schedule="$1"
if [ -z "$schedule" ]; then
schedule="*/30 * * * *" # 每30分钟
fi
log "INFO" "设置定时同步任务: $schedule"
# 创建定时任务脚本
local cron_script="/tmp/末日重生_定时同步.sh"
cat > "$cron_script" << 'CRON_EOF'
#!/bin/bash
# 《末日重生》定时同步脚本
PROJECT_DIR="/root/.openclaw/workspace/projects/末日重生_囤货"
LOG_FILE="/tmp/末日重生_同步日志.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
log "INFO" "开始定时同步任务"
cd "$PROJECT_DIR"
# 检查是否有未提交的更改
if [ -n "$(git status --porcelain)" ]; then
log "INFO" "检测到未提交的更改,自动提交..."
# 自动提交
commit_message="定时更新: $(date '+%Y年%m月%d日 %H:%M:%S')"
git add .
if git commit -m "$commit_message" >/dev/null 2>&1; then
commit_hash=$(git rev-parse --short HEAD)
log "INFO" "✅ 自动提交成功: $commit_hash"
else
log "ERROR" "❌ 自动提交失败"
fi
fi
# 同步到远程
log "INFO" "同步到远程仓库..."
if git pull --rebase origin master >/dev/null 2>&1 && git push origin master >/dev/null 2>&1; then
log "INFO" "✅ 同步成功"
else
log "WARN" "⚠️ 同步失败,下次重试"
fi
# 创建每日备份(只在特定时间)
if [ "$(date '+%H')" = "03" ]; then # 凌晨3点
log "INFO" "创建每日备份..."
tar -czf "/tmp/末日重生_备份_$(date '+%Y%m%d').tar.gz" -C "$PROJECT_DIR" .
log "INFO" "✅ 备份创建完成"
fi
log "INFO" "定时同步任务完成"
CRON_EOF
chmod +x "$cron_script"
# 添加cron任务
(crontab -l 2>/dev/null | grep -v "$cron_script"; echo "$schedule $cron_script") | crontab -
log "INFO" "✅ 定时任务设置完成"
echo "定时任务: $schedule"
echo "任务脚本: $cron_script"
return 0
}
# 主菜单
show_menu() {
echo ""
echo "📚 《末日重生》项目版本管理系统"
echo "================================="
echo ""
echo "1. 🔍 检查项目状态"
echo "2. 📝 自动提交更改"
echo "3. 🏷️ 创建版本标签"
echo "4. 🔄 同步到远程仓库"
echo "5. 💾 创建项目备份"
echo "6. 📊 生成状态报告"
echo "7. ⏰ 设置定时同步"
echo "8. 🚀 一键全流程"
echo "9. 📋 显示帮助"
echo "0. ❌ 退出"
echo ""
echo "================================="
}
# 一键全流程
full_workflow() {
log "INFO" "开始一键全流程..."
echo "🚀 执行一键全流程"
echo "----------------"
# 1. 检查状态
if check_git_status; then
echo "✅ 步骤1: 检查状态完成"
else
echo " 步骤1: 无未提交更改"
fi
# 2. 自动提交
if auto_commit "一键更新: $(date '+%Y年%m月%d日 %H:%M:%S')"; then
echo "✅ 步骤2: 自动提交完成"
else
echo "⚠️ 步骤2: 提交跳过"
fi
# 3. 检查是否需要创建标签
local commit_count=$(git rev-list --count HEAD 2>/dev/null || echo 0)
if [ $((commit_count % 10)) -eq 0 ]; then
if create_version_tag; then
echo "✅ 步骤3: 版本标签创建"
else
echo "⚠️ 步骤3: 标签跳过"
fi
fi
# 4. 同步到远程
if sync_to_remote; then
echo "✅ 步骤4: 远程同步完成"
else
echo "❌ 步骤4: 同步失败"
fi
# 5. 生成报告
if generate_status_report; then
echo "✅ 步骤5: 状态报告生成"
fi
log "INFO" "一键全流程完成"
echo "🎉 全流程执行完毕!"
}
# 显示帮助
show_help() {
echo ""
echo "📖 《末日重生》Git版本管理工具使用说明"
echo "========================================"
echo ""
echo "主要功能:"
echo " 🔍 检查状态 - 检查Git状态和未提交更改"
echo " 📝 自动提交 - 自动提交所有更改到本地仓库"
echo " 🏷️ 版本标签 - 创建版本标签,记录重要里程碑"
echo " 🔄 远程同步 - 同步到Gitea远程仓库"
echo " 💾 项目备份 - 创建项目备份文件"
echo " 📊 状态报告 - 生成详细的项目状态报告"
echo " ⏰ 定时同步 - 设置定时自动同步任务"
echo " 🚀 一键流程 - 执行完整的版本管理流程"
echo ""
echo "使用方式:"
echo " ./git_version_manager.sh [选项]"
echo ""
echo "选项:"
echo " status 检查项目状态"
echo " commit 自动提交更改"
echo " tag 创建版本标签"
echo " sync 同步到远程"
echo " backup 创建备份"
echo " report 生成报告"
echo " cron 设置定时任务"
echo " workflow 执行一键流程"
echo " menu 显示交互菜单"
echo " help 显示帮助"
echo ""
echo "示例:"
echo " ./git_version_manager.sh status"
echo " ./git_version_manager.sh workflow"
echo " ./git_version_manager.sh menu"
echo ""
}
# 主函数
main() {
init
case "$1" in
"status")
check_git_status
;;
"commit")
auto_commit "$2"
;;
"tag")
create_version_tag "$2" "$3"
;;
"sync")
sync_to_remote "$2"
;;
"backup")
create_backup "$2"
;;
"report")
generate_status_report
;;
"cron")
setup_cron_job "$2"
;;
"workflow"|"auto")
full_workflow
;;
"menu")
while true; do
show_menu
echo "请选择操作 (0-9): "
read choice
case $choice in
1) check_git_status ;;
2) auto_commit ;;
3) create_version_tag ;;
4) sync_to_remote ;;
5) create_backup ;;
6) generate_status_report ;;
7) setup_cron_job ;;
8) full_workflow ;;
9) show_help ;;
0)
echo "再见!"
exit 0
;;
*)
echo "❌ 无效选择"
;;
esac
echo ""
echo "按回车键继续..."
read
done
;;
"help"|"--help"|"-h")
show_help
;;
*)
echo "使用: $0 [命令]"
echo "可用命令: status, commit, tag, sync, backup, report, cron, workflow, menu, help"
exit 1
;;
esac
}
# 运行主函数
main "$@"