From 95c4fb71ae1a5116e2bd9d72dff9c2341982407c Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Sun, 4 May 2025 15:53:44 +0800 Subject: [PATCH] feat: handle command hooks feat: handle copy feat: handle remove feat: handle move and home ~ path refactor: improve error handling in cmd-hook feat: handlePwd --- services/cmd-hook/command.go | 148 ++++++++++++++++++++++++++--------- services/cmd-hook/main.go | 1 - services/cmd-hook/utils.go | 20 +++-- 3 files changed, 127 insertions(+), 42 deletions(-) diff --git a/services/cmd-hook/command.go b/services/cmd-hook/command.go index 53bc88a..0eec2d1 100644 --- a/services/cmd-hook/command.go +++ b/services/cmd-hook/command.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "os" "path/filepath" @@ -26,12 +27,13 @@ type FileObject struct { var commandHandlers = map[string]CommandHandler{ "ls": handleLs, "cd": handleCd, - "touch": handleTouch, - "mkdir": handleMkdir, - "cp": handleCp, - "rm": handleRm, - "rmdir": handleRmdir, - "mv": handleMv, + "touch": handleCreate, + "mkdir": handleCreate, + "cp": handleCopy, + "rm": handleRemove, + "rmdir": handleRemove, + "mv": handleMove, + "pwd": handlePwd, } func handleCommand(cmd string) (CommandParams, error) { @@ -55,27 +57,30 @@ func handleCd(cmd string) (CommandParams, error) { } func handleLs(cmd string) (CommandParams, error) { - fmt.Println("handleLs", cmd) - parts := strings.Fields(cmd)[1:] - path := "." - if len(parts) > 1 { - path = parts[1] + files := getFilePathList(cmd) + if len(files) == 0 { + files = append(files, ".") } - files := make([]FileObject, 0) - err := discover(&files, path, 0) - if err != nil { - return CommandParams{}, err + results := make([]FileObject, 0) + for _, path := range files { + err := discover(&results, path, 0) + if err != nil { + return CommandParams{}, err + } } return CommandParams{ - Discover: files, + Discover: results, }, nil } func discover(files *[]FileObject, path string, level int) error { absPath := resolvePath(path) fileType, err := fileExists(absPath) + if errors.Is(err, os.ErrNotExist) { + return nil + } if err != nil { return fmt.Errorf("ls: cannot access '%s': %v", path, err) } @@ -111,32 +116,103 @@ func discover(files *[]FileObject, path string, level int) error { return nil } -func handleTouch(cmd string) (CommandParams, error) { - // TODO: Implement touch command - return CommandParams{}, nil +func handleCreate(cmd string) (CommandParams, error) { + files := getFilePathList(cmd) + results := make([]FileObject, 0, len(files)) + for _, absPath := range files { + fileType, err := fileExists(absPath) + if errors.Is(err, os.ErrNotExist) { + continue + } + if err != nil { + return CommandParams{}, err + } + results = append(results, FileObject{ + Path: absPath, + Type: fileType, + Discovered: true, + }) + } + return CommandParams{Add: results}, nil } -func handleMkdir(cmd string) (CommandParams, error) { - // TODO: Implement mkdir command - return CommandParams{}, nil +func handleCopy(cmd string) (CommandParams, error) { + files := getFilePathList(cmd) + if len(files) < 2 { + return CommandParams{}, nil + } + dest := files[len(files)-1] + results := make([]FileObject, 0) + discover(&results, dest, 0) + return CommandParams{Discover: results}, nil } -func handleCp(cmd string) (CommandParams, error) { - // TODO: Implement cp command - return CommandParams{}, nil +func handleRemove(cmd string) (CommandParams, error) { + files := getFilePathList(cmd) + results := make([]FileObject, 0, len(files)) + for _, absPath := range files { + _, err := fileExists(absPath) + // If the file exists, ignore it + if err == nil { + continue + } + if !errors.Is(err, os.ErrNotExist) { + return CommandParams{}, err + } + results = append(results, FileObject{ + Path: absPath, + Type: FileTypeFile, // whatever + Discovered: true, + }) + } + return CommandParams{Remove: results}, nil } -func handleRm(cmd string) (CommandParams, error) { - // TODO: Implement rm command - return CommandParams{}, nil +func handleMove(cmd string) (CommandParams, error) { + files := getFilePathList(cmd) + if len(files) < 2 { + return CommandParams{}, nil + } + sources := files[:len(files)-1] + dest := files[len(files)-1] + result := CommandParams{ + Add: make([]FileObject, 0, len(sources)), + Remove: make([]FileObject, 0, len(sources)), + } + for _, source := range sources { + _, err := fileExists(source) + if err == nil { + continue + } + if !errors.Is(err, os.ErrNotExist) { + return CommandParams{}, err + } + result.Remove = append(result.Remove, FileObject{ + Path: source, + Type: FileTypeFile, // whatever + Discovered: true, + }) + } + + discover(&result.Add, dest, 0) + return result, nil } -func handleRmdir(cmd string) (CommandParams, error) { - // TODO: Implement rmdir command - return CommandParams{}, nil -} - -func handleMv(cmd string) (CommandParams, error) { - // TODO: Implement mv command - return CommandParams{}, nil +func handlePwd(cmd string) (CommandParams, error) { + pwd := os.Getenv("PWD") + parts := strings.Split(pwd, "/") + currentPath := "/" + results := make([]FileObject, 0, len(parts)) + for _, part := range parts { + currentPath = filepath.Join(currentPath, part) + results = append(results, FileObject{ + Path: currentPath, + Type: FileTypeDir, + Discovered: true, + }) + } + return CommandParams{ + Pwd: os.Getenv("PWD"), + Add: results, + }, nil } diff --git a/services/cmd-hook/main.go b/services/cmd-hook/main.go index 9ecd5bf..ed3474f 100644 --- a/services/cmd-hook/main.go +++ b/services/cmd-hook/main.go @@ -61,7 +61,6 @@ func main() { os.Exit(1) } - fmt.Println(string(jsonData)) req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/v1/commands", backendUrl), bytes.NewBuffer(jsonData)) if err != nil { fmt.Fprintf(os.Stderr, "Error creating request: %v\n", err) diff --git a/services/cmd-hook/utils.go b/services/cmd-hook/utils.go index efc2ca5..61d6880 100644 --- a/services/cmd-hook/utils.go +++ b/services/cmd-hook/utils.go @@ -3,6 +3,7 @@ package main import ( "os" "path/filepath" + "strings" ) type FileType string @@ -16,6 +17,10 @@ func resolvePath(path string) string { if filepath.IsAbs(path) { return path } + if strings.HasPrefix(path, "~") { + homeDir := os.Getenv("HOME") + return filepath.Join(homeDir, path[1:]) + } return filepath.Join(os.Getenv("PWD"), path) } @@ -30,10 +35,15 @@ func fileExists(path string) (FileType, error) { return FileTypeFile, nil } -func isDir(path string) bool { - info, err := os.Stat(path) - if err != nil { - return false +func getFilePathList(cmd string) []string { + parts := strings.Fields(cmd)[1:] + results := make([]string, 0, len(parts)) + for _, part := range parts { + if strings.HasPrefix(part, "-") { + continue + } + absPath := resolvePath(part) + results = append(results, absPath) } - return info.IsDir() + return results }