reset.go

 1package goose
 2
 3import (
 4	"context"
 5	"database/sql"
 6	"fmt"
 7	"sort"
 8)
 9
10// Reset rolls back all migrations
11func Reset(db *sql.DB, dir string, opts ...OptionsFunc) error {
12	ctx := context.Background()
13	return ResetContext(ctx, db, dir, opts...)
14}
15
16// ResetContext rolls back all migrations
17func ResetContext(ctx context.Context, db *sql.DB, dir string, opts ...OptionsFunc) error {
18	option := &options{}
19	for _, f := range opts {
20		f(option)
21	}
22	migrations, err := CollectMigrations(dir, minVersion, maxVersion)
23	if err != nil {
24		return fmt.Errorf("failed to collect migrations: %w", err)
25	}
26	if option.noVersioning {
27		return DownToContext(ctx, db, dir, minVersion, opts...)
28	}
29
30	statuses, err := dbMigrationsStatus(ctx, db)
31	if err != nil {
32		return fmt.Errorf("failed to get status of migrations: %w", err)
33	}
34	sort.Sort(sort.Reverse(migrations))
35
36	for _, migration := range migrations {
37		if !statuses[migration.Version] {
38			continue
39		}
40		if err = migration.DownContext(ctx, db); err != nil {
41			return fmt.Errorf("failed to db-down: %w", err)
42		}
43	}
44
45	return nil
46}
47
48func dbMigrationsStatus(ctx context.Context, db *sql.DB) (map[int64]bool, error) {
49	dbMigrations, err := store.ListMigrations(ctx, db, TableName())
50	if err != nil {
51		return nil, err
52	}
53	// The most recent record for each migration specifies
54	// whether it has been applied or rolled back.
55	results := make(map[int64]bool)
56
57	for _, m := range dbMigrations {
58		if _, ok := results[m.VersionID]; ok {
59			continue
60		}
61		results[m.VersionID] = m.IsApplied
62	}
63	return results, nil
64}