From 928f7bcf27323dd851df9509c04566890e965e95 Mon Sep 17 00:00:00 2001 From: engigu Date: Mon, 22 Dec 2025 21:36:06 +0800 Subject: [PATCH] chore: adjust deps fucnction --- Dockerfile | 3 + internal/controllers/runtime_controller.go | 50 ++++++++--- internal/router/router.go | 12 +-- internal/services/deps_env/conda_service.go | 93 ++++++++++++++++----- 4 files changed, 121 insertions(+), 37 deletions(-) diff --git a/Dockerfile b/Dockerfile index e4b7a8e..ffc72ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,6 +58,9 @@ RUN sed -i 's@deb.debian.org@mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.li && "${CONDA_DIR}"/bin/conda config --set show_channel_urls yes \ && "${CONDA_DIR}"/bin/conda config --set channel_priority strict \ && "${CONDA_DIR}"/bin/conda init \ + && "${CONDA_DIR}"/bin/conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main \ + && "${CONDA_DIR}"/bin/conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free \ + && "${CONDA_DIR}"/bin/conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge \ && "${CONDA_DIR}"/bin/python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \ && "${CONDA_DIR}"/bin/conda clean -afy diff --git a/internal/controllers/runtime_controller.go b/internal/controllers/runtime_controller.go index d3a2632..002660c 100644 --- a/internal/controllers/runtime_controller.go +++ b/internal/controllers/runtime_controller.go @@ -25,7 +25,12 @@ func (rc *RuntimeController) GetAvailableRuntimes(c *gin.Context) { // ListEnvs 列出指定运行时的所有环境 func (rc *RuntimeController) ListEnvs(c *gin.Context) { - runtimeType := c.Param("type") + runtimeType := c.Query("type") + if runtimeType == "" { + utils.BadRequest(c, "缺少 type 参数") + return + } + manager := rc.runtimeService.GetManager(runtimeType) if manager == nil { utils.NotFound(c, "运行时类型不存在") @@ -48,7 +53,12 @@ func (rc *RuntimeController) ListEnvs(c *gin.Context) { // CreateEnv 创建环境 func (rc *RuntimeController) CreateEnv(c *gin.Context) { - runtimeType := c.Param("type") + runtimeType := c.Query("type") + if runtimeType == "" { + utils.BadRequest(c, "缺少 type 参数") + return + } + manager := rc.runtimeService.GetManager(runtimeType) if manager == nil { utils.NotFound(c, "运行时类型不存在") @@ -75,8 +85,13 @@ func (rc *RuntimeController) CreateEnv(c *gin.Context) { // DeleteEnv 删除环境 func (rc *RuntimeController) DeleteEnv(c *gin.Context) { - runtimeType := c.Param("type") - envName := c.Param("name") + runtimeType := c.Query("type") + envName := c.Query("name") + + if runtimeType == "" || envName == "" { + utils.BadRequest(c, "缺少 type 或 name 参数") + return + } manager := rc.runtimeService.GetManager(runtimeType) if manager == nil { @@ -99,8 +114,13 @@ func (rc *RuntimeController) DeleteEnv(c *gin.Context) { // ListPackages 列出环境中的包 func (rc *RuntimeController) ListPackages(c *gin.Context) { - runtimeType := c.Param("type") - envName := c.Param("name") + runtimeType := c.Query("type") + envName := c.Query("env") + + if runtimeType == "" || envName == "" { + utils.BadRequest(c, "缺少 type 或 env 参数") + return + } manager := rc.runtimeService.GetManager(runtimeType) if manager == nil { @@ -119,8 +139,13 @@ func (rc *RuntimeController) ListPackages(c *gin.Context) { // InstallPackage 安装包 func (rc *RuntimeController) InstallPackage(c *gin.Context) { - runtimeType := c.Param("type") - envName := c.Param("name") + runtimeType := c.Query("type") + envName := c.Query("env") + + if runtimeType == "" || envName == "" { + utils.BadRequest(c, "缺少 type 或 env 参数") + return + } manager := rc.runtimeService.GetManager(runtimeType) if manager == nil { @@ -147,8 +172,13 @@ func (rc *RuntimeController) InstallPackage(c *gin.Context) { // UninstallPackage 卸载包 func (rc *RuntimeController) UninstallPackage(c *gin.Context) { - runtimeType := c.Param("type") - envName := c.Param("name") + runtimeType := c.Query("type") + envName := c.Query("env") + + if runtimeType == "" || envName == "" { + utils.BadRequest(c, "缺少 type 或 env 参数") + return + } manager := rc.runtimeService.GetManager(runtimeType) if manager == nil { diff --git a/internal/router/router.go b/internal/router/router.go index 9f5189e..b8722d4 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -189,12 +189,12 @@ func Setup(c *Controllers) *gin.Engine { runtime := authorized.Group("/runtime") { runtime.GET("", c.Runtime.GetAvailableRuntimes) - runtime.GET("/:type/envs", c.Runtime.ListEnvs) - runtime.POST("/:type/envs", c.Runtime.CreateEnv) - runtime.DELETE("/:type/envs/:name", c.Runtime.DeleteEnv) - runtime.GET("/:type/envs/:name/packages", c.Runtime.ListPackages) - runtime.POST("/:type/envs/:name/packages", c.Runtime.InstallPackage) - runtime.DELETE("/:type/envs/:name/packages", c.Runtime.UninstallPackage) + runtime.GET("/envs", c.Runtime.ListEnvs) + runtime.POST("/envs", c.Runtime.CreateEnv) + runtime.DELETE("/envs", c.Runtime.DeleteEnv) + runtime.GET("/packages", c.Runtime.ListPackages) + runtime.POST("/packages", c.Runtime.InstallPackage) + runtime.DELETE("/packages", c.Runtime.UninstallPackage) } } } diff --git a/internal/services/deps_env/conda_service.go b/internal/services/deps_env/conda_service.go index 63fe876..85b7639 100644 --- a/internal/services/deps_env/conda_service.go +++ b/internal/services/deps_env/conda_service.go @@ -3,12 +3,20 @@ package deps_env import ( "bufio" "encoding/json" + "os" "os/exec" + "path/filepath" "strings" + "baihu/internal/constant" "baihu/internal/logger" ) +// getEnvsDir 获取虚拟环境存储目录 +func getEnvsDir() string { + return filepath.Join(constant.DataDir, "envs") +} + // CondaManager Conda 运行时管理器 type CondaManager struct { condaPath string @@ -54,9 +62,16 @@ func (cm *CondaManager) getCondaPath() string { return cm.condaPath } +// condaEnvDetail 环境详情 +type condaEnvDetail struct { + Name string `json:"name"` + Active bool `json:"active"` +} + // condaEnvJSON conda env list --json 的输出结构 type condaEnvJSON struct { - Envs []string `json:"envs"` + Envs []string `json:"envs"` + EnvsDetails map[string]condaEnvDetail `json:"envs_details"` } // ListEnvs 列出所有 Conda 环境 @@ -80,35 +95,27 @@ func (cm *CondaManager) ListEnvs() ([]RuntimeEnv, error) { var envs []RuntimeEnv for _, envPath := range envJSON.Envs { - name := extractEnvName(envPath) - // 过滤以 . 开头的环境 - if strings.HasPrefix(name, ".") { - continue + detail, ok := envJSON.EnvsDetails[envPath] + name := "" + active := false + if ok { + name = detail.Name + active = detail.Active + } + // 如果没有 name,使用路径 + if name == "" { + name = envPath } envs = append(envs, RuntimeEnv{ Name: name, Path: envPath, - Active: false, + Active: active, }) } return envs, nil } -// extractEnvName 从路径中提取环境名称 -func extractEnvName(envPath string) string { - parts := strings.Split(envPath, "/") - if len(parts) > 0 { - name := parts[len(parts)-1] - // 如果是 base 环境,路径可能是 /opt/conda 这样的 - if name == "conda" || name == "miniconda3" || name == "anaconda3" { - return "base" - } - return name - } - return envPath -} - // CreateEnv 创建 Conda 环境 func (cm *CondaManager) CreateEnv(name string, version string) error { condaPath := cm.getCondaPath() @@ -116,21 +123,65 @@ func (cm *CondaManager) CreateEnv(name string, version string) error { return exec.ErrNotFound } - args := []string{"create", "-n", name, "-y"} + envsDir := getEnvsDir() + // 确保目录存在 + if err := os.MkdirAll(envsDir, 0755); err != nil { + return err + } + + envPath := filepath.Join(envsDir, name) + args := []string{"create", "-p", envPath, "-y"} if version != "" { args = append(args, "python="+version) } + logger.Infof("Creating conda env: %s %v", condaPath, args) cmd := exec.Command(condaPath, args...) output, err := cmd.CombinedOutput() if err != nil { logger.Errorf("Failed to create conda env: %v, output: %s", err, string(output)) return err } + logger.Infof("Conda env created: %s", envPath) + + // 写入 environments.txt + if err := cm.appendToEnvironmentsTxt(envPath); err != nil { + logger.Errorf("Failed to write environments.txt: %v", err) + } return nil } +// appendToEnvironmentsTxt 将环境路径追加到 environments.txt +func (cm *CondaManager) appendToEnvironmentsTxt(envPath string) error { + absPath, err := filepath.Abs(envPath) + if err != nil { + return err + } + + envsDir := getEnvsDir() + envsTxtPath := filepath.Join(envsDir, "environments.txt") + + // 读取现有内容,检查是否已存在 + content, _ := os.ReadFile(envsTxtPath) + lines := strings.Split(string(content), "\n") + for _, line := range lines { + if strings.TrimSpace(line) == absPath { + return nil // 已存在 + } + } + + // 追加写入 + f, err := os.OpenFile(envsTxtPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer f.Close() + + _, err = f.WriteString(absPath + "\n") + return err +} + // DeleteEnv 删除 Conda 环境 func (cm *CondaManager) DeleteEnv(name string) error { condaPath := cm.getCondaPath()