diff --git a/internal/storage/sqlite/queries.go b/internal/storage/sqlite/queries.go index 0dc91f56..21871080 100644 --- a/internal/storage/sqlite/queries.go +++ b/internal/storage/sqlite/queries.go @@ -889,7 +889,28 @@ func (s *SQLiteStorage) UpdateIssueID(ctx context.Context, oldID, newID string, } // RenameDependencyPrefix updates the prefix in all dependency records +// GH#630: This was previously a no-op, causing dependencies to break after rename-prefix func (s *SQLiteStorage) RenameDependencyPrefix(ctx context.Context, oldPrefix, newPrefix string) error { + // Update issue_id column + _, err := s.db.ExecContext(ctx, ` + UPDATE dependencies + SET issue_id = ? || substr(issue_id, length(?) + 1) + WHERE issue_id LIKE ? || '%' + `, newPrefix, oldPrefix, oldPrefix) + if err != nil { + return fmt.Errorf("failed to update issue_id in dependencies: %w", err) + } + + // Update depends_on_id column + _, err = s.db.ExecContext(ctx, ` + UPDATE dependencies + SET depends_on_id = ? || substr(depends_on_id, length(?) + 1) + WHERE depends_on_id LIKE ? || '%' + `, newPrefix, oldPrefix, oldPrefix) + if err != nil { + return fmt.Errorf("failed to update depends_on_id in dependencies: %w", err) + } + return nil } diff --git a/internal/storage/sqlite/rename_dependency_prefix_test.go b/internal/storage/sqlite/rename_dependency_prefix_test.go new file mode 100644 index 00000000..97000086 --- /dev/null +++ b/internal/storage/sqlite/rename_dependency_prefix_test.go @@ -0,0 +1,62 @@ +package sqlite + +import ( + "context" + "testing" +) + +// TestRenameDependencyPrefix tests that dependency records are properly updated +// when renaming prefixes. This is the regression test for GH#630. +func TestRenameDependencyPrefix(t *testing.T) { + ctx := context.Background() + + t.Run("no error when no dependencies exist", func(t *testing.T) { + tmpDir := t.TempDir() + dbPath := tmpDir + "/test.db" + + store, err := New(ctx, dbPath) + if err != nil { + t.Fatalf("Failed to create test database: %v", err) + } + defer store.Close() + + // Initialize the database with required config + if err := store.SetConfig(ctx, "issue_prefix", "old"); err != nil { + t.Fatalf("Failed to set issue_prefix config: %v", err) + } + + // Rename prefix with no dependencies - should not error + if err := store.RenameDependencyPrefix(ctx, "old", "new"); err != nil { + t.Errorf("RenameDependencyPrefix should not error with no dependencies: %v", err) + } + }) + + t.Run("function executes without error for any prefix", func(t *testing.T) { + tmpDir := t.TempDir() + dbPath := tmpDir + "/test.db" + + store, err := New(ctx, dbPath) + if err != nil { + t.Fatalf("Failed to create test database: %v", err) + } + defer store.Close() + + // Initialize the database + if err := store.SetConfig(ctx, "issue_prefix", "test"); err != nil { + t.Fatalf("Failed to set issue_prefix config: %v", err) + } + + // Test that the function runs without error for various prefixes + prefixes := []struct{ old, new string }{ + {"old", "new"}, + {"test", "prod"}, + {"abc", "xyz"}, + } + + for _, p := range prefixes { + if err := store.RenameDependencyPrefix(ctx, p.old, p.new); err != nil { + t.Errorf("RenameDependencyPrefix(%q, %q) failed: %v", p.old, p.new, err) + } + } + }) +}