mirror

Mirror free and open-source projects you like with minimal effort
git clone git://git.server.ky/slackcoder/mirror
Log | Files | Refs | README

config.go (2959B)


      1 package service
      2 
      3 import (
      4 	"fmt"
      5 	"os"
      6 	"path/filepath"
      7 	"time"
      8 
      9 	"git.server.ky/slackcoder/mirror/internal"
     10 	"github.com/BurntSushi/toml"
     11 )
     12 
     13 type StagingMethod string
     14 
     15 const (
     16 	StagingMethodNone       = "none"
     17 	StagingMethodTemporary  = "temporary"
     18 	StagingMethodPersistent = "persistent"
     19 )
     20 
     21 // Global parameters
     22 type GlobalConfig struct {
     23 	// MaxInterval is the maximum time to wait before syncing with a
     24 	// mirror. The wait time is a randomly generated time between the Min
     25 	// and Max intervals. The mirror is immediately downloaded once if both
     26 	// the Min and Max intervals are set to zero.
     27 	MaxInterval *Duration `toml:"max-interval"`
     28 	// MinInterval is the minimum time to wait before syncing with a mirror.
     29 	MinInterval   *Duration `toml:"min-interval"`
     30 	StagingMethod string    `toml:"staging-method,omitempty"`
     31 	StagingPath   string    `toml:"staging-path,omitempty"`
     32 }
     33 
     34 type Config struct {
     35 	GlobalConfig `toml:"global"`
     36 	Mirrors      []*Mirror `toml:"mirrors,omitempty"`
     37 }
     38 
     39 func (c *Config) String() string {
     40 	return internal.MustTOML(c)
     41 }
     42 
     43 var DefaultConfig = Config{
     44 	GlobalConfig: GlobalConfig{
     45 		MaxInterval:   DurationRef(24 * time.Hour),
     46 		MinInterval:   DurationRef(time.Hour),
     47 		StagingMethod: StagingMethodNone,
     48 		StagingPath:   "/tmp/mirror",
     49 	},
     50 }
     51 
     52 // Read the given configuration file.
     53 func readConfigFile(fp string) (*Config, error) {
     54 	var config Config
     55 
     56 	f, err := os.Open(fp)
     57 	if err != nil {
     58 		return nil, err
     59 	}
     60 	defer f.Close()
     61 
     62 	_, err = toml.NewDecoder(f).Decode(&config)
     63 	if err != nil {
     64 		return nil, fmt.Errorf("loading configuration file: %w", err)
     65 	}
     66 
     67 	return &config, nil
     68 }
     69 
     70 // Read all configuration in the given directory.
     71 func readConfigDir(fp string) (*Config, error) {
     72 	var cfg Config
     73 
     74 	confDDir, err := os.ReadDir(fp)
     75 	if os.IsNotExist(err) {
     76 		// No directory is an empty one.
     77 		return &Config{}, nil
     78 	} else if err != nil {
     79 		return nil, err
     80 	}
     81 
     82 	for _, entry := range confDDir {
     83 		if filepath.Ext(entry.Name()) != ".toml" {
     84 			continue
     85 		}
     86 
     87 		entryCfg, err := readConfigFile(filepath.Join(fp, entry.Name()))
     88 		if err != nil {
     89 			return nil, err
     90 		}
     91 
     92 		cfg.Append(entryCfg)
     93 	}
     94 
     95 	return &cfg, nil
     96 }
     97 
     98 // Read all configuration in the given directory.
     99 func ReadConfig(fps ...string) (*Config, error) {
    100 	var cfg Config
    101 
    102 	for _, fp := range fps {
    103 		stat, err := os.Stat(fp)
    104 		if err != nil {
    105 			return nil, err
    106 		}
    107 
    108 		var c *Config
    109 
    110 		if stat.IsDir() {
    111 			c, err = readConfigDir(fp)
    112 			if err != nil {
    113 				return nil, err
    114 			}
    115 		} else {
    116 			c, err = readConfigFile(fp)
    117 		}
    118 
    119 		cfg.Append(c)
    120 	}
    121 
    122 	return &cfg, nil
    123 }
    124 
    125 // Apply the given configuration parameters.
    126 func (c *Config) Append(src *Config) {
    127 	if src.MaxInterval != nil {
    128 		c.MaxInterval = src.MaxInterval
    129 	}
    130 	if src.MinInterval != nil {
    131 		c.MinInterval = src.MinInterval
    132 	}
    133 	if src.StagingMethod != "" {
    134 		c.StagingMethod = src.StagingMethod
    135 	}
    136 	if src.StagingPath != "" {
    137 		c.StagingPath = src.StagingPath
    138 	}
    139 	c.Mirrors = append(c.Mirrors, src.Mirrors...)
    140 }