diff --git a/cmd/status.go b/cmd/status.go new file mode 100644 index 0000000..3c3506f --- /dev/null +++ b/cmd/status.go @@ -0,0 +1,22 @@ +package cmd + +import ( + "github.com/RohitRavindra-dev/devlocal/internal/filesystem" + "github.com/RohitRavindra-dev/devlocal/internal/service/status" + "github.com/spf13/cobra" +) + +var statusCmd = &cobra.Command{ + Use: "status", + Short: "View the current status of devlocal setup", + PreRunE: func(cmd *cobra.Command, args []string) error { + return filesystem.ValidateDevLocalFilesystem() + }, + RunE: func(cmd *cobra.Command, args []string) error { + return status.Run() + }, +} + +func init() { + rootCmd.AddCommand(statusCmd) +} diff --git a/internal/filesystem/utils.go b/internal/filesystem/utils.go index 35843d0..476bb25 100644 --- a/internal/filesystem/utils.go +++ b/internal/filesystem/utils.go @@ -1,6 +1,7 @@ package filesystem import ( + "fmt" "os" "path/filepath" @@ -8,18 +9,22 @@ import ( "gopkg.in/yaml.v3" ) -func exists(path string) (bool, error) { - _, err := os.Stat(path) +func FileExists(path string) (bool, error) { + info, err := os.Stat(path) - if err == nil { - return true, nil + if os.IsNotExist(err) { + return false, fmt.Errorf("%s does not exist", path) } - if os.IsNotExist(err) { - return false, nil + if err != nil { + return false, err + } + + if info.IsDir() { + return false, fmt.Errorf("%s is a directory, expected a file", path) } - return false, err + return true, nil } func LoadDevlocalConfig() (*config.DevlocalConfigYaml, error) { diff --git a/internal/git/worktrees.go b/internal/git/worktrees.go index 5dd37ac..1fdd513 100644 --- a/internal/git/worktrees.go +++ b/internal/git/worktrees.go @@ -74,3 +74,18 @@ func sanitizeToTrackedFiles(files []string) []string { return filesTracked } + +func IsSkipWorktree(file string) (bool, error) { + out, err := exec.Command( + "git", + "ls-files", + "-v", + file, + ).CombinedOutput() + + if err != nil { + return false, err + } + + return len(out) > 0 && out[0] == 'S', nil +} diff --git a/internal/service/status/reporter.go b/internal/service/status/reporter.go new file mode 100644 index 0000000..f61adad --- /dev/null +++ b/internal/service/status/reporter.go @@ -0,0 +1,76 @@ +package status + +import ( + "fmt" + + "github.com/RohitRavindra-dev/devlocal/internal/config" + "github.com/RohitRavindra-dev/devlocal/internal/filesystem" + "github.com/RohitRavindra-dev/devlocal/internal/git" +) + +func displayConfigVersion(version int) { + fmt.Printf("[Version] %d \n", version) +} + +func displayOverlookStatus(fileNames []string) { + fmt.Println("[Overlooked files]") + if len(fileNames) == 0 { + fmt.Println("\t- No files registed in config for overlooking!") + return + } + for _, filename := range fileNames { + exists, err := filesystem.FileExists(filename) + overlookStatus := "✗" + overlookComment := "Being tracked" + if exists { + + if isOverlooked, _ := git.IsSkipWorktree(filename); isOverlooked { + overlookStatus = "✓" + overlookComment = "Overlooked" + } + + } else { + overlookComment = err.Error() + } + + fmt.Printf("\t%s %s \n\t\t- %s\n", overlookStatus, filename, overlookComment) + + } +} + +func displayPatchesStatus(patches []string) { + fmt.Println("[Patches]") + if len(patches) == 0 { + fmt.Println("\t- No patches registed in config for patching!") + return + } +} + +func displayDevlocalConfig(config *config.DevlocalConfigYaml) error { + fmt.Println("\n===============================") + fmt.Println("| devlocal [Status] |") + fmt.Printf("===============================\n\n") + displayConfigVersion(config.Version) + fmt.Println() + displayOverlookStatus(config.Overlook) + fmt.Println() + displayPatchesStatus(config.Patches) + fmt.Printf("===============================\n\n") + + return nil +} + +func Run() error { + + //load config + config, err := filesystem.LoadDevlocalConfig() + if err != nil { + return err + } + + if err := displayDevlocalConfig(config); err != nil { + return err + } + + return nil +}