package local import ( "fmt" "os" "path/filepath" "strings" "git.apinb.com/ops/files/internal/config" ) const containerName = "local" type Client struct { rootPath string objectsPath string stagingPath string locksPath string externalBaseURL string signingSecret string accessTTLSeconds int64 minimumFreeBytes uint64 } func New(storageConfig config.StorageConf) (*Client, error) { rootPath, err := filepath.Abs(storageConfig.Local.RootPath) if err != nil { return nil, fmt.Errorf("解析本地存储根目录: %w", err) } if err := os.MkdirAll(rootPath, 0o750); err != nil { return nil, fmt.Errorf("创建本地存储根目录: %w", err) } rootPath, err = filepath.EvalSymlinks(rootPath) if err != nil { return nil, fmt.Errorf("解析本地存储真实路径: %w", err) } client := &Client{ rootPath: filepath.Clean(rootPath), objectsPath: filepath.Join(rootPath, "objects"), stagingPath: filepath.Join(rootPath, ".staging"), locksPath: filepath.Join(rootPath, ".locks"), externalBaseURL: strings.TrimRight(storageConfig.ExternalBaseURL, "/"), signingSecret: storageConfig.SigningSecret, accessTTLSeconds: storageConfig.AccessTTLSeconds, minimumFreeBytes: storageConfig.Local.MinimumFreeSpaceMB * 1024 * 1024, } for _, directory := range []string{client.objectsPath, client.stagingPath, client.locksPath} { if err := client.ensureDirectory(directory); err != nil { return nil, err } } if _, err := client.Status(nil); err != nil { return nil, err } return client, nil } func (c *Client) Provider() string { return "local" } func (c *Client) Container() string { return containerName }