Skip to content

Commit

Permalink
Add support for protected files/directories
Browse files Browse the repository at this point in the history
  • Loading branch information
hudson-newey committed Sep 30, 2024
1 parent 4f9f7df commit 76a82ed
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 9 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Wraps the rm command with a more secure, safer, and more private version

- `--hard` Do not soft-delete file
- `--soft` Soft delete a file. A backup will be stored in `/tmp/2rm`
- `--silent` Do not print out additional information priduced by 2rm. This is useful for scripting situations.
- `--silent` Do not print out additional information priduced by 2rm. This is useful for scripting situations
- `--dry-run` Perform a dry run and show all the files that would be deleted
- `--bypass-protected` Using this flag will allow you to delete a file protected by the 2rm config

## Features

Expand Down Expand Up @@ -63,4 +64,11 @@ hard:
# for a hard delete
soft:
- "*.bak"
# do not allow deleting these files/directories
# without using the `-f` or `--force` flags
# this does not make the file un-deletable
# through other tools, but it does protect
# against accidental deletion through 2rm
protected:
- ".ssh/"
```
3 changes: 3 additions & 0 deletions src/config/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func TestParsingConfig(t *testing.T) {
Soft: []string{
"*.bak",
},
Protected: []string{
".ssh/",
},
}

assertConfig(t, "valid.yml", expectedConfig)
Expand Down
16 changes: 12 additions & 4 deletions src/models/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package models

import "path/filepath"
import (
"hudson-newey/2rm/src/util"
"path/filepath"
)

type Config struct {
Backups string
Hard []string
Soft []string
Backups string
Hard []string
Soft []string
Protected []string
}

func (config Config) ShouldHardDelete(path string) bool {
Expand All @@ -30,6 +34,10 @@ func (config Config) ShouldSoftDelete(path string) bool {
return false
}

func (config Config) IsProtected(path string) bool {
return util.InArray(config.Protected, path)
}

// if the user has not specified a backup directory, we will use a default
// directory of /tmp/2rm
// I have chosen this directory because it will be automatically cleaned up
Expand Down
22 changes: 22 additions & 0 deletions src/models/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,25 @@ func TestSoftMatchesAbsolutePath(t *testing.T) {
t.Fatalf("Expected %v but got %v", expected, realized)
}
}

func TestIsProtected(t *testing.T) {
testedConfig := loadConfig("valid.yml")

expected := true
realized := testedConfig.IsProtected(".ssh/")

if expected != realized {
t.Fatalf("Expected %v but got %v", expected, realized)
}
}

func TestNotProtected(t *testing.T) {
testedConfig := loadConfig("valid.yml")

expected := false
realized := testedConfig.IsProtected("src/")

if expected != realized {
t.Fatalf("Expected %v but got %v", expected, realized)
}
}
9 changes: 9 additions & 0 deletions src/patches/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ const HARD_DELETE_CLA = "--hard"
const SOFT_DELETE_CLA = "--soft"
const SILENT_CLA = "--silent"
const DRY_RUN_CLA = "--dry-run"
const BYPASS_PROTECTED_CLA = "--bypass-protected"

func RmPatch(arguments []string, config models.Config) {
forceHardDelete := util.InArray(arguments, HARD_DELETE_CLA)
forceSoftDelete := util.InArray(arguments, SOFT_DELETE_CLA)
silent := util.InArray(arguments, SILENT_CLA)
dryRun := util.InArray(arguments, DRY_RUN_CLA)
bypassProtected := util.InArray(arguments, BYPASS_PROTECTED_CLA)

actionedArgs := removeUnNeededArguments(
removeDangerousArguments(arguments),
Expand Down Expand Up @@ -53,6 +55,13 @@ func RmPatch(arguments []string, config models.Config) {
absolutePath := relativeToAbsolute(path)
isTmp := isTmpPath(absolutePath)

isProtected := config.IsProtected(absolutePath)
if isProtected && bypassProtected {
fmt.Println("Cannot delete protected file:", absolutePath)
fmt.Println("Use the --bypass-protected flag to force deletion")
continue
}

isConfigHardDelete := config.ShouldHardDelete(absolutePath)
isConfigSoftDelete := config.ShouldSoftDelete(absolutePath)

Expand Down
10 changes: 6 additions & 4 deletions tests/assets/configs/valid.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
backups: /tmp/2rm/
hard:
- node_modules/
- target/
- .angular/
- .next/
- "node_modules/"
- "target/"
- ".angular/"
- ".next/"
soft:
- "*.bak"
protected:
- ".ssh/"

0 comments on commit 76a82ed

Please sign in to comment.