Rename project from TopDeck to Canon
- Module github.com/cdnutter/canon, binary/command cmd/canon, Docker image and compose project "canon" - Environment variables now use the CANON_ prefix - Default site title is "<Your name>'s Canon" (or "Canon" with no name); a Site title set in Settings still overrides it - Existing topdeck.db (and WAL files) is renamed to canon.db on start - README: upgrade notes, including moving the old compose volume Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
58a29b7339
commit
3923444b3b
26 files changed
+215
-120
No files matched your search
+24
-1
@@ -6,6 +6,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
@@ -18,7 +19,10 @@ type Store struct {
|
||||
}
|
||||
|
||||
func Open(dataDir string) (*Store, error) {
|
||||
path := filepath.Join(dataDir, "topdeck.db")
|
||||
path := filepath.Join(dataDir, "canon.db")
|
||||
if err := adoptLegacyDB(dataDir, path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dsn := fmt.Sprintf("file:%s?_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)&_pragma=synchronous(NORMAL)&_txlock=immediate", path)
|
||||
db, err := sql.Open("sqlite", dsn)
|
||||
if err != nil {
|
||||
@@ -35,6 +39,25 @@ func Open(dataDir string) (*Store, error) {
|
||||
|
||||
func (s *Store) Close() error { return s.db.Close() }
|
||||
|
||||
// adoptLegacyDB renames a database from before the project was called
|
||||
// Canon (topdeck.db, plus its WAL files) so upgrades keep their data.
|
||||
func adoptLegacyDB(dataDir, path string) error {
|
||||
legacy := filepath.Join(dataDir, "topdeck.db")
|
||||
if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
if _, err := os.Stat(legacy); err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, suffix := range []string{"-wal", "-shm", ""} {
|
||||
err := os.Rename(legacy+suffix, path+suffix)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return fmt.Errorf("renaming %s to %s: %w", legacy+suffix, path+suffix, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// migrations are applied in order; the index into this slice (plus one) is
|
||||
// the schema version stored in PRAGMA user_version.
|
||||
var migrations = []string{
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -177,3 +179,31 @@ func TestCustomList(t *testing.T) {
|
||||
t.Errorf("movie aspect = %q", m.Aspect())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdoptLegacyDB(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
s, err := Open(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.CreateList(context.Background(), List{Title: "Keep me", Category: "movie", MaxItems: 5}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s.Close()
|
||||
// Pretend this data dir predates the rename.
|
||||
for _, suffix := range []string{"", "-wal", "-shm"} {
|
||||
os.Rename(filepath.Join(dir, "canon.db"+suffix), filepath.Join(dir, "topdeck.db"+suffix))
|
||||
}
|
||||
s, err = Open(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer s.Close()
|
||||
lists, err := s.Lists(context.Background(), true)
|
||||
if err != nil || len(lists) != 1 || lists[0].Title != "Keep me" {
|
||||
t.Fatalf("legacy data not adopted: %v %v", lists, err)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(dir, "topdeck.db")); !os.IsNotExist(err) {
|
||||
t.Errorf("topdeck.db should have been renamed")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user