diff --git a/README.md b/README.md index 089dae5..66b77c5 100644 --- a/README.md +++ b/README.md @@ -168,15 +168,11 @@ bridge config, database and python virtualenv (if applicable). Note that deleting a bridge through the Beeper client settings will *not* delete the bridge database that is stored locally; you must -delete that yourself, or use `bbctl delete` instead. The bridge -databases are stored in `~/.local/share/bbctl/prod` by default. -However, note that if you use any option that causes the bridge -database to be stored in a separate location, such as `-l` which -stores it in the current working directory, then `bbctl delete` will -*not* delete the bridge database, and you will again have to delete it -manually. - -If you later re-add a self-hosted bridge after deleting it but not -deleting the local database, you should expect errors, as the bridge -will have been removed from Matrix rooms that it thinks it is a member -of. +delete that yourself, or use `bbctl delete` instead. (If you created +the bridge database with `bbctl run -l`, then run `bbctl delete -l` +from the same working directory to delete it.) + +If you later re-add a self-hosted bridge after deleting it from the +Beeper servers but not deleting the local database, you should expect +errors, as the bridge will have been removed from Matrix rooms that it +thinks it is a member of. diff --git a/cmd/bbctl/delete.go b/cmd/bbctl/delete.go index 8abd8b4..d707a50 100644 --- a/cmd/bbctl/delete.go +++ b/cmd/bbctl/delete.go @@ -5,7 +5,9 @@ import ( "fmt" "io/fs" "os" + "path" "path/filepath" + "strings" "github.com/AlecAivazis/survey/v2" "github.com/fatih/color" @@ -23,6 +25,12 @@ var deleteCommand = &cli.Command{ Action: deleteBridge, Before: RequiresAuth, Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "local-dev", + Aliases: []string{"l"}, + Usage: "Delete the bridge database and config from your current working directory. Useful for developing bridges.", + EnvVars: []string{"BEEPER_BRIDGE_LOCAL"}, + }, &cli.BoolFlag{ Name: "force", Aliases: []string{"f"}, @@ -43,6 +51,18 @@ func deleteBridge(ctx *cli.Context) error { } else if bridge == "hungryserv" { return UserError{"You really shouldn't do that"} } + var err error + dataDir := GetEnvConfig(ctx).BridgeDataDir + var bridgeDir string + localDev := ctx.Bool("local-dev") + if localDev { + bridgeDir, err = os.Getwd() + if err != nil { + return fmt.Errorf("failed to get working directory: %w", err) + } + } else { + bridgeDir = filepath.Join(dataDir, bridge) + } homeserver := ctx.String("homeserver") accessToken := GetEnvConfig(ctx).AccessToken if !ctx.Bool("force") { @@ -60,7 +80,7 @@ func deleteBridge(ctx *cli.Context) error { } var confirmation bool - err := survey.AskOne(&survey.Confirm{Message: fmt.Sprintf("Are you sure you want to permanently delete %s?", bridge)}, &confirmation) + err = survey.AskOne(&survey.Confirm{Message: fmt.Sprintf("Are you sure you want to permanently delete %s?", bridge)}, &confirmation) if err != nil { return err } else if !confirmation { @@ -71,8 +91,7 @@ func deleteBridge(ctx *cli.Context) error { return fmt.Errorf("error deleting bridge: %w", err) } fmt.Println("Started deleting bridge") - bridgeDir := filepath.Join(GetEnvConfig(ctx).BridgeDataDir, bridge) - err = os.RemoveAll(bridgeDir) + err = deleteLocalBridgeData(bridgeDir, !localDev) if err != nil && !errors.Is(err, fs.ErrNotExist) { log.Printf("Failed to delete [magenta]%s[reset]: [red]%v[reset]", bridgeDir, err) } else { @@ -80,3 +99,38 @@ func deleteBridge(ctx *cli.Context) error { } return nil } + +func isLocalBridgeFile(name string) bool { + if name == "config.yaml" { + return true + } + if strings.HasSuffix(name, ".db") { + return true + } + if strings.HasSuffix(name, ".db-shm") { + return true + } + if strings.HasSuffix(name, ".db-wal") { + return true + } + return false +} + +func deleteLocalBridgeData(bridgeDir string, deleteWholeDir bool) error { + if deleteWholeDir { + return os.RemoveAll(bridgeDir) + } + items, err := os.ReadDir(bridgeDir) + if err != nil { + return err + } + for _, item := range items { + if isLocalBridgeFile(item.Name()) { + err := os.Remove(path.Join(bridgeDir, item.Name())) + if err != nil { + return err + } + } + } + return nil +}