-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(cmd): Update command line stuff
- Rename package from command to cmd. - Split up source files by functionality. - Add dep on github.com/rafaelespinoza/alf. - Adjust code for alf package. - Improve usage funcs. - Update README. - Remove debug flag, was for figuring out flag parsing but that's mostly figured out now.
- Loading branch information
1 parent
77a911e
commit 0c07e70
Showing
14 changed files
with
464 additions
and
396 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Package cmd contains all the CLI stuff. | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/rafaelespinoza/alf" | ||
"github.com/rafaelespinoza/godfish" | ||
) | ||
|
||
var ( | ||
// commonArgs are flag inputs for use in any subcommand. | ||
commonArgs struct { | ||
Conf string | ||
Files string | ||
} | ||
// bin is the name of the binary. | ||
bin = os.Args[0] | ||
// theDriver is passed in from a Driver's package main. | ||
theDriver godfish.Driver | ||
) | ||
|
||
// Root abstracts a top-level command from package main. | ||
type Root interface { | ||
// Run is the entry point. It should be called with os.Args[1:]. | ||
Run(ctx context.Context, args []string) error | ||
} | ||
|
||
// New constructs a top-level command with subcommands. | ||
func New(driver godfish.Driver) Root { | ||
theDriver = driver | ||
del := &alf.Delegator{ | ||
Description: "main command for " + bin, | ||
Subs: map[string]alf.Directive{ | ||
"create-migration": makeCreateMigration("create-migration"), | ||
"info": makeInfo("info"), | ||
"init": makeInit("init"), | ||
"migrate": makeMigrate("migrate"), | ||
"remigrate": makeRemigrate("remigrate"), | ||
"rollback": makeRollback("rollback"), | ||
"version": makeVersion("version"), | ||
}, | ||
} | ||
|
||
rootFlags := flag.NewFlagSet("godfish", flag.ExitOnError) | ||
rootFlags.Usage = func() { | ||
fmt.Fprintf(rootFlags.Output(), `Usage: | ||
%s [flags] command [sub-flags] | ||
Description: | ||
godfish is a database migration manager. It tracks the status of migrations | ||
by recording a timestamp in a table called "schema_migrations" in the | ||
"migration_id" column. Those timestamps correspond to SQL migration files | ||
that you write and store somewhere on the filesystem. You need to configure | ||
the path to the SQL migration files as well as the name of the driver to use | ||
(ie: postgres, mysql, potato, potato). | ||
Configuration options are set with flags or with a configuration file. Options | ||
specified via flags will take precedence over the config file. | ||
Specify database connection params with environment variable: | ||
DB_DSN= | ||
The following flags should go before the command. | ||
`, | ||
bin) | ||
printFlagDefaults(rootFlags) | ||
fmt.Fprintf( | ||
rootFlags.Output(), ` | ||
Commands: | ||
These will have their own set of flags. Put them after the command. | ||
%v | ||
Examples: | ||
%s [command] -h | ||
`, | ||
strings.Join(del.DescribeSubcommands(), "\n\t"), bin) | ||
} | ||
|
||
rootFlags.StringVar(&commonArgs.Conf, "conf", ".godfish.json", "path to godfish config file") | ||
rootFlags.StringVar( | ||
&commonArgs.Files, | ||
"files", | ||
"", | ||
"path to migration files, can also set with config file", | ||
) | ||
del.Flags = rootFlags | ||
|
||
return &alf.Root{ | ||
Delegator: del, | ||
PrePerform: func(_ context.Context) error { | ||
// Look for config file and if present, merge those values with | ||
// input flag values. | ||
var conf godfish.Config | ||
if data, ierr := os.ReadFile(commonArgs.Conf); ierr != nil { | ||
// probably no config file present, rely on arguments instead. | ||
} else if ierr = json.Unmarshal(data, &conf); ierr != nil { | ||
return ierr | ||
} | ||
if commonArgs.Files == "" && conf.PathToFiles != "" { | ||
commonArgs.Files = conf.PathToFiles | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
} | ||
|
||
// printFlagDefaults calls PrintDefaults on f. It helps make help message | ||
// formatting more consistent. | ||
func printFlagDefaults(f *flag.FlagSet) { | ||
fmt.Printf("\n%s flags:\n\n", f.Name()) | ||
f.PrintDefaults() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
|
||
"github.com/rafaelespinoza/alf" | ||
"github.com/rafaelespinoza/godfish" | ||
) | ||
|
||
func makeCreateMigration(name string) alf.Directive { | ||
var label string | ||
var reversible bool | ||
|
||
return &alf.Command{ | ||
Description: "generate migration files", | ||
Setup: func(p flag.FlagSet) *flag.FlagSet { | ||
flags := flag.NewFlagSet(name, flag.ExitOnError) | ||
flags.StringVar( | ||
&label, | ||
"name", | ||
"", | ||
"label the migration, ie: create_foos_table, update_bars_qux", | ||
) | ||
flags.BoolVar( | ||
&reversible, | ||
"reversible", | ||
true, | ||
"create a reversible migration?", | ||
) | ||
flags.Usage = func() { | ||
fmt.Printf(`Usage: %s [godfish-flags] %s [%s-flags] | ||
Generate migration files: one meant for the "forward" direction, | ||
another meant for "reverse". Optionally create a migration in the forward | ||
direction only by passing the flag "-reversible=false". The "name" flag has | ||
no effects other than on the generated filename. The output filename | ||
automatically has a "version". Timestamp format: %s. | ||
`, | ||
bin, name, name, godfish.TimeFormat, | ||
) | ||
printFlagDefaults(&p) | ||
printFlagDefaults(flags) | ||
} | ||
return flags | ||
}, | ||
Run: func(_ context.Context) error { | ||
migration, err := godfish.NewMigrationParams(label, reversible, commonArgs.Files) | ||
if err != nil { | ||
return err | ||
} | ||
return migration.GenerateFiles() | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/rafaelespinoza/alf" | ||
"github.com/rafaelespinoza/godfish" | ||
) | ||
|
||
func makeInfo(name string) alf.Directive { | ||
var direction, version string | ||
|
||
return &alf.Command{ | ||
Description: "output applied migrations, migrations to apply", | ||
Setup: func(p flag.FlagSet) *flag.FlagSet { | ||
flags := flag.NewFlagSet(name, flag.ExitOnError) | ||
flags.StringVar( | ||
&direction, | ||
"direction", | ||
"forward", | ||
"which way to look? (forward|reverse)", | ||
) | ||
flags.StringVar( | ||
&version, | ||
"version", | ||
"", | ||
fmt.Sprintf("timestamp of migration, format: %s", godfish.TimeFormat), | ||
) | ||
flags.Usage = func() { | ||
fmt.Printf(`Usage: %s [godfish-flags] %s [%s-flags] | ||
List applied migrations, preview migrations to apply. | ||
It's an introspection tool that can be used to show exactly which migration | ||
versions would be applied, in either a forward or reverse direction, before | ||
applying them. | ||
Migrations are categorized as: | ||
- Available. Known to godfish, either already applied, or can be applied. | ||
- Applied. They have been migrated against the DB. | ||
- To Apply. They haven't been applied yet, but can be. | ||
It also takes a "direction" flag if you want to know what would be applied | ||
in a rollback or remigrate operation. The "version" flag can be used to | ||
limit or extend the range of migrations to apply. | ||
`, | ||
bin, name, name) | ||
printFlagDefaults(&p) | ||
printFlagDefaults(flags) | ||
} | ||
return flags | ||
}, | ||
Run: func(_ context.Context) error { | ||
direction := whichDirection(direction) | ||
return godfish.Info(theDriver, commonArgs.Files, direction, version) | ||
}, | ||
} | ||
} | ||
|
||
func whichDirection(input string) (direction godfish.Direction) { | ||
direction = godfish.DirForward | ||
d := strings.ToLower(input) | ||
if strings.HasPrefix(d, "rev") || strings.HasPrefix(d, "back") { | ||
direction = godfish.DirReverse | ||
} | ||
return | ||
} |
Oops, something went wrong.