diff --git a/README.md b/README.md index cfe6875..e8a9f26 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,13 @@ In this case, you can modify your `~/.local/share/2rm/config.yml` file to always You can specify what directories are soft-deleted anb hard-deleted by using the `~/.local/share/2rm/config.yml` file. ```yml +# ~/.local/share/2rm/config.yml + # defaults to /tmp/2rm/ if not specified # in the config file # any files that are soft deleted will be # backed up in the `backups` directory -backups: /tmp/2rm +backups: /tmp/2rm/ hard: - node_modules/ - target/ @@ -59,5 +61,5 @@ hard: # regardless of it they are configured # for a hard delete soft: - - *.bak + - "*.bak" ``` diff --git a/makefile b/makefile index 5b8f7eb..e1b42e5 100644 --- a/makefile +++ b/makefile @@ -6,6 +6,9 @@ build: mkdir -p $(OUT_DIR) go build -o $(OUT_DIR)/2rm ./src/main.go +test: + go test ./src/... + clean: rm -rf $(OUT_DIR) diff --git a/src/commands/commands_test.go b/src/commands/commands_test.go new file mode 100644 index 0000000..0f9e0a2 --- /dev/null +++ b/src/commands/commands_test.go @@ -0,0 +1,7 @@ +package commands + +import "testing" + +func TestCommandsEcho(t *testing.T) { + Execute("echo 'Hello World'") +} diff --git a/src/config/parse.go b/src/config/parse.go index 6c2c466..0371585 100644 --- a/src/config/parse.go +++ b/src/config/parse.go @@ -11,6 +11,13 @@ import ( func ParseConfig(path string) models.Config { parsedConfig := models.Config{} + _, err := os.Stat(path) + if os.IsNotExist(err) { + // if the config file does not exist, we want to return an empty config + // this will act as a default config + return parsedConfig + } + content, err := os.ReadFile(path) if err != nil { log.Fatal(err) diff --git a/src/config/parse_test.go b/src/config/parse_test.go new file mode 100644 index 0000000..b5f9006 --- /dev/null +++ b/src/config/parse_test.go @@ -0,0 +1,73 @@ +package config + +import ( + "hudson-newey/2rm/src/models" + "path/filepath" + "reflect" + "testing" +) + +func assertConfig(t *testing.T, configPath string, expectedConfig models.Config) { + testConfigDir := "../../tests/assets/configs/" + absolutePath, err := filepath.Abs(testConfigDir + configPath) + if err != nil { + t.Errorf("Failed to get absolute path") + } + + realizedConfig := ParseConfig(absolutePath) + + if !reflect.DeepEqual(expectedConfig, realizedConfig) { + t.Errorf("Expected %v but got %v", expectedConfig, realizedConfig) + } +} + +func TestParsingConfig(t *testing.T) { + expectedConfig := models.Config{ + Backups: "/tmp/2rm/", + Hard: []string{ + "node_modules/", + "target/", + ".angular/", + ".next/", + }, + Soft: []string{ + "*.bak", + }, + } + + assertConfig(t, "valid.yml", expectedConfig) +} + +// this test asserts that we can parse a partial config +// we do not have to check every combination of partial configs +// because that would result in a massive explosion of tests +// that would not provide much value +func TestOnlyHardConfig(t *testing.T) { + expectedConfig := models.Config{ + Hard: []string{ + "node_modules/", + "target/", + ".angular/", + ".next/", + }, + } + + assertConfig(t, "only_hard.yml", expectedConfig) +} + +func TestOnlyBackups(t *testing.T) { + expectedConfig := models.Config{ + Backups: "/tmp/2rm/", + } + assertConfig(t, "only_backups.yml", expectedConfig) +} + +func TestParsingEmptyConfig(t *testing.T) { + expectedConfig := models.Config{} + assertConfig(t, "empty.yml", expectedConfig) +} + +func TestParsingConfigWithMissingFile(t *testing.T) { + expectedConfig := models.Config{} + assertConfig(t, "missing.yml", expectedConfig) +} diff --git a/src/models/config_test.go b/src/models/config_test.go new file mode 100644 index 0000000..c9f4b21 --- /dev/null +++ b/src/models/config_test.go @@ -0,0 +1,55 @@ +package models + +import "testing" + +func TestShouldHardDelete(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestShouldHardDeleteFalse(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestShouldHardDeleteEmpty(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestShouldSoftDelete(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestShouldSoftDeleteFalse(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestShouldSoftDeleteEmpty(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestSoftDeleteDir(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestSoftDeleteDirDefault(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestMatchesPatternFile(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestMatchesPatternDirectory(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestMatchesPatternGlobPostfix(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestMatchesPatternGlobPrefix(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} + +func TestMatchesAbsolutePath(t *testing.T) { + t.Fatal("This test needs to be implemented!") +} diff --git a/src/patches/rm.go b/src/patches/rm.go index 8d7f851..db4dc4a 100644 --- a/src/patches/rm.go +++ b/src/patches/rm.go @@ -26,6 +26,12 @@ func RmPatch(arguments []string, config models.Config) { removeDangerousArguments(arguments), ) + if shouldPassthrough(actionedArgs) { + command := "rm " + strings.Join(actionedArgs, " ") + commands.Execute(command) + return + } + filePaths := extractFilePaths(actionedArgs) extractedArguments := extractArguments(actionedArgs) @@ -55,6 +61,20 @@ func RmPatch(arguments []string, config models.Config) { } } +// sometimes we want to pass through the arguments to the original rm command +// e.g. when executing --help or --version +func shouldPassthrough(arguments []string) bool { + passthroughArguments := []string{"--help", "--version"} + + for _, arg := range arguments { + if util.InArray(passthroughArguments, arg) { + return true + } + } + + return false +} + func removeUnNeededArguments(arguments []string) []string { unNeededArguments := []string{"-r", HARD_DELETE_CLA, SOFT_DELETE_CLA, SILENT_CLA} returnedArguments := []string{} diff --git a/src/patches/rm_test.go b/src/patches/rm_test.go new file mode 100644 index 0000000..8411d5b --- /dev/null +++ b/src/patches/rm_test.go @@ -0,0 +1 @@ +package patches diff --git a/src/util/util.go b/src/util/util.go index ce1f9d0..2168c2c 100644 --- a/src/util/util.go +++ b/src/util/util.go @@ -1,12 +1,11 @@ package util func InArray[T comparable](arr []T, query T) bool { - for _, value := range(arr) { - if (value == query) { + for _, value := range arr { + if value == query { return true } } return false } - diff --git a/src/util/util_test.go b/src/util/util_test.go new file mode 100644 index 0000000..168f64b --- /dev/null +++ b/src/util/util_test.go @@ -0,0 +1,21 @@ +package util + +import "testing" + +func TestInArrayTrue(t *testing.T) { + expectedResult := true + realizedResult := InArray([]int{1, 2, 3}, 1) + + if realizedResult != expectedResult { + t.Fatalf("Expected %v but got %v", expectedResult, realizedResult) + } +} + +func TestInArrayFalse(t *testing.T) { + expectedResult := false + realizedResult := InArray([]int{1, 2, 3}, 4) + + if realizedResult != expectedResult { + t.Fatalf("Expected %v but got %v", expectedResult, realizedResult) + } +} diff --git a/tests/assets/configs/empty.yml b/tests/assets/configs/empty.yml new file mode 100644 index 0000000..e69de29 diff --git a/tests/assets/configs/only_backups.yml b/tests/assets/configs/only_backups.yml new file mode 100644 index 0000000..fb7868e --- /dev/null +++ b/tests/assets/configs/only_backups.yml @@ -0,0 +1 @@ +backups: /tmp/2rm/ diff --git a/tests/assets/configs/only_hard.yml b/tests/assets/configs/only_hard.yml new file mode 100644 index 0000000..a8bbbe6 --- /dev/null +++ b/tests/assets/configs/only_hard.yml @@ -0,0 +1,5 @@ +hard: + - node_modules/ + - target/ + - .angular/ + - .next/ diff --git a/tests/assets/configs/readme.txt b/tests/assets/configs/readme.txt new file mode 100644 index 0000000..bf4dcbc --- /dev/null +++ b/tests/assets/configs/readme.txt @@ -0,0 +1 @@ +This directory contains the configs that we use in tests diff --git a/tests/assets/configs/valid.yml b/tests/assets/configs/valid.yml new file mode 100644 index 0000000..251d0e5 --- /dev/null +++ b/tests/assets/configs/valid.yml @@ -0,0 +1,8 @@ +backups: /tmp/2rm/ +hard: + - node_modules/ + - target/ + - .angular/ + - .next/ +soft: + - "*.bak"