mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-10 16:51:11 +08:00
【新增】插件git同步模块,用于同步项目内容,加速项目开发
【调整】前端暗色问题
This commit is contained in:
1379
frontend/scripts/tools/file-handle.sh
Normal file
1379
frontend/scripts/tools/file-handle.sh
Normal file
File diff suppressed because it is too large
Load Diff
860
frontend/scripts/tools/git-handle.sh
Normal file
860
frontend/scripts/tools/git-handle.sh
Normal file
@@ -0,0 +1,860 @@
|
||||
#!/bin/bash
|
||||
|
||||
#######################################
|
||||
# Git操作处理脚本
|
||||
#
|
||||
# 此脚本提供了一系列与Git操作相关的函数,包括仓库检查、
|
||||
# 代码拉取推送、分支管理、标签管理、日志查看等Git常用
|
||||
# 操作的封装,使Git操作更加便捷和安全。
|
||||
#
|
||||
# 作者: chudong
|
||||
# 版本: 1.0.0
|
||||
#######################################
|
||||
|
||||
# 导入通知处理脚本
|
||||
GIT_TOOL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$GIT_TOOL_DIR/notice-handle.sh"
|
||||
|
||||
#######################################
|
||||
# 检查是否为Git项目
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 是Git项目
|
||||
# 1 - 不是Git项目
|
||||
#######################################
|
||||
check_git_repository() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if [ ! -d "$repo_path" ]; then
|
||||
notice_error "路径 '$repo_path' 不存在或不是一个目录"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到指定目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 检查是否存在.git目录
|
||||
if [ -d ".git" ] || git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
cd "$current_dir"
|
||||
notice_success "'$repo_path' 是一个有效的Git仓库"
|
||||
return 0
|
||||
else
|
||||
cd "$current_dir"
|
||||
notice_error "'$repo_path' 不是一个Git仓库"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 拉取Git项目更新
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 分支名称,默认为当前分支
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_pull() {
|
||||
local repo_path="${1:-.}"
|
||||
local branch="$2"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 如果没有指定分支,则拉取当前分支
|
||||
if [ -z "$branch" ]; then
|
||||
notice_info "拉取当前分支的最新代码..."
|
||||
git pull
|
||||
else
|
||||
notice_info "拉取 '$branch' 分支的最新代码..."
|
||||
git pull origin "$branch"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "Git拉取成功"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "Git拉取失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 推送Git项目变更
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 分支名称,默认为当前分支
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_push() {
|
||||
local repo_path="${1:-.}"
|
||||
local branch="$2"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 如果没有指定分支,则推送当前分支
|
||||
if [ -z "$branch" ]; then
|
||||
# 获取当前分支名称
|
||||
local current_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||
if [ -z "$current_branch" ]; then
|
||||
notice_error "无法获取当前分支名称"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
notice_info "推送到当前分支 '$current_branch'..."
|
||||
git push origin "$current_branch"
|
||||
else
|
||||
notice_info "推送到 '$branch' 分支..."
|
||||
git push origin "$branch"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "Git推送成功"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "Git推送失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 提交Git变更
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 提交信息
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_commit() {
|
||||
local repo_path="${1:-.}"
|
||||
local commit_message="$2"
|
||||
|
||||
if [ -z "$commit_message" ]; then
|
||||
notice_error "请提供提交信息"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 检查是否有变更需要提交
|
||||
if ! git diff --quiet || ! git diff --staged --quiet; then
|
||||
# 添加所有变更
|
||||
git add .
|
||||
|
||||
# 提交变更
|
||||
git commit -m "$commit_message"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "Git提交成功: $commit_message"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "Git提交失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
notice_warning "没有变更需要提交"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 获取Git提交记录日志
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 记录数量,默认为10
|
||||
# $3: 格式化输出格式,默认为 "%h - %an, %ar : %s"
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 标准输出: Git日志信息
|
||||
#######################################
|
||||
git_log() {
|
||||
local repo_path="${1:-.}"
|
||||
local count="${2:-10}"
|
||||
local format="${3:-%h - %an, %ar : %s}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
notice_info "获取最近 $count 条提交记录:"
|
||||
git log -n "$count" --pretty=format:"$format"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "获取Git提交记录失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 创建Git分支
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 新分支名称
|
||||
# $3: 基于的分支名称,默认为当前分支
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_create_branch() {
|
||||
local repo_path="${1:-.}"
|
||||
local new_branch="$2"
|
||||
local base_branch="$3"
|
||||
|
||||
if [ -z "$new_branch" ]; then
|
||||
notice_error "请提供新分支名称"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 如果没有指定基础分支,则基于当前分支创建
|
||||
if [ -z "$base_branch" ]; then
|
||||
git checkout -b "$new_branch"
|
||||
else
|
||||
git checkout -b "$new_branch" "$base_branch"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "成功创建并切换到分支 '$new_branch'"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "创建分支 '$new_branch' 失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 切换Git分支
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 目标分支名称
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_checkout_branch() {
|
||||
local repo_path="${1:-.}"
|
||||
local target_branch="$2"
|
||||
|
||||
if [ -z "$target_branch" ]; then
|
||||
notice_error "请提供目标分支名称"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
git checkout "$target_branch"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "已切换到分支 '$target_branch'"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "切换到分支 '$target_branch' 失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 删除Git分支
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 要删除的分支名称
|
||||
# $3: 是否强制删除 ("force" 表示强制删除未合并的分支)
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_delete_branch() {
|
||||
local repo_path="${1:-.}"
|
||||
local branch_name="$2"
|
||||
local force="$3"
|
||||
|
||||
if [ -z "$branch_name" ]; then
|
||||
notice_error "请提供要删除的分支名称"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 检查是否为当前分支
|
||||
local current_branch=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||
if [ "$current_branch" = "$branch_name" ]; then
|
||||
notice_error "无法删除当前所在的分支 '$branch_name',请先切换到其他分支"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 根据是否强制删除选择不同的命令
|
||||
if [ "$force" = "force" ]; then
|
||||
git branch -D "$branch_name"
|
||||
else
|
||||
git branch -d "$branch_name"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "已删除分支 '$branch_name'"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
if [ "$force" != "force" ]; then
|
||||
notice_error "删除分支 '$branch_name' 失败,可能该分支尚未合并,请添加 'force' 参数强制删除"
|
||||
else
|
||||
notice_error "删除分支 '$branch_name' 失败"
|
||||
fi
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 查看Git分支列表
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 分支类型 ("all" 表示所有分支,"remote" 表示远程分支,默认为本地分支)
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 标准输出: 分支列表
|
||||
#######################################
|
||||
git_list_branches() {
|
||||
local repo_path="${1:-.}"
|
||||
local branch_type="${2:-local}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 根据分支类型选择不同的命令
|
||||
case "$branch_type" in
|
||||
"all")
|
||||
notice_info "所有分支列表:"
|
||||
git branch -a
|
||||
;;
|
||||
"remote")
|
||||
notice_info "远程分支列表:"
|
||||
git branch -r
|
||||
;;
|
||||
*)
|
||||
notice_info "本地分支列表:"
|
||||
git branch
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "获取分支列表失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 获取Git当前分支名称
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 成功,并打印分支名称
|
||||
# 1 - 失败
|
||||
# 标准输出: 当前分支名称
|
||||
#######################################
|
||||
git_current_branch() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
local branch_name=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||
|
||||
if [ -n "$branch_name" ]; then
|
||||
notice_info "当前分支: $branch_name"
|
||||
echo "$branch_name"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "无法获取当前分支名称,可能处于分离的HEAD状态"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 查看Git仓库状态
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 标准输出: 仓库状态信息
|
||||
#######################################
|
||||
git_status() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
notice_info "Git仓库状态:"
|
||||
git status
|
||||
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 创建Git标签
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 标签名称
|
||||
# $3: 标签消息,默认为标签名称
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_create_tag() {
|
||||
local repo_path="${1:-.}"
|
||||
local tag_name="$2"
|
||||
local tag_message="${3:-$tag_name}"
|
||||
|
||||
if [ -z "$tag_name" ]; then
|
||||
notice_error "请提供标签名称"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
git tag -a "$tag_name" -m "$tag_message"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "已创建标签 '$tag_name'"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "创建标签 '$tag_name' 失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 删除Git标签
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 标签名称
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_delete_tag() {
|
||||
local repo_path="${1:-.}"
|
||||
local tag_name="$2"
|
||||
|
||||
if [ -z "$tag_name" ]; then
|
||||
notice_error "请提供标签名称"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
git tag -d "$tag_name"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "已删除标签 '$tag_name'"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "删除标签 '$tag_name' 失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 列出Git标签
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 标准输出: 标签列表
|
||||
#######################################
|
||||
git_list_tags() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
notice_info "标签列表:"
|
||||
git tag
|
||||
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 比较两个提交之间的差异
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 起始提交或分支
|
||||
# $3: 目标提交或分支,默认为当前分支
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 标准输出: 差异内容
|
||||
#######################################
|
||||
git_diff() {
|
||||
local repo_path="${1:-.}"
|
||||
local start_commit="$2"
|
||||
local end_commit="$3"
|
||||
|
||||
if [ -z "$start_commit" ]; then
|
||||
notice_error "请提供起始提交或分支"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 如果没有指定目标提交,则与当前分支比较
|
||||
if [ -z "$end_commit" ]; then
|
||||
notice_info "比较 '$start_commit' 与当前分支的差异:"
|
||||
git diff "$start_commit"
|
||||
else
|
||||
notice_info "比较 '$start_commit' 与 '$end_commit' 的差异:"
|
||||
git diff "$start_commit" "$end_commit"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "比较差异失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 合并分支
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# $2: 要合并的源分支
|
||||
# $3: 目标分支,默认为当前分支
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_merge() {
|
||||
local repo_path="${1:-.}"
|
||||
local source_branch="$2"
|
||||
local target_branch="$3"
|
||||
|
||||
if [ -z "$source_branch" ]; then
|
||||
notice_error "请提供要合并的源分支"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 如果指定了目标分支,则先切换到目标分支
|
||||
if [ -n "$target_branch" ]; then
|
||||
git checkout "$target_branch"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
notice_error "切换到目标分支 '$target_branch' 失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
notice_info "合并分支 '$source_branch'..."
|
||||
git merge "$source_branch"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "成功合并分支 '$source_branch'"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "合并分支 '$source_branch' 失败,可能存在冲突"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 解决冲突后继续合并
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_merge_continue() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
# 检查是否有未解决的冲突
|
||||
if git diff --name-only --diff-filter=U | grep -q .; then
|
||||
notice_error "仍有未解决的冲突,请先解决冲突"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 提交解决的冲突
|
||||
git add .
|
||||
git commit --no-edit
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "成功完成合并"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "完成合并失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 取消合并
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
git_merge_abort() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
git merge --abort
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
notice_success "已取消合并"
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
else
|
||||
notice_error "取消合并失败"
|
||||
cd "$current_dir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 获取远程仓库信息
|
||||
# 参数:
|
||||
# $1: 项目路径,默认为当前目录
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 标准输出: 远程仓库信息
|
||||
#######################################
|
||||
git_remote_info() {
|
||||
local repo_path="${1:-.}"
|
||||
|
||||
if ! check_git_repository "$repo_path"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 保存当前目录
|
||||
local current_dir=$(pwd)
|
||||
|
||||
# 切换到仓库目录
|
||||
cd "$repo_path" || return 1
|
||||
|
||||
notice_info "远程仓库信息:"
|
||||
git remote -v
|
||||
|
||||
cd "$current_dir"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 使用示例
|
||||
#######################################
|
||||
|
||||
# # 检查是否为Git仓库
|
||||
# check_git_repository "/path/to/repo"
|
||||
|
||||
# # 代码拉取与推送
|
||||
# git_pull "/path/to/repo" "main"
|
||||
# git_push "/path/to/repo" "feature/branch"
|
||||
# git_commit "/path/to/repo" "修复了某个问题"
|
||||
|
||||
# # 查看日志和状态
|
||||
# git_log "/path/to/repo" 5 "%h - %an, %ar : %s"
|
||||
# git_status "/path/to/repo"
|
||||
|
||||
# # 分支管理
|
||||
# git_create_branch "/path/to/repo" "feature/new-feature" "main"
|
||||
# git_checkout_branch "/path/to/repo" "develop"
|
||||
# git_delete_branch "/path/to/repo" "old-branch" "force"
|
||||
# git_list_branches "/path/to/repo" "all"
|
||||
# git_current_branch "/path/to/repo"
|
||||
|
||||
# # 标签管理
|
||||
# git_create_tag "/path/to/repo" "v1.0.0" "第一个正式版本"
|
||||
# git_delete_tag "/path/to/repo" "v0.9.9"
|
||||
# git_list_tags "/path/to/repo"
|
||||
|
||||
# # 比较与合并
|
||||
# git_diff "/path/to/repo" "v1.0.0" "v1.1.0"
|
||||
# git_merge "/path/to/repo" "feature/completed" "main"
|
||||
# git_merge_continue "/path/to/repo"
|
||||
# git_merge_abort "/path/to/repo"
|
||||
|
||||
# # 远程仓库
|
||||
# git_remote_info "/path/to/repo"
|
||||
76
frontend/scripts/tools/help.md
Normal file
76
frontend/scripts/tools/help.md
Normal file
@@ -0,0 +1,76 @@
|
||||
以下是根据你提供的脚本生成的说明文档:
|
||||
|
||||
### 脚本概述
|
||||
这些脚本主要包含了Git操作、文件处理、通知处理以及通用工具处理等功能,旨在提供便捷、安全的操作封装,使各项任务更加高效。
|
||||
|
||||
### 各脚本功能及函数说明
|
||||
|
||||
#### 1. `git-handle.sh`
|
||||
此脚本提供了与Git操作相关的函数,如仓库检查、代码拉取推送、分支管理等。
|
||||
|
||||
| 函数名 | 参数 | 返回值 | 使用方法 |
|
||||
| ---- | ---- | ---- | ---- |
|
||||
| `check_git_repository` | `$1: 项目路径,默认为当前目录` | `0 - 是Git项目<br>1 - 不是Git项目` | `check_git_repository /path/to/repo` |
|
||||
| `git_list_branches` | `$1: 项目路径,默认为当前目录<br>$2: 分支类型 ("all" 表示所有分支,"remote" 表示远程分支,默认为本地分支)` | `0 - 成功<br>1 - 失败` | `git_list_branches /path/to/repo all` |
|
||||
| `git_current_branch` | `$1: 项目路径,默认为当前目录` | `0 - 成功,并打印分支名称<br>1 - 失败` | `git_current_branch /path/to/repo` |
|
||||
|
||||
#### 2. `file-handle.sh`
|
||||
该脚本提供了文件和文件夹的创建、删除、读写、权限设置等操作。
|
||||
|
||||
| 函数名 | 参数 | 返回值 | 使用方法 |
|
||||
| ---- | ---- | ---- | ---- |
|
||||
| `create_file` | `$1: 文件路径` | `0 - 成功<br>1 - 失败` | `create_file /path/to/file.txt` |
|
||||
| `create_directory` | `$1: 文件夹路径` | `0 - 成功<br>1 - 失败` | `create_directory /path/to/directory` |
|
||||
| `delete_file` | `$1: 文件路径` | `0 - 成功<br>1 - 失败` | `delete_file /path/to/file.txt` |
|
||||
| `delete_directory` | `$1: 文件夹路径<br>$2: 是否强制删除 ("force" 表示强制删除)` | `0 - 成功<br>1 - 失败` | `delete_directory /path/to/directory force` |
|
||||
| `rename_directory` | `$1: 旧文件夹路径<br>$2: 新文件夹路径` | `0 - 成功<br>1 - 失败` | `rename_directory old/directory/path new/directory/path` |
|
||||
| `rename_file` | `$1: 旧文件路径<br>$2: 新文件路径` | `0 - 成功<br>1 - 失败` | `rename_file old/file/path.txt new/file/path.txt` |
|
||||
| `copy_file` | `$1: 源文件路径<br>$2: 目标文件路径<br>$3: 是否强制覆盖 ("force" 表示强制覆盖)` | `0 - 成功<br>1 - 失败` | `copy_file source/file.txt target/file.txt force` |
|
||||
| `copy_directory` | `$1: 源文件夹路径<br>$2: 目标文件夹路径<br>$3: 是否强制覆盖 ("force" 表示强制覆盖)` | `0 - 成功<br>1 - 失败` | `copy_directory source/dir target/dir force` |
|
||||
| `file_exists` | `$1: 文件路径` | `0 - 文件存在<br>1 - 文件不存在` | `file_exists /path/to/file.txt` |
|
||||
| `directory_exists` | `$1: 文件夹路径` | `0 - 文件夹存在<br>1 - 文件夹不存在` | `directory_exists /path/to/directory` |
|
||||
| `get_file_size` | `$1: 文件路径<br>$2: 单位 (B, K, M, G)` | `0 - 成功<br>1 - 失败` | `get_file_size /path/to/file.txt M` |
|
||||
| `read_file_content` | `$1: 文件路径` | `0 - 成功<br>1 - 失败` | `read_file_content /path/to/file.txt` |
|
||||
| `write_file_content` | `$1: 文件路径<br>$2: 要写入的内容<br>$3: 是否覆盖已存在的文件 ("force" 表示强制覆盖)` | `0 - 成功<br>1 - 失败` | `write_file_content /path/to/file.txt "Hello, World!" force` |
|
||||
| `append_file_content` | `$1: 文件路径<br>$2: 要追加的内容` | `0 - 成功<br>1 - 失败` | `append_file_content /path/to/file.txt "New line"` |
|
||||
| `find_files` | `$1: 目录路径<br>$2: 文件名模式(支持通配符)<br>$3: 是否递归搜索 ("recursive" 表示递归)` | `0 - 成功<br>1 - 失败` | `find_files /path/to/search "*.txt" recursive` |
|
||||
| `find_directories` | `$1: 目录路径<br>$2: 文件夹名模式(支持通配符)<br>$3: 是否递归搜索 ("recursive" 表示递归)` | `0 - 成功<br>1 - 失败` | `find_directories /path/to/search "data*" recursive` |
|
||||
| `set_file_permission` | `$1: 文件路径<br>$2: 权限模式 (例如: "755", "644")` | `0 - 成功<br>1 - 失败` | `set_file_permission /path/to/file.txt "755"` |
|
||||
| `compare_files` | `$1: 第一个文件路径<br>$2: 第二个文件路径` | `0 - 文件内容相同<br>1 - 文件内容不同或出错` | `compare_files file1.txt file2.txt` |
|
||||
| `get_file_type` | `$1: 文件路径` | `0 - 成功<br>1 - 失败` | `get_file_type /path/to/file` |
|
||||
| `check_file_checksum` | `$1: 文件路径<br>$2: 校验和算法 (md5, sha1, sha256, sha512)<br>$3: 期望的校验和值 (可选)` | `0 - 校验成功或校验和已输出<br>1 - 校验失败或出错` | `check_file_checksum /path/to/file.txt sha256` |
|
||||
| `get_file_mtime` | `$1: 文件路径` | `0 - 成功<br>1 - 失败` | `get_file_mtime /path/to/file.txt` |
|
||||
| `encrypt_file` | `$1: 文件路径<br>$2: 加密后文件路径<br>$3: 密码` | `0 - 成功<br>1 - 失败` | `encrypt_file /path/to/file.txt /path/to/file.enc "password123"` |
|
||||
| `watch_file_changes` | `$1: 要监控的文件路径<br>$2: 检查间隔时间(秒,默认为 1)<br>$3: 运行最大时间(秒,默认为 60)` | `0 - 文件被修改或创建<br>1 - 超时或出错` | `watch_file_changes /path/to/file.txt 2 120` |
|
||||
|
||||
#### 3. `notice-handle.sh`
|
||||
该脚本提供了在终端中显示不同类型通知的函数,以及交互式的用户输入、确认、单选和多选菜单功能。
|
||||
|
||||
| 函数名 | 参数 | 返回值 | 使用方法 |
|
||||
| ---- | ---- | ---- | ---- |
|
||||
| `notice_info` | `$1: 消息内容` | `0 - 成功<br>1 - 失败` | `notice_info "这是一条信息通知"` |
|
||||
| `notice_success` | `$1: 消息内容` | `0 - 成功<br>1 - 失败` | `notice_success "操作成功完成"` |
|
||||
| `notice_warning` | `$1: 消息内容` | `0 - 成功<br>1 - 失败` | `notice_warning "请注意这个警告"` |
|
||||
| `notice_error` | `$1: 消息内容` | `0 - 成功<br>1 - 失败` | `notice_error "发生了错误"` |
|
||||
| `notice_debug` | `$1: 消息内容` | `0 - 成功<br>1 - 失败` | `DEBUG=true notice_debug "这是调试信息"` |
|
||||
| `notice_system` | `$1: 通知类型<br>$2: 消息内容` | `0 - 成功<br>1 - 失败` | `notice_system "系统通知" "这是一条系统通知消息"` |
|
||||
| `notice_progress` | `$1: 当前进度<br>$2: 总进度<br>$3: 描述信息` | `0 - 成功<br>1 - 失败` | `notice_progress 5 10 "文件下载中"` |
|
||||
| `notice_prompt` | `$1: 提示文本<br>$2: 用于存储用户输入的变量名<br>$3: 默认值 (可选)` | `0 - 成功<br>1 - 失败` | `notice_prompt "请输入您的名字" "user_name"` |
|
||||
| `notice_confirm` | `$1: 提示文本<br>$2: 默认选项 (可选,"y"或"n",默认为"n")` | `0 - 用户确认是<br>1 - 用户确认否` | `notice_confirm "是否继续?"` |
|
||||
| `notice_select_menu` | `$1: 菜单标题<br>$2: 用于存储选择结果的变量名<br>$3...$n: 菜单选项` | `0 - 用户选择了一个选项<br>1 - 用户取消选择 (按q)<br>2 - 参数错误` | `notice_select_menu "请选择一个操作系统" "selected_os" "Linux" "MacOS" "Windows" "其他"` |
|
||||
| `notice_multi_select_menu` | `$1: 菜单标题<br>$2: 用于存储选择结果的变量名 (将存储为选中项的索引,用逗号分隔)<br>$3...$n: 菜单选项` | `0 - 用户完成选择<br>1 - 用户取消选择 (按q)<br>2 - 参数错误` | `notice_multi_select_menu "请选择您喜欢的编程语言" "selected_langs" "Python" "JavaScript" "Bash" "Go" "Rust" "Java"` |
|
||||
|
||||
#### 4. `other-handle.sh`
|
||||
此脚本提供了通用工具函数,如系统环境检测、依赖检测、配置文件解析等。
|
||||
|
||||
| 函数名 | 参数 | 返回值 | 使用方法 |
|
||||
| ---- | ---- | ---- | ---- |
|
||||
| `check_environment` | 无 | `0 - 成功检测<br>1 - 检测失败` | `check_environment` |
|
||||
| `parse_yaml_config` | `$1: YAML配置文件路径<br>$2: 用于存储解析后配置的关联数组名称` | `0 - 成功解析配置<br>1 - 解析失败` | `declare -A CONFIG; parse_yaml_config "config.yaml" CONFIG` |
|
||||
| `parse_arguments` | `$@: 所有命令行参数` | `0 - 成功解析参数<br>1 - 解析参数时出错` | `parse_arguments --name="示例项目" --debug -v -o output.txt input1.txt input2.txt` |
|
||||
| `yq_get_value` | `$1: YAML文件路径<br>$2: YAML路径表达式` | `0 - 成功获取值<br>1 - 失败` | `yq_get_value "example.yaml" ".name"` |
|
||||
| `yq_has_path` | `$1: YAML文件路径<br>$2: YAML路径表达式` | `0 - 路径存在<br>1 - 路径不存在` | `yq_has_path "example.yaml" ".version"` |
|
||||
| `run_examples` | 无 | 无 | `run_examples` |
|
||||
|
||||
### 总结
|
||||
这些脚本涵盖了Git操作、文件处理、通知显示和通用工具等多个方面,通过封装常用操作,提高了脚本的可维护性和易用性。在使用时,可根据具体需求调用相应的函数,并按照函数说明提供正确的参数。
|
||||
694
frontend/scripts/tools/notice-handle.sh
Normal file
694
frontend/scripts/tools/notice-handle.sh
Normal file
@@ -0,0 +1,694 @@
|
||||
#!/bin/bash
|
||||
|
||||
#######################################
|
||||
# 通知处理脚本
|
||||
#
|
||||
# 此脚本提供了一系列用于在终端中显示不同类型通知的函数,
|
||||
# 包括普通信息、成功、警告、错误、调试信息等,以及交互式
|
||||
# 的用户输入、确认、单选和多选菜单功能。
|
||||
#
|
||||
# 作者: chudong
|
||||
# 版本: 1.0.0
|
||||
#######################################
|
||||
|
||||
# 定义颜色
|
||||
RED='\033[0;31m' # 错误
|
||||
GREEN='\033[0;32m' # 成功
|
||||
YELLOW='\033[0;33m' # 警告
|
||||
BLUE='\033[0;34m' # 信息
|
||||
PURPLE='\033[0;35m' # 调试
|
||||
CYAN='\033[0;36m' # 提示
|
||||
NC='\033[0m' # 无颜色
|
||||
|
||||
#######################################
|
||||
# 普通信息通知
|
||||
# 参数:
|
||||
# $1: 消息内容
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
notice_info() {
|
||||
local message="$1"
|
||||
|
||||
if [ -z "$message" ]; then
|
||||
echo "${BLUE}[信息] 未提供消息内容${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${BLUE}[信息] $message${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 成功信息通知
|
||||
# 参数:
|
||||
# $1: 消息内容
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
notice_success() {
|
||||
local message="$1"
|
||||
|
||||
if [ -z "$message" ]; then
|
||||
echo "${GREEN}[成功] 未提供消息内容${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${GREEN}[成功] $message${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 警告信息通知
|
||||
# 参数:
|
||||
# $1: 消息内容
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
notice_warning() {
|
||||
local message="$1"
|
||||
|
||||
if [ -z "$message" ]; then
|
||||
echo "${YELLOW}[警告] 未提供消息内容${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${YELLOW}[警告] $message${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 错误信息通知
|
||||
# 参数:
|
||||
# $1: 消息内容
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
notice_error() {
|
||||
local message="$1"
|
||||
|
||||
if [ -z "$message" ]; then
|
||||
echo "${RED}[错误] 未提供消息内容${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${RED}[错误] $message${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 调试信息通知(仅在调试模式下显示)
|
||||
# 参数:
|
||||
# $1: 消息内容
|
||||
# 环境变量:
|
||||
# DEBUG: 设置为 "true" 时启用调试输出
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败(仅在调试模式下且未提供消息内容时)
|
||||
#######################################
|
||||
notice_debug() {
|
||||
local message="$1"
|
||||
local debug_mode="${DEBUG:-false}"
|
||||
|
||||
if [ "$debug_mode" = "true" ]; then
|
||||
if [ -z "$message" ]; then
|
||||
echo "${PURPLE}[调试] 未提供消息内容${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${PURPLE}[调试] $message${NC}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 系统通知(使用系统原生通知功能)
|
||||
# 参数:
|
||||
# $1: 通知标题
|
||||
# $2: 通知消息内容
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
notice_system() {
|
||||
local title="$1"
|
||||
local message="$2"
|
||||
|
||||
if [ -z "$title" ] || [ -z "$message" ]; then
|
||||
echo "${RED}[错误] 系统通知需要标题和消息内容${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检测系统类型,使用适当的系统通知方法
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
# MacOS
|
||||
osascript -e "display notification \"$message\" with title \"$title\""
|
||||
elif [ "$(uname)" = "Linux" ] && command -v notify-send &> /dev/null; then
|
||||
# Linux 并且有 notify-send
|
||||
notify-send "$title" "$message"
|
||||
else
|
||||
# 回退到普通输出
|
||||
echo "${CYAN}[系统通知] $title: $message${NC}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 进度条通知
|
||||
# 参数:
|
||||
# $1: 当前进度值
|
||||
# $2: 总进度值
|
||||
# $3: 进度描述 (可选,默认为"处理中")
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
notice_progress() {
|
||||
local current="$1"
|
||||
local total="$2"
|
||||
local description="${3:-处理中}"
|
||||
|
||||
if [ -z "$current" ] || [ -z "$total" ]; then
|
||||
echo "${RED}[错误] 进度条需要当前值和总值${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 计算百分比
|
||||
local percent=$((current * 100 / total))
|
||||
local completed=$((percent / 2))
|
||||
local remaining=$((50 - completed))
|
||||
|
||||
# 创建进度条
|
||||
local bar="["
|
||||
for ((i=0; i<completed; i++)); do
|
||||
bar+="#"
|
||||
done
|
||||
|
||||
for ((i=0; i<remaining; i++)); do
|
||||
bar+="-"
|
||||
done
|
||||
|
||||
bar+="] $percent%"
|
||||
|
||||
# 显示进度条
|
||||
echo -n "${CYAN}$description: $bar\r${NC}"
|
||||
|
||||
# 如果完成了,添加换行
|
||||
if [ "$current" -ge "$total" ]; then
|
||||
echo ""
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 用户输入提示
|
||||
# 参数:
|
||||
# $1: 提示文本
|
||||
# $2: 用于存储用户输入的变量名
|
||||
# $3: 默认值 (可选)
|
||||
# 返回值:
|
||||
# 0 - 成功
|
||||
# 1 - 失败
|
||||
# 注意:
|
||||
# 此函数通过 eval 设置调用者环境中的变量,
|
||||
# 必须通过 source 方式调用脚本才能生效
|
||||
#######################################
|
||||
notice_prompt() {
|
||||
local prompt="$1"
|
||||
local variable_name="$2"
|
||||
local default_value="$3"
|
||||
|
||||
if [ -z "$prompt" ] || [ -z "$variable_name" ]; then
|
||||
echo "${RED}[错误] 用户输入提示需要提示文本和变量名${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local input=""
|
||||
|
||||
# 显示带有默认值的提示(如果有)
|
||||
if [ -n "$default_value" ]; then
|
||||
echo -n "${CYAN}$prompt [${default_value}]: ${NC}"
|
||||
read input
|
||||
|
||||
# 如果用户未输入任何内容,使用默认值
|
||||
if [ -z "$input" ]; then
|
||||
input="$default_value"
|
||||
fi
|
||||
else
|
||||
echo -n "${CYAN}$prompt: ${NC}"
|
||||
read input
|
||||
fi
|
||||
|
||||
# 为调用脚本设置变量
|
||||
# 注意:这只在 source 调用此脚本时有效
|
||||
eval "$variable_name=\"$input\""
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 确认消息通知(询问用户是/否)
|
||||
# 参数:
|
||||
# $1: 提示文本
|
||||
# $2: 默认选项 (可选,"y"或"n",默认为"n")
|
||||
# 返回值:
|
||||
# 0 - 用户确认是
|
||||
# 1 - 用户确认否
|
||||
#######################################
|
||||
notice_confirm() {
|
||||
local message="$1"
|
||||
local default="${2:-n}" # 默认为否
|
||||
|
||||
if [ -z "$message" ]; then
|
||||
echo "${RED}[错误] 确认消息需要提示文本${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local prompt=""
|
||||
|
||||
# 根据默认值设置提示
|
||||
if [ "$default" = "y" ]; then
|
||||
prompt="[Y/n]"
|
||||
else
|
||||
prompt="[y/N]"
|
||||
fi
|
||||
|
||||
# 询问用户
|
||||
while true; do
|
||||
echo -n "${CYAN}$message $prompt ${NC}"
|
||||
read response
|
||||
|
||||
# 如果用户未输入任何内容,使用默认值
|
||||
if [ -z "$response" ]; then
|
||||
response="$default"
|
||||
fi
|
||||
|
||||
# 检查响应
|
||||
case "$response" in
|
||||
[Yy]*)
|
||||
return 0
|
||||
;;
|
||||
[Nn]*)
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
echo "${YELLOW}请输入 y 或 n${NC}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 单选菜单函数,支持键盘方向键控制
|
||||
# 参数:
|
||||
# $1: 菜单标题
|
||||
# $2: 用于存储选择结果的变量名
|
||||
# $3...$n: 菜单选项
|
||||
# 使用方法:
|
||||
# notice_select_menu "请选择一个选项" "selected_option" "选项1" "选项2" "选项3"
|
||||
# echo "用户选择了: $selected_option"
|
||||
# 返回值:
|
||||
# 0 - 用户选择了一个选项
|
||||
# 1 - 用户取消选择 (按q)
|
||||
# 2 - 参数错误
|
||||
#######################################
|
||||
notice_select_menu() {
|
||||
local title="$1"
|
||||
local return_var="$2"
|
||||
|
||||
# 检查参数
|
||||
if [ -z "$title" ] || [ -z "$return_var" ] || [ $# -lt 3 ]; then
|
||||
echo "${RED}[错误] 单选菜单需要标题、返回变量名和至少一个选项${NC}"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# 移除前两个参数,剩下的是菜单选项
|
||||
shift 2
|
||||
local options=("$@")
|
||||
local selected=0
|
||||
local option_count=${#options[@]}
|
||||
local result=""
|
||||
|
||||
# 检查是否支持 tput (但不强制依赖)
|
||||
local has_tput=false
|
||||
if command -v tput &>/dev/null; then
|
||||
has_tput=true
|
||||
fi
|
||||
|
||||
# 隐藏光标 (如果支持)
|
||||
if [ "$has_tput" = true ]; then
|
||||
tput civis 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 保存终端设置
|
||||
local saved_tty=""
|
||||
if [ -t 0 ]; then
|
||||
saved_tty=$(stty -g)
|
||||
fi
|
||||
|
||||
# 设置终端为非规范模式,禁用回显
|
||||
stty -icanon -echo 2>/dev/null || true
|
||||
|
||||
while true; do
|
||||
# 清屏和显示标题
|
||||
clear 2>/dev/null || printf "\033c" || echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
||||
echo "${CYAN}$title${NC}"
|
||||
echo "${CYAN}(使用方向键↑↓移动,回车确认,q退出)${NC}"
|
||||
echo ""
|
||||
|
||||
# 显示选项
|
||||
for i in "${!options[@]}"; do
|
||||
if [ $i -eq $selected ]; then
|
||||
echo "${GREEN}>> $((i+1)). ${options[$i]} <<${NC}"
|
||||
else
|
||||
echo " $((i+1)). ${options[$i]}"
|
||||
fi
|
||||
done
|
||||
|
||||
# 读取用户输入
|
||||
local key=""
|
||||
IFS= read -r -s -n1 key
|
||||
|
||||
# 处理特殊键
|
||||
if [[ $key == $'\e' ]]; then
|
||||
if read -r -s -n2 -t 0.1 key2; then
|
||||
key+="$key2"
|
||||
fi
|
||||
|
||||
case "$key" in
|
||||
$'\e[A') # 上箭头
|
||||
((selected--))
|
||||
if [ $selected -lt 0 ]; then
|
||||
selected=$((option_count - 1))
|
||||
fi
|
||||
;;
|
||||
$'\e[B') # 下箭头
|
||||
((selected++))
|
||||
if [ $selected -ge $option_count ]; then
|
||||
selected=0
|
||||
fi
|
||||
;;
|
||||
$'\e[C'|$'\e[D') # 左右箭头 (忽略)
|
||||
;;
|
||||
*) # 其他ESC序列 (忽略)
|
||||
;;
|
||||
esac
|
||||
continue
|
||||
fi
|
||||
|
||||
# 处理其他键
|
||||
case "$key" in
|
||||
"q"|"Q")
|
||||
# 恢复终端设置
|
||||
if [ -n "$saved_tty" ]; then
|
||||
stty "$saved_tty" 2>/dev/null || true
|
||||
fi
|
||||
# 显示光标 (如果支持)
|
||||
if [ "$has_tput" = true ]; then
|
||||
tput cnorm 2>/dev/null || true
|
||||
fi
|
||||
echo ""
|
||||
return 1
|
||||
;;
|
||||
"w"|"W") # 向上兼容原始的 w/s 控制
|
||||
((selected--))
|
||||
if [ $selected -lt 0 ]; then
|
||||
selected=$((option_count - 1))
|
||||
fi
|
||||
;;
|
||||
"s"|"S") # 向上兼容原始的 w/s 控制
|
||||
((selected++))
|
||||
if [ $selected -ge $option_count ]; then
|
||||
selected=0
|
||||
fi
|
||||
;;
|
||||
"") # 回车键
|
||||
result="$selected"
|
||||
break
|
||||
;;
|
||||
[0-9]) # 数字键 - 直接跳转
|
||||
local num=$((key - 1))
|
||||
if [ $num -ge 0 ] && [ $num -lt $option_count ]; then
|
||||
selected=$num
|
||||
result="$selected"
|
||||
break
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 恢复终端设置
|
||||
if [ -n "$saved_tty" ]; then
|
||||
stty "$saved_tty" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 显示光标 (如果支持)
|
||||
if [ "$has_tput" = true ]; then
|
||||
tput cnorm 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 设置返回变量
|
||||
eval "$return_var=\"$result\""
|
||||
|
||||
echo ""
|
||||
echo "${GREEN}已选择: ${options[$result]}${NC}"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 多选菜单函数,支持键盘方向键控制
|
||||
# 参数:
|
||||
# $1: 菜单标题
|
||||
# $2: 用于存储选择结果的变量名 (将存储为选中项的索引,用逗号分隔)
|
||||
# $3...$n: 菜单选项
|
||||
# 使用方法:
|
||||
# notice_multi_select_menu "请选择多个选项" "selected_options" "选项1" "选项2" "选项3"
|
||||
# echo "用户选择了索引: $selected_options"
|
||||
# IFS=',' read -ra SELECTED_INDICES <<< "$selected_options"
|
||||
# for i in "${SELECTED_INDICES[@]}"; do
|
||||
# echo "选中了选项: ${原选项数组[$i]}"
|
||||
# done
|
||||
# 返回值:
|
||||
# 0 - 用户完成选择
|
||||
# 1 - 用户取消选择 (按q)
|
||||
# 2 - 参数错误
|
||||
#######################################
|
||||
notice_multi_select_menu() {
|
||||
local title="$1"
|
||||
local return_var="$2"
|
||||
|
||||
# 检查参数
|
||||
if [ -z "$title" ] || [ -z "$return_var" ] || [ $# -lt 3 ]; then
|
||||
echo "${RED}[错误] 多选菜单需要标题、返回变量名和至少一个选项${NC}"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# 移除前两个参数,剩下的是菜单选项
|
||||
shift 2
|
||||
local options=("$@")
|
||||
local cursor=0
|
||||
local option_count=${#options[@]}
|
||||
local result=""
|
||||
|
||||
# 初始化选中状态数组 (0表示未选中,1表示已选中)
|
||||
local selected_status=()
|
||||
for ((i=0; i<option_count; i++)); do
|
||||
selected_status[$i]=0
|
||||
done
|
||||
|
||||
# 检查是否支持 tput (但不强制依赖)
|
||||
local has_tput=false
|
||||
if command -v tput &>/dev/null; then
|
||||
has_tput=true
|
||||
fi
|
||||
|
||||
# 隐藏光标 (如果支持)
|
||||
if [ "$has_tput" = true ]; then
|
||||
tput civis 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 保存终端设置
|
||||
local saved_tty=""
|
||||
if [ -t 0 ]; then
|
||||
saved_tty=$(stty -g)
|
||||
fi
|
||||
|
||||
# 设置终端为非规范模式,禁用回显
|
||||
stty -icanon -echo 2>/dev/null || true
|
||||
|
||||
while true; do
|
||||
# 清屏和显示标题
|
||||
clear 2>/dev/null || printf "\033c" || echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
|
||||
echo "${CYAN}$title${NC}"
|
||||
echo "${CYAN}(使用方向键↑↓移动,空格键选择/取消,回车确认,q退出)${NC}"
|
||||
echo ""
|
||||
|
||||
# 显示选项
|
||||
for i in "${!options[@]}"; do
|
||||
if [ $i -eq $cursor ]; then
|
||||
if [ ${selected_status[$i]} -eq 1 ]; then
|
||||
echo "${GREEN}>> [X] ${options[$i]} <<${NC}"
|
||||
else
|
||||
echo "${GREEN}>> [ ] ${options[$i]} <<${NC}"
|
||||
fi
|
||||
else
|
||||
if [ ${selected_status[$i]} -eq 1 ]; then
|
||||
echo " [X] ${options[$i]}"
|
||||
else
|
||||
echo " [ ] ${options[$i]}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 读取用户输入
|
||||
local key=""
|
||||
IFS= read -r -s -n1 key
|
||||
|
||||
# 处理特殊键
|
||||
if [[ $key == $'\e' ]]; then
|
||||
if read -r -s -n2 -t 0.1 key2; then
|
||||
key+="$key2"
|
||||
fi
|
||||
|
||||
case "$key" in
|
||||
$'\e[A') # 上箭头
|
||||
((cursor--))
|
||||
if [ $cursor -lt 0 ]; then
|
||||
cursor=$((option_count - 1))
|
||||
fi
|
||||
;;
|
||||
$'\e[B') # 下箭头
|
||||
((cursor++))
|
||||
if [ $cursor -ge $option_count ]; then
|
||||
cursor=0
|
||||
fi
|
||||
;;
|
||||
$'\e[C') # 右箭头 (忽略)
|
||||
;;
|
||||
$'\e[D') # 左箭头 (忽略)
|
||||
;;
|
||||
*) # 其他ESC序列 (忽略)
|
||||
;;
|
||||
esac
|
||||
continue
|
||||
fi
|
||||
|
||||
# 处理其他键
|
||||
case "$key" in
|
||||
"q"|"Q")
|
||||
# 恢复终端设置
|
||||
if [ -n "$saved_tty" ]; then
|
||||
stty "$saved_tty" 2>/dev/null || true
|
||||
fi
|
||||
# 显示光标 (如果支持)
|
||||
if [ "$has_tput" = true ]; then
|
||||
tput cnorm 2>/dev/null || true
|
||||
fi
|
||||
echo ""
|
||||
return 1
|
||||
;;
|
||||
" ") # 空格键
|
||||
# 切换选中状态
|
||||
if [ ${selected_status[$cursor]} -eq 0 ]; then
|
||||
selected_status[$cursor]=1
|
||||
else
|
||||
selected_status[$cursor]=0
|
||||
fi
|
||||
;;
|
||||
"") # 回车键
|
||||
# 构建结果字符串 (选中项的索引,用逗号分隔)
|
||||
local first=true
|
||||
for i in "${!selected_status[@]}"; do
|
||||
if [ ${selected_status[$i]} -eq 1 ]; then
|
||||
if [ "$first" = true ]; then
|
||||
result="$i"
|
||||
first=false
|
||||
else
|
||||
result="$result,$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
break
|
||||
;;
|
||||
[0-9]) # 数字键 - 直接跳转
|
||||
local num=$((key))
|
||||
if [ $num -lt $option_count ]; then
|
||||
cursor=$num
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 恢复终端设置
|
||||
if [ -n "$saved_tty" ]; then
|
||||
stty "$saved_tty" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 显示光标 (如果支持)
|
||||
if [ "$has_tput" = true ]; then
|
||||
tput cnorm 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 设置返回变量
|
||||
eval "$return_var=\"$result\""
|
||||
|
||||
echo ""
|
||||
echo "${GREEN}已选择索引: $result${NC}"
|
||||
|
||||
# 显示已选项
|
||||
if [ -n "$result" ]; then
|
||||
echo "${GREEN}已选择选项:${NC}"
|
||||
IFS=',' read -ra SELECTED_INDICES <<< "$result"
|
||||
for i in "${SELECTED_INDICES[@]}"; do
|
||||
echo "${GREEN} - ${options[$i]}${NC}"
|
||||
done
|
||||
else
|
||||
echo "${YELLOW}未选择任何选项${NC}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 使用示例
|
||||
#######################################
|
||||
|
||||
# notice_info "这是一条信息通知"
|
||||
# notice_success "操作成功完成"
|
||||
# notice_warning "请注意这个警告"
|
||||
# notice_error "发生了错误"
|
||||
# DEBUG=true notice_debug "这是调试信息"
|
||||
# notice_system "系统通知" "这是一条系统通知消息"
|
||||
|
||||
# # 进度条示例
|
||||
# for i in {1..10}; do
|
||||
# notice_progress $i 10 "文件下载中"
|
||||
# sleep 0.5
|
||||
# done
|
||||
|
||||
# # 用户输入示例
|
||||
# notice_prompt "请输入您的名字" "user_name"
|
||||
# echo "您好, $user_name!"
|
||||
|
||||
# # 确认示例
|
||||
# if notice_confirm "是否继续?"; then
|
||||
# echo "用户选择继续"
|
||||
# else
|
||||
# echo "用户选择取消"
|
||||
# fi
|
||||
|
||||
# # 单选菜单示例
|
||||
# notice_select_menu "请选择一个操作系统" "selected_os" "Linux" "MacOS" "Windows" "其他"
|
||||
# echo "您选择了: $selected_os"
|
||||
|
||||
# # 多选菜单示例
|
||||
# notice_multi_select_menu "请选择您喜欢的编程语言" "selected_langs" "Python" "JavaScript" "Bash" "Go" "Rust" "Java"
|
||||
# echo "选择的索引: $selected_langs"
|
||||
611
frontend/scripts/tools/other-handle.sh
Normal file
611
frontend/scripts/tools/other-handle.sh
Normal file
@@ -0,0 +1,611 @@
|
||||
#!/bin/bash
|
||||
|
||||
#######################################
|
||||
# 通用工具处理脚本
|
||||
#
|
||||
# 此脚本提供了一系列通用工具函数,包括系统环境检测、
|
||||
# 依赖检测、工作区检测、配置文件解析、命令行参数解析
|
||||
# 以及yq工具的常用操作方法。
|
||||
#
|
||||
# 作者: chudong
|
||||
# 版本: 1.0.0
|
||||
#######################################
|
||||
|
||||
# 引入通知处理脚本
|
||||
OTHER_TOOL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$OTHER_TOOL_DIR/notice-handle.sh"
|
||||
|
||||
#######################################
|
||||
# 检测系统环境信息
|
||||
# 全局变量:
|
||||
# OS_TYPE - 操作系统类型 (Linux/MacOS/Windows/Unknown)
|
||||
# OS_NAME - 操作系统名称 (如 Ubuntu, Debian, macOS等)
|
||||
# OS_VERSION - 操作系统版本
|
||||
# ARCH - 系统架构 (x86_64, arm64等)
|
||||
# SHELL_TYPE - Shell类型 (bash, zsh等)
|
||||
# 返回值:
|
||||
# 0 - 成功检测
|
||||
# 1 - 检测失败
|
||||
#######################################
|
||||
check_environment() {
|
||||
notice_info "检测系统环境..."
|
||||
|
||||
# 检测操作系统类型
|
||||
case "$(uname -s)" in
|
||||
Linux*)
|
||||
OS_TYPE="Linux"
|
||||
if [ -f /etc/os-release ]; then
|
||||
OS_NAME=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
|
||||
OS_VERSION=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"')
|
||||
else
|
||||
OS_NAME="Unknown Linux"
|
||||
OS_VERSION="Unknown"
|
||||
fi
|
||||
;;
|
||||
Darwin*)
|
||||
OS_TYPE="MacOS"
|
||||
OS_NAME="macOS"
|
||||
OS_VERSION=$(sw_vers -productVersion)
|
||||
;;
|
||||
CYGWIN*|MINGW*|MSYS*)
|
||||
OS_TYPE="Windows"
|
||||
OS_NAME="Windows"
|
||||
OS_VERSION="Unknown"
|
||||
;;
|
||||
*)
|
||||
OS_TYPE="Unknown"
|
||||
OS_NAME="Unknown"
|
||||
OS_VERSION="Unknown"
|
||||
notice_error "无法识别的操作系统类型: $(uname -s)"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# 检测系统架构
|
||||
ARCH=$(uname -m)
|
||||
|
||||
# 检测Shell类型
|
||||
SHELL_TYPE=$(basename "$SHELL")
|
||||
|
||||
# 输出检测结果
|
||||
notice_success "系统环境检测完成"
|
||||
notice_info "操作系统类型: $OS_TYPE"
|
||||
notice_info "操作系统版本: $OS_VERSION"
|
||||
notice_info "系统架构: $ARCH"
|
||||
notice_info "Shell类型: $SHELL_TYPE"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 检测yq依赖是否安装
|
||||
# 参数:
|
||||
# $1: 最低版本要求 (可选,格式如 "4.0.0")
|
||||
# 全局变量:
|
||||
# YQ_PATH - yq命令的完整路径
|
||||
# YQ_VERSION - yq的版本号
|
||||
# 返回值:
|
||||
# 0 - yq已安装且版本符合要求
|
||||
# 1 - yq未安装或版本不符合要求
|
||||
#######################################
|
||||
check_yq_dependency() {
|
||||
local min_version="${1:-0.0.0}"
|
||||
local yq_cmd
|
||||
|
||||
notice_info "检测yq依赖..."
|
||||
|
||||
# 检查yq命令是否可用
|
||||
yq_cmd=$(command -v yq)
|
||||
if [ -z "$yq_cmd" ]; then
|
||||
notice_error "yq 未安装"
|
||||
notice_info "请安装yq: https://github.com/mikefarah/yq#install"
|
||||
return 1
|
||||
fi
|
||||
|
||||
YQ_PATH="$yq_cmd"
|
||||
YQ_VERSION=$("$YQ_PATH" --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||
|
||||
# 检查版本要求
|
||||
if [ "$min_version" != "0.0.0" ]; then
|
||||
# 简单版本比较函数
|
||||
version_lt() {
|
||||
[ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ] && [ "$1" != "$2" ]
|
||||
}
|
||||
|
||||
if version_lt "$YQ_VERSION" "$min_version"; then
|
||||
notice_error "yq版本过低: $YQ_VERSION (需要 $min_version 或更高)"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
notice_success "yq依赖检测通过 (版本: $YQ_VERSION, 路径: $YQ_PATH)"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 检测当前目录是否为工作区根目录
|
||||
# 参数:
|
||||
# $@: 表示工作区的标志文件或目录 (默认为 package.json, .git等)
|
||||
# 全局变量:
|
||||
# WORKSPACE_ROOT - 工作区根目录的绝对路径
|
||||
# 返回值:
|
||||
# 0 - 在工作区根目录中
|
||||
# 1 - 不在工作区根目录中
|
||||
#######################################
|
||||
check_workspace() {
|
||||
local markers=("$@")
|
||||
local current_dir
|
||||
local parent_dir
|
||||
|
||||
notice_info "检测工作区..."
|
||||
|
||||
# 如果未指定标志,使用默认值
|
||||
if [ ${#markers[@]} -eq 0 ]; then
|
||||
markers=("package.json" ".git" "pnpm-workspace.yaml" "turbo.json")
|
||||
fi
|
||||
|
||||
# 获取当前目录的绝对路径
|
||||
current_dir=$(pwd)
|
||||
parent_dir="$current_dir"
|
||||
|
||||
while [ "$parent_dir" != "/" ]; do
|
||||
for marker in "${markers[@]}"; do
|
||||
if [ -e "$parent_dir/$marker" ]; then
|
||||
WORKSPACE_ROOT="$parent_dir"
|
||||
notice_success "找到工作区根目录: $WORKSPACE_ROOT"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
parent_dir=$(dirname "$parent_dir")
|
||||
done
|
||||
|
||||
notice_error "未找到工作区根目录"
|
||||
return 1
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 解析YAML配置文件
|
||||
# 参数:
|
||||
# $1: YAML配置文件路径
|
||||
# $2: 用于存储解析后配置的关联数组名称
|
||||
# 返回值:
|
||||
# 0 - 成功解析配置
|
||||
# 1 - 解析失败
|
||||
# 使用示例:
|
||||
# declare -A CONFIG
|
||||
# parse_yaml_config "config.yaml" CONFIG
|
||||
# echo "用户名: ${CONFIG[username]}"
|
||||
#######################################
|
||||
parse_yaml_config() {
|
||||
local config_file="$1"
|
||||
local config_var="$2"
|
||||
|
||||
notice_info "解析配置文件: $config_file"
|
||||
|
||||
# 检查文件是否存在
|
||||
if [ ! -f "$config_file" ]; then
|
||||
notice_error "配置文件不存在: $config_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查yq依赖
|
||||
if ! check_yq_dependency "4.0.0"; then
|
||||
notice_error "解析YAML需要yq 4.0.0或更高版本"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查文件格式是否为YAML
|
||||
if ! "$YQ_PATH" e '.' "$config_file" > /dev/null 2>&1; then
|
||||
notice_error "无效的YAML文件: $config_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 将YAML转换为扁平的键值对
|
||||
local key_values
|
||||
key_values=$("$YQ_PATH" e 'to_entries | .[] | select(.value != null) | [.key, .value] | join("=")' "$config_file")
|
||||
|
||||
# 解析键值对到关联数组
|
||||
while IFS= read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
IFS='=' read -r key value <<< "$line"
|
||||
# 使用eval给指定的数组变量赋值
|
||||
eval "$config_var[\$key]=\$value"
|
||||
fi
|
||||
done <<< "$key_values"
|
||||
|
||||
notice_success "配置文件解析完成"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 解析命令行参数
|
||||
# 参数:
|
||||
# $@: 所有命令行参数
|
||||
# 全局变量:
|
||||
# PARAMS - 关联数组,存储所有解析后的参数
|
||||
# POSITIONAL - 数组,存储所有位置参数
|
||||
# 返回值:
|
||||
# 0 - 成功解析参数
|
||||
# 1 - 解析参数时出错
|
||||
# 使用示例:
|
||||
# parse_arguments "$@"
|
||||
# echo "输出文件: ${PARAMS[output]}"
|
||||
# echo "调试模式: ${PARAMS[debug]}"
|
||||
# echo "第一个位置参数: ${POSITIONAL[0]}"
|
||||
#######################################
|
||||
parse_arguments() {
|
||||
# 初始化全局参数数组
|
||||
declare -gA PARAMS
|
||||
declare -ga POSITIONAL=()
|
||||
|
||||
notice_info "解析命令行参数..."
|
||||
|
||||
# 如果没有参数,返回成功
|
||||
if [ $# -eq 0 ]; then
|
||||
notice_warning "没有提供命令行参数"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 解析所有参数
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
# 长选项 (--option=value 或 --option value)
|
||||
--*=*)
|
||||
key="${1#--}"
|
||||
key="${key%%=*}"
|
||||
value="${1#*=}"
|
||||
PARAMS["$key"]="$value"
|
||||
shift
|
||||
;;
|
||||
--*)
|
||||
key="${1#--}"
|
||||
if [[ "$2" != -* && $# -gt 1 ]]; then
|
||||
PARAMS["$key"]="$2"
|
||||
shift 2
|
||||
else
|
||||
# 布尔标志
|
||||
PARAMS["$key"]="true"
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
# 短选项 (-o value 或 -o)
|
||||
-*)
|
||||
if [ ${#1} -gt 2 ]; then
|
||||
# 组合短选项 (-abc)
|
||||
flags="${1:1}"
|
||||
for ((i=0; i<${#flags}; i++)); do
|
||||
flag="${flags:$i:1}"
|
||||
PARAMS["$flag"]="true"
|
||||
done
|
||||
shift
|
||||
else
|
||||
# 单个短选项 (-a value 或 -a)
|
||||
key="${1:1}"
|
||||
if [[ "$2" != -* && $# -gt 1 ]]; then
|
||||
PARAMS["$key"]="$2"
|
||||
shift 2
|
||||
else
|
||||
# 布尔标志
|
||||
PARAMS["$key"]="true"
|
||||
shift
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
# 位置参数
|
||||
*)
|
||||
POSITIONAL+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 输出解析结果
|
||||
if [ ${#PARAMS[@]} -gt 0 ]; then
|
||||
notice_info "命名参数:"
|
||||
for key in "${!PARAMS[@]}"; do
|
||||
notice_info " - $key: ${PARAMS[$key]}"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${#POSITIONAL[@]} -gt 0 ]; then
|
||||
notice_info "位置参数:"
|
||||
for ((i=0; i<${#POSITIONAL[@]}; i++)); do
|
||||
notice_info " - $i: ${POSITIONAL[$i]}"
|
||||
done
|
||||
fi
|
||||
|
||||
notice_success "命令行参数解析完成"
|
||||
return 0
|
||||
}
|
||||
|
||||
#######################################
|
||||
# yq常用操作方法集合
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# 从YAML文件获取指定路径的值
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: YAML路径表达式
|
||||
# 返回值:
|
||||
# 0 - 成功获取值
|
||||
# 1 - 失败
|
||||
# 标准输出: 查询到的值
|
||||
#######################################
|
||||
yq_get_value() {
|
||||
local file="$1"
|
||||
local path="$2"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
notice_error "文件不存在: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e "$path" "$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 设置YAML文件中指定路径的值
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: YAML路径表达式
|
||||
# $3: 要设置的值
|
||||
# 返回值:
|
||||
# 0 - 成功设置值
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
yq_set_value() {
|
||||
local file="$1"
|
||||
local path="$2"
|
||||
local value="$3"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
notice_error "文件不存在: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e "$path = $value" -i "$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 删除YAML文件中指定路径的值
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: YAML路径表达式
|
||||
# 返回值:
|
||||
# 0 - 成功删除值
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
yq_delete_path() {
|
||||
local file="$1"
|
||||
local path="$2"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
notice_error "文件不存在: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e "del($path)" -i "$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 合并两个YAML文件
|
||||
# 参数:
|
||||
# $1: 目标文件路径
|
||||
# $2: 源文件路径
|
||||
# 返回值:
|
||||
# 0 - 成功合并文件
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
yq_merge_files() {
|
||||
local target_file="$1"
|
||||
local source_file="$2"
|
||||
|
||||
if [ ! -f "$target_file" ] || [ ! -f "$source_file" ]; then
|
||||
notice_error "文件不存在"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' "$target_file" "$source_file" > "${target_file}.tmp" \
|
||||
&& mv "${target_file}.tmp" "$target_file"
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 检查YAML文件中是否存在某个路径
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: YAML路径表达式
|
||||
# 返回值:
|
||||
# 0 - 路径存在
|
||||
# 1 - 路径不存在或文件不存在
|
||||
#######################################
|
||||
yq_has_path() {
|
||||
local file="$1"
|
||||
local path="$2"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
notice_error "文件不存在: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 若路径存在,则值不为null,返回true
|
||||
if [ "$("$YQ_PATH" e "$path" "$file")" != "null" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 为YAML数组添加元素
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: 数组路径表达式
|
||||
# $3: 要添加的值
|
||||
# 返回值:
|
||||
# 0 - 成功添加元素
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
yq_array_append() {
|
||||
local file="$1"
|
||||
local array_path="$2"
|
||||
local value="$3"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
notice_error "文件不存在: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e "$array_path += [$value]" -i "$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 获取YAML数组长度
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: 数组路径表达式
|
||||
# 返回值:
|
||||
# 0 - 成功获取长度
|
||||
# 1 - 失败
|
||||
# 标准输出: 数组长度
|
||||
#######################################
|
||||
yq_array_length() {
|
||||
local file="$1"
|
||||
local array_path="$2"
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
notice_error "文件不存在: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e "$array_path | length" "$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 将YAML转换为JSON
|
||||
# 参数:
|
||||
# $1: YAML文件路径
|
||||
# $2: 输出JSON文件路径 (可选,默认为与YAML文件同名但扩展名为.json)
|
||||
# 返回值:
|
||||
# 0 - 成功转换
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
yq_to_json() {
|
||||
local yaml_file="$1"
|
||||
local json_file="${2:-${yaml_file%.*}.json}"
|
||||
|
||||
if [ ! -f "$yaml_file" ]; then
|
||||
notice_error "YAML文件不存在: $yaml_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e -o=json '.' "$yaml_file" > "$json_file"
|
||||
notice_success "转换完成: $yaml_file -> $json_file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 将JSON转换为YAML
|
||||
# 参数:
|
||||
# $1: JSON文件路径
|
||||
# $2: 输出YAML文件路径 (可选,默认为与JSON文件同名但扩展名为.yaml)
|
||||
# 返回值:
|
||||
# 0 - 成功转换
|
||||
# 1 - 失败
|
||||
#######################################
|
||||
yq_from_json() {
|
||||
local json_file="$1"
|
||||
local yaml_file="${2:-${json_file%.*}.yaml}"
|
||||
|
||||
if [ ! -f "$json_file" ]; then
|
||||
notice_error "JSON文件不存在: $json_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$YQ_PATH" e -p=json -o=yaml '.' "$json_file" > "$yaml_file"
|
||||
notice_success "转换完成: $json_file -> $yaml_file"
|
||||
return $?
|
||||
}
|
||||
|
||||
#######################################
|
||||
# 使用示例
|
||||
#######################################
|
||||
|
||||
# 运行所有示例函数
|
||||
run_examples() {
|
||||
notice_info "运行示例..."
|
||||
|
||||
# 1. 环境检测示例
|
||||
check_environment
|
||||
echo ""
|
||||
|
||||
# 2. yq依赖检测示例
|
||||
check_yq_dependency
|
||||
echo ""
|
||||
|
||||
# 3. 工作区检测示例
|
||||
check_workspace
|
||||
echo ""
|
||||
|
||||
# 4. 配置文件解析示例(假设有配置文件)
|
||||
if [ -f "config.yaml" ]; then
|
||||
declare -A CONFIG
|
||||
parse_yaml_config "config.yaml" CONFIG
|
||||
echo "解析到的配置项:"
|
||||
for key in "${!CONFIG[@]}"; do
|
||||
echo " $key: ${CONFIG[$key]}"
|
||||
done
|
||||
echo ""
|
||||
else
|
||||
notice_warning "示例配置文件 config.yaml 不存在,跳过解析示例"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 5. 命令行参数解析示例
|
||||
parse_arguments --name="示例项目" --debug -v -o output.txt input1.txt input2.txt
|
||||
echo ""
|
||||
|
||||
# 6. yq操作示例(假设有YAML文件)
|
||||
if [ -f "example.yaml" ]; then
|
||||
notice_info "yq操作示例:"
|
||||
echo "- 获取值示例:"
|
||||
yq_get_value "example.yaml" ".name"
|
||||
echo ""
|
||||
|
||||
echo "- 检查路径示例:"
|
||||
if yq_has_path "example.yaml" ".version"; then
|
||||
echo "version 字段存在"
|
||||
else
|
||||
echo "version 字段不存在"
|
||||
fi
|
||||
echo ""
|
||||
else
|
||||
notice_warning "示例YAML文件 example.yaml 不存在,跳过yq操作示例"
|
||||
fi
|
||||
|
||||
notice_success "示例运行完成"
|
||||
}
|
||||
|
||||
# 如果直接运行此脚本,显示帮助
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
if [ "$1" = "--examples" ] || [ "$1" = "-e" ]; then
|
||||
run_examples
|
||||
else
|
||||
notice_info "此脚本提供以下功能:"
|
||||
echo " 1. 系统环境检测 (check_environment)"
|
||||
echo " 2. yq依赖检测 (check_yq_dependency)"
|
||||
echo " 3. 工作区检测 (check_workspace)"
|
||||
echo " 4. YAML配置文件解析 (parse_yaml_config)"
|
||||
echo " 5. 命令行参数解析 (parse_arguments)"
|
||||
echo " 6. yq常用操作 (yq_*)"
|
||||
echo ""
|
||||
echo "使用 --examples 或 -e 参数可以运行示例"
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user