apply go formatting (#41)

pull/42/head
Marcus Kok 1 year ago committed by GitHub
parent 8ebfc35ccc
commit a135494bbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -14,94 +14,93 @@ import (
) )
func init() { func init() {
RootCmd.AddCommand(addCommand) RootCmd.AddCommand(addCommand)
} }
var addCommand = &cobra.Command { var addCommand = &cobra.Command{
Use: "add", Use: "add",
Short: "Adds config to be tracked by dotctl", Short: "Adds config to be tracked by dotctl",
Long: "TODO: add longer description", // TODO add more description Long: "TODO: add longer description", // TODO add more description
Run: runAddCommand, Run: runAddCommand,
} }
func runAddCommand(cmd *cobra.Command, args []string) { func runAddCommand(cmd *cobra.Command, args []string) {
fs := FileSystem fs := FileSystem
testing := viper.GetBool("testing") testing := viper.GetBool("testing")
if len(args) <= 0 { if len(args) <= 0 {
fmt.Println("ERROR: requires config path") fmt.Println("ERROR: requires config path")
return return
} }
configSrc := args[0] configSrc := args[0]
dirs := strings.Split(configSrc, "/") dirs := strings.Split(configSrc, "/")
name := dirs[len(dirs) - 1] // take the last section of the path, this should be the name name := dirs[len(dirs)-1] // take the last section of the path, this should be the name
if name[0] == '.' { if name[0] == '.' {
name = name[1:] name = name[1:]
} }
links := viper.GetStringMap("links") links := viper.GetStringMap("links")
links[name] = configSrc links[name] = configSrc
viper.Set("links", links) viper.Set("links", links)
dotfilePath := viper.Get("dotfile-path").(string) dotfilePath := viper.Get("dotfile-path").(string)
dotfileDest := filepath.Join(dotfilePath, name) dotfileDest := filepath.Join(dotfilePath, name)
if DryRun { if DryRun {
fmt.Printf("Will copy %s -> %s \n", configSrc, dotfileDest) fmt.Printf("Will copy %s -> %s \n", configSrc, dotfileDest)
return return
} }
_, err := fs.Stat(dotfileDest) _, err := fs.Stat(dotfileDest)
if err == nil { if err == nil {
fmt.Printf("Looks like %s exists in current dotfile directory\n", dotfileDest) fmt.Printf("Looks like %s exists in current dotfile directory\n", dotfileDest)
fmt.Println("Do you want to overwrite it?") fmt.Println("Do you want to overwrite it?")
confirm := promptui.Prompt{ confirm := promptui.Prompt{
Label: "overwrite config", Label: "overwrite config",
IsConfirm: true, IsConfirm: true,
} }
overwrite, _ := confirm.Run() overwrite, _ := confirm.Run()
if strings.ToUpper(overwrite) == "Y" { if strings.ToUpper(overwrite) == "Y" {
addConfigToDir(fs, configSrc, dotfileDest) addConfigToDir(fs, configSrc, dotfileDest)
} }
fmt.Printf("Just set up %s to link to %s\n", configSrc, dotfileDest) fmt.Printf("Just set up %s to link to %s\n", configSrc, dotfileDest)
} else { } else {
addConfigToDir(fs, configSrc, dotfileDest) addConfigToDir(fs, configSrc, dotfileDest)
} }
if !testing { if !testing {
err := viper.WriteConfig() err := viper.WriteConfig()
if err != nil { if err != nil {
fmt.Printf("Problem updating dotctl config %s", err) fmt.Printf("Problem updating dotctl config %s", err)
} }
} }
} }
func addConfigToDir(fs afero.Fs, configSrc, dotfileDest string) { func addConfigToDir(fs afero.Fs, configSrc, dotfileDest string) {
configFile, err := fs.Open(configSrc) configFile, err := fs.Open(configSrc)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer configFile.Close() defer configFile.Close()
fileInfo, err := configFile.Stat() fileInfo, err := configFile.Stat()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
if fileInfo.IsDir() { if fileInfo.IsDir() {
err = tools.CopyDir(fs, configSrc, dotfileDest) err = tools.CopyDir(fs, configSrc, dotfileDest)
} else { } else {
err = tools.CopyFile(fs, configSrc, dotfileDest) err = tools.CopyFile(fs, configSrc, dotfileDest)
} }
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
fmt.Printf("Copied %s -> %s\n", configSrc, dotfileDest) fmt.Printf("Copied %s -> %s\n", configSrc, dotfileDest)
} }

@ -14,76 +14,75 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
func init() { func init() {
RootCmd.AddCommand(initCommand) RootCmd.AddCommand(initCommand)
} }
func copyExistingConfigs(programs []string, fs afero.Fs) { func copyExistingConfigs(programs []string, fs afero.Fs) {
// takes list of programs and backs up configs for them // takes list of programs and backs up configs for them
destRoot := DotfilePath destRoot := DotfilePath
configRoot := ConfigPath configRoot := ConfigPath
for _, program := range(programs) { for _, program := range programs {
// TODO: do something here // TODO: do something here
err := tools.CopyDir(fs, filepath.Join(configRoot, program), filepath.Join(destRoot, program)) err := tools.CopyDir(fs, filepath.Join(configRoot, program), filepath.Join(destRoot, program))
if err != nil { if err != nil {
log.Fatalf("Problem copying %s", err.Error()) log.Fatalf("Problem copying %s", err.Error())
} }
} }
} }
func createDotfileStructure(programs []string, fs afero.Fs) { func createDotfileStructure(programs []string, fs afero.Fs) {
// takes list of programs and creates dotfiles for them // takes list of programs and creates dotfiles for them
dotfileRoot := DotfilePath dotfileRoot := DotfilePath
fmt.Printf("creating dotfile directory structure at %s\n", dotfileRoot) fmt.Printf("creating dotfile directory structure at %s\n", dotfileRoot)
for _, program := range(programs) { for _, program := range programs {
if err := fs.MkdirAll(path.Join(dotfileRoot, program), os.ModePerm); err != nil { if err := fs.MkdirAll(path.Join(dotfileRoot, program), os.ModePerm); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
} }
var initCommand = &cobra.Command { var initCommand = &cobra.Command{
Use: "init", Use: "init",
Short: "Copy configs to dotfile directory", Short: "Copy configs to dotfile directory",
Long: "Searches existing config directory for configs and then copies them to dotfile directory", Long: "Searches existing config directory for configs and then copies them to dotfile directory",
Run: runInitCommand, Run: runInitCommand,
} }
func runInitCommand(cmd *cobra.Command, args []string) { func runInitCommand(cmd *cobra.Command, args []string) {
fs := FileSystem fs := FileSystem
// if user has passed a dotfile path flag need to add it to // if user has passed a dotfile path flag need to add it to
// viper's search path for a config file // viper's search path for a config file
testing := viper.GetBool("testing") testing := viper.GetBool("testing")
viper.AddConfigPath(filepath.Join(DotfilePath, "dotctl")) viper.AddConfigPath(filepath.Join(DotfilePath, "dotctl"))
if(viper.Get("testing") == true && fs.Name() != "MemMapFS") { if viper.Get("testing") == true && fs.Name() != "MemMapFS" {
log.Fatalf("wrong filesystem, got %s", fs.Name()) log.Fatalf("wrong filesystem, got %s", fs.Name())
} }
err := fs.MkdirAll(path.Join(DotfilePath, "dotctl"), 0755) err := fs.MkdirAll(path.Join(DotfilePath, "dotctl"), 0755)
if err != nil { if err != nil {
log.Fatalf("Unable to create dotfile structure: %s", error.Error(err)) log.Fatalf("Unable to create dotfile structure: %s", error.Error(err))
} }
_, err = fs.Create(path.Join(DotfilePath, "dotctl/config.yml")) _, err = fs.Create(path.Join(DotfilePath, "dotctl/config.yml"))
if err != nil { if err != nil {
panic(fmt.Errorf("Unable to create config file %w", err)) panic(fmt.Errorf("Unable to create config file %w", err))
} }
if !testing { if !testing {
err = viper.WriteConfig() err = viper.WriteConfig()
if err != nil && viper.Get("testing") != true { if err != nil && viper.Get("testing") != true {
log.Fatalf("Unable to write config on init: %s\n", err) log.Fatalf("Unable to write config on init: %s\n", err)
} }
_, err = git.PlainInit(DotfilePath, false) _, err = git.PlainInit(DotfilePath, false)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
gitignoreContent := []byte (` gitignoreContent := []byte(`
# ignore dotctl config for individual installations # ignore dotctl config for individual installations
dotctl/ dotctl/
@ -93,13 +92,13 @@ func runInitCommand(cmd *cobra.Command, args []string) {
*.tmp *.tmp
`) `)
err := afero.WriteFile(fs, filepath.Join(DotfilePath, ".gitignore"), gitignoreContent, 0644) err := afero.WriteFile(fs, filepath.Join(DotfilePath, ".gitignore"), gitignoreContent, 0644)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
fmt.Fprintf(cmd.OutOrStdout(), "Successfully created dotfiles repository at %s\n", DotfilePath) fmt.Fprintf(cmd.OutOrStdout(), "Successfully created dotfiles repository at %s\n", DotfilePath)
} }

@ -11,76 +11,72 @@ import (
) )
func init() { func init() {
RootCmd.AddCommand(linkCommand) RootCmd.AddCommand(linkCommand)
linkCommand.AddCommand(listCommand) linkCommand.AddCommand(listCommand)
} }
var linkCommand = &cobra.Command{
var linkCommand = &cobra.Command { Use: "link",
Use: "link", Run: runLinkCommand,
Run: runLinkCommand, Short: "generate symlinks according to config",
Short: "generate symlinks according to config", Long: "add longer description", // TODO add longer description here
Long: "add longer description", // TODO add longer description here
} }
func runLinkCommand(cmd *cobra.Command, args []string) { func runLinkCommand(cmd *cobra.Command, args []string) {
fs := FileSystem fs := FileSystem
fmt.Println("Symlinking dotfiles...") fmt.Println("Symlinking dotfiles...")
dotfileRoot := viper.Get("dotfile-path").(string) dotfileRoot := viper.Get("dotfile-path").(string)
links := viper.GetStringMapString("links") links := viper.GetStringMapString("links")
for configName, configPath := range links { for configName, configPath := range links {
if configName == ".git" || configName == "dotctl" { if configName == ".git" || configName == "dotctl" {
continue continue
} }
dotPath := filepath.Join(dotfileRoot, configName) dotPath := filepath.Join(dotfileRoot, configName)
if configPath == ""{ if configPath == "" {
fmt.Fprintf(cmd.OutOrStdout(), "Warning: could not find config for %s\n", configName) fmt.Fprintf(cmd.OutOrStdout(), "Warning: could not find config for %s\n", configName)
} }
// destination needs to be removed before symlink
// destination needs to be removed before symlink if DryRun {
if(DryRun) { log.Printf("Existing directory %s will be removed\n", configPath)
log.Printf("Existing directory %s will be removed\n", configPath)
} else {
} else { fs.RemoveAll(configPath)
fs.RemoveAll(configPath) }
}
testing := viper.Get("testing")
testing := viper.Get("testing")
if DryRun {
if(DryRun) { log.Printf("Will link %s -> %s\n", configPath, dotPath)
log.Printf("Will link %s -> %s\n", configPath, dotPath) } else {
} else { if testing == true {
if(testing == true) { fmt.Fprintf(cmd.OutOrStdout(), "%s,%s", configPath, dotPath)
fmt.Fprintf(cmd.OutOrStdout(), "%s,%s", configPath, dotPath) } else {
} else { err := afero.OsFs.SymlinkIfPossible(afero.OsFs{}, dotPath, configPath)
err := afero.OsFs.SymlinkIfPossible(afero.OsFs{}, dotPath, configPath) if err != nil {
if err != nil { log.Fatalf("Cannot symlink %s: %s\n", configName, err.Error())
log.Fatalf("Cannot symlink %s: %s\n", configName, err.Error()) } else {
} else { fmt.Printf("%s linked\n", configName)
fmt.Printf("%s linked\n", configName) }
} }
} }
} }
}
} }
var listCommand = &cobra.Command{
var listCommand = &cobra.Command { Use: "list",
Use: "list", Run: runListCommand,
Run: runListCommand, Short: "list configs that should be symlinked",
Short: "list configs that should be symlinked", Long: "add longer description", // TODO add longer description here
Long: "add longer description", // TODO add longer description here
} }
func runListCommand(cmd *cobra.Command, args []string) { func runListCommand(cmd *cobra.Command, args []string) {
links := viper.GetStringMapString("links") links := viper.GetStringMapString("links")
fmt.Println("Configs added:") fmt.Println("Configs added:")
for configName, configPath := range links { for configName, configPath := range links {
fmt.Printf("%s: %s\n", configName, configPath) fmt.Printf("%s: %s\n", configName, configPath)
} }
} }

@ -10,65 +10,64 @@ import (
) )
func init() { func init() {
RootCmd.AddCommand(removeCommand) RootCmd.AddCommand(removeCommand)
} }
var removeCommand = &cobra.Command { var removeCommand = &cobra.Command{
Use: "rm", Use: "rm",
Short: "remove dotfile link", Short: "remove dotfile link",
Long: "TODO: add longer description", Long: "TODO: add longer description",
Run: runRemoveCommand, Run: runRemoveCommand,
} }
func runRemoveCommand(cmd *cobra.Command, args []string) { func runRemoveCommand(cmd *cobra.Command, args []string) {
fs := FileSystem fs := FileSystem
if len(args) <= 0 { if len(args) <= 0 {
fmt.Println("ERROR: missing specified config") fmt.Println("ERROR: missing specified config")
return return
} }
dotfile := args[0] dotfile := args[0]
links := viper.GetStringMapString("links") links := viper.GetStringMapString("links")
dotfileConfigPath := links[dotfile] dotfileConfigPath := links[dotfile]
err := fs.Remove(dotfileConfigPath) err := fs.Remove(dotfileConfigPath)
if err != nil { if err != nil {
fmt.Printf("ERROR: problem removing symlink %s: %s\n", dotfileConfigPath, err) fmt.Printf("ERROR: problem removing symlink %s: %s\n", dotfileConfigPath, err)
return return
} }
dotfileSavedPath := filepath.Join(DotfilePath, dotfile) dotfileSavedPath := filepath.Join(DotfilePath, dotfile)
savedFile, err := fs.Open(dotfileSavedPath) savedFile, err := fs.Open(dotfileSavedPath)
if err != nil { if err != nil {
fmt.Printf("ERROR: problem viewing saved dotfile(s): %s\n", err) fmt.Printf("ERROR: problem viewing saved dotfile(s): %s\n", err)
return return
} }
fileInfo, err := savedFile.Stat() fileInfo, err := savedFile.Stat()
if err != nil { if err != nil {
fmt.Printf("ERROR: problem getting file info: %s\n", err) fmt.Printf("ERROR: problem getting file info: %s\n", err)
return return
} }
if fileInfo.IsDir() { if fileInfo.IsDir() {
err = tools.CopyDir(fs, dotfileSavedPath, dotfileConfigPath) err = tools.CopyDir(fs, dotfileSavedPath, dotfileConfigPath)
} else { } else {
err = tools.CopyFile(fs, dotfileSavedPath, dotfileConfigPath) err = tools.CopyFile(fs, dotfileSavedPath, dotfileConfigPath)
} }
if err != nil { if err != nil {
fmt.Printf("ERROR: problem copying over dotfile(s) %s\n", err) fmt.Printf("ERROR: problem copying over dotfile(s) %s\n", err)
return return
} }
delete(links, dotfile) delete(links, dotfile)
viper.Set("links", links) viper.Set("links", links)
err = viper.WriteConfig() err = viper.WriteConfig()
if err != nil { if err != nil {
fmt.Printf("ERROR: problem saving config: %s\n", err) fmt.Printf("ERROR: problem saving config: %s\n", err)
return return
} }
fmt.Printf("%s symlink removed, copied files over to %s\n", dotfile, dotfileConfigPath) fmt.Printf("%s symlink removed, copied files over to %s\n", dotfile, dotfileConfigPath)
} }

@ -13,7 +13,6 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var RootCmd = &cobra.Command{ var RootCmd = &cobra.Command{
Use: "dotctl", Use: "dotctl",
Short: "dotfile management", Short: "dotfile management",
@ -38,63 +37,60 @@ var DryRun bool
var FileSystem afero.Fs var FileSystem afero.Fs
func init() { func init() {
// define flags and config sections // define flags and config sections
// Cobra also supports local flags, which will only run // Cobra also supports local flags, which will only run
// when this action is called directly. // when this action is called directly.
defaultDotPath := os.Getenv("HOME") + "/dotfiles/" defaultDotPath := os.Getenv("HOME") + "/dotfiles/"
defaultConfPath := os.Getenv("HOME") + "/.config/" defaultConfPath := os.Getenv("HOME") + "/.config/"
RootCmd.PersistentFlags().StringVar( RootCmd.PersistentFlags().StringVar(
&DotfilePath, &DotfilePath,
"dotfile-path", "dotfile-path",
defaultDotPath, defaultDotPath,
"Path pointing to dotfiles directory", "Path pointing to dotfiles directory",
) )
RootCmd.PersistentFlags().StringVar( RootCmd.PersistentFlags().StringVar(
&ConfigPath, &ConfigPath,
"config-path", "config-path",
defaultConfPath, defaultConfPath,
"Path pointing to config directory", "Path pointing to config directory",
) )
RootCmd.PersistentFlags().BoolVarP(&DryRun, "dry-run", "d", false, "Only output which symlinks will be created") RootCmd.PersistentFlags().BoolVarP(&DryRun, "dry-run", "d", false, "Only output which symlinks will be created")
viper.BindPFlag("dotfile-path", RootCmd.PersistentFlags().Lookup("dotfile-path")) viper.BindPFlag("dotfile-path", RootCmd.PersistentFlags().Lookup("dotfile-path"))
viper.BindPFlag("config-path", RootCmd.PersistentFlags().Lookup("config-path")) viper.BindPFlag("config-path", RootCmd.PersistentFlags().Lookup("config-path"))
viper.BindEnv("testing") viper.BindEnv("testing")
viper.SetDefault("testing", false) viper.SetDefault("testing", false)
viper.SetConfigName("config.yml") viper.SetConfigName("config.yml")
viper.SetConfigType("yaml") viper.SetConfigType("yaml")
viper.AddConfigPath("./tmp/dotfiles/dotctl") viper.AddConfigPath("./tmp/dotfiles/dotctl")
viper.AddConfigPath(filepath.Join(DotfilePath, "dotctl")) viper.AddConfigPath(filepath.Join(DotfilePath, "dotctl"))
viper.SetDefault("links", map[string]string{}) viper.SetDefault("links", map[string]string{})
err := viper.ReadInConfig() err := viper.ReadInConfig()
if err != nil { if err != nil {
fmt.Println("No config detected. You can generate one by using 'dotctl init'") fmt.Println("No config detected. You can generate one by using 'dotctl init'")
} }
FileSystem = UseFilesystem() FileSystem = UseFilesystem()
} }
func UseFilesystem() afero.Fs { func UseFilesystem() afero.Fs {
testing := viper.Get("testing") testing := viper.Get("testing")
if(testing == "true") { if testing == "true" {
return afero.NewMemMapFs() return afero.NewMemMapFs()
} else { } else {
return afero.NewOsFs() return afero.NewOsFs()
} }
} }
func CheckIfError(err error) { func CheckIfError(err error) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
return return
} }

@ -11,57 +11,52 @@ import (
) )
func init() { func init() {
RootCmd.AddCommand(statusCommand) RootCmd.AddCommand(statusCommand)
} }
var statusCommand = &cobra.Command { var statusCommand = &cobra.Command{
Use: "status", Use: "status",
Short: "View status of dotctl", Short: "View status of dotctl",
Long: "TODO: add longer description", Long: "TODO: add longer description",
Run: runStatusCommand, Run: runStatusCommand,
} }
func runStatusCommand(cmd *cobra.Command, args[]string) { func runStatusCommand(cmd *cobra.Command, args []string) {
fs := FileSystem fs := FileSystem
links := viper.GetStringMapString("links") links := viper.GetStringMapString("links")
var ignoredDirs = []string{".git", "dotctl", ".gitignore"} var ignoredDirs = []string{".git", "dotctl", ".gitignore"}
dotfiles, err := afero.ReadDir(fs, viper.GetString("dotfile-path")) dotfiles, err := afero.ReadDir(fs, viper.GetString("dotfile-path"))
if err != nil { if err != nil {
log.Fatalf("Cannot read dotfile dir: %s\n", err) log.Fatalf("Cannot read dotfile dir: %s\n", err)
} }
var linkedConfigs []string var linkedConfigs []string
var orphanedConfigs []string var orphanedConfigs []string
fmt.Fprintln(cmd.OutOrStdout(), "Config directories currently in dotfile path:\n") fmt.Fprintln(cmd.OutOrStdout(), "Config directories currently in dotfile path:")
for _, dotfileDir := range(dotfiles) {
dirName := dotfileDir.Name()
if !slices.Contains(ignoredDirs, dirName) {
if links[dirName] != "" {
// fmt.Fprintf(cmd.OutOrStdout(), "%s -> %s\n", dirName, links[dirName])
linkedConfigs = append(linkedConfigs, dirName, links[dirName])
} else {
// fmt.Fprintln(cmd.OutOrStdout(), dirName)
orphanedConfigs = append(orphanedConfigs, dirName)
}
}
}
for i := 0; i < len(linkedConfigs); i += 2 { for _, dotfileDir := range dotfiles {
fmt.Fprintf(cmd.OutOrStdout(), "%s (links to %s)\n", linkedConfigs[i], linkedConfigs[i+1]) dirName := dotfileDir.Name()
} if !slices.Contains(ignoredDirs, dirName) {
fmt.Fprintln(cmd.OutOrStdout(), "================") if links[dirName] != "" {
linkedConfigs = append(linkedConfigs, dirName, links[dirName])
} else {
orphanedConfigs = append(orphanedConfigs, dirName)
}
}
}
fmt.Fprintln(cmd.OutOrStdout(), "Orphaned configs") for i := 0; i < len(linkedConfigs); i += 2 {
fmt.Fprintf(cmd.OutOrStdout(), "%s (links to %s)\n", linkedConfigs[i], linkedConfigs[i+1])
for _, conf := range(orphanedConfigs) { }
fmt.Fprintln(cmd.OutOrStdout(), conf) fmt.Fprintln(cmd.OutOrStdout(), "================")
}
fmt.Fprintln(cmd.OutOrStdout(), "Orphaned configs")
for _, conf := range orphanedConfigs {
fmt.Fprintln(cmd.OutOrStdout(), conf)
}
} }

@ -21,15 +21,15 @@ var remoteRepository string
func init() { func init() {
RootCmd.AddCommand(syncCommand) RootCmd.AddCommand(syncCommand)
syncCommand.Flags().StringVarP( syncCommand.Flags().StringVarP(
&remoteRepository, &remoteRepository,
"remote", "remote",
"r", "r",
"", "",
"URL of remote repository", "URL of remote repository",
) )
viper.BindPFlag("dotctl-origin", syncCommand.Flags().Lookup("remote")) viper.BindPFlag("dotctl-origin", syncCommand.Flags().Lookup("remote"))
} }
var syncCommand = &cobra.Command{ var syncCommand = &cobra.Command{
@ -40,29 +40,29 @@ var syncCommand = &cobra.Command{
} }
func validateInput(input string) error { func validateInput(input string) error {
if input == "" { if input == "" {
return errors.New("Missing input") return errors.New("Missing input")
} }
return nil return nil
} }
func gitAddFiles(worktree *git.Worktree, fs afero.Fs) error { func gitAddFiles(worktree *git.Worktree, fs afero.Fs) error {
dotfilepath := viper.GetString("dotfile-path") dotfilepath := viper.GetString("dotfile-path")
entries, err := afero.ReadDir(fs, dotfilepath) entries, err := afero.ReadDir(fs, dotfilepath)
if err != nil { if err != nil {
return err return err
} }
for _, entry := range(entries) { for _, entry := range entries {
if(entry.Name() == "dotctl") { if entry.Name() == "dotctl" {
continue continue
} }
_, err = worktree.Add(entry.Name()) _, err = worktree.Add(entry.Name())
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }
func runSyncCommand(cmd *cobra.Command, args []string) { func runSyncCommand(cmd *cobra.Command, args []string) {
@ -91,117 +91,116 @@ func runSyncCommand(cmd *cobra.Command, args []string) {
w, err := r.Worktree() w, err := r.Worktree()
CheckIfError(err) CheckIfError(err)
username := promptui.Prompt{ username := promptui.Prompt{
Label: "username", Label: "username",
Validate: validateInput, Validate: validateInput,
} }
password := promptui.Prompt{
Label: "password",
Validate: validateInput,
HideEntered: true,
Mask: '*',
}
usernameVal, err := username.Run() password := promptui.Prompt{
CheckIfError(err) Label: "password",
Validate: validateInput,
HideEntered: true,
Mask: '*',
}
passwordVal, err := password.Run() usernameVal, err := username.Run()
CheckIfError(err) CheckIfError(err)
passwordVal, err := password.Run()
CheckIfError(err)
fmt.Println("Pulling from remote") fmt.Println("Pulling from remote")
err = w.Pull(&git.PullOptions{ err = w.Pull(&git.PullOptions{
RemoteName: "origin", RemoteName: "origin",
Auth: &http.BasicAuth { Auth: &http.BasicAuth{
Username: usernameVal, Username: usernameVal,
Password: passwordVal, Password: passwordVal,
}, },
}) })
if err != nil{ if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
fmt.Fprintf(cmd.OutOrStdout(), "successfully pulled from %s", origin) fmt.Fprintf(cmd.OutOrStdout(), "successfully pulled from %s", origin)
} }
status, err := w.Status() status, err := w.Status()
if err != nil { if err != nil {
log.Fatalln("Error getting status", err) log.Fatalln("Error getting status", err)
} }
if !status.IsClean() { if !status.IsClean() {
fmt.Println("Changes detected, do you want to push them?") fmt.Println("Changes detected, do you want to push them?")
confirm := promptui.Prompt { confirm := promptui.Prompt{
Label: "commit and push changes", Label: "commit and push changes",
IsConfirm: true, IsConfirm: true,
} }
_, err := confirm.Run() _, err := confirm.Run()
if err != nil { if err != nil {
fmt.Println("Will not push changes") fmt.Println("Will not push changes")
return return
} }
fmt.Println("Pushing changes...") fmt.Println("Pushing changes...")
err = gitAddFiles(w, FileSystem) err = gitAddFiles(w, FileSystem)
if err != nil { if err != nil {
log.Fatalf("Could not add files: %s\n", err) log.Fatalf("Could not add files: %s\n", err)
return return
} }
commitMessage := "backup " + time.Now().String() commitMessage := "backup " + time.Now().String()
commit, err := w.Commit(commitMessage, &git.CommitOptions{ commit, err := w.Commit(commitMessage, &git.CommitOptions{
Author: &object.Signature{ Author: &object.Signature{
Name: "dotctl CLI", Name: "dotctl CLI",
Email: "example@example.com", Email: "example@example.com",
When: time.Now(), When: time.Now(),
}, },
}) })
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
obj, err := r.CommitObject(commit) obj, err := r.CommitObject(commit)
if err != nil { if err != nil {
log.Fatalf("Cannot commit: %s",err) log.Fatalf("Cannot commit: %s", err)
} }
fmt.Println(obj) fmt.Println(obj)
err = r.Push(&git.PushOptions{ err = r.Push(&git.PushOptions{
RemoteName: "origin", RemoteName: "origin",
Auth: &http.BasicAuth { Auth: &http.BasicAuth{
Username: usernameVal, Username: usernameVal,
Password: passwordVal, Password: passwordVal,
}, },
}) })
CheckIfError(err) CheckIfError(err)
} }
// a pull deletes the dotctl config from the filesystem, need to recreate it // a pull deletes the dotctl config from the filesystem, need to recreate it
rewriteConfig() rewriteConfig()
} }
func rewriteConfig() { func rewriteConfig() {
fs := UseFilesystem() fs := UseFilesystem()
err := fs.MkdirAll(path.Join(DotfilePath, "dotctl"), 0755) err := fs.MkdirAll(path.Join(DotfilePath, "dotctl"), 0755)
if err != nil { if err != nil {
log.Fatalf("Unable to create dotfile structure: %s", error.Error(err)) log.Fatalf("Unable to create dotfile structure: %s", error.Error(err))
} }
_, err = fs.Create(path.Join(DotfilePath, "dotctl/config")) _, err = fs.Create(path.Join(DotfilePath, "dotctl/config"))
if err != nil { if err != nil {
panic(fmt.Errorf("Unable to create config file %w", err)) panic(fmt.Errorf("Unable to create config file %w", err))
} }
err = viper.WriteConfig() err = viper.WriteConfig()
if err != nil { if err != nil {
fmt.Println("Error: could not write config: ", err) fmt.Println("Error: could not write config: ", err)
} }
} }

@ -12,16 +12,16 @@ import (
) )
var ( var (
version = "dev" version = "dev"
commit = "none" commit = "none"
date = "unknown" date = "unknown"
) )
func SetVersionInfo(version, commit, date string) { func SetVersionInfo(version, commit, date string) {
cmd.RootCmd.Version = fmt.Sprintf("%s [Built on %s from Git Sha %s]", version, date, commit) cmd.RootCmd.Version = fmt.Sprintf("%s [Built on %s from Git Sha %s]", version, date, commit)
} }
func main() { func main() {
SetVersionInfo(versioninfo.Version, versioninfo.Revision, versioninfo.LastCommit.Format(time.RFC3339)) SetVersionInfo(versioninfo.Version, versioninfo.Revision, versioninfo.LastCommit.Format(time.RFC3339))
cmd.Execute() cmd.Execute()
} }

@ -9,78 +9,76 @@ import (
) )
func init() { func init() {
tools.SetTestFs() tools.SetTestFs()
} }
func TestCopyFile(t *testing.T) { func TestCopyFile(t *testing.T) {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fs.MkdirAll("test/src", 0755) fs.MkdirAll("test/src", 0755)
fs.MkdirAll("test/dest", 0755) fs.MkdirAll("test/dest", 0755)
err := afero.WriteFile(fs, "test/src/a.txt", []byte("file a"), 0644) err := afero.WriteFile(fs, "test/src/a.txt", []byte("file a"), 0644)
if err != nil { if err != nil {
t.Errorf("problem creating source file: %s", err.Error()) t.Errorf("problem creating source file: %s", err.Error())
} }
err = tools.CopyFile(fs, "test/src/a.txt", "test/dest/a.txt") err = tools.CopyFile(fs, "test/src/a.txt", "test/dest/a.txt")
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
_, err = fs.Stat("test/dest/a.txt") _, err = fs.Stat("test/dest/a.txt")
if os.IsNotExist(err) { if os.IsNotExist(err) {
t.Errorf("expected destination file does not exist") t.Errorf("expected destination file does not exist")
} }
result, err := afero.ReadFile(fs, "test/dest/a.txt") result, err := afero.ReadFile(fs, "test/dest/a.txt")
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
if string(result) != "file a" { if string(result) != "file a" {
t.Errorf("expected 'file a' got '%s'", string(result)) t.Errorf("expected 'file a' got '%s'", string(result))
} }
} }
func TestCopyDir(t *testing.T) { func TestCopyDir(t *testing.T) {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
fs.MkdirAll("test/src/dirA", 0755) fs.MkdirAll("test/src/dirA", 0755)
fs.MkdirAll("test/dest/", 0755) fs.MkdirAll("test/dest/", 0755)
fs.Mkdir("test/src/dirA/dirB", 0755) fs.Mkdir("test/src/dirA/dirB", 0755)
err := afero.WriteFile(fs, "test/src/dirA/a.txt", []byte("file a"), 0644) err := afero.WriteFile(fs, "test/src/dirA/a.txt", []byte("file a"), 0644)
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
err = afero.WriteFile(fs, "test/src/dirA/dirB/b.txt", []byte("file b"), 0644) err = afero.WriteFile(fs, "test/src/dirA/dirB/b.txt", []byte("file b"), 0644)
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
err = tools.CopyDir(fs, "test/src", "test/dest") err = tools.CopyDir(fs, "test/src", "test/dest")
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
result, err := afero.ReadFile(fs, "test/dest/dirA/a.txt") result, err := afero.ReadFile(fs, "test/dest/dirA/a.txt")
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
if string(result) != "file a" { if string(result) != "file a" {
t.Errorf("expected 'file a' got '%s'", string(result)) t.Errorf("expected 'file a' got '%s'", string(result))
} }
result, err = afero.ReadFile(fs, "test/dest/dirA/dirB/b.txt") result, err = afero.ReadFile(fs, "test/dest/dirA/dirB/b.txt")
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
if string(result) != "file b" { if string(result) != "file b" {
t.Errorf("expected 'file b' got '%s'", string(result)) t.Errorf("expected 'file b' got '%s'", string(result))
} }
} }

@ -12,24 +12,24 @@ import (
) )
func TestInitCommand(t *testing.T) { func TestInitCommand(t *testing.T) {
viper.Set("testing", true) viper.Set("testing", true)
fs := cmd.FileSystem fs := cmd.FileSystem
dotctl := cmd.RootCmd dotctl := cmd.RootCmd
actual := new(bytes.Buffer) actual := new(bytes.Buffer)
dotctl.SetOut(actual) dotctl.SetOut(actual)
dotctl.SetErr(actual) dotctl.SetErr(actual)
dotctl.SetArgs([]string{"init"}) dotctl.SetArgs([]string{"init"})
dotctl.Execute() dotctl.Execute()
homedir := os.Getenv("HOME") homedir := os.Getenv("HOME")
_, err := afero.ReadFile(fs, filepath.Join(homedir, "dotfiles/dotctl/config.yml")) _, err := afero.ReadFile(fs, filepath.Join(homedir, "dotfiles/dotctl/config.yml"))
if err != nil { if err != nil {
t.Error(err.Error()) t.Error(err.Error())
} }
} }

@ -13,33 +13,31 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestLinkCommand(t *testing.T) { func TestLinkCommand(t *testing.T) {
viper.Set("testing", true) viper.Set("testing", true)
cmd.FileSystem = afero.NewMemMapFs() cmd.FileSystem = afero.NewMemMapFs()
fs := cmd.FileSystem fs := cmd.FileSystem
homedir := os.Getenv("HOME") homedir := os.Getenv("HOME")
fs.MkdirAll(filepath.Join(homedir, "dotfiles/dotctl"), 0755) fs.MkdirAll(filepath.Join(homedir, "dotfiles/dotctl"), 0755)
links := map[string]string { links := map[string]string{
"someconfig": filepath.Join(homedir, ".config/someconfig"), "someconfig": filepath.Join(homedir, ".config/someconfig"),
} }
viper.Set("links", links) viper.Set("links", links)
dotctl := cmd.RootCmd dotctl := cmd.RootCmd
actual := new(bytes.Buffer) actual := new(bytes.Buffer)
dotctl.SetOut(actual) dotctl.SetOut(actual)
dotctl.SetErr(actual) dotctl.SetErr(actual)
dotctl.SetArgs([]string{"link"}) dotctl.SetArgs([]string{"link"})
dotctl.Execute() dotctl.Execute()
someconfig := filepath.Join(homedir, ".config/someconfig/") someconfig := filepath.Join(homedir, ".config/someconfig/")
somedot := filepath.Join(homedir, "dotfiles/someconfig/") somedot := filepath.Join(homedir, "dotfiles/someconfig/")
expected := fmt.Sprintf("%s,%s", someconfig, somedot) expected := fmt.Sprintf("%s,%s", someconfig, somedot)
assert.Equal(t, expected, actual.String(), "actual differs from expected") assert.Equal(t, expected, actual.String(), "actual differs from expected")
} }

@ -12,34 +12,34 @@ import (
) )
func TestStatusCommand(t *testing.T) { func TestStatusCommand(t *testing.T) {
cmd.FileSystem = afero.NewMemMapFs() cmd.FileSystem = afero.NewMemMapFs()
viper.Set("testing", true) viper.Set("testing", true)
fs := cmd.FileSystem fs := cmd.FileSystem
homedir := os.Getenv("HOME") homedir := os.Getenv("HOME")
fs.MkdirAll(filepath.Join(homedir, "dotfiles/dotctl"), 0755) fs.MkdirAll(filepath.Join(homedir, "dotfiles/dotctl"), 0755)
fs.MkdirAll(filepath.Join(homedir, "dotfiles/someconfig"), 0755) fs.MkdirAll(filepath.Join(homedir, "dotfiles/someconfig"), 0755)
fs.MkdirAll(filepath.Join(homedir, "dotfiles/somelinkedconfig"), 0755) fs.MkdirAll(filepath.Join(homedir, "dotfiles/somelinkedconfig"), 0755)
var links = map[string]string { var links = map[string]string{
"somelinkedconfig": "configpath", "somelinkedconfig": "configpath",
} }
viper.Set("links", links) viper.Set("links", links)
dotctl := cmd.RootCmd dotctl := cmd.RootCmd
actual := new(bytes.Buffer) actual := new(bytes.Buffer)
dotctl.SetOut(actual) dotctl.SetOut(actual)
dotctl.SetErr(actual) dotctl.SetErr(actual)
dotctl.SetArgs([]string{"status"}) dotctl.SetArgs([]string{"status"})
dotctl.Execute() dotctl.Execute()
// expected := "Config directories currently in dotfile path:\n" + // expected := "Config directories currently in dotfile path:\n" +
// "someconfig\nsomelinkedconfig - configpath\n" // "someconfig\nsomelinkedconfig - configpath\n"
// assert.Equal(t, expected, actual.String(), "actual differs from expected") // assert.Equal(t, expected, actual.String(), "actual differs from expected")
} }

@ -9,70 +9,69 @@ import (
"github.com/spf13/afero" "github.com/spf13/afero"
) )
func CopyFile(os afero.Fs, srcFile, destFile string) error{ func CopyFile(os afero.Fs, srcFile, destFile string) error {
// helper function to copy files over // helper function to copy files over
// ignore pre-existing git files // ignore pre-existing git files
if strings.Contains(srcFile, ".git") { if strings.Contains(srcFile, ".git") {
return nil return nil
} }
sourceFileStat, err := os.Stat(srcFile) sourceFileStat, err := os.Stat(srcFile)
if err != nil { if err != nil {
return err return err
} }
if !sourceFileStat.Mode().IsRegular() { if !sourceFileStat.Mode().IsRegular() {
return fmt.Errorf("%s is not a regular file", srcFile) return fmt.Errorf("%s is not a regular file", srcFile)
} }
source, err := os.Open(srcFile)
if err != nil {
return err
}
defer source.Close()
source, err := os.Open(srcFile) destination, err := os.Create(destFile)
if err != nil { if err != nil {
return err fmt.Printf("Error creating destination file %s\n", destFile)
} return err
defer source.Close() }
defer destination.Close()
destination, err := os.Create(destFile) _, err = io.Copy(destination, source)
if err != nil {
fmt.Printf("Error creating destination file %s\n", destFile)
return err
}
defer destination.Close()
_, err = io.Copy(destination, source) return err
return err
} }
func CopyDir(os afero.Fs, srcDir, destDir string) error { func CopyDir(os afero.Fs, srcDir, destDir string) error {
os.Mkdir(destDir, 0755) os.Mkdir(destDir, 0755)
entries, err := afero.ReadDir(os, srcDir) entries, err := afero.ReadDir(os, srcDir)
if err != nil { if err != nil {
return err return err
} }
for _, entry := range(entries) { for _, entry := range entries {
if entry.IsDir() { if entry.IsDir() {
if entry.Name() == ".git" { if entry.Name() == ".git" {
continue continue
} }
subDir := filepath.Join(srcDir, entry.Name()) subDir := filepath.Join(srcDir, entry.Name())
destSubDir := filepath.Join(destDir, entry.Name()) destSubDir := filepath.Join(destDir, entry.Name())
err := os.MkdirAll(destSubDir, entry.Mode().Perm()) err := os.MkdirAll(destSubDir, entry.Mode().Perm())
if err != nil { if err != nil {
return err return err
} }
CopyDir(os, subDir, destSubDir) CopyDir(os, subDir, destSubDir)
continue continue
} }
sourcePath := filepath.Join(srcDir, entry.Name()) sourcePath := filepath.Join(srcDir, entry.Name())
destPath := filepath.Join(destDir, entry.Name()) destPath := filepath.Join(destDir, entry.Name())
err := CopyFile(os, sourcePath, destPath) err := CopyFile(os, sourcePath, destPath)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }

@ -8,9 +8,8 @@ import (
var AppFs afero.Fs = afero.NewOsFs() var AppFs afero.Fs = afero.NewOsFs()
func SetTestFs() { func SetTestFs() {
log.Println("setting test fs") log.Println("setting test fs")
testFs := afero.NewMemMapFs() testFs := afero.NewMemMapFs()
AppFs = testFs AppFs = testFs
} }

Loading…
Cancel
Save