From 9a28f0425843791e932fb92c716c4816117ad492 Mon Sep 17 00:00:00 2001 From: Marcus Kok <47163063+Marcusk19@users.noreply.github.com> Date: Sun, 10 Mar 2024 15:42:13 -0400 Subject: [PATCH] add symlink command (#8) --- .gitignore | 2 ++ cmd/backup.go | 7 +------ cmd/init.go | 4 +++- cmd/link.go | 43 +++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 37 ++++++++++++++++++++++++------------- go.mod | 2 +- go.sum | 2 ++ 7 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 cmd/link.go diff --git a/.gitignore b/.gitignore index 0c539a1..c35431b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ vendor/ # Go workspace file go.work + +tmp/ diff --git a/cmd/backup.go b/cmd/backup.go index aaaefe7..0808d9d 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -10,23 +10,18 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" "github.com/spf13/afero" "github.com/spf13/cobra" - "github.com/spf13/viper" ) func init() { RootCmd.AddCommand(backupCommand) - RootCmd.PersistentFlags().StringVar(&DotfilePath, "dotfile-path", "~/.dotfiles", "Path pointing to dotfiles directory") - RootCmd.MarkFlagRequired("dotfile-path") - viper.BindPFlag("dotfile-path", RootCmd.PersistentFlags().Lookup("dotfile-path")) } var backupCommand = &cobra.Command { Use: "backup", + Short: "Add and commit files in dotfiles directory", Run: runBackup, } -var DotfilePath string - func gitAddFiles(worktree *git.Worktree, fs afero.Fs) error { entries, err := afero.ReadDir(fs, DotfilePath) if err != nil { diff --git a/cmd/init.go b/cmd/init.go index 1091b97..b4f8d66 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -24,7 +24,7 @@ func copyExistingConfigs(programs []string, destRootOpt ...string) { destRoot = destRootOpt[0] } - configRoot := os.Getenv("HOME") + "/.config/" + configRoot := ConfigPath for _, program := range(programs) { // TODO: do something here print(configRoot + program) @@ -48,6 +48,8 @@ func createDotfileStructure(programs []string) { var initCommand = &cobra.Command { Use: "init", + Short: "Copy configs to dotfile directory", + Long: "Searches existing config directory for configs and then copies them to dotfile directory", Run: func(cmd *cobra.Command, args []string) { var rootpath string if len(args) <= 0 { diff --git a/cmd/link.go b/cmd/link.go new file mode 100644 index 0000000..bb46d74 --- /dev/null +++ b/cmd/link.go @@ -0,0 +1,43 @@ +package cmd + +import ( + "fmt" + "log" + "path/filepath" + + "github.com/spf13/afero" + "github.com/spf13/cobra" +) + +func init() { + RootCmd.AddCommand(linkCommand) +} + +var linkCommand = &cobra.Command { + Use: "link", + Run: runLinkCommand, +} + +func runLinkCommand(cmd *cobra.Command, args []string) { + fmt.Println("Symlinking dotfiles...") + entries, err := afero.ReadDir(fs, DotfilePath) + if err != nil { + log.Fatal(err) + } + for _, entry := range(entries) { + if entry.Name() == ".git" { + continue + } + dotPath := filepath.Join(DotfilePath, entry.Name()) + configPath := filepath.Join(ConfigPath, entry.Name()) + + // destination needs to be removed before symlink + fs.RemoveAll(configPath) + + err = afero.OsFs.SymlinkIfPossible(afero.OsFs{}, dotPath, configPath) + if err != nil { + log.Fatalf("Cannot symlink %s: %s", entry.Name(), err.Error()) + } + } + +} diff --git a/cmd/root.go b/cmd/root.go index 1ea8830..8d67e5f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,5 +1,5 @@ /* -Copyright © 2024 NAME HERE +Copyright © 2024 Marcus Kok */ package cmd @@ -8,23 +8,16 @@ import ( "os" "github.com/spf13/cobra" + "github.com/spf13/viper" ) - -// RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: "bender", - Short: "Change literals to whitespace", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + Short: "dotfile management", + Long: `Bender is a CLI tool for syncing your + dotfiles. It provides an opiniated way to symlink + a dotfile directory to various config directories.`, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -36,6 +29,9 @@ func Execute() { } } +var DotfilePath string +var ConfigPath string + func init() { // define flags and config sections @@ -43,6 +39,21 @@ func init() { // Cobra also supports local flags, which will only run // when this action is called directly. + defaultDotPath := os.Getenv("HOME") + "/.dotfiles/" + defaultConfPath := os.Getenv("HOME") + "/.config/" + RootCmd.PersistentFlags().StringVar( + &DotfilePath, + "dotfile-path", + defaultDotPath, + "Path pointing to dotfiles directory", + ) + RootCmd.PersistentFlags().StringVar( + &ConfigPath, + "config-path", + defaultConfPath, + "Path pointing to config directory", + ) + viper.BindPFlag("dotfile-path", RootCmd.PersistentFlags().Lookup("dotfile-path")) RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } diff --git a/go.mod b/go.mod index 03672df..e6458e8 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/go-git/go-git/v5 v5.11.0 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 ) @@ -37,7 +38,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect go.uber.org/atomic v1.9.0 // indirect diff --git a/go.sum b/go.sum index b5cf38e..7b0423d 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcej github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=