代码拉取完成,页面将自动刷新
package config
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"sync"
"gitee.com/gitwcx/jenv/sdk/constants"
)
var (
ErrJDKExists = errors.New("JDK already exists")
ErrJDKNotFound = errors.New("JDK not found")
ErrInvalidPath error = errors.New("Invalid Java installation path")
ErrNotInitialized = errors.New("jenvnot initialized")
)
var (
instance *Config
instanceLock sync.RWMutex
configPath string
)
type Config struct {
Current string `json:"current"`
SymlinkPath string `json:"symlink_path"`
Initialized bool `json:"initialized"`
EnvBackUpPath string `json:"env_backup_path"`
Jdks map[string]JDK `json:"jdks"` // 将数组改为 map
Theme string `json:"theme"` // Current theme name
// 添加互斥锁保护并发访问
lock sync.RWMutex
}
type JDK struct {
Name string `json:"name"`
Path string `json:"path"`
}
// GetInstance 返回配置的单例实例
func GetInstance() (*Config, error) {
instanceLock.RLock()
if instance != nil {
fmt.Println("[info] GetInstance instance != nil")
defer instanceLock.RUnlock()
return instance, nil
}
instanceLock.RUnlock()
instanceLock.Lock()
defer instanceLock.Unlock()
// 双重检查
if instance != nil {
fmt.Println("[info] GetInstance instance once != nil")
return instance, nil
}
// 加载配置
cfg, err := loadConfigFromFile()
if err != nil {
return nil, err
}
instance = cfg
return instance, nil
}
// 从文件加载配置
func loadConfigFromFile() (*Config, error) {
fmt.Println("loadConfigFromFile ...")
// 1. 获取config.json path
configPath, err := GetConfigPath()
if err != nil {
fmt.Println("[error] GetConfigPath ", err)
return nil, err
}
//2. 判断config.json 存在与否
if _, err := os.Stat(configPath); os.IsNotExist(err) {
// 如果不存在,则创建默认配置
// 默认backupFilepath 与configFilePath 在同一个folder
backupFilePath := GetDefaultBackupFilePath()
defaultSymlinkPath := GetDefaultSymlinkPath()
cfg := &Config{
Current: "",
SymlinkPath: defaultSymlinkPath,
Initialized: false,
EnvBackUpPath: backupFilePath,
Jdks: make(map[string]JDK), // 初始化 map
}
// 保存配置到文件
if err := cfg.doSave(); err != nil {
return nil, fmt.Errorf("保存配置文件失败: %w", err)
}
return cfg, nil
}
// 读取配置文件
data, err := os.ReadFile(configPath)
if err != nil {
return nil, err
}
// 解析配置文件
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, err
}
return &cfg, nil
}
func (c *Config) Save() error {
// 获取锁,防止并发修改
c.lock.Lock()
defer c.lock.Unlock()
return c.doSave()
}
// doSave 保存配置到文件
func (c *Config) doSave() error {
path, err := GetConfigPath()
if err != nil {
return err
}
// 新增:确保配置目录存在
configDir := filepath.Dir(path)
if err := os.MkdirAll(configDir, 0755); err != nil {
return fmt.Errorf("创建配置目录失败: %w", err)
}
data, err := json.MarshalIndent(c, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}
// SetSymlinkPath 设置符号链接路径
func (c *Config) SetSymlinkPath(symlinkPath string) {
c.lock.Lock()
defer c.lock.Unlock()
c.SymlinkPath = symlinkPath
c.doSave()
}
// SetCurrentJDK 设置当前JDK
func (c *Config) SetCurrentJDK(jdkName string) error {
c.lock.Lock()
defer c.lock.Unlock()
// 检查JDK是否存在
if _, exists := c.Jdks[jdkName]; !exists {
return ErrJDKNotFound
}
c.Current = jdkName
return c.doSave()
}
// AddJDK 添加新的JDK
func (c *Config) AddJDK(name, path string) error {
// 验证Java路径
if !ValidateJavaPath(path) {
return ErrInvalidPath
}
c.lock.Lock()
defer c.lock.Unlock()
// 检查是否已存在同名JDK
if _, exists := c.Jdks[name]; exists {
return ErrJDKExists
}
// 添加新JDK
c.Jdks[name] = JDK{Name: name, Path: path}
// 保存更新后的配置到文件
return c.doSave()
}
// RemoveJDK 移除JDK
func (c *Config) RemoveJDK(name string) error {
c.lock.Lock()
defer c.lock.Unlock()
// 检查JDK是否存在
if _, exists := c.Jdks[name]; !exists {
return ErrJDKNotFound
}
// 删除JDK
delete(c.Jdks, name)
// 如果移除的是当前JDK,则取消设置
if c.Current == name {
c.Current = ""
}
// 保存更新后的配置到文件
return c.doSave()
}
// 保留原有的工具函数
func ValidateJavaPath(path string) bool {
name, ok := constants.Sdks[constants.SdkType].ExecName[runtime.GOOS]
if !ok {
return false
}
for _, n := range name {
execPath := filepath.Join(path, n)
_, err := os.Stat(execPath)
if err == nil {
return true
}
}
return false
}
func GetDefaultSymlinkPath() string {
return constants.GetDefaultSymlinkPath(constants.SdkType)
}
// CreateSymlink creates a symbolic link from source to target
func CreateSymlink(source, target string) error {
// 如果目标已存在,先删除
_ = os.Remove(target)
// 创建符号链接的父目录
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
return err
}
// 创建符号链接
return os.Symlink(source, target)
}
// SetConfigPath sets a custom path for the config file
func SetConfigPath(path string) {
instanceLock.Lock()
defer instanceLock.Unlock()
configPath = path
// 重置实例,强制下次重新加载
instance = nil
}
// GetConfigPath returns the path to the config file
func GetConfigPath() (string, error) {
// 如果已设置自定义配置路径,直接返回
if configPath != "" {
fmt.Println("GetConfigPath configPath = ", configPath)
return configPath, nil
}
// 否则使用默认路径
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
fmt.Println("GetConfigPath sdkType = ", constants.SdkType)
configDir := filepath.Join(home, constants.DEFAULT_FOLDER, constants.SdkType)
if err := os.MkdirAll(configDir, 0755); err != nil {
return "", err
}
var configFile = filepath.Join(configDir, constants.DEFAULT_CONFIG_FILE)
fmt.Println("GetConfigPath configFile = ", configFile)
return configFile, nil
}
// InitializeConfig 初始化配置文件,如果配置文件不存在则创建
func InitializeConfig(configFilePath string) error {
// 检查配置文件是否存在
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
// 创建默认配置
cfg := &Config{
Jdks: make(map[string]JDK),
Current: "",
SymlinkPath: GetDefaultSymlinkPath(), // 使用跨平台的默认路径
Initialized: false,
EnvBackUpPath: "",
}
// 保存配置到文件
if err := cfg.doSave(); err != nil {
return fmt.Errorf("保存配置文件失败: %v", err)
}
}
return nil
}
func ResetConfig() {
instanceLock.Lock()
defer instanceLock.Unlock()
configPath = ""
instance = nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。