Initial release of bdrclone
This commit is contained in:
127
internal/config/config.go
Normal file
127
internal/config/config.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const DefaultUserAgent = "pan.baidu.com"
|
||||
|
||||
type Config struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
AccessToken string `json:"access_token,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
ExpiresAt time.Time `json:"expires_at,omitempty"`
|
||||
Root string `json:"root"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
UploadParts int `json:"upload_parts"`
|
||||
PartSize int64 `json:"part_size,omitempty"`
|
||||
}
|
||||
|
||||
func DefaultPath() (string, error) {
|
||||
dir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("find config directory: %w", err)
|
||||
}
|
||||
return filepath.Join(dir, "bdrclone", "config.json"), nil
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, fmt.Errorf("config %q does not exist; run `bdrclone config` first", path)
|
||||
}
|
||||
return nil, fmt.Errorf("read config: %w", err)
|
||||
}
|
||||
var cfg Config
|
||||
if err := json.Unmarshal(b, &cfg); err != nil {
|
||||
return nil, fmt.Errorf("parse config: %w", err)
|
||||
}
|
||||
cfg.applyDefaults()
|
||||
return &cfg, cfg.Validate(false)
|
||||
}
|
||||
|
||||
func Save(path string, cfg *Config) error {
|
||||
cfg.applyDefaults()
|
||||
if err := cfg.Validate(false); err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := json.MarshalIndent(cfg, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode config: %w", err)
|
||||
}
|
||||
b = append(b, '\n')
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
|
||||
return fmt.Errorf("create config directory: %w", err)
|
||||
}
|
||||
tmp, err := os.CreateTemp(filepath.Dir(path), ".config-*")
|
||||
if err != nil {
|
||||
return fmt.Errorf("create temporary config: %w", err)
|
||||
}
|
||||
tmpName := tmp.Name()
|
||||
defer os.Remove(tmpName)
|
||||
if err := tmp.Chmod(0o600); err != nil {
|
||||
tmp.Close()
|
||||
return fmt.Errorf("secure config: %w", err)
|
||||
}
|
||||
if _, err := tmp.Write(b); err != nil {
|
||||
tmp.Close()
|
||||
return fmt.Errorf("write config: %w", err)
|
||||
}
|
||||
if err := tmp.Close(); err != nil {
|
||||
return fmt.Errorf("close config: %w", err)
|
||||
}
|
||||
if err := os.Rename(tmpName, path); err != nil {
|
||||
return fmt.Errorf("replace config: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) Validate(requireToken bool) error {
|
||||
if strings.TrimSpace(c.ClientID) == "" || strings.TrimSpace(c.ClientSecret) == "" {
|
||||
return errors.New("client_id and client_secret are required")
|
||||
}
|
||||
if requireToken && c.RefreshToken == "" && c.AccessToken == "" {
|
||||
return errors.New("no OAuth token; run `bdrclone auth` first")
|
||||
}
|
||||
if c.UploadParts < 1 || c.UploadParts > 32 {
|
||||
return errors.New("upload_parts must be between 1 and 32")
|
||||
}
|
||||
if c.PartSize != 0 && c.PartSize < 4<<20 {
|
||||
return errors.New("part_size must be 0 or at least 4 MiB")
|
||||
}
|
||||
if c.PartSize > 32<<20 {
|
||||
return errors.New("part_size cannot exceed Baidu's 32 MiB maximum")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) applyDefaults() {
|
||||
if c.RedirectURI == "" {
|
||||
c.RedirectURI = "http://127.0.0.1:53682/callback"
|
||||
}
|
||||
if c.Root == "" {
|
||||
c.Root = "/"
|
||||
}
|
||||
if !strings.HasPrefix(c.Root, "/") {
|
||||
c.Root = "/" + c.Root
|
||||
}
|
||||
c.Root = strings.TrimSuffix(c.Root, "/")
|
||||
if c.Root == "" {
|
||||
c.Root = "/"
|
||||
}
|
||||
if c.UserAgent == "" {
|
||||
c.UserAgent = DefaultUserAgent
|
||||
}
|
||||
if c.UploadParts == 0 {
|
||||
c.UploadParts = 3
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user