v0.10.0: ports and adapters refactor
- Extract shared manifest types into internal/manifest/types leaf package. - Extract SQLite adapter into internal/manifest/sqlite. - Extract JSONL adapter into internal/manifest/jsonl. - Isolate modernc.org/sqlite import to sqlite/adapter.go. - Add adapter-backed registry with manifest.Default. - Adapter-agnostic ConvertManifest in types/. - MemoryAdapter for in-memory manifest testing. - CLI uses manifest.Default registry directly. - SQLite LogWriter type assertion moved into SQLiteAdapter. - Manifest interface includes Entries(); EntryReader removed. - No behavior changes. 100% coverage across all 6 packages.
This commit is contained in:
+17
-78
@@ -1,84 +1,21 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Format string
|
||||
|
||||
const (
|
||||
FormatJSONL Format = "jsonl"
|
||||
FormatSQLite Format = "sqlite"
|
||||
"gitea.k3s.k0.nu/tools/photocli/internal/manifest/types"
|
||||
)
|
||||
|
||||
func Open(dir string, format Format) (Manifest, error) {
|
||||
jsonlPath := JSONLPath(dir)
|
||||
sqlitePath := SQLitePath(dir)
|
||||
jsonlExists := FileExists(jsonlPath)
|
||||
sqliteExists := FileExists(sqlitePath)
|
||||
|
||||
switch {
|
||||
case format == FormatJSONL && jsonlExists:
|
||||
return LoadJSONL(dir), nil
|
||||
case format == FormatSQLite && sqliteExists:
|
||||
return LoadSQLite(dir)
|
||||
case format == FormatJSONL && sqliteExists:
|
||||
return ConvertFromSQLite(dir)
|
||||
case format == FormatSQLite && jsonlExists:
|
||||
return ConvertFromJSONL(dir)
|
||||
default:
|
||||
if format == FormatJSONL {
|
||||
return LoadJSONL(dir), nil
|
||||
}
|
||||
return LoadSQLite(dir)
|
||||
}
|
||||
return Default.Open(dir, format)
|
||||
}
|
||||
|
||||
func ConvertFromJSONL(dir string) (Manifest, error) {
|
||||
src := LoadJSONL(dir)
|
||||
if err := src.OpenAppend(); err != nil {
|
||||
return nil, fmt.Errorf("open jsonl for read: %w", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, _ := LoadSQLite(dir)
|
||||
if err := dst.OpenAppend(); err != nil {
|
||||
return nil, fmt.Errorf("open sqlite for write: %w", err)
|
||||
}
|
||||
|
||||
for id, e := range src.Entries() {
|
||||
e.ID = id
|
||||
dst.AddEntry(e)
|
||||
}
|
||||
|
||||
os.Remove(JSONLPath(dir))
|
||||
return dst, nil
|
||||
return types.ConvertManifest(dir, JSONLAdapter, SQLiteAdapter)
|
||||
}
|
||||
|
||||
func ConvertFromSQLite(dir string) (Manifest, error) {
|
||||
src, _ := LoadSQLite(dir)
|
||||
if err := src.OpenAppend(); err != nil {
|
||||
return nil, fmt.Errorf("open sqlite for read: %w", err)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst := LoadJSONL(dir)
|
||||
if err := dst.OpenAppend(); err != nil {
|
||||
return nil, fmt.Errorf("open jsonl for write: %w", err)
|
||||
}
|
||||
|
||||
for id, e := range src.Entries() {
|
||||
e.ID = id
|
||||
dst.AddEntry(e)
|
||||
}
|
||||
if err := dst.Save(); err != nil {
|
||||
return nil, fmt.Errorf("save jsonl: %w", err)
|
||||
}
|
||||
|
||||
os.Remove(SQLitePath(dir))
|
||||
return dst, nil
|
||||
return types.ConvertManifest(dir, SQLiteAdapter, JSONLAdapter)
|
||||
}
|
||||
|
||||
func FileExists(path string) bool {
|
||||
@@ -90,19 +27,21 @@ func FileExists(path string) bool {
|
||||
}
|
||||
|
||||
func ParseFormat(s string) (Format, error) {
|
||||
switch strings.ToLower(s) {
|
||||
case "jsonl", "json":
|
||||
return FormatJSONL, nil
|
||||
case "sqlite", "db", "sqlite3":
|
||||
return FormatSQLite, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown manifest format %q (use jsonl or sqlite)", s)
|
||||
}
|
||||
return Default.ParseFormat(s)
|
||||
}
|
||||
|
||||
func OpenLogWriter(m Manifest, dir string) (LogWriter, error) {
|
||||
if sm, ok := m.(*sqliteManifest); ok && sm.DB() != nil {
|
||||
return NewSQLiteLogWriter(sm.DB())
|
||||
format := FormatJSONL
|
||||
if reporter, ok := m.(types.FormatReporter); ok {
|
||||
format = reporter.ManifestFormat()
|
||||
}
|
||||
return NewFileLogWriter(LogPath(dir))
|
||||
return Default.OpenLogWriter(m, dir, format)
|
||||
}
|
||||
|
||||
func osRemove(path string) error {
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.SetRemoveFunc(osRemove)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user