1
0

完成一个简易的全局skill、command管理器

This commit is contained in:
2026-02-25 14:33:56 +08:00
parent f4cb809f9d
commit 2d327b5af8
60 changed files with 6053 additions and 1 deletions

View File

@@ -0,0 +1,109 @@
package repo
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"skillmgr/internal/config"
)
// URLToPathName 将 URL 转换为缓存目录名
// 例如: https://github.com/user/repo.git -> github.com_user_repo
func URLToPathName(url string) string {
clean := strings.TrimPrefix(url, "https://")
clean = strings.TrimPrefix(clean, "http://")
clean = strings.TrimSuffix(clean, ".git")
clean = strings.ReplaceAll(clean, "/", "_")
return clean
}
// CloneOrPull 克隆或更新仓库
// 如果仓库不存在则 clone存在则 pull
func CloneOrPull(url, branch string) (string, error) {
cachePath, err := config.GetCachePath()
if err != nil {
return "", err
}
repoPath := filepath.Join(cachePath, URLToPathName(url))
// 检查是否已存在
if _, err := os.Stat(filepath.Join(repoPath, ".git")); err == nil {
// 已存在,执行 pull
return repoPath, pullRepo(repoPath, branch)
}
// 不存在,执行 clone
return repoPath, cloneRepo(url, branch, repoPath)
}
// cloneRepo 克隆仓库
func cloneRepo(url, branch, dest string) error {
args := []string{"clone", "--depth", "1"}
if branch != "" {
args = append(args, "--branch", branch)
}
args = append(args, url, dest)
cmd := exec.Command("git", args...)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("git clone 失败: %w\n%s", err, output)
}
return nil
}
// pullRepo 更新仓库
func pullRepo(path, branch string) error {
// 先 fetch
fetchCmd := exec.Command("git", "-C", path, "fetch", "origin")
if output, err := fetchCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git fetch 失败: %w\n%s", err, output)
}
// 然后 pull
pullArgs := []string{"-C", path, "pull", "origin"}
if branch != "" {
pullArgs = append(pullArgs, branch)
}
pullCmd := exec.Command("git", pullArgs...)
output, err := pullCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("git pull 失败: %w\n%s", err, output)
}
return nil
}
// GetRepoPath 获取仓库缓存路径
func GetRepoPath(url string) (string, error) {
cachePath, err := config.GetCachePath()
if err != nil {
return "", err
}
return filepath.Join(cachePath, URLToPathName(url)), nil
}
// CloneTemporary 克隆临时仓库到临时目录
// 返回临时目录路径和清理函数
func CloneTemporary(url, branch string) (repoPath string, cleanup func(), err error) {
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "skillmgr-temp-*")
if err != nil {
return "", nil, fmt.Errorf("创建临时目录失败: %w", err)
}
cleanup = func() {
os.RemoveAll(tmpDir)
}
// 克隆到临时目录
if err := cloneRepo(url, branch, tmpDir); err != nil {
cleanup()
return "", nil, err
}
return tmpDir, cleanup, nil
}