Compare commits

...

2 commits

4 changed files with 143 additions and 26 deletions

View file

@ -43,6 +43,14 @@
"Projects"
]
},
"externalConfigurations": [
{
"label": "Neovim",
"gitRepoURL": "https://codeflow.dananglin.me.uk/linux-home/nvim.d.git",
"gitRef": "746f07efdb203a46a7a02ada987cd97b68fa92d6",
"gitRepoPath": "nvim"
}
],
"git": {
"gpgSign": false,
"user": {

100
magefiles/external.go Normal file
View file

@ -0,0 +1,100 @@
//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 := cloneNvimConfigRepo(cfg.GitRepoURL, cfg.GitRef)
if err != nil {
return fmt.Errorf("unable to clone the git repository: %w", err)
}
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 cloneNvimConfigRepo(repoURL, repoRef string) (string, error) {
cloneDir, err := os.MkdirTemp("/tmp", "neovim-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
}

View file

@ -8,52 +8,60 @@ import (
"strings"
)
const configDir string = "hosts"
const dir string = "hosts"
type Config struct {
ManagedConfigurations []string `json:"managedConfigurations"`
BashProfile ConfigBashProfile `json:"bashProfile"`
Directories ConfigDirectories `json:"directories"`
Git ConfigGit `json:"git"`
BashProfile BashProfile `json:"bashProfile"`
Directories Directories `json:"directories"`
Git Git `json:"git"`
ExternalConfigurations []ExternalConfig `json:"externalConfigurations"`
}
type ConfigDirectories struct {
type Directories struct {
UseDefaultDirectories bool `json:"useDefaultDirectories"`
IncludeXDGDirectories bool `json:"includeXDGDirectories"`
AdditionalDirectories []string `json:"additionalDirectories"`
}
type ConfigGit struct {
type Git struct {
GpgSign bool `json:"gpgSign"`
User ConfigGitUser `json:"user"`
User GitUser `json:"user"`
}
type ConfigGitUser struct {
type GitUser struct {
Email string `json:"email"`
Name string `json:"name"`
SigningKey string `json:"signingKey"`
}
type ConfigBashProfile struct {
type BashProfile struct {
Manage bool `json:"manage"`
Filename string `json:"filename"`
SessionPaths []ConfigBashProfileSessionPath `json:"sessionPaths"`
SessionPaths []BashProfileSessionPath `json:"sessionPaths"`
XdgDirectories map[string]string `json:"xdgDirectories"`
EnvironmentVariables map[string]string `json:"environmentVariables"`
Aliases map[string]string `json:"aliases"`
Commands []ConfigBashProfileCommand `json:"commands"`
Commands []BashProfileCommand `json:"commands"`
}
type ConfigBashProfileSessionPath struct {
type BashProfileSessionPath struct {
Path string `json:"path"`
Description string `json:"description"`
}
type ConfigBashProfileCommand struct {
type BashProfileCommand struct {
Command string `json:"command"`
Description string `json:"description"`
}
type ExternalConfig struct {
Label string `json:"label"`
GitRepoURL string `json:"gitRepoURL"`
GitRef string `json:"gitRef"`
GitRepoPath string `json:"gitRepoPath"`
}
func NewConfig() (Config, error) {
cfg := defaultConfig()
@ -89,24 +97,25 @@ func configFilePath() (string, error) {
identifier := hostnameParts[1]
return filepath.Join(configDir, identifier+".json"), nil
return filepath.Join(dir, identifier+".json"), nil
}
func defaultConfig() Config {
return Config{
Directories: ConfigDirectories{
Directories: Directories{
UseDefaultDirectories: true,
IncludeXDGDirectories: true,
AdditionalDirectories: []string{},
},
Git: ConfigGit{
Git: Git{
GpgSign: false,
User: ConfigGitUser{
User: GitUser{
Email: "",
Name: "",
SigningKey: "",
},
},
ManagedConfigurations: []string{},
ExternalConfigurations: []ExternalConfig{},
}
}

View file

@ -3,12 +3,12 @@ package utilities
import (
"errors"
"fmt"
"html/template"
"io/fs"
"os"
"path/filepath"
"slices"
"strings"
"text/template"
"codeflow.dananglin.me.uk/linux-home/manager/magefiles/internal/config"
"codeflow.dananglin.me.uk/linux-home/manager/magefiles/internal/templatefuncs"