From 55a0d18f857392a2336cd53ddc550b59522eb710 Mon Sep 17 00:00:00 2001 From: shreyasbhat0 Date: Thu, 30 Nov 2023 17:25:31 +0530 Subject: [PATCH] feat: implement file handler for dive cli --- cli/common/command_builder.go | 4 +- cli/common/command_builder_test.go | 4 +- cli/common/files.go | 197 +++++++++++++++++++++++++++-- cli/common/interfaces.go | 16 ++- cli/common/spinner.go | 19 ++- 5 files changed, 215 insertions(+), 25 deletions(-) diff --git a/cli/common/command_builder.go b/cli/common/command_builder.go index 40327277..280a83e2 100644 --- a/cli/common/command_builder.go +++ b/cli/common/command_builder.go @@ -92,9 +92,9 @@ func (dc *diveCommandBuilder) SetLong(long string) CommandBuilder { } // SetRun sets the Run field of the command. -func (dc *diveCommandBuilder) SetRun(run func(cmd *cobra.Command, args []string)) CommandBuilder { +func (dc *diveCommandBuilder) SetRun(run func(cmd *cobra.Command, args []string) error) CommandBuilder { - dc.cmd.Run = run + dc.cmd.RunE = run return dc } diff --git a/cli/common/command_builder_test.go b/cli/common/command_builder_test.go index c7fb3ebe..141e2366 100644 --- a/cli/common/command_builder_test.go +++ b/cli/common/command_builder_test.go @@ -16,8 +16,10 @@ func TestDiveCommandBuilder(t *testing.T) { builder.SetUse("testCommand"). SetShort("Short description"). SetLong("Long description"). - SetRun(func(cmd *cobra.Command, args []string) { + SetRun(func(cmd *cobra.Command, args []string) error { cmd.Println("test function") + + return nil }) // Add flags diff --git a/cli/common/files.go b/cli/common/files.go index 6a42a539..9f5ed96a 100644 --- a/cli/common/files.go +++ b/cli/common/files.go @@ -1,31 +1,204 @@ package common -import "os" +import ( + "encoding/json" + "io/fs" + "os" + "path/filepath" + "strings" +) type diveFileHandler struct{} func NewDiveFileHandler() *diveFileHandler { return &diveFileHandler{} } +func (df *diveFileHandler) ReadFile(filePath string) ([]byte, error) { -func (f *diveFileHandler) ReadFile(filePath string) ([]byte, error) { - return nil, nil + fileData, err := os.ReadFile(filePath) + if err != nil { + return nil, Errorcf(FileError, "Error While Reading File %s", err.Error()) + } + + return fileData, nil +} + +func (df *diveFileHandler) ReadJson(fileName string, obj interface{}) error { + pwd, err := df.GetPwd() + if err != nil { + return WrapMessageToError(err, "Error While Reading File") + } + + filePath := filepath.Join(pwd, fileName) + + data, err := df.ReadFile(filePath) + if err != nil { + return err + } + + if len(data) != 0 { + if err := json.Unmarshal(data, obj); err != nil { + return WrapCodeToError(err, FileError, "Failed to Unmarshal Data") + } + } + + return nil } -func (f *diveFileHandler) ReadJson(filePath string, obj interface{}) (string, error) { - return "nil", nil +func (df *diveFileHandler) ReadAppFile(fileName string) ([]byte, error) { + + uhd, err := df.GetHomeDir() + if err != nil { + return nil, WrapMessageToError(err, "Failed to Read App File") + } + appFilePath := filepath.Join(uhd, ".dive", fileName) + + data, err := df.ReadFile(appFilePath) + + if err != nil { + return nil, WrapMessageToError(err, "Failed To Read App File") + } + + return data, nil } -func (f *diveFileHandler) WriteFile(filePath string, data []byte) error { + +func (df *diveFileHandler) WriteAppFile(fileName string, data []byte) error { + + uhd, err := df.GetHomeDir() + if err != nil { + return WrapMessageToErrorf(err, "Failed To Write App File %s", fileName) + } + appFileDir := filepath.Join(uhd, ".dive") + + err = df.MkdirAll(appFileDir, os.ModePerm) + + if err != nil { + return WrapMessageToErrorf(err, "Failed To Write App File %s", fileName) + } + + appFilePath := filepath.Join(appFileDir, fileName) + + file, err := df.OpenFile(appFilePath, "append|write|create", 0644) + if err != nil { + return WrapMessageToErrorf(err, "Failed To Write App File %s", fileName) + } + + defer file.Close() + + _, err = file.Write(data) + + if err != nil { + return WrapMessageToErrorf(err, "Failed To Write App File %s", fileName) + } + + return nil +} + +func (df *diveFileHandler) WriteFile(fileName string, data []byte) error { + + pwd, err := df.GetPwd() + + if err != nil { + return WrapMessageToErrorf(err, "Failed to Write File %s", fileName) + } + filePath := filepath.Join(pwd, fileName) + + file, err := df.OpenFile(filePath, "write|append|create", 0644) + + if err != nil { + return WrapMessageToError(err, "Failed") + } + + defer file.Close() + + _, err = file.Write(data) + + if err != nil { + return WrapMessageToErrorf(err, "Failed To Write App File %s", fileName) + } + return nil } -func (f *diveFileHandler) WriteJson(filePath string, data interface{}) error { + +func (df *diveFileHandler) WriteJson(fileName string, data interface{}) error { + + serializedData, err := json.Marshal(data) + + if err != nil { + return WithCode(err, FileError) + } + + err = df.WriteFile(fileName, serializedData) + if err != nil { + return WithCode(err, FileError) + } return nil } -func (f *diveFileHandler) GetPwd() string { - return "" + +func (df *diveFileHandler) GetPwd() (string, error) { + + pwd, err := os.Getwd() + if err != nil { + return "", Errorc(FileError, "Failed To Get PWD") + } + return pwd, err } -func (f *diveFileHandler) MkdirAll(dirPath string, permission string) error { + +func (df *diveFileHandler) MkdirAll(dirPath string, permission fs.FileMode) error { + + _, err := os.Stat(dirPath) + if os.IsNotExist(err) { + if err := os.MkdirAll(dirPath, permission); err != nil { + return WrapCodeToError(err, FileError, "Failed to Create Directory") + } + } else if err != nil { + + return WrapCodeToError(err, FileError, "Failed to check directory existence") + } + return nil } -func (f *diveFileHandler) OpenFile(filePath string, fileOpenMode string, permission int) (*os.File, error) { - return nil, nil + +func (df *diveFileHandler) OpenFile(filePath string, fileOpenMode string, permission int) (*os.File, error) { + mode := parseFileOpenMode(fileOpenMode) + file, err := os.OpenFile(filePath, mode, fs.FileMode(permission)) + if err != nil { + return nil, WrapCodeToError(err, FileError, "Failed to Open File") + } + + return file, nil + +} + +func (df *diveFileHandler) GetHomeDir() (string, error) { + + uhd, err := os.UserHomeDir() + if err != nil { + return "", Errorc(FileError, "Failed To Get User HomeDir") + } + return uhd, err +} + +func parseFileOpenMode(fileOpenMode string) int { + modes := strings.Split(fileOpenMode, "|") + + var mode int + for _, m := range modes { + switch strings.TrimSpace(m) { + case "append": + mode |= os.O_APPEND + case "create": + mode |= os.O_CREATE + case "truncate": + mode |= os.O_TRUNC + case "write": + mode |= os.O_WRONLY + case "readwrite": + mode |= os.O_RDWR + case "read": + mode |= os.O_RDONLY + } + + } + + return mode } diff --git a/cli/common/interfaces.go b/cli/common/interfaces.go index d7f03d93..fbda6222 100644 --- a/cli/common/interfaces.go +++ b/cli/common/interfaces.go @@ -1,6 +1,7 @@ package common import ( + "io/fs" "os" "github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings" @@ -43,11 +44,14 @@ type Context interface { type FileHandler interface { ReadFile(filePath string) ([]byte, error) - ReadJson(filePath string, obj interface{}) (string, error) - WriteFile(filePath string, data []byte) error - WriteJson(filePath string, data interface{}) error - GetPwd() string - MkdirAll(dirPath string, permission string) error + ReadJson(fileName string, obj interface{}) error + ReadAppFile(fileName string) ([]byte, error) + WriteFile(fileName string, data []byte) error + WriteJson(fileName string, data interface{}) error + WriteAppFile(fileName string, data []byte) error + GetPwd() (string, error) + GetHomeDir() (string, error) + MkdirAll(dirPath string, permission fs.FileMode) error OpenFile(filePath string, fileOpenMode string, permission int) (*os.File, error) } @@ -92,7 +96,7 @@ type CommandBuilder interface { SetLong(long string) CommandBuilder // SetRun sets the Run field of the command. - SetRun(run func(cmd *cobra.Command, args []string)) CommandBuilder + SetRun(run func(cmd *cobra.Command, args []string) error) CommandBuilder ToggleHelpCommand(enable bool) CommandBuilder } diff --git a/cli/common/spinner.go b/cli/common/spinner.go index 033408f6..5fd6c68c 100644 --- a/cli/common/spinner.go +++ b/cli/common/spinner.go @@ -19,7 +19,18 @@ func NewDiveSpinner() *diveSpinner { } -func (s *diveSpinner) Start(message string) {} -func (s *diveSpinner) Stop() {} -func (s *diveSpinner) SetMessage(message string) {} -func (s *diveSpinner) SetColor(color string) {} +func (ds *diveSpinner) SetMessage(message string, color string) { + panic("not implemented") // TODO: Implement +} + +func (ds *diveSpinner) SetColor(color string) { + panic("not implemented") // TODO: Implement +} + +func (ds *diveSpinner) Start(message string) { + panic("not implemented") // TODO: Implement +} + +func (ds *diveSpinner) Stop(message string) { + panic("not implemented") // TODO: Implement +}