e03b18ea21
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
81 lines
2.9 KiB
Go
81 lines
2.9 KiB
Go
package offsitekeys
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// dirFS: a folder listing for `ls <dir>` and `rm -rf <path>`, as the provider's restricted shell answers them.
|
|
type dirFS struct {
|
|
entries map[string]bool // full paths under /home
|
|
cmds []string
|
|
stick string // a path whose rm "succeeds" but stays (the re-list must catch it)
|
|
}
|
|
|
|
func (f *dirFS) Run(_ context.Context, cmd string, _ []byte) ([]byte, error) {
|
|
f.cmds = append(f.cmds, cmd)
|
|
a := strings.Fields(cmd)
|
|
switch {
|
|
case a[0] == "ls" && len(a) == 2:
|
|
var names []string
|
|
for p := range f.entries {
|
|
if strings.HasPrefix(p, a[1]+"/") {
|
|
names = append(names, strings.TrimPrefix(p, a[1]+"/"))
|
|
}
|
|
}
|
|
sort.Strings(names)
|
|
return []byte(strings.Join(names, "\n") + "\n"), nil
|
|
case a[0] == "rm" && a[1] == "-rf":
|
|
if a[2] != f.stick {
|
|
delete(f.entries, a[2])
|
|
}
|
|
return nil, nil
|
|
}
|
|
return nil, errors.New("Command not found")
|
|
}
|
|
func (f *dirFS) Close() error { return nil }
|
|
|
|
type dirDialer struct{ fs *dirFS }
|
|
|
|
func (d dirDialer) Dial(context.Context, Target, string) (Shell, error) { return d.fs, nil }
|
|
|
|
// R-32 — the purge removes the repository and every set-aside copy, and NOTHING else in the folder.
|
|
// COMPANION RED-PROOF (observed): drop the IsSetAsidePath filter (remove every listed entry) → this fails with
|
|
// "want the repo + 2 set-asides removed, got [… /home/felhom-repo-notes … /home/other]". Restored.
|
|
func TestPurgeRepos_R32_RemovesRepoAndSetAsidesOnly(t *testing.T) {
|
|
fs := &dirFS{entries: map[string]bool{
|
|
"/home/felhom-repo": true, "/home/felhom-repo.orphaned-20260721": true, "/home/felhom-repo.orphaned-20260721-2": true,
|
|
"/home/felhom-repo-notes": true, "/home/other": true,
|
|
}}
|
|
removed, err := (&Registrar{Dialer: dirDialer{fs}}).PurgeRepos(context.Background(), tgt, "pw")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(removed) != 3 {
|
|
t.Fatalf("want the repo + 2 set-asides removed, got %v", removed)
|
|
}
|
|
if !fs.entries["/home/felhom-repo-notes"] || !fs.entries["/home/other"] || len(fs.entries) != 2 {
|
|
t.Fatalf("other entries must stay: %v", fs.entries)
|
|
}
|
|
}
|
|
|
|
// A copy that survives the delete fails the purge (so RESET keeps the sub-account).
|
|
func TestPurgeRepos_R32_SurvivorFails(t *testing.T) {
|
|
fs := &dirFS{entries: map[string]bool{"/home/felhom-repo": true}, stick: "/home/felhom-repo"}
|
|
if _, err := (&Registrar{Dialer: dirDialer{fs}}).PurgeRepos(context.Background(), tgt, "pw"); err == nil {
|
|
t.Fatal("a repository still present after the purge must fail it")
|
|
}
|
|
}
|
|
|
|
// An empty folder (already purged, e.g. a re-run) is success with nothing removed.
|
|
func TestPurgeRepos_R32_EmptyIsSuccess(t *testing.T) {
|
|
fs := &dirFS{entries: map[string]bool{}}
|
|
removed, err := (&Registrar{Dialer: dirDialer{fs}}).PurgeRepos(context.Background(), tgt, "pw")
|
|
if err != nil || len(removed) != 0 {
|
|
t.Fatalf("an empty folder is success; got %v %v", removed, err)
|
|
}
|
|
}
|