1
0
Files
Skill/manager/internal/repo/git.go

110 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
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.
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
}