2021-04-22 09:36:11 +00:00
|
|
|
package config
|
2021-01-12 03:53:51 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-10-24 14:57:44 +00:00
|
|
|
"io"
|
|
|
|
"net/http"
|
2021-01-12 03:53:51 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2021-04-22 09:36:11 +00:00
|
|
|
|
2021-11-19 09:44:53 +00:00
|
|
|
"github.com/make-go-great/copy-go"
|
2022-05-31 09:24:33 +00:00
|
|
|
"github.com/make-go-great/diff-go"
|
2021-01-12 03:53:51 +00:00
|
|
|
)
|
|
|
|
|
2021-05-05 09:37:38 +00:00
|
|
|
type configReal struct {
|
2022-10-24 14:57:44 +00:00
|
|
|
httpClient *http.Client
|
2021-04-22 09:36:11 +00:00
|
|
|
configApps
|
|
|
|
}
|
|
|
|
|
2021-05-05 09:37:38 +00:00
|
|
|
var _ Config = (*configReal)(nil)
|
2021-01-12 03:53:51 +00:00
|
|
|
|
2021-04-22 10:54:17 +00:00
|
|
|
// Install internal -> external
|
2021-05-05 09:37:38 +00:00
|
|
|
func (c *configReal) Install() error {
|
2021-01-18 08:29:01 +00:00
|
|
|
for _, app := range c.Apps {
|
2021-04-22 10:54:17 +00:00
|
|
|
for _, p := range app.Paths {
|
2022-10-24 14:57:44 +00:00
|
|
|
if p.External == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:54:17 +00:00
|
|
|
if err := copy.Replace(p.Internal, p.External); err != nil {
|
|
|
|
return fmt.Errorf("failed to replace %s -> %s: %w", p.Internal, p.External, err)
|
2021-01-18 08:29:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:54:17 +00:00
|
|
|
// Update external -> internal
|
2021-05-05 09:37:38 +00:00
|
|
|
func (c *configReal) Update() error {
|
2021-01-18 08:32:25 +00:00
|
|
|
for _, app := range c.Apps {
|
2021-04-22 10:54:17 +00:00
|
|
|
for _, p := range app.Paths {
|
2022-10-24 14:57:44 +00:00
|
|
|
if p.External == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:54:17 +00:00
|
|
|
if err := copy.Replace(p.External, p.Internal); err != nil {
|
|
|
|
return fmt.Errorf("failed to replace %s -> %s: %w", p.External, p.Internal, err)
|
2021-01-18 08:32:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-18 08:29:01 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-10-24 14:57:44 +00:00
|
|
|
func (c *configReal) Download() error {
|
|
|
|
for _, app := range c.Apps {
|
|
|
|
for _, p := range app.Paths {
|
|
|
|
if p.URL == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
httpRsp, err := c.httpClient.Get(p.URL)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("http client: failed to get: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := io.ReadAll(httpRsp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("io: failed to read all: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-10-31 15:43:54 +00:00
|
|
|
// Copy from github.com/make-go-great/copy-go
|
|
|
|
// Make sure nested dir is exist before copying file
|
|
|
|
dstDir := filepath.Dir(p.Internal)
|
|
|
|
if err := os.MkdirAll(dstDir, os.ModePerm); err != nil {
|
|
|
|
return fmt.Errorf("failed to mkdir %s: %w", dstDir, err)
|
|
|
|
}
|
|
|
|
|
2022-10-24 14:57:44 +00:00
|
|
|
if err := os.WriteFile(p.Internal, data, 0o600); err != nil {
|
|
|
|
return fmt.Errorf("os: failed to write file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
httpRsp.Body.Close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:36:19 +00:00
|
|
|
// Clean remove unused config inside config dir
|
2021-05-05 09:37:38 +00:00
|
|
|
func (c *configReal) Clean() error {
|
2021-04-22 10:54:17 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-05-31 09:27:06 +00:00
|
|
|
func (c *configReal) Diff() error {
|
2021-04-23 03:21:48 +00:00
|
|
|
for _, app := range c.Apps {
|
|
|
|
for _, p := range app.Paths {
|
2022-12-01 04:08:56 +00:00
|
|
|
if p.External == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-05-31 09:24:33 +00:00
|
|
|
if err := diff.Diff(p.Internal, p.External); err != nil {
|
2021-04-23 03:21:48 +00:00
|
|
|
return fmt.Errorf("failed to compare %s with %s: %w", p.Internal, p.External, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:54:17 +00:00
|
|
|
func getUnusedDirs(apps map[string]App) (map[string]struct{}, error) {
|
2021-03-17 04:29:51 +00:00
|
|
|
files, err := os.ReadDir(configDirPath)
|
2021-01-20 07:34:25 +00:00
|
|
|
if err != nil {
|
2021-04-22 10:54:17 +00:00
|
|
|
return nil, fmt.Errorf("failed to read dir %s: %w", configDirPath, err)
|
2021-01-20 07:34:25 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:36:19 +00:00
|
|
|
// Get all dirs inside config dir
|
2021-01-20 07:34:25 +00:00
|
|
|
unusedDirs := make(map[string]struct{})
|
2021-03-17 04:29:51 +00:00
|
|
|
for _, file := range files {
|
2021-04-22 10:36:19 +00:00
|
|
|
// Ignore config file
|
2021-03-17 04:29:51 +00:00
|
|
|
if file.Name() == configFile {
|
2021-01-20 07:34:25 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-17 04:29:51 +00:00
|
|
|
unusedDirs[file.Name()] = struct{}{}
|
2021-01-20 07:34:25 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:36:19 +00:00
|
|
|
// Removed used dirs
|
2021-04-22 10:54:17 +00:00
|
|
|
for name := range apps {
|
2021-01-20 07:36:33 +00:00
|
|
|
delete(unusedDirs, name)
|
2021-01-20 07:34:25 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:54:17 +00:00
|
|
|
return unusedDirs, nil
|
2021-01-12 03:53:51 +00:00
|
|
|
}
|