1package goose
2
3import (
4 "context"
5 "database/sql"
6 "fmt"
7 "io/fs"
8 "strconv"
9)
10
11// Deprecated: VERSION will no longer be supported in the next major release.
12const VERSION = "v3.18.0"
13
14var (
15 minVersion = int64(0)
16 maxVersion = int64((1 << 63) - 1)
17 timestampFormat = "20060102150405"
18 verbose = false
19 noColor = false
20
21 // base fs to lookup migrations
22 baseFS fs.FS = osFS{}
23)
24
25// SetVerbose set the goose verbosity mode
26func SetVerbose(v bool) {
27 verbose = v
28}
29
30// SetBaseFS sets a base FS to discover migrations. It can be used with 'embed' package.
31// Calling with 'nil' argument leads to default behaviour: discovering migrations from os filesystem.
32// Note that modifying operations like Create will use os filesystem anyway.
33func SetBaseFS(fsys fs.FS) {
34 if fsys == nil {
35 fsys = osFS{}
36 }
37
38 baseFS = fsys
39}
40
41// Run runs a goose command.
42//
43// Deprecated: Use RunContext.
44func Run(command string, db *sql.DB, dir string, args ...string) error {
45 ctx := context.Background()
46 return RunContext(ctx, command, db, dir, args...)
47}
48
49// RunContext runs a goose command.
50func RunContext(ctx context.Context, command string, db *sql.DB, dir string, args ...string) error {
51 return run(ctx, command, db, dir, args)
52}
53
54// RunWithOptions runs a goose command with options.
55//
56// Deprecated: Use RunWithOptionsContext.
57func RunWithOptions(command string, db *sql.DB, dir string, args []string, options ...OptionsFunc) error {
58 ctx := context.Background()
59 return RunWithOptionsContext(ctx, command, db, dir, args, options...)
60}
61
62// RunWithOptionsContext runs a goose command with options.
63func RunWithOptionsContext(ctx context.Context, command string, db *sql.DB, dir string, args []string, options ...OptionsFunc) error {
64 return run(ctx, command, db, dir, args, options...)
65}
66
67func run(ctx context.Context, command string, db *sql.DB, dir string, args []string, options ...OptionsFunc) error {
68 switch command {
69 case "up":
70 if err := UpContext(ctx, db, dir, options...); err != nil {
71 return err
72 }
73 case "up-by-one":
74 if err := UpByOneContext(ctx, db, dir, options...); err != nil {
75 return err
76 }
77 case "up-to":
78 if len(args) == 0 {
79 return fmt.Errorf("up-to must be of form: goose [OPTIONS] DRIVER DBSTRING up-to VERSION")
80 }
81
82 version, err := strconv.ParseInt(args[0], 10, 64)
83 if err != nil {
84 return fmt.Errorf("version must be a number (got '%s')", args[0])
85 }
86 if err := UpToContext(ctx, db, dir, version, options...); err != nil {
87 return err
88 }
89 case "create":
90 if len(args) == 0 {
91 return fmt.Errorf("create must be of form: goose [OPTIONS] DRIVER DBSTRING create NAME [go|sql]")
92 }
93
94 migrationType := "go"
95 if len(args) == 2 {
96 migrationType = args[1]
97 }
98 if err := Create(db, dir, args[0], migrationType); err != nil {
99 return err
100 }
101 case "down":
102 if err := DownContext(ctx, db, dir, options...); err != nil {
103 return err
104 }
105 case "down-to":
106 if len(args) == 0 {
107 return fmt.Errorf("down-to must be of form: goose [OPTIONS] DRIVER DBSTRING down-to VERSION")
108 }
109
110 version, err := strconv.ParseInt(args[0], 10, 64)
111 if err != nil {
112 return fmt.Errorf("version must be a number (got '%s')", args[0])
113 }
114 if err := DownToContext(ctx, db, dir, version, options...); err != nil {
115 return err
116 }
117 case "fix":
118 if err := Fix(dir); err != nil {
119 return err
120 }
121 case "redo":
122 if err := RedoContext(ctx, db, dir, options...); err != nil {
123 return err
124 }
125 case "reset":
126 if err := ResetContext(ctx, db, dir, options...); err != nil {
127 return err
128 }
129 case "status":
130 if err := StatusContext(ctx, db, dir, options...); err != nil {
131 return err
132 }
133 case "version":
134 if err := VersionContext(ctx, db, dir, options...); err != nil {
135 return err
136 }
137 default:
138 return fmt.Errorf("%q: no such command", command)
139 }
140 return nil
141}