diff options
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 56 |
1 files changed, 51 insertions, 5 deletions
@@ -344,7 +344,7 @@ func handleAPIBrowse(w http.ResponseWriter, r *http.Request) { } defer tx.Rollback() - parent, err := idForPath(tx, decodeWebPath(params.Path), false) + parent, err := idForDirectoryPath(tx, decodeWebPath(params.Path), false) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return @@ -621,7 +621,7 @@ func getOrphanReplacement(webPath string) (*webOrphanImage, error) { return nil, nil } - parent, err := idForPath(tx, path[:len(path)-1], false) + parent, err := idForDirectoryPath(tx, path[:len(path)-1], false) if err != nil { return nil, err } @@ -1070,7 +1070,7 @@ func cmdWeb(args []string) error { // --- Import ------------------------------------------------------------------ -func idForPath(tx *sql.Tx, path []string, create bool) (int64, error) { +func idForDirectoryPath(tx *sql.Tx, path []string, create bool) (int64, error) { var parent sql.NullInt64 for _, name := range path { if err := tx.QueryRow(`SELECT id FROM node @@ -1130,7 +1130,7 @@ func (dm *directoryManager) IDForDirectoryPath( return id, nil } - id, err := idForPath(tx, list, true) + id, err := idForDirectoryPath(tx, list, true) if err != nil { return 0, err } @@ -1688,7 +1688,7 @@ func syncRoot(c *syncContext, fsPath string) error { // // Synchronizing F → D or * → F are special cases not worth implementing. crumbs := decodeWebPath(filepath.ToSlash(fsPath)) - dbParent, err := idForPath(c.tx, crumbs, true) + dbParent, err := idForDirectoryPath(c.tx, crumbs, true) if err != nil { return err } @@ -1881,6 +1881,51 @@ func cmdSync(args []string) error { return tx.Commit() } +// --- Removal ----------------------------------------------------------------- + +// cmdRemove is for manual removal of subtrees from the database. +// Beware that inputs are database, not filesystem paths. +func cmdRemove(args []string) error { + if len(args) < 2 { + return errors.New("usage: GD PATH...") + } + if err := openDB(args[0]); err != nil { + return err + } + + tx, err := db.BeginTx(context.Background(), nil) + if err != nil { + return err + } + defer tx.Rollback() + + for _, path := range args[1:] { + var id sql.NullInt64 + for _, name := range decodeWebPath(path) { + if err := tx.QueryRow(`SELECT id FROM node + WHERE parent IS ? AND name = ?`, + id, name).Scan(&id); err != nil { + return err + } + } + if id.Int64 == 0 { + return errors.New("can't remove root") + } + + if _, err = tx.Exec(disposeCTE+` + INSERT OR IGNORE INTO orphan(sha1, path) + SELECT sha1, path FROM orphaned`, id); err != nil { + return err + } + if _, err = tx.Exec(disposeCTE+` + DELETE FROM node WHERE id + IN (SELECT DISTINCT id FROM children)`, id); err != nil { + return err + } + } + return tx.Commit() +} + // --- Tagging ----------------------------------------------------------------- // cmdTag mass imports tags from data passed on stdin as a TSV @@ -2338,6 +2383,7 @@ var commands = map[string]struct { "import": {cmdImport}, "tag": {cmdTag}, "sync": {cmdSync}, + "remove": {cmdRemove}, "check": {cmdCheck}, "thumbnail": {cmdThumbnail}, "dhash": {cmdDhash}, |