307 lines
7.8 KiB
Bash
Executable File
307 lines
7.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# git-ops.sh - Git 操作封装
|
|
# 用法:
|
|
# ./git-ops.sh clone <repo> <name> - 克隆仓库
|
|
# ./git-ops.sh pull <name> - 拉取更新
|
|
# ./git-ops.sh checkout <name> <ref> - 切换版本
|
|
# ./git-ops.sh fetch <name> - 获取远程更新
|
|
# ./git-ops.sh status <name> - 查看状态
|
|
# ./git-ops.sh has-updates <name> - 检查是否有更新
|
|
|
|
set -e
|
|
|
|
SKILLS_DIR="$HOME/.claude/skills"
|
|
REPOS_DIR="$SKILLS_DIR/repos"
|
|
REGISTRY_SCRIPT="$SKILLS_DIR/skill-manager/scripts/registry.sh"
|
|
|
|
# 颜色定义
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# 从 URL 提取技能名称
|
|
extract_name() {
|
|
local repo="$1"
|
|
# 处理各种格式
|
|
# https://github.com/org/skill-name.git -> skill-name
|
|
# git@github.com:org/skill-name.git -> skill-name
|
|
echo "$repo" | sed -E 's|.*/([^/]+)(\.git)?$|\1|' | sed 's/\.git$//'
|
|
}
|
|
|
|
# 克隆仓库
|
|
cmd_clone() {
|
|
local repo="$1"
|
|
local name="${2:-$(extract_name "$repo")}"
|
|
|
|
if [ -z "$repo" ]; then
|
|
echo -e "${RED}用法: git-ops.sh clone <repo> [name]${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
local target_dir="$REPOS_DIR/$name"
|
|
|
|
# 检查是否已存在
|
|
if [ -d "$target_dir" ]; then
|
|
echo -e "${YELLOW}技能已存在: $name${NC}"
|
|
echo "使用 'git-ops.sh pull $name' 更新"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BLUE}克隆技能: $name${NC}"
|
|
echo "仓库: $repo"
|
|
echo "目标: $target_dir"
|
|
echo "----------------------------------------"
|
|
|
|
# 确保 repos 目录存在
|
|
mkdir -p "$REPOS_DIR"
|
|
|
|
# 克隆仓库
|
|
if git clone "$repo" "$target_dir"; then
|
|
echo -e "${GREEN}✓ 克隆成功${NC}"
|
|
|
|
# 检查 skill.yaml
|
|
if [ ! -f "$target_dir/skill.yaml" ]; then
|
|
echo -e "${YELLOW}⚠ 警告: 未找到 skill.yaml${NC}"
|
|
fi
|
|
|
|
# 获取版本
|
|
local version="unknown"
|
|
if [ -f "$target_dir/skill.yaml" ] && command -v yq &> /dev/null; then
|
|
version=$(yq e '.version // "1.0.0"' "$target_dir/skill.yaml")
|
|
fi
|
|
|
|
# 添加到 registry
|
|
"$REGISTRY_SCRIPT" add "$name" "$repo" "$version"
|
|
|
|
echo -e "${GREEN}✓ 技能安装完成: $name ($version)${NC}"
|
|
else
|
|
echo -e "${RED}✗ 克隆失败${NC}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 拉取更新
|
|
cmd_pull() {
|
|
local name="$1"
|
|
|
|
if [ -z "$name" ]; then
|
|
echo -e "${RED}用法: git-ops.sh pull <name>${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
local repo_dir="$REPOS_DIR/$name"
|
|
|
|
if [ ! -d "$repo_dir" ]; then
|
|
echo -e "${RED}技能不存在: $name${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BLUE}更新技能: $name${NC}"
|
|
echo "----------------------------------------"
|
|
|
|
cd "$repo_dir"
|
|
|
|
# 获取当前版本
|
|
local old_version="unknown"
|
|
if [ -f "skill.yaml" ] && command -v yq &> /dev/null; then
|
|
old_version=$(yq e '.version // "unknown"' skill.yaml)
|
|
fi
|
|
|
|
# 拉取更新
|
|
if git pull origin main 2>/dev/null || git pull origin master 2>/dev/null; then
|
|
# 获取新版本
|
|
local new_version="unknown"
|
|
if [ -f "skill.yaml" ] && command -v yq &> /dev/null; then
|
|
new_version=$(yq e '.version // "unknown"' skill.yaml)
|
|
fi
|
|
|
|
if [ "$old_version" != "$new_version" ]; then
|
|
echo -e "${GREEN}✓ 版本更新: $old_version → $new_version${NC}"
|
|
"$REGISTRY_SCRIPT" update "$name" version "$new_version"
|
|
else
|
|
echo -e "${GREEN}✓ 已是最新版本: $new_version${NC}"
|
|
fi
|
|
|
|
# 更新 last_updated
|
|
"$REGISTRY_SCRIPT" update "$name" last_updated "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
else
|
|
echo -e "${RED}✗ 更新失败${NC}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 切换版本
|
|
cmd_checkout() {
|
|
local name="$1"
|
|
local ref="$2"
|
|
|
|
if [ -z "$name" ] || [ -z "$ref" ]; then
|
|
echo -e "${RED}用法: git-ops.sh checkout <name> <ref>${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
local repo_dir="$REPOS_DIR/$name"
|
|
|
|
if [ ! -d "$repo_dir" ]; then
|
|
echo -e "${RED}技能不存在: $name${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BLUE}切换版本: $name → $ref${NC}"
|
|
echo "----------------------------------------"
|
|
|
|
cd "$repo_dir"
|
|
|
|
# 获取当前版本
|
|
local old_ref=$(git describe --tags --always 2>/dev/null || git rev-parse --short HEAD)
|
|
|
|
# 切换版本
|
|
if git checkout "$ref" 2>/dev/null; then
|
|
echo -e "${GREEN}✓ 版本切换: $old_ref → $ref${NC}"
|
|
|
|
# 更新 registry
|
|
"$REGISTRY_SCRIPT" update "$name" version "$ref"
|
|
"$REGISTRY_SCRIPT" update "$name" last_updated "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
else
|
|
echo -e "${RED}✗ 切换失败: $ref 不存在${NC}"
|
|
echo "可用的 tag:"
|
|
git tag -l | head -10
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 获取远程更新
|
|
cmd_fetch() {
|
|
local name="$1"
|
|
|
|
if [ -z "$name" ]; then
|
|
echo -e "${RED}用法: git-ops.sh fetch <name>${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
local repo_dir="$REPOS_DIR/$name"
|
|
|
|
if [ ! -d "$repo_dir" ]; then
|
|
echo -e "${RED}技能不存在: $name${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
cd "$repo_dir"
|
|
git fetch origin --tags --quiet
|
|
echo -e "${GREEN}✓ 已获取远程更新: $name${NC}"
|
|
}
|
|
|
|
# 查看状态
|
|
cmd_status() {
|
|
local name="$1"
|
|
|
|
if [ -z "$name" ]; then
|
|
echo -e "${RED}用法: git-ops.sh status <name>${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
local repo_dir="$REPOS_DIR/$name"
|
|
|
|
if [ ! -d "$repo_dir" ]; then
|
|
echo -e "${RED}技能不存在: $name${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BLUE}技能状态: $name${NC}"
|
|
echo "----------------------------------------"
|
|
|
|
cd "$repo_dir"
|
|
|
|
local branch=$(git branch --show-current 2>/dev/null || echo "detached")
|
|
local commit=$(git rev-parse --short HEAD)
|
|
local remote_url=$(git config --get remote.origin.url)
|
|
|
|
echo "分支: $branch"
|
|
echo "Commit: $commit"
|
|
echo "远程: $remote_url"
|
|
|
|
if [ -f "skill.yaml" ] && command -v yq &> /dev/null; then
|
|
local version=$(yq e '.version // "unknown"' skill.yaml)
|
|
echo "版本: $version"
|
|
fi
|
|
|
|
echo ""
|
|
echo "最近提交:"
|
|
git log --oneline -3
|
|
}
|
|
|
|
# 检查是否有更新
|
|
cmd_has_updates() {
|
|
local name="$1"
|
|
|
|
if [ -z "$name" ]; then
|
|
echo -e "${RED}用法: git-ops.sh has-updates <name>${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
local repo_dir="$REPOS_DIR/$name"
|
|
|
|
if [ ! -d "$repo_dir" ]; then
|
|
echo -e "${RED}技能不存在: $name${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
cd "$repo_dir"
|
|
|
|
# 获取远程更新
|
|
git fetch origin --quiet 2>/dev/null || true
|
|
|
|
# 比较本地和远程
|
|
local local_head=$(git rev-parse HEAD)
|
|
local remote_head=$(git rev-parse origin/main 2>/dev/null || git rev-parse origin/master 2>/dev/null || echo "")
|
|
|
|
if [ -z "$remote_head" ]; then
|
|
echo "unknown"
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$local_head" != "$remote_head" ]; then
|
|
echo "yes"
|
|
# 显示更新数量
|
|
local behind=$(git rev-list HEAD..origin/main --count 2>/dev/null || git rev-list HEAD..origin/master --count 2>/dev/null || echo "0")
|
|
echo "behind: $behind commits"
|
|
else
|
|
echo "no"
|
|
fi
|
|
}
|
|
|
|
# 主命令分发
|
|
case "${1:-help}" in
|
|
clone)
|
|
cmd_clone "$2" "$3"
|
|
;;
|
|
pull)
|
|
cmd_pull "$2"
|
|
;;
|
|
checkout)
|
|
cmd_checkout "$2" "$3"
|
|
;;
|
|
fetch)
|
|
cmd_fetch "$2"
|
|
;;
|
|
status)
|
|
cmd_status "$2"
|
|
;;
|
|
has-updates)
|
|
cmd_has_updates "$2"
|
|
;;
|
|
*)
|
|
echo "用法: git-ops.sh <command> [args]"
|
|
echo ""
|
|
echo "命令:"
|
|
echo " clone <repo> [name] 克隆仓库"
|
|
echo " pull <name> 拉取更新"
|
|
echo " checkout <name> <ref> 切换版本"
|
|
echo " fetch <name> 获取远程更新"
|
|
echo " status <name> 查看状态"
|
|
echo " has-updates <name> 检查是否有更新"
|
|
;;
|
|
esac
|