Skip to content

Commit 76a82ed

Browse files
committed
Add support for protected files/directories
1 parent 4f9f7df commit 76a82ed

File tree

6 files changed

+61
-9
lines changed

6 files changed

+61
-9
lines changed

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ Wraps the rm command with a more secure, safer, and more private version
88

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

1415
## Features
1516

@@ -63,4 +64,11 @@ hard:
6364
# for a hard delete
6465
soft:
6566
- "*.bak"
67+
# do not allow deleting these files/directories
68+
# without using the `-f` or `--force` flags
69+
# this does not make the file un-deletable
70+
# through other tools, but it does protect
71+
# against accidental deletion through 2rm
72+
protected:
73+
- ".ssh/"
6674
```

src/config/parse_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ func TestParsingConfig(t *testing.T) {
3434
Soft: []string{
3535
"*.bak",
3636
},
37+
Protected: []string{
38+
".ssh/",
39+
},
3740
}
3841

3942
assertConfig(t, "valid.yml", expectedConfig)

src/models/config.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package models
22

3-
import "path/filepath"
3+
import (
4+
"hudson-newey/2rm/src/util"
5+
"path/filepath"
6+
)
47

58
type Config struct {
6-
Backups string
7-
Hard []string
8-
Soft []string
9+
Backups string
10+
Hard []string
11+
Soft []string
12+
Protected []string
913
}
1014

1115
func (config Config) ShouldHardDelete(path string) bool {
@@ -30,6 +34,10 @@ func (config Config) ShouldSoftDelete(path string) bool {
3034
return false
3135
}
3236

37+
func (config Config) IsProtected(path string) bool {
38+
return util.InArray(config.Protected, path)
39+
}
40+
3341
// if the user has not specified a backup directory, we will use a default
3442
// directory of /tmp/2rm
3543
// I have chosen this directory because it will be automatically cleaned up

src/models/config_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,25 @@ func TestSoftMatchesAbsolutePath(t *testing.T) {
100100
t.Fatalf("Expected %v but got %v", expected, realized)
101101
}
102102
}
103+
104+
func TestIsProtected(t *testing.T) {
105+
testedConfig := loadConfig("valid.yml")
106+
107+
expected := true
108+
realized := testedConfig.IsProtected(".ssh/")
109+
110+
if expected != realized {
111+
t.Fatalf("Expected %v but got %v", expected, realized)
112+
}
113+
}
114+
115+
func TestNotProtected(t *testing.T) {
116+
testedConfig := loadConfig("valid.yml")
117+
118+
expected := false
119+
realized := testedConfig.IsProtected("src/")
120+
121+
if expected != realized {
122+
t.Fatalf("Expected %v but got %v", expected, realized)
123+
}
124+
}

src/patches/rm.go

+9
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ const HARD_DELETE_CLA = "--hard"
1717
const SOFT_DELETE_CLA = "--soft"
1818
const SILENT_CLA = "--silent"
1919
const DRY_RUN_CLA = "--dry-run"
20+
const BYPASS_PROTECTED_CLA = "--bypass-protected"
2021

2122
func RmPatch(arguments []string, config models.Config) {
2223
forceHardDelete := util.InArray(arguments, HARD_DELETE_CLA)
2324
forceSoftDelete := util.InArray(arguments, SOFT_DELETE_CLA)
2425
silent := util.InArray(arguments, SILENT_CLA)
2526
dryRun := util.InArray(arguments, DRY_RUN_CLA)
27+
bypassProtected := util.InArray(arguments, BYPASS_PROTECTED_CLA)
2628

2729
actionedArgs := removeUnNeededArguments(
2830
removeDangerousArguments(arguments),
@@ -53,6 +55,13 @@ func RmPatch(arguments []string, config models.Config) {
5355
absolutePath := relativeToAbsolute(path)
5456
isTmp := isTmpPath(absolutePath)
5557

58+
isProtected := config.IsProtected(absolutePath)
59+
if isProtected && bypassProtected {
60+
fmt.Println("Cannot delete protected file:", absolutePath)
61+
fmt.Println("Use the --bypass-protected flag to force deletion")
62+
continue
63+
}
64+
5665
isConfigHardDelete := config.ShouldHardDelete(absolutePath)
5766
isConfigSoftDelete := config.ShouldSoftDelete(absolutePath)
5867

tests/assets/configs/valid.yml

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
backups: /tmp/2rm/
22
hard:
3-
- node_modules/
4-
- target/
5-
- .angular/
6-
- .next/
3+
- "node_modules/"
4+
- "target/"
5+
- ".angular/"
6+
- ".next/"
77
soft:
88
- "*.bak"
9+
protected:
10+
- ".ssh/"

0 commit comments

Comments
 (0)