diff --git a/README.md b/README.md index c244841..824f375 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ dot files manager. Let's start with an example: ``` -files: +map: i3: imwheelrc: - config/alacritty: + config/alacritty.yml: config/redshift.conf: ``` @@ -48,10 +48,29 @@ map: os: linux imwheelrc: os: linux - config/alacritty: + config/alacritty.yml: os: macos docker/config.json: as: copy + +opt: + cd: dots/ +``` + +In this example, all files live under a subdirectory `dots/`. +``` +$ tree . +. +├── dots +│   ├── config +│   │   └── alacritty.yml +│   ├── docker +│   │   └── config.json +│   ├── i3 +│   ├── imwheelrc +│   ├── xinitrc +│   └── Xresources +└── dot.yml ``` ## Features diff --git a/fixtures/01-dots-basic.yml b/fixtures/01-dots-basic.yml index d272111..75cc78d 100644 --- a/fixtures/01-dots-basic.yml +++ b/fixtures/01-dots-basic.yml @@ -1,11 +1,8 @@ -files: - fixtures/gitconfig: - to: out/gitconfig - os: all # all, linux, macos - fixtures/zshrc: - to: out/zshrc - as: copy - os: linux - opt: # copy opts NYI +# basic mapping -# handle directories +map: + gitconfig: + zshrc: + +opt: + cd: fixtures/ diff --git a/fixtures/02-dots-basic.yml b/fixtures/02-dots-basic.yml index 786897d..ec535c7 100644 --- a/fixtures/02-dots-basic.yml +++ b/fixtures/02-dots-basic.yml @@ -1,13 +1,9 @@ -files: +# infer destination (goes to $HOME) +# uses prefix + +map: gitconfig: - dst: out/gitconfig - os: all # all, linux, macos zshrc: - dst: out/zshrc - typ: copy - os: linux - opts: # copy opts NYI -files_opts: - dir: fixtures/ - -# handle directories + to: ~/.zshrc +opt: + cd: fixtures/ diff --git a/fixtures/03-dots-os-as.yml b/fixtures/03-dots-os-as.yml new file mode 100644 index 0000000..56a4eaa --- /dev/null +++ b/fixtures/03-dots-os-as.yml @@ -0,0 +1,13 @@ +# to, os, as + +map: + gitconfig: + to: out/gitconfig + os: all # all, linux, macos + zshrc: + to: out/zshrc + as: copy + os: linux + +opt: + cd: fixtures/ diff --git a/fixtures/dots.yml b/fixtures/dots.yml deleted file mode 100644 index 4a24b21..0000000 --- a/fixtures/dots.yml +++ /dev/null @@ -1,13 +0,0 @@ -files: - gitconfig: - dst: out/gitconfig - os: all # all, linux, macos - zshrc: - dst: out/zshrc - typ: copy - os: linux - opt: # copy opts NYI -files_opts: - dir: fixtures/ - -# handle directories diff --git a/main.go b/main.go index d233dd7..1d7a758 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "io/ioutil" "log" "os" - "os/user" "strings" "fmt" "path" @@ -27,35 +26,24 @@ type Opts struct { } type Dots struct { - Opts Opts `yaml:"opts"` + Opts Opts `yaml:"opt"` FileMappings []FileMapping `yaml:"map"` } func (d *Dots) UnmarshalYAML(unmarshal func(interface{}) error) error { var tmpDots struct { - Opts Opts `yaml:"files_opts"` + Opts Opts `yaml:"opt"` Mappings map[string]FileMapping `yaml:"map"` } err := unmarshal(&tmpDots) if err != nil { return err } - d.Opts.Cd = tmpDots.Opts.Cd + d.Opts = tmpDots.Opts for file, mapping := range tmpDots.Mappings { mapping.From = file - mapping.To = expandTilde(mapping.To) - if len(mapping.To) == 0 { - mapping.To = inferDestination(mapping.From) - } - if len(d.Opts.Cd) > 0 { - mapping.From = path.Join(d.Opts.Cd, file) - } - if len(mapping.As) == 0 { - mapping.As = "link" - } d.FileMappings = append(d.FileMappings, mapping) } - return nil } @@ -101,7 +89,7 @@ func isDirectory(path string) bool { return fileInfo.IsDir() } -func validateDots(dots *Dots) (bool, []error) { +func validateDots(dots Dots) (bool, []error) { var errs []error for _, mapping := range dots.FileMappings { if ! pathExists(mapping.From) { @@ -113,10 +101,40 @@ func validateDots(dots *Dots) (bool, []error) { return len(errs) == 0, errs } +func transformDots(dots Dots) Dots { + opts := dots.Opts + mappings := dots.FileMappings + + var newDots Dots + newDots.Opts = opts + + for _, mapping := range mappings { + if len(mapping.To) > 0 { + // expand destination ~ + mapping.To = expandTilde(mapping.To) + } else { + // infer destination based on From + mapping.To = inferDestination(mapping.From) + } + if len(opts.Cd) > 0 { + // Cd set: add prefix to From + mapping.From = path.Join(opts.Cd, mapping.From) + } + // default As to symlink + if len(mapping.As) == 0 { + mapping.As = "link" + } + + newDots.FileMappings = append(newDots.FileMappings, mapping) + } + + return newDots +} + func getHomeDir() string { - usr, _ := user.Current() - return usr.HomeDir + return os.Getenv("HOME") } + func expandTilde(path string) string { if strings.HasPrefix(path, "~") { homeDir := getHomeDir() @@ -134,14 +152,17 @@ func readDotFile() Dots { if err := yaml.Unmarshal([]byte(rcFileData), &dots); err != nil { logger.Fatalf("cannot decode data: %v", err) } - valid, errs := validateDots(&dots) + + newDots := transformDots(dots) + valid, errs := validateDots(newDots) if ! valid { for _, err := range errs { logger.Printf("failed validating dots file: %v", err) } os.Exit(1) } - return dots + + return newDots } func doLink(file string, dst string) {