150 lines
3.0 KiB
Go
150 lines
3.0 KiB
Go
|
package config
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
|
||
|
"github.com/haunt98/copy-go"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
configDirPath = "data"
|
||
|
configFile = "data.json"
|
||
|
)
|
||
|
|
||
|
type config struct {
|
||
|
configApps
|
||
|
}
|
||
|
|
||
|
var _ Config = (*config)(nil)
|
||
|
|
||
|
type configApps struct {
|
||
|
Apps map[string]App `json:"apps"`
|
||
|
}
|
||
|
|
||
|
// Read from file
|
||
|
type App struct {
|
||
|
Paths []Path `json:"paths"`
|
||
|
}
|
||
|
|
||
|
type Path struct {
|
||
|
Internal string `json:"internal"`
|
||
|
External string `json:"external"`
|
||
|
}
|
||
|
|
||
|
// LoadConfig return config, configDemo
|
||
|
func LoadConfig(path string) (*config, *configDemo, error) {
|
||
|
configPath := getConfigPath(path)
|
||
|
bytes, err := os.ReadFile(configPath)
|
||
|
if err != nil {
|
||
|
if errors.Is(err, os.ErrNotExist) {
|
||
|
return nil, nil, fmt.Errorf("file not exist %s: %w", configPath, err)
|
||
|
}
|
||
|
|
||
|
return nil, nil, fmt.Errorf("failed to read file%s: %w", configPath, err)
|
||
|
}
|
||
|
|
||
|
var cfgApps configApps
|
||
|
if err = json.Unmarshal(bytes, &cfgApps); err != nil {
|
||
|
return nil, nil, fmt.Errorf("failed to unmarshal: %w", err)
|
||
|
}
|
||
|
|
||
|
cfg := config{
|
||
|
configApps: cfgApps,
|
||
|
}
|
||
|
|
||
|
cfgDemo := configDemo{
|
||
|
configApps: cfgApps,
|
||
|
}
|
||
|
|
||
|
return &cfg, &cfgDemo, nil
|
||
|
}
|
||
|
|
||
|
// Install internal -> external
|
||
|
func (c *config) Install() error {
|
||
|
for _, app := range c.Apps {
|
||
|
for _, p := range app.Paths {
|
||
|
if err := copy.Replace(p.Internal, p.External); err != nil {
|
||
|
return fmt.Errorf("failed to replace %s -> %s: %w", p.Internal, p.External, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Update external -> internal
|
||
|
func (c *config) Update() error {
|
||
|
for _, app := range c.Apps {
|
||
|
for _, p := range app.Paths {
|
||
|
if err := copy.Replace(p.External, p.Internal); err != nil {
|
||
|
return fmt.Errorf("failed to replace %s -> %s: %w", p.External, p.Internal, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Clean remove unused config inside config dir
|
||
|
func (c *config) Clean() error {
|
||
|
unusedDirs, err := getUnusedDirs(c.Apps)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Delete ununsed dirs to save some space
|
||
|
for dir := range unusedDirs {
|
||
|
dirPath := filepath.Join(configDirPath, dir)
|
||
|
if err := os.RemoveAll(dirPath); err != nil {
|
||
|
return fmt.Errorf("failed to remove %s: %w", dir, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c *config) Compare() error {
|
||
|
for _, app := range c.Apps {
|
||
|
for _, p := range app.Paths {
|
||
|
if err := copy.Compare(p.Internal, p.External); err != nil {
|
||
|
return fmt.Errorf("failed to compare %s with %s: %w", p.Internal, p.External, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func getConfigPath(path string) string {
|
||
|
return filepath.Join(path, configDirPath, configFile)
|
||
|
}
|
||
|
|
||
|
func getUnusedDirs(apps map[string]App) (map[string]struct{}, error) {
|
||
|
files, err := os.ReadDir(configDirPath)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to read dir %s: %w", configDirPath, err)
|
||
|
}
|
||
|
|
||
|
// Get all dirs inside config dir
|
||
|
unusedDirs := make(map[string]struct{})
|
||
|
for _, file := range files {
|
||
|
// Ignore config file
|
||
|
if file.Name() == configFile {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
unusedDirs[file.Name()] = struct{}{}
|
||
|
}
|
||
|
|
||
|
// Removed used dirs
|
||
|
for name := range apps {
|
||
|
delete(unusedDirs, name)
|
||
|
}
|
||
|
|
||
|
return unusedDirs, nil
|
||
|
}
|