manager/magefiles/external.go

103 lines
2.3 KiB
Go
Raw Normal View History

//go:build mage
package main
import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"codeflow.dananglin.me.uk/linux-home/manager/magefiles/internal/config"
"codeflow.dananglin.me.uk/linux-home/manager/magefiles/internal/walk"
"github.com/magefile/mage/sh"
)
// Externalconfigs downloads and manages neovim configuration from a remote git repository.
func Externalconfigs() error {
cfg, err := config.NewConfig()
if err != nil {
return fmt.Errorf(
"unable to load the configuration: %w",
err,
)
}
homeConfigDir, err := os.UserConfigDir()
if err != nil {
return fmt.Errorf(
"unable to get the user's home configuration directory: %w",
err,
)
}
for _, externalConfig := range slices.All(cfg.ExternalConfigurations) {
if err := manageExternalConfig(externalConfig, homeConfigDir); err != nil {
return fmt.Errorf("received an error while processing %s: %w", externalConfig.Label, err)
}
}
return nil
}
func manageExternalConfig(cfg config.ExternalConfig, homeConfigDir string) error {
clonedRepo, err := downloadRepo(cfg.GitRepoURL, cfg.GitRef)
if err != nil {
return fmt.Errorf("unable to clone the git repository: %w", err)
}
defer os.RemoveAll(clonedRepo)
fmt.Println("Git repository cloned to:", clonedRepo)
validationFunc := func(relativePath string) bool {
split := strings.SplitN(relativePath, "/", 2)
if len(split) < 1 {
return false
}
rootPath := split[0]
return rootPath == cfg.GitRepoPath
}
if err = filepath.WalkDir(
clonedRepo,
walk.CopyFiles(homeConfigDir, clonedRepo, rootManagedDir, validationFunc),
); err != nil {
return fmt.Errorf("received an error while copying the files: %w", err)
}
return nil
}
func downloadRepo(repoURL, repoRef string) (string, error) {
cloneDir, err := os.MkdirTemp("/tmp", "config-")
if err != nil {
return "", fmt.Errorf("unable to create the temporary directory: %w", err)
}
git := sh.RunCmd("git", "-C", cloneDir)
commands := [][]string{
{"init"},
{"remote", "add", "origin", repoURL},
{"fetch", "origin", repoRef},
{"checkout", "FETCH_HEAD"},
}
for _, command := range slices.All(commands) {
if err := git(command...); err != nil {
return "", err
}
}
if err := os.RemoveAll(filepath.Join(cloneDir, ".git")); err != nil {
return "", fmt.Errorf("unable to remove the .git folder: %w", err)
}
return cloneDir, nil
}