diff --git a/pkg/starrs/migrator.go b/pkg/starrs/migrator.go index 258f6220..b0c88866 100644 --- a/pkg/starrs/migrator.go +++ b/pkg/starrs/migrator.go @@ -63,12 +63,18 @@ func AppTables(app string) AppTable { "ImportLists": {Table: "ImportLists", Column: "RootFolderPath", Name: "Name"}, }, "Sonarr": { - "Series": {Table: "Series", Column: "Path", Name: `""`}, - "ImportLists": {Table: "ImportLists", Column: "RootFolderPath", Name: "Name"}, + "Series": {Table: "Series", Column: "Path", Name: `""`}, + "EpisodeFiles": {Table: "EpisodeFiles", Column: "RelativePath", Name: `""`}, + "MetadataFiles": {Table: "MetadataFiles", Column: "RelativePath", Name: `""`}, + "SubtitleFiles": {Table: "SubtitleFiles", Column: "RelativePath", Name: `""`}, + "ImportLists": {Table: "ImportLists", Column: "RootFolderPath", Name: "Name"}, }, "Whisparr": { - "Series": {Table: "Series", Column: "Path", Name: `""`}, - "ImportLists": {Table: "ImportLists", Column: "RootFolderPath", Name: "Name"}, + "Series": {Table: "Series", Column: "Path", Name: `""`}, + "EpisodeFiles": {Table: "EpisodeFiles", Column: "RelativePath", Name: `""`}, + "MetadataFiles": {Table: "MetadataFiles", Column: "RelativePath", Name: `""`}, + "SubtitleFiles": {Table: "SubtitleFiles", Column: "RelativePath", Name: `""`}, + "ImportLists": {Table: "ImportLists", Column: "RootFolderPath", Name: "Name"}, }, }[app] } @@ -369,13 +375,12 @@ func (s *Starrs) updateFilesRootFolder( counter++ wr.EventsEmit(s.ctx, "DBfileCount", map[string]int64{table.Table: counter}) - if !strings.HasPrefix(entry.Path, oldPath) { - s.log.Debugf("Skipping path (wrong prefix): %s", entry.Path) + update, ok := rewritePathForTable(entry.Path, table, oldPath, newPath) + if !ok { + s.log.Debugf("Skipping path (no rewrite needed): %s", entry.Path) continue } - update := strings.Replace(entry.Path, oldPath, newPath, 1) - rep, err := sql.Update(table.Table, table.Column, update, "Id="+fmt.Sprint(entry.ID)) if err != nil { return 0, err @@ -388,6 +393,24 @@ func (s *Starrs) updateFilesRootFolder( return rowsAffected, nil } +func rewritePathForTable(path string, table TableColumn, oldPath, newPath string) (string, bool) { + if table.Column != "RelativePath" { + if !strings.HasPrefix(path, oldPath) { + return "", false + } + + return strings.Replace(path, oldPath, newPath, 1), true + } + + oldSlash := pickSlash(oldPath) + newSlash := pickSlash(newPath) + if oldSlash == newSlash || !strings.Contains(path, oldSlash) { + return "", false + } + + return strings.ReplaceAll(path, oldSlash, newSlash), true +} + func (s *Starrs) migratorInfo(sql *sqlConn, config *AppConfig) (*MigratorInfo, error) { table := AppTables(config.App) info := &MigratorInfo{ diff --git a/pkg/starrs/migrator_test.go b/pkg/starrs/migrator_test.go new file mode 100644 index 00000000..5bc91583 --- /dev/null +++ b/pkg/starrs/migrator_test.go @@ -0,0 +1,90 @@ +package starrs + +import "testing" + +func TestRewritePathForTablePathColumn(t *testing.T) { + table := TableColumn{Table: "Series", Column: "Path"} + + updated, ok := rewritePathForTable( + "/data/media/TV/Show", + table, + trailingSlash("/data/media"), + trailingSlash("/mnt/storage"), + ) + if !ok { + t.Fatal("expected path rewrite to apply for Path column") + } + + if updated != "/mnt/storage/TV/Show" { + t.Fatalf("unexpected rewritten path: %s", updated) + } +} + +func TestRewritePathForTableRelativePathWinToLinux(t *testing.T) { + table := TableColumn{Table: "EpisodeFiles", Column: "RelativePath"} + + updated, ok := rewritePathForTable( + `Season 01\Show - S01E01.mkv`, + table, + `D:\\Media\\TV\\Show`, + `/mnt/media/TV/Show`, + ) + if !ok { + t.Fatal("expected path rewrite to apply for RelativePath column") + } + + if updated != "Season 01/Show - S01E01.mkv" { + t.Fatalf("unexpected rewritten relative path: %s", updated) + } +} + +func TestRewritePathForTableRelativePathLinuxToWin(t *testing.T) { + table := TableColumn{Table: "SubtitleFiles", Column: "RelativePath"} + + updated, ok := rewritePathForTable( + "Season 01/Show - S01E01.en.srt", + table, + "/mnt/media/TV/Show", + `D:\Media\TV\Show`, + ) + if !ok { + t.Fatal("expected path rewrite to apply for RelativePath column") + } + + if updated != `Season 01\Show - S01E01.en.srt` { + t.Fatalf("unexpected rewritten relative path: %s", updated) + } +} + +func TestAppTablesIncludeSonarrRelativePathTables(t *testing.T) { + sonarr := AppTables("Sonarr") + if _, ok := sonarr["Series"]; !ok { + t.Fatal("Sonarr table map missing Series") + } + if _, ok := sonarr["ImportLists"]; !ok { + t.Fatal("Sonarr table map missing ImportLists") + } + + for _, name := range []string{"EpisodeFiles", "MetadataFiles", "SubtitleFiles"} { + column, ok := sonarr[name] + if !ok { + t.Fatalf("Sonarr table map missing %s", name) + } + if column.Column != "RelativePath" { + t.Fatalf("expected %s column to be RelativePath, got %s", name, column.Column) + } + } +} + +func TestAppTablesIncludeWhisparrRelativePathTables(t *testing.T) { + whisparr := AppTables("Whisparr") + for _, name := range []string{"EpisodeFiles", "MetadataFiles", "SubtitleFiles"} { + column, ok := whisparr[name] + if !ok { + t.Fatalf("Whisparr table map missing %s", name) + } + if column.Column != "RelativePath" { + t.Fatalf("expected %s column to be RelativePath, got %s", name, column.Column) + } + } +}