#!/bin/bash # =================================================== # Git 操作脚本 - git-operations.sh # 用于处理 Git 仓库管理、同步和提交相关功能 # =================================================== # 依赖文件操作脚本的函数 source "$(dirname "$0")/file-operations.sh" # Git 操作模块 prepare_git_repo() { local git_url="$1" local branch="$2" local alias="$3" local target_dir="$GIT_DIR/${alias:-$(basename "$git_url" .git)}" # 检查目标目录是否存在 if [[ ! -d "$target_dir" ]]; then log_info "目标目录不存在,尝试克隆仓库" if ! git clone "$git_url" "$target_dir"; then log_error "克隆仓库失败" return 1 fi fi # 切换到目标目录 cd "$target_dir" || { log_error "无法切换到目标目录" return 1 } # 检查是否是 Git 仓库 if [[ ! -d ".git" ]]; then log_error "目标目录不是有效的 Git 仓库" return 1 } # 清理未提交的更改 if [[ -n "$(git status --porcelain)" ]]; then log_warn "发现未提交的更改,正在清理..." git reset --hard HEAD git clean -fd fi # 拉取最新代码 log_info "拉取最新代码..." if ! git pull; then log_error "拉取代码失败" return 1 fi # 切换到指定分支 if [[ -n "$branch" ]]; then log_info "切换到分支: $branch" if ! git checkout "$branch"; then log_error "切换分支失败" return 1 fi fi log_info "Git 仓库准备完成" return 0 } # 获取源项目的最新提交信息 get_source_commit_info() { cd "$PROJECT_ROOT" || return 1 local commit_hash=$(git rev-parse HEAD) local commit_msg=$(git log -1 --pretty=%B) echo "$commit_hash|$commit_msg" } # 提交更改 commit_changes() { local commit_info commit_info=$(get_source_commit_info) || { log_error "获取源项目提交信息失败" return 1 } local commit_hash=$(echo "$commit_info" | cut -d'|' -f1) local commit_msg=$(echo "$commit_info" | cut -d'|' -f2) # 添加所有更改 git add . # 提交更改 if git commit -m "sync: $commit_msg (from $commit_hash)"; then log_info "提交成功" return 0 else log_error "提交失败" return 1 fi } # 推送更改到远程仓库 push_changes() { local current_branch=$(git rev-parse --abbrev-ref HEAD) # 检查是否有远程仓库 if ! git remote | grep -q origin; then log_error "未找到远程仓库 origin" return 1 fi # 推送到远程仓库 log_info "正在推送更改到远程仓库..." if git push origin "$current_branch"; then log_info "推送成功" return 0 else log_error "推送失败" return 1 fi } # 选择 Git 项目目录 select_git_dirs() { local git_dirs=() local selected_indices=() local SYNC_MAPPINGS=() # 检查配置文件是否存在 if [[ ! -f "$SYNC_CONFIG_FILE" ]]; then log_error "配置文件不存在: $SYNC_CONFIG_FILE" return 1 fi # 检查是否安装了 yq if ! command -v yq &> /dev/null; then log_error "未安装 yq,无法读取配置文件" return 1 fi # 检查工作区是否存在 if ! yq e ".workspaces.$SELECTED_WORKSPACE" "$SYNC_CONFIG_FILE" &> /dev/null; then log_error "工作区 $SELECTED_WORKSPACE 不存在于配置文件中" return 1 fi # 获取工作区的所有 Git 仓库配置 local count count=$(yq e ".workspaces.$SELECTED_WORKSPACE.sync_mappings | length" "$SYNC_CONFIG_FILE") if [[ $count -eq 0 ]]; then log_error "工作区 $SELECTED_WORKSPACE 未配置任何 Git 仓库" return 1 fi # 构建显示列表和映射信息 local all_mappings=() for ((i=0; i /dev/null; then log_warn "未安装 yq,将使用默认配置" return 1 fi # 使用 yq 解析 YAML local mappings mappings=$(yq e ".workspaces.$workspace.sync_mappings" "$SYNC_CONFIG_FILE") if [[ "$mappings" != "null" ]]; then # 解析每个映射 local count count=$(yq e ".workspaces.$workspace.sync_mappings | length" "$SYNC_CONFIG_FILE") for ((i=0; i /dev/null; then log_warn "未安装 yq,无法更新配置" return 1 fi # 创建备份 if [[ -f "$SYNC_CONFIG_FILE" ]]; then cp "$SYNC_CONFIG_FILE" "${SYNC_CONFIG_FILE}.bak" fi # 清空现有映射 yq e -i ".workspaces.$workspace.sync_mappings = []" "$SYNC_CONFIG_FILE" # 添加新的映射 for mapping in "${SYNC_MAPPINGS[@]}"; do IFS='|' read -r git_url branch sync_dir git_dir alias <<< "$mapping" yq e -i ".workspaces.$workspace.sync_mappings += [{\"source\": {\"git_url\": \"$git_url\", \"branch\": \"$branch\", \"alias\": \"$alias\"}, \"target\": {\"sync_dir\": \"$sync_dir\", \"git_dir\": \"$git_dir\"}}]" "$SYNC_CONFIG_FILE" done # 删除备份 rm -f "${SYNC_CONFIG_FILE}.bak" log_info "工作区配置已更新" return 0 } # 读取配置 read_config() { if [[ -z "$SYNC_CONFIG_FILE" ]]; then log_error "配置文件未初始化,请确保已找到项目根目录" return 1 fi if [[ -f "$SYNC_CONFIG_FILE" ]]; then # 使用 yq 解析 YAML(如果安装了的话) if command -v yq &> /dev/null; then SELECTED_WORKSPACE=$(yq e '.config.workspace' "$SYNC_CONFIG_FILE") TARGET_GIT_DIR=$(yq e '.config.target_git_dir' "$SYNC_CONFIG_FILE") BRANCH=$(yq e '.config.branch' "$SYNC_CONFIG_FILE") SYNC_STRUCTURE=$(yq e '.config.sync_structure' "$SYNC_CONFIG_FILE") PARALLEL_BUILD=$(yq e '.config.parallel_build' "$SYNC_CONFIG_FILE") DRY_RUN=$(yq e '.config.dry_run' "$SYNC_CONFIG_FILE") else log_warn "未安装 yq,将使用默认配置" fi else log_error "配置文件不存在: $SYNC_CONFIG_FILE" return 1 fi } # 保存配置 save_config() { if [[ -z "$SYNC_CONFIG_FILE" ]]; then log_error "配置文件未初始化,请确保已找到项目根目录" return 1 fi if ! command -v yq &> /dev/null; then log_warn "未安装 yq,无法保存配置" return 1 fi # 创建备份 if [[ -f "$SYNC_CONFIG_FILE" ]]; then cp "$SYNC_CONFIG_FILE" "${SYNC_CONFIG_FILE}.bak" fi # 保存配置 if ! yq e -i ".config.workspace = \"$SELECTED_WORKSPACE\"" "$SYNC_CONFIG_FILE" \ && yq e -i ".config.target_git_dir = \"$TARGET_GIT_DIR\"" "$SYNC_CONFIG_FILE" \ && yq e -i ".config.branch = \"$BRANCH\"" "$SYNC_CONFIG_FILE" \ && yq e -i ".config.sync_structure = $SYNC_STRUCTURE" "$SYNC_CONFIG_FILE" \ && yq e -i ".config.parallel_build = $PARALLEL_BUILD" "$SYNC_CONFIG_FILE" \ && yq e -i ".config.dry_run = $DRY_RUN" "$SYNC_CONFIG_FILE"; then log_error "保存配置失败" # 恢复备份 if [[ -f "${SYNC_CONFIG_FILE}.bak" ]]; then mv "${SYNC_CONFIG_FILE}.bak" "$SYNC_CONFIG_FILE" fi return 1 fi # 删除备份 rm -f "${SYNC_CONFIG_FILE}.bak" log_info "配置已保存" return 0 } # 导出函数 export -f prepare_git_repo export -f get_source_commit_info export -f commit_changes export -f push_changes export -f select_git_dirs export -f read_workspace_config export -f update_workspace_config export -f read_config export -f save_config