manager/magefiles/directories.go

131 lines
2.8 KiB
Go

//go:build mage
package main
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"slices"
)
const (
dirModePerm fs.FileMode = 0o700
)
// Directories ensure that the directories specified in the configuration is present within the home directory.
func Directories() error {
config, err := newConfig()
if err != nil {
return fmt.Errorf("unable to load the configuration: %w", err)
}
userHome, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("unable to get the user's home directory: %w", err)
}
directories := make([]string, 0)
if config.Directories.UseDefaultDirectories{
defaultHomeDirs := homeDirectories(userHome, defaultDirectories())
directories = append(directories, defaultHomeDirs...)
}
if config.Directories.IncludeXDGDirectories{
directories = append(directories, xdgDirectories()...)
}
if len(config.Directories.AdditionalDirectories) != 0 {
additionalHomeDirs := homeDirectories(userHome, config.Directories.AdditionalDirectories)
directories = append(directories, additionalHomeDirs...)
}
for _, dir := range slices.All(directories) {
if err := ensureDirectory(dir); err != nil {
return fmt.Errorf("unable to ensure that %s is present: %w", dir, err)
}
fmt.Printf("Successfully ensured %s is present.\n", dir)
}
return nil
}
func ensureDirectory(path string) error {
info, err := os.Stat(path)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
if err := os.Mkdir(path, dirModePerm); err != nil {
return fmt.Errorf("unable to create the directory: %w", err)
}
return nil
}
return fmt.Errorf(
"received an unexpected error after attempting to get the directory information: %w",
err,
)
}
if !info.IsDir() {
return errors.New("the path exists but it is not a directory")
}
if info.Mode().Perm() != dirModePerm {
if err := os.Chmod(path, dirModePerm); err != nil {
return fmt.Errorf("unable to update the directory's mode to %d: %w", dirModePerm, err)
}
}
return nil
}
func defaultDirectories() []string {
return []string{
".local",
".local/bin",
"Applications",
"Documents",
"Downloads",
"Games",
"Git",
"Music",
"Pictures",
"Templates",
"Videos",
}
}
func homeDirectories(userHome string, directories []string) []string{
absolutePaths := make([]string, len(directories))
for ind := range slices.All(directories) {
absolutePaths[ind] = filepath.Join(userHome, directories[ind])
}
return absolutePaths
}
func xdgDirectories() []string {
xdgEnvVars := []string{
"XDG_DATA_HOME",
"XDG_CONFIG_HOME",
"XDG_CACHE_HOME",
"XDG_STATE_HOME",
}
directories := make([]string, 0)
for _, envVar := range slices.All(xdgEnvVars) {
directory := os.Getenv(envVar)
if directory != "" {
directories = append(directories, directory)
}
}
return directories
}