Refuse an unversioned database that already has a files table (closes #11)
check / check (push) Failing after 2s

A database at user_version 0 that already has a files table was not
created by sfdupes: a foreign or partially initialized file. scan used
to run its CREATE TABLE on it and fail with a raw SQLite error, and
report and trees gave only a bare version mismatch. All three now
check for a files table at version 0 and refuse such a database with
the schema-version error telling the operator to remove the file and
rescan. A genuinely empty database is unchanged: scan creates the
schema, report and trees refuse it as before.

Model: opus-4-8 (implementation); opus-5-5 (rebase)
This commit is contained in:
2026-10-04 08:02:43 +00:00
parent 2eeba3df6f
commit f2e71e4f41
4 changed files with 81 additions and 1 deletions
+37
View File
@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"slices"
"strings"
"testing"
)
@@ -77,6 +78,42 @@ func TestOpenScanDatabaseCreates(t *testing.T) {
}
}
func TestOpenDatabaseUnversionedForeign(t *testing.T) {
t.Parallel()
// A database that has a files table but user_version 0, written by
// some other tool. report, trees and scan must refuse it with the
// schema-version error, not adopt it and not emit a raw SQLite
// "table files already exists".
path := testDBPath(t)
db, err := sql.Open("sqlite", path)
if err != nil {
t.Fatal(err)
}
_, err = db.ExecContext(t.Context(), "CREATE TABLE files (x INTEGER)")
if err != nil {
t.Fatal(err)
}
_ = db.Close()
_, err = openReportDatabase(t.Context(), path)
if !errors.Is(err, errSchemaVersion) ||
!strings.Contains(err.Error(), "remove the file and rescan") {
t.Fatalf("report: err = %v, want errSchemaVersion telling the "+
"operator to remove the file and rescan", err)
}
_, err = openScanDatabase(t.Context(), path)
if !errors.Is(err, errSchemaVersion) ||
!strings.Contains(err.Error(), "remove the file and rescan") {
t.Fatalf("scan: err = %v, want errSchemaVersion telling the "+
"operator to remove the file and rescan", err)
}
}
func TestOpenReportDatabaseMissing(t *testing.T) {
t.Parallel()