diff --git a/CHANGELOG.md b/CHANGELOG.md index e26d65a1a..31dd00ec9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### To be Released +* chore(deps): Upgrade urfave/cli to v2 [#774](https://github.com/Scalingo/cli/pull/774) + Caution: scalingo commands must come before any flag or argument. For example + `scalingo --app hello-world restart` must be rewritten `scalingo restart --app hello-world` + # 1.24.2 * fix(releases): Correctly auto generate changelog [#772](https://github.com/Scalingo/cli/pull/772) diff --git a/README.md b/README.md index 32e15ab6a..dcc70d8d1 100644 --- a/README.md +++ b/README.md @@ -300,7 +300,7 @@ Pushing the tag triggers a GitHub Action which builds the cross-platform binarie When the GitHub Action finished, restart the Scalingo application `cli-download-service`: ```shell -scalingo --region osc-fr1 --app cli-download-service restart +scalingo restart --region osc-fr1 --app cli-download-service ``` It serves as cache between GitHub and our customers for a more efficient check of what is the new CLI version. diff --git a/cmd/addon_providers_list.go b/cmd/addon_providers_list.go index 61565e8cd..05cb26f7f 100644 --- a/cmd/addon_providers_list.go +++ b/cmd/addon_providers_list.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/addon_providers" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,10 +13,11 @@ var ( Category: "Addons - Global", Description: "List all addons you can add to your app.", Usage: "List all addons", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if err := addon_providers.List(); err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "addons-list") diff --git a/cmd/addons.go b/cmd/addons.go index b82fafca3..777174af0 100644 --- a/cmd/addons.go +++ b/cmd/addons.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/addons" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,16 +13,16 @@ var ( Name: "addons", Category: "Addons", Usage: "List used add-ons", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` List all addons used by your app: $ scalingo -a myapp addons # See also 'addons-add' and 'addons-remove' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err = addons.List(currentApp) } else { cli.ShowCommandHelp(c, "addons") @@ -31,6 +31,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "addons") @@ -39,24 +40,25 @@ var ( AddonsAddCommand = cli.Command{ Name: "addons-add", Category: "Addons", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Provision an add-on for your application", Description: ` Provision an add-on for your application: $ scalingo -a myapp addons-add # See also 'addons-list' and 'addons-plans' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 2 { - err = addons.Provision(currentApp, c.Args()[0], c.Args()[1]) + if c.Args().Len() == 2 { + err = addons.Provision(currentApp, c.Args().First(), c.Args().Slice()[1]) } else { cli.ShowCommandHelp(c, "addons-add") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "addons-add") @@ -66,24 +68,25 @@ var ( AddonsRemoveCommand = cli.Command{ Name: "addons-remove", Category: "Addons", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Remove an existing addon from your app", Description: ` Remove an existing addon from your app: $ scalingo -a myapp addons-remove # See also 'addons' and 'addons-add' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 1 { - err = addons.Destroy(currentApp, c.Args()[0]) + if c.Args().Len() == 1 { + err = addons.Destroy(currentApp, c.Args().First()) } else { cli.ShowCommandHelp(c, "addons-remove") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "addons-remove") @@ -93,24 +96,25 @@ var ( AddonsUpgradeCommand = cli.Command{ Name: "addons-upgrade", Category: "Addons", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Upgrade or downgrade an add-on attached to your app", Description: ` Upgrade an addon attached to your app: $ scalingo -a myapp addons-upgrade # See also 'addons-plans' and 'addons-remove' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 2 { - err = addons.Upgrade(currentApp, c.Args()[0], c.Args()[1]) + if c.Args().Len() == 2 { + err = addons.Upgrade(currentApp, c.Args().First(), c.Args().Slice()[1]) } else { cli.ShowCommandHelp(c, "addons-upgrade") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "addons-upgrade") @@ -121,25 +125,26 @@ var ( Name: "addons-info", Category: "Addons", Usage: "Display information about an add-on attached to your app", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` Display information about an add-on attached to your app: $ scalingo --app my-app addons-info --addon # See also 'addons' and 'addons-upgrade' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "addons-info") - return + return nil } currentApp := detect.CurrentApp(c) - currentAddon := c.Args()[0] + currentAddon := c.Args().First() err := addons.Info(currentApp, currentAddon) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "addons-info") diff --git a/cmd/addons_providers_plans_list.go b/cmd/addons_providers_plans_list.go index a9fde185c..a21f42e43 100644 --- a/cmd/addons_providers_plans_list.go +++ b/cmd/addons_providers_plans_list.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/addon_providers" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,14 +13,15 @@ var ( Category: "Addons - Global", Description: "List the plans for an addon.\n Example:\n scalingo addon-plans scalingo-mongodb", Usage: "List plans", - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "addons-plans") - return + return nil } - if err := addon_providers.Plans(c.Args()[0]); err != nil { + if err := addon_providers.Plans(c.Args().First()); err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.AddonsPlansAutoComplete(c) diff --git a/cmd/alerts.go b/cmd/alerts.go index 43bd871d1..9d03a595b 100644 --- a/cmd/alerts.go +++ b/cmd/alerts.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/alerts" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,7 +13,7 @@ var ( alertsListCommand = cli.Command{ Name: "alerts", Category: "Alerts", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "List the alerts of an application", Description: `List all the alerts of an application: @@ -21,16 +21,17 @@ var ( # See also commands 'alerts-add', 'alerts-update' and 'alerts-remove'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "alerts") - return + return nil } err := alerts.List(detect.CurrentApp(c)) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "alerts") @@ -41,14 +42,14 @@ var ( Name: "alerts-add", Category: "Alerts", Usage: "Add an alert to an application", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "container-type, c", Usage: "Specify the container type affected by the alert"}, - cli.StringFlag{Name: "metric, m", Usage: "Specify the metric you want the alert to apply on"}, - cli.Float64Flag{Name: "limit, l", Usage: "Target value for the metric the alert will maintain"}, - cli.DurationFlag{Name: "duration-before-trigger", Usage: "Alert is activated if the value is above the limit for the given duration"}, - cli.DurationFlag{Name: "remind-every, r", Usage: "Send the alert at regular interval when activated"}, - cli.BoolFlag{Name: "below, b", Usage: "Send the alert when metric value is *below* the limit"}, - cli.StringSliceFlag{Name: "notifiers, n", Usage: "notifiers' id notified when an alert is activated. Can be specified multiple times."}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "container-type", Aliases: []string{"c"}, Usage: "Specify the container type affected by the alert"}, + &cli.StringFlag{Name: "metric", Aliases: []string{"m"}, Usage: "Specify the metric you want the alert to apply on"}, + &cli.Float64Flag{Name: "limit", Aliases: []string{"l"}, Usage: "Target value for the metric the alert will maintain"}, + &cli.DurationFlag{Name: "duration-before-trigger", Usage: "Alert is activated if the value is above the limit for the given duration"}, + &cli.DurationFlag{Name: "remind-every", Aliases: []string{"r"}, Usage: "Send the alert at regular interval when activated"}, + &cli.BoolFlag{Name: "below", Aliases: []string{"b"}, Usage: "Send the alert when metric value is *below* the limit"}, + &cli.StringSliceFlag{Name: "notifiers", Aliases: []string{"n"}, Usage: "notifiers' id notified when an alert is activated. Can be specified multiple times."}, }, Description: `Add an alert to an application metric. @@ -61,13 +62,13 @@ var ( # See also commands 'alerts-update' and 'alerts-remove' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if !isValidAlertAddOpts(c) { err := cli.ShowCommandHelp(c, "alerts-add") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) @@ -85,6 +86,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "alerts-add") @@ -95,15 +97,15 @@ var ( Name: "alerts-update", Category: "Alerts", Usage: "Update an alert", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "container-type, c", Usage: "Specify the container type affected by the alert"}, - cli.StringFlag{Name: "metric, m", Usage: "Specify the metric you want the alert to apply on"}, - cli.Float64Flag{Name: "limit, l", Usage: "Target value for the metric the alert will maintain"}, - cli.DurationFlag{Name: "duration-before-trigger", Usage: "Alert is activated if the value is above the limit for the given duration"}, - cli.DurationFlag{Name: "remind-every, r", Usage: "Send the alert at regular interval when activated"}, - cli.BoolFlag{Name: "below, b", Usage: "Send the alert when metric value is *below* the limit"}, - cli.BoolFlag{Name: "disabled, d", Usage: "Disable the alert (nothing is sent)"}, - cli.StringSliceFlag{Name: "notifiers, n", Usage: "notifiers' id notified when an alert is activated. Can be specified multiple times."}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "container-type", Aliases: []string{"c"}, Usage: "Specify the container type affected by the alert"}, + &cli.StringFlag{Name: "metric", Aliases: []string{"m"}, Usage: "Specify the metric you want the alert to apply on"}, + &cli.Float64Flag{Name: "limit", Aliases: []string{"l"}, Usage: "Target value for the metric the alert will maintain"}, + &cli.DurationFlag{Name: "duration-before-trigger", Usage: "Alert is activated if the value is above the limit for the given duration"}, + &cli.DurationFlag{Name: "remind-every", Aliases: []string{"r"}, Usage: "Send the alert at regular interval when activated"}, + &cli.BoolFlag{Name: "below", Aliases: []string{"b"}, Usage: "Send the alert when metric value is *below* the limit"}, + &cli.BoolFlag{Name: "disabled", Aliases: []string{"d"}, Usage: "Disable the alert (nothing is sent)"}, + &cli.StringSliceFlag{Name: "notifiers", Aliases: []string{"n"}, Usage: "notifiers' id notified when an alert is activated. Can be specified multiple times."}, }, Description: `Update an existing alert. @@ -116,16 +118,16 @@ var ( # See also 'alerts-disable' and 'alerts-enable' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { err := cli.ShowCommandHelp(c, "alerts-update") if err != nil { errorQuit(err) } - return + return nil } - alertID := c.Args()[0] + alertID := c.Args().First() currentApp := detect.CurrentApp(c) params := scalingo.AlertUpdateParams{} if c.IsSet("c") { @@ -165,6 +167,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "alerts-add") @@ -175,7 +178,7 @@ var ( Name: "alerts-enable", Category: "Alerts", Usage: "Enable an alert", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Enable an alert. Example @@ -183,23 +186,24 @@ var ( # See also commands 'alerts-update' and 'alerts-remove' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { err := cli.ShowCommandHelp(c, "alerts-enable") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) disabled := false - err := alerts.Update(currentApp, c.Args()[0], scalingo.AlertUpdateParams{ + err := alerts.Update(currentApp, c.Args().First(), scalingo.AlertUpdateParams{ Disabled: &disabled, }) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "alerts-enable") @@ -210,7 +214,7 @@ var ( Name: "alerts-disable", Category: "Alerts", Usage: "Disable an alert", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Disable an alert. Example @@ -218,23 +222,24 @@ var ( # See also commands 'alerts-update' and 'alerts-remove' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { err := cli.ShowCommandHelp(c, "alerts-disable") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) disabled := true - err := alerts.Update(currentApp, c.Args()[0], scalingo.AlertUpdateParams{ + err := alerts.Update(currentApp, c.Args().First(), scalingo.AlertUpdateParams{ Disabled: &disabled, }) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "alerts-disable") @@ -245,7 +250,7 @@ var ( Name: "alerts-remove", Category: "Alerts", Usage: "Remove an alert from an application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Remove an alert. Example @@ -253,17 +258,18 @@ var ( # See also commands 'alerts-add' and 'alerts-update' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "alerts-remove") - return + return nil } currentApp := detect.CurrentApp(c) - err := alerts.Remove(currentApp, c.Args()[0]) + err := alerts.Remove(currentApp, c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "alerts-remove") @@ -272,7 +278,7 @@ var ( ) func isValidAlertAddOpts(c *cli.Context) bool { - if len(c.Args()) > 0 { + if c.Args().Len() > 0 { return false } for _, opt := range []string{"container-type", "metric", "limit"} { diff --git a/cmd/apps.go b/cmd/apps.go index 948a9b51c..046796672 100644 --- a/cmd/apps.go +++ b/cmd/apps.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -14,10 +14,11 @@ var ( Category: "Global", Description: "List your apps and give some details about them", Usage: "List your apps", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if err := apps.List(); err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "apps") @@ -27,18 +28,19 @@ var ( appsInfoCommand = cli.Command{ Name: "apps-info", Category: "App Management", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Display the application information", Description: `Display various application information such as the force HTTPS status, the stack configured, sticky sessions, etc. Example: scalingo apps-info --app my-app `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) if err := apps.Info(currentApp); err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "apps-info") diff --git a/cmd/autocomplete/addons_add.go b/cmd/autocomplete/addons_add.go index dbaf997e2..9371482a4 100644 --- a/cmd/autocomplete/addons_add.go +++ b/cmd/autocomplete/addons_add.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/addons_plans.go b/cmd/autocomplete/addons_plans.go index 7d01bc033..449048de9 100644 --- a/cmd/autocomplete/addons_plans.go +++ b/cmd/autocomplete/addons_plans.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/addons_remove.go b/cmd/autocomplete/addons_remove.go index 9b5d2d58d..577c97924 100644 --- a/cmd/autocomplete/addons_remove.go +++ b/cmd/autocomplete/addons_remove.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/addons_upgrade.go b/cmd/autocomplete/addons_upgrade.go index 4af4c9592..3ba920ff6 100644 --- a/cmd/autocomplete/addons_upgrade.go +++ b/cmd/autocomplete/addons_upgrade.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/cmdflags.go b/cmd/autocomplete/cmdflags.go index 56661de6c..9f8fe5c6e 100644 --- a/cmd/autocomplete/cmdflags.go +++ b/cmd/autocomplete/cmdflags.go @@ -3,11 +3,11 @@ package autocomplete import ( "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func CmdFlagsAutoComplete(c *cli.Context, command string) error { - var cmd cli.Command + var cmd *cli.Command for _, cmd = range c.App.Commands { if cmd.Name == command { break diff --git a/cmd/autocomplete/collaborators_add.go b/cmd/autocomplete/collaborators_add.go index b28011d1f..e2afdd3fe 100644 --- a/cmd/autocomplete/collaborators_add.go +++ b/cmd/autocomplete/collaborators_add.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/collaborators_remove.go b/cmd/autocomplete/collaborators_remove.go index a5bec9e2b..bc185a94a 100644 --- a/cmd/autocomplete/collaborators_remove.go +++ b/cmd/autocomplete/collaborators_remove.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/current_app.go b/cmd/autocomplete/current_app.go index b26e58c54..a4b38edd4 100644 --- a/cmd/autocomplete/current_app.go +++ b/cmd/autocomplete/current_app.go @@ -3,7 +3,7 @@ package autocomplete import ( "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/detect" "github.com/Scalingo/cli/utils" @@ -27,7 +27,7 @@ func CurrentAppCompletion(c *cli.Context) string { appName = os.Getenv("SCALINGO_APP") } if dir, ok := utils.DetectGit(); appName == "" && ok { - appName, err = detect.GetAppNameFromGitRemote(dir, c.GlobalString("remote")) + appName, err = detect.GetAppNameFromGitRemote(dir, c.String("remote")) if err != nil { debug.Println(err) } diff --git a/cmd/autocomplete/db_tunnel.go b/cmd/autocomplete/db_tunnel.go index 2a53b2177..19659c292 100644 --- a/cmd/autocomplete/db_tunnel.go +++ b/cmd/autocomplete/db_tunnel.go @@ -6,7 +6,7 @@ import ( "regexp" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/deployments.go b/cmd/autocomplete/deployments.go index ee641242a..6e5ebfe18 100644 --- a/cmd/autocomplete/deployments.go +++ b/cmd/autocomplete/deployments.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/domains_remove.go b/cmd/autocomplete/domains_remove.go index 8d6d94301..f609b7be1 100644 --- a/cmd/autocomplete/domains_remove.go +++ b/cmd/autocomplete/domains_remove.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/env_unset.go b/cmd/autocomplete/env_unset.go index fc2952f4b..368cf8b30 100644 --- a/cmd/autocomplete/env_unset.go +++ b/cmd/autocomplete/env_unset.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/flag_app.go b/cmd/autocomplete/flag_app.go index 8aea5b1fd..f1b2f8ee7 100644 --- a/cmd/autocomplete/flag_app.go +++ b/cmd/autocomplete/flag_app.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/go-scalingo/v4/debug" ) diff --git a/cmd/autocomplete/flag_remote.go b/cmd/autocomplete/flag_remote.go index 707bb0e2f..815c6c904 100644 --- a/cmd/autocomplete/flag_remote.go +++ b/cmd/autocomplete/flag_remote.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/utils" ) diff --git a/cmd/autocomplete/flags.go b/cmd/autocomplete/flags.go index dca9455d0..84f1bb976 100644 --- a/cmd/autocomplete/flags.go +++ b/cmd/autocomplete/flags.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func getFlagByName(lastArg string, flags []cli.Flag) (bool, cli.Flag) { @@ -43,7 +43,7 @@ func CountFlags(flags []string) int { } func GetFlagNames(flag cli.Flag) []string { - names := strings.Split(flag.GetName(), ",") + names := strings.Split(flag.Names()[0], ",") for i := range names { if i == 0 { @@ -61,8 +61,7 @@ func DisplayFlags(flags []cli.Flag) { found, lastFlag := getFlagByName(lastArg, flags) isBoolFlag := false - switch lastFlag.(type) { - case cli.BoolFlag, cli.BoolTFlag: + if _, ok := lastFlag.(*cli.BoolFlag); ok { isBoolFlag = true && found } @@ -72,7 +71,7 @@ func DisplayFlags(flags []cli.Flag) { isSliceFlag := false switch flag.(type) { - case cli.IntSliceFlag, cli.StringSliceFlag: + case *cli.IntSliceFlag, *cli.StringSliceFlag: isSliceFlag = true } if CountFlags(names) == 0 || isSliceFlag { diff --git a/cmd/autocomplete/help.go b/cmd/autocomplete/help.go index f005b507f..2b08e50c0 100644 --- a/cmd/autocomplete/help.go +++ b/cmd/autocomplete/help.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func HelpAutoComplete(c *cli.Context) error { diff --git a/cmd/autocomplete/keys_remove.go b/cmd/autocomplete/keys_remove.go index 9071ea915..ee9e272ba 100644 --- a/cmd/autocomplete/keys_remove.go +++ b/cmd/autocomplete/keys_remove.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/log_drains_remove.go b/cmd/autocomplete/log_drains_remove.go index 835b71317..172ef35ce 100644 --- a/cmd/autocomplete/log_drains_remove.go +++ b/cmd/autocomplete/log_drains_remove.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/notifiers_remove.go b/cmd/autocomplete/notifiers_remove.go index 959096e1c..964a5352f 100644 --- a/cmd/autocomplete/notifiers_remove.go +++ b/cmd/autocomplete/notifiers_remove.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/region_migrations.go b/cmd/autocomplete/region_migrations.go index 5377d1567..8da5b83e1 100644 --- a/cmd/autocomplete/region_migrations.go +++ b/cmd/autocomplete/region_migrations.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" errgo "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/restart.go b/cmd/autocomplete/restart.go index e5c0afe84..e64dcd0cf 100644 --- a/cmd/autocomplete/restart.go +++ b/cmd/autocomplete/restart.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/scale.go b/cmd/autocomplete/scale.go index 57f84445b..5c97b58ad 100644 --- a/cmd/autocomplete/scale.go +++ b/cmd/autocomplete/scale.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autocomplete/stacks.go b/cmd/autocomplete/stacks.go index b51ee0fb7..7e8334462 100644 --- a/cmd/autocomplete/stacks.go +++ b/cmd/autocomplete/stacks.go @@ -3,7 +3,7 @@ package autocomplete import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" diff --git a/cmd/autoscalers.go b/cmd/autoscalers.go index 5177f84e2..ca32472ef 100644 --- a/cmd/autoscalers.go +++ b/cmd/autoscalers.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/autoscalers" "github.com/Scalingo/cli/cmd/autocomplete" @@ -14,18 +14,19 @@ var ( Name: "autoscalers", Category: "Autoscalers", Usage: "List the autoscalers of an application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: "List all the autoscalers of an application and display information about them.", - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "autoscalers") - return + return nil } err := autoscalers.List(detect.CurrentApp(c)) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "autoscalers") @@ -36,12 +37,12 @@ var ( Name: "autoscalers-add", Category: "Autoscalers", Usage: "Add an autoscaler to an application", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "container-type, c", Usage: "Specify the container type affected by the autoscaler"}, - cli.StringFlag{Name: "metric, m", Usage: "Specify the metric you want the autoscaling to apply on"}, - cli.Float64Flag{Name: "target, t", Usage: "Target value for the metric the autoscaler will maintain"}, - cli.IntFlag{Name: "min-containers", Usage: "lower limit the autoscaler will never scale below"}, - cli.IntFlag{Name: "max-containers", Usage: "upper limit the autoscaler will never scale above"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "container-type", Aliases: []string{"c"}, Usage: "Specify the container type affected by the autoscaler"}, + &cli.StringFlag{Name: "metric", Aliases: []string{"m"}, Usage: "Specify the metric you want the autoscaling to apply on"}, + &cli.Float64Flag{Name: "target", Aliases: []string{"t"}, Usage: "Target value for the metric the autoscaler will maintain"}, + &cli.IntFlag{Name: "min-containers", Usage: "lower limit the autoscaler will never scale below"}, + &cli.IntFlag{Name: "max-containers", Usage: "upper limit the autoscaler will never scale above"}, }, Description: `Add an autoscaler to an application. It will automatically scale the application up or down depending on the target defined for the given metric. @@ -50,13 +51,13 @@ var ( Example scalingo --app my-app autoscalers-add --container-type web --metric cpu --target 0.75 --min-containers 2 --max-containers 4 `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if !isValidAutoscalerAddOpts(c) { err := cli.ShowCommandHelp(c, "autoscalers-add") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) @@ -70,6 +71,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "autoscalers-add") @@ -80,13 +82,13 @@ var ( Name: "autoscalers-update", Category: "Autoscalers", Usage: "Update an autoscaler", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "container-type, c", Usage: "Specify the container type affected by the autoscaler"}, - cli.StringFlag{Name: "metric, m", Usage: "Specify the metric you want the autoscaling to apply on"}, - cli.Float64Flag{Name: "target, t", Usage: "Target value for the metric the autoscaler will maintain"}, - cli.IntFlag{Name: "min-containers", Usage: "lower limit the autoscaler will never scale below"}, - cli.IntFlag{Name: "max-containers", Usage: "upper limit the autoscaler will never scale above"}, - cli.BoolFlag{Name: "disabled, d", Usage: "disable/enable the given autoscaler"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "container-type", Aliases: []string{"c"}, Usage: "Specify the container type affected by the autoscaler"}, + &cli.StringFlag{Name: "metric", Aliases: []string{"m"}, Usage: "Specify the metric you want the autoscaling to apply on"}, + &cli.Float64Flag{Name: "target", Aliases: []string{"t"}, Usage: "Target value for the metric the autoscaler will maintain"}, + &cli.IntFlag{Name: "min-containers", Usage: "lower limit the autoscaler will never scale below"}, + &cli.IntFlag{Name: "max-containers", Usage: "upper limit the autoscaler will never scale above"}, + &cli.BoolFlag{Name: "disabled", Aliases: []string{"d"}, Usage: "disable/enable the given autoscaler"}, }, Description: `Update an autoscaler. @@ -96,13 +98,13 @@ var ( scalingo --app my-app autoscalers-update --container-type web --max-containers 5 scalingo --app my-app autoscalers-update --container-type web --metric p95_response_time --target 67 `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 || !c.IsSet("c") { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 || !c.IsSet("c") { err := cli.ShowCommandHelp(c, "autoscalers-update") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) @@ -131,6 +133,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "autoscalers-update") @@ -141,29 +144,30 @@ var ( Name: "autoscalers-enable", Category: "Autoscalers", Usage: "Enable an autoscaler", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Enable an autoscaler. Example scalingo --app my-app autoscalers-enable web `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { err := cli.ShowCommandHelp(c, "autoscalers-enable") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) disabled := false - err := autoscalers.Update(currentApp, c.Args()[0], scalingo.AutoscalerUpdateParams{ + err := autoscalers.Update(currentApp, c.Args().First(), scalingo.AutoscalerUpdateParams{ Disabled: &disabled, }) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "autoscalers-enable") @@ -174,29 +178,30 @@ var ( Name: "autoscalers-disable", Category: "Autoscalers", Usage: "Disable an autoscaler", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Disable an autoscaler. Example scalingo --app my-app autoscalers-disable web `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { err := cli.ShowCommandHelp(c, "autoscalers-disable") if err != nil { errorQuit(err) } - return + return nil } currentApp := detect.CurrentApp(c) disabled := true - err := autoscalers.Update(currentApp, c.Args()[0], scalingo.AutoscalerUpdateParams{ + err := autoscalers.Update(currentApp, c.Args().First(), scalingo.AutoscalerUpdateParams{ Disabled: &disabled, }) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "autoscalers-disable") @@ -207,22 +212,23 @@ var ( Name: "autoscalers-remove", Category: "Autoscalers", Usage: "Remove an autoscaler from an application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Remove an autoscaler for a container type of an application Example scalingo --app my-app autoscalers-remove web`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "autoscalers-remove") - return + return nil } currentApp := detect.CurrentApp(c) - err := autoscalers.Remove(currentApp, c.Args()[0]) + err := autoscalers.Remove(currentApp, c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "autoscalers-remove") @@ -231,7 +237,7 @@ var ( ) func isValidAutoscalerAddOpts(c *cli.Context) bool { - if len(c.Args()) > 0 { + if c.Args().Len() > 0 { return false } for _, opt := range []string{ diff --git a/cmd/backups.go b/cmd/backups.go index b8bc91d81..11d99648c 100644 --- a/cmd/backups.go +++ b/cmd/backups.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/db" "github.com/Scalingo/cli/detect" @@ -16,13 +16,13 @@ var ( Name: "backups", Category: "Addons", Usage: "List backups for an addon", - Flags: []cli.Flag{appFlag, addonFlag}, + Flags: []cli.Flag{&appFlag, &addonFlag}, Description: ` List all available backups for an addon: $ scalingo --app my-app --addon addon_uuid backups # See also 'addons' and 'backups-download' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) addonName := addonNameFromFlags(c) if addonName == "" { @@ -33,6 +33,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, } @@ -40,12 +41,12 @@ var ( Name: "backups-create", Category: "Addons", Usage: "Ask for a new backup", - Flags: []cli.Flag{appFlag, addonFlag}, + Flags: []cli.Flag{&appFlag, &addonFlag}, Description: ` Ask for a new backup of your addon: $ scalingo --app my-app --addon addon_uuid backups-download --backup my_backup # See also 'backups' and 'addons'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) addonName := addonNameFromFlags(c) if addonName == "" { @@ -57,6 +58,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, } @@ -64,21 +66,24 @@ var ( Name: "backups-download", Category: "Addons", Usage: "Download a backup", - Flags: []cli.Flag{appFlag, addonFlag, cli.StringFlag{ - Name: "backup, b", - Usage: "ID of the backup to download", - }, cli.StringFlag{ - Name: "output, o", - Usage: "Output file (- for stdout)", - }, cli.BoolFlag{ - Name: "silent, s", - Usage: "Do not show progress bar and loading messages", + Flags: []cli.Flag{&appFlag, &addonFlag, &cli.StringFlag{ + Name: "backup", + Aliases: []string{"b"}, + Usage: "ID of the backup to download", + }, &cli.StringFlag{ + Name: "output", + Aliases: []string{"o"}, + Usage: "Output file (- for stdout)", + }, &cli.BoolFlag{ + Name: "silent", + Aliases: []string{"s"}, + Usage: "Do not show progress bar and loading messages", }}, Description: ` Download a specific backup: $ scalingo --app my-app --addon addon_uuid backups-download --backup my_backup # See also 'backups' and 'addons'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) addonName := addonNameFromFlags(c) if addonName == "" { @@ -95,6 +100,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, } diff --git a/cmd/changelog.go b/cmd/changelog.go index 4e61d0318..0b8413788 100644 --- a/cmd/changelog.go +++ b/cmd/changelog.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/update" @@ -15,11 +15,12 @@ var ( Description: `Show the Scalingo CLI changelog from last version Example 'scalingo changelog'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := update.ShowLastChangelog() if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "changelog") diff --git a/cmd/collaborators.go b/cmd/collaborators.go index aca5c5fd9..ecd6913c2 100644 --- a/cmd/collaborators.go +++ b/cmd/collaborators.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/collaborators" @@ -13,11 +13,11 @@ var ( Name: "collaborators", Category: "Collaborators", Usage: "List the collaborators of an application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: "List all the collaborators of an application and display information about them.", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "collaborators") } else { err := collaborators.List(currentApp) @@ -25,6 +25,7 @@ var ( errorQuit(err) } } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "collaborators") @@ -35,18 +36,19 @@ var ( Name: "collaborators-add", Category: "Collaborators", Usage: "Invite someone to work on an application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: "Invite someone to collaborate on an application, an invitation will be sent to the given email\n scalingo -a myapp collaborators-add user@example.com", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "collaborators-add") } else { - err := collaborators.Add(currentApp, c.Args()[0]) + err := collaborators.Add(currentApp, c.Args().First()) if err != nil { errorQuit(err) } } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "collaborators-add") @@ -58,18 +60,19 @@ var ( Name: "collaborators-remove", Category: "Collaborators", Usage: "Revoke permission to collaborate on an application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: "Revoke the invitation of collaboration to the given email\n scalingo -a myapp collaborators-remove user@example.com", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "collaborators-remove") } else { - err := collaborators.Remove(currentApp, c.Args()[0]) + err := collaborators.Remove(currentApp, c.Args().First()) if err != nil { errorQuit(err) } } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "collaborators-remove") diff --git a/cmd/commands.go b/cmd/commands.go index c671a398f..9e0199329 100644 --- a/cmd/commands.go +++ b/cmd/commands.go @@ -5,7 +5,7 @@ import ( "github.com/Scalingo/go-scalingo/v4/debug" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/config" "github.com/Scalingo/cli/detect" @@ -14,21 +14,21 @@ import ( ) type AppCommands struct { - commands []cli.Command + commands []*cli.Command } type Command struct { - cli.Command + *cli.Command // Regional flag not available if Global is true Global bool } func (cmds *AppCommands) addCommand(cmd Command) { if !cmd.Global { - regionFlag := cli.StringFlag{Name: "region", Value: "", Usage: "Name of the region to use"} + regionFlag := &cli.StringFlag{Name: "region", Value: "", Usage: "Name of the region to use"} cmd.Command.Flags = append(cmd.Command.Flags, regionFlag) - action := cmd.Command.Action.(func(c *cli.Context)) - cmd.Command.Action = func(c *cli.Context) { + action := cmd.Command.Action + cmd.Command.Action = func(c *cli.Context) error { token := os.Getenv("SCALINGO_API_TOKEN") currentUser, err := config.C.CurrentUser() @@ -45,10 +45,7 @@ func (cmds *AppCommands) addCommand(cmd Command) { if err != nil { errorQuit(err) } - currentRegion := c.GlobalString("region") - if currentRegion == "" { - currentRegion = c.String("region") - } + currentRegion := c.String("region") // Detecting Region from git remote if currentRegion == "" { @@ -65,6 +62,8 @@ func (cmds *AppCommands) addCommand(cmd Command) { config.C.ScalingoRegion = currentRegion } action(c) + + return nil } } cmds.commands = append(cmds.commands, cmd.Command) @@ -81,7 +80,7 @@ func getDefaultRegion(regionsCache config.RegionsCache) scalingo.Region { return defaultRegion } -func (cmds *AppCommands) Commands() []cli.Command { +func (cmds *AppCommands) Commands() []*cli.Command { return cmds.commands } @@ -97,176 +96,176 @@ func NewAppCommands() *AppCommands { } var ( - regionalCommands = []cli.Command{ + regionalCommands = []*cli.Command{ // Apps - appsCommand, - CreateCommand, - DestroyCommand, - renameCommand, - appsInfoCommand, - openCommand, - dashboardCommand, + &appsCommand, + &CreateCommand, + &DestroyCommand, + &renameCommand, + &appsInfoCommand, + &openCommand, + &dashboardCommand, // Apps Actions - logsCommand, - logsArchivesCommand, - runCommand, - oneOffStopCommand, + &logsCommand, + &logsArchivesCommand, + &runCommand, + &oneOffStopCommand, // Apps Process Actions - psCommand, - scaleCommand, - RestartCommand, + &psCommand, + &scaleCommand, + &RestartCommand, // Routing Settings - forceHTTPSCommand, - stickySessionCommand, - routerLogsCommand, - setCanonicalDomainCommand, - unsetCanonicalDomainCommand, + &forceHTTPSCommand, + &stickySessionCommand, + &routerLogsCommand, + &setCanonicalDomainCommand, + &unsetCanonicalDomainCommand, // Events - UserTimelineCommand, - TimelineCommand, + &UserTimelineCommand, + &TimelineCommand, // Environment - envCommand, - envGetCommand, - envSetCommand, - envUnsetCommand, + &envCommand, + &envGetCommand, + &envSetCommand, + &envUnsetCommand, // Domains - DomainsListCommand, - DomainsAddCommand, - DomainsRemoveCommand, - DomainsSSLCommand, + &DomainsListCommand, + &DomainsAddCommand, + &DomainsRemoveCommand, + &DomainsSSLCommand, // Deployments - deploymentsListCommand, - deploymentLogCommand, - deploymentFollowCommand, - deploymentDeployCommand, - deploymentCacheResetCommand, + &deploymentsListCommand, + &deploymentLogCommand, + &deploymentFollowCommand, + &deploymentDeployCommand, + &deploymentCacheResetCommand, // Collaborators - CollaboratorsListCommand, - CollaboratorsAddCommand, - CollaboratorsRemoveCommand, + &CollaboratorsListCommand, + &CollaboratorsAddCommand, + &CollaboratorsRemoveCommand, // Stacks - stacksListCommand, - stacksSetCommand, + &stacksListCommand, + &stacksSetCommand, // Addons - AddonProvidersListCommand, - AddonProvidersPlansCommand, - AddonsListCommand, - AddonsAddCommand, - AddonsRemoveCommand, - AddonsUpgradeCommand, - AddonsInfoCommand, + &AddonProvidersListCommand, + &AddonProvidersPlansCommand, + &AddonsListCommand, + &AddonsAddCommand, + &AddonsRemoveCommand, + &AddonsUpgradeCommand, + &AddonsInfoCommand, // Integration Link - integrationLinkShowCommand, - integrationLinkCreateCommand, - integrationLinkUpdateCommand, - integrationLinkDeleteCommand, - integrationLinkManualDeployCommand, - integrationLinkManualReviewAppCommand, + &integrationLinkShowCommand, + &integrationLinkCreateCommand, + &integrationLinkUpdateCommand, + &integrationLinkDeleteCommand, + &integrationLinkManualDeployCommand, + &integrationLinkManualReviewAppCommand, // Review Apps - reviewAppsShowCommand, + &reviewAppsShowCommand, // Notifiers - NotifiersListCommand, - NotifiersDetailsCommand, - NotifiersAddCommand, - NotifiersUpdateCommand, - NotifiersRemoveCommand, + &NotifiersListCommand, + &NotifiersDetailsCommand, + &NotifiersAddCommand, + &NotifiersUpdateCommand, + &NotifiersRemoveCommand, // Notification platforms - NotificationPlatformListCommand, + &NotificationPlatformListCommand, // DB Access - DbTunnelCommand, - RedisConsoleCommand, - MongoConsoleCommand, - MySQLConsoleCommand, - PgSQLConsoleCommand, - InfluxDBConsoleCommand, + &DbTunnelCommand, + &RedisConsoleCommand, + &MongoConsoleCommand, + &MySQLConsoleCommand, + &PgSQLConsoleCommand, + &InfluxDBConsoleCommand, // Databases - databaseBackupsConfig, + &databaseBackupsConfig, // Backups - backupsListCommand, - backupsCreateCommand, - backupsDownloadCommand, - backupDownloadCommand, + &backupsListCommand, + &backupsCreateCommand, + &backupsDownloadCommand, + &backupDownloadCommand, // Alerts - alertsListCommand, - alertsAddCommand, - alertsUpdateCommand, - alertsEnableCommand, - alertsDisableCommand, - alertsRemoveCommand, + &alertsListCommand, + &alertsAddCommand, + &alertsUpdateCommand, + &alertsEnableCommand, + &alertsDisableCommand, + &alertsRemoveCommand, // Stats - StatsCommand, + &StatsCommand, // Autoscalers - autoscalersListCommand, - autoscalersAddCommand, - autoscalersRemoveCommand, - autoscalersUpdateCommand, - autoscalersDisableCommand, - autoscalersEnableCommand, + &autoscalersListCommand, + &autoscalersAddCommand, + &autoscalersRemoveCommand, + &autoscalersUpdateCommand, + &autoscalersDisableCommand, + &autoscalersEnableCommand, // Migrations - migrationCreateCommand, - migrationRunCommand, - migrationAbortCommand, - migrationListCommand, - migrationFollowCommand, + &migrationCreateCommand, + &migrationRunCommand, + &migrationAbortCommand, + &migrationListCommand, + &migrationFollowCommand, // Log drains - logDrainsAddCommand, - logDrainsListCommand, - logDrainsRemoveCommand, + &logDrainsAddCommand, + &logDrainsListCommand, + &logDrainsRemoveCommand, - gitSetup, - gitShow, + &gitSetup, + &gitShow, // Cron tasks - cronTasksListCommand, + &cronTasksListCommand, } - globalCommands = []cli.Command{ + globalCommands = []*cli.Command{ // SSH keys - listSSHKeyCommand, - addSSHKeyCommand, - removeSSHKeyCommand, + &listSSHKeyCommand, + &addSSHKeyCommand, + &removeSSHKeyCommand, - integrationsListCommand, - integrationsAddCommand, - integrationsDeleteCommand, - integrationsImportKeysCommand, + &integrationsListCommand, + &integrationsAddCommand, + &integrationsDeleteCommand, + &integrationsImportKeysCommand, // Sessions - LoginCommand, - LogoutCommand, - RegionsListCommand, - ConfigCommand, - selfCommand, + &LoginCommand, + &LogoutCommand, + &RegionsListCommand, + &ConfigCommand, + &selfCommand, // Version - UpdateCommand, + &UpdateCommand, // Changelog - changelogCommand, + &changelogCommand, // Help - HelpCommand, + &HelpCommand, } ) diff --git a/cmd/config.go b/cmd/config.go index 565e4fb9b..cff60b5df 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/config" @@ -13,7 +13,7 @@ var ( Category: "Global", Usage: "Configure the CLI", Flags: []cli.Flag{ - cli.StringFlag{Name: "region", Value: "", Usage: "Configure the default region used by the CLI"}, + &cli.StringFlag{Name: "region", Value: "", Usage: "Configure the default region used by the CLI"}, }, Description: ` Example @@ -21,7 +21,7 @@ var ( Can also be configured using the environment variable SCALINGO_REGION=agora-fr1`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if c.String("region") != "" { err := config.SetRegion(c.String("region")) if err != nil { @@ -33,6 +33,7 @@ var ( if c.String("region") == "" { config.Display() } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "config") diff --git a/cmd/create.go b/cmd/create.go index 3e9264041..d16285ad0 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -10,23 +10,24 @@ import ( var ( CreateCommand = cli.Command{ Name: "create", - ShortName: "c", + Aliases: []string{"c"}, Category: "Global", Description: "Create a new app:\n Example:\n 'scalingo create mynewapp'\n 'scalingo create mynewapp --remote \"staging\"'", Flags: []cli.Flag{ - cli.StringFlag{Name: "remote", Value: "scalingo", Usage: "Remote to add to your current git repository", EnvVar: ""}, - cli.StringFlag{Name: "buildpack", Value: "", Usage: "URL to a custom buildpack that Scalingo should use to build your application", EnvVar: ""}, + &cli.StringFlag{Name: "remote", Value: "scalingo", Usage: "Remote to add to your current git repository"}, + &cli.StringFlag{Name: "buildpack", Value: "", Usage: "URL to a custom buildpack that Scalingo should use to build your application"}, }, Usage: "Create a new app", - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { _ = cli.ShowCommandHelp(c, "create") - return + return nil } - err := apps.Create(c.Args()[0], c.String("remote"), c.String("buildpack")) + err := apps.Create(c.Args().First(), c.String("remote"), c.String("buildpack")) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "create") diff --git a/cmd/cron_tasks.go b/cmd/cron_tasks.go index 30c9540b5..9ec7d6bc1 100644 --- a/cmd/cron_tasks.go +++ b/cmd/cron_tasks.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/crontasks" @@ -12,16 +12,16 @@ var ( cronTasksListCommand = cli.Command{ Name: "cron-tasks", Category: "Cron Tasks", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "List the cron tasks of an application", Description: `List all the cron tasks of an application: $ scalingo --app my-app cron-jobs`, - Action: func(c *cli.Context) { - if len(c.Args()) > 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() > 0 { cli.ShowCommandHelp(c, "cron-tasks") - return + return nil } currentApp := detect.CurrentApp(c) @@ -29,6 +29,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "cron-tasks") diff --git a/cmd/dashboard.go b/cmd/dashboard.go index 66391ee08..dc714ed79 100644 --- a/cmd/dashboard.go +++ b/cmd/dashboard.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,15 +13,15 @@ var ( dashboardCommand = cli.Command{ Name: "dashboard", Category: "App Management", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Open app dashboard on default web browser", Description: `Open app dashboard on default web browser: $ scalingo --app my-app dashboard`, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "dashboard") - return + return nil } currentApp := detect.CurrentApp(c) @@ -30,6 +30,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "dashboard") diff --git a/cmd/databases.go b/cmd/databases.go index 0ec0dd1a8..3f77ffd76 100644 --- a/cmd/databases.go +++ b/cmd/databases.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/db" "github.com/Scalingo/cli/detect" @@ -21,10 +21,10 @@ var ( Name: "backups-config", Category: "Addons", Usage: "Configure the periodic backups of a database", - Flags: []cli.Flag{appFlag, addonFlag, cli.StringFlag{ + Flags: []cli.Flag{&appFlag, &addonFlag, &cli.StringFlag{ Name: "schedule-at", Usage: "Enable daily backups and schedule them at the specified hour of the day (in local time zone). It is also possible to specify the timezone to use.", - }, cli.BoolFlag{ + }, &cli.BoolFlag{ Name: "unschedule", Usage: "Disable the periodic backups", }}, @@ -37,7 +37,7 @@ Examples # See also 'addons' and 'backup-download' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) addonName := addonNameFromFlags(c) if addonName == "" { @@ -89,6 +89,7 @@ Examples } else { io.Status("Periodic backups are disabled") } + return nil }, } ) diff --git a/cmd/db_tunnel.go b/cmd/db_tunnel.go index d7d1e9f06..6c65f746f 100644 --- a/cmd/db_tunnel.go +++ b/cmd/db_tunnel.go @@ -3,7 +3,7 @@ package cmd import ( "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/crypto/sshkeys" @@ -16,11 +16,11 @@ var ( Name: "db-tunnel", Category: "App Management", Usage: "Create an encrypted connection to access your database", - Flags: []cli.Flag{appFlag, - cli.IntFlag{Name: "port, p", Usage: "Local port to bind (default 10000)"}, - cli.StringFlag{Name: "identity, i", Usage: "SSH Private Key"}, - cli.StringFlag{Name: "bind, b", Usage: "IP to bind (default 127.0.0.1)"}, - cli.BoolTFlag{Name: "reconnect", Usage: "true by default, automatically reconnect to the tunnel when disconnected"}, + Flags: []cli.Flag{&appFlag, + &cli.IntFlag{Name: "port", Aliases: []string{"p"}, Usage: "Local port to bind (default 10000)"}, + &cli.StringFlag{Name: "identity", Aliases: []string{"i"}, Usage: "SSH Private Key"}, + &cli.StringFlag{Name: "bind", Aliases: []string{"b"}, Usage: "IP to bind (default 127.0.0.1)"}, + &cli.BoolFlag{Name: "reconnect", Value: true, Usage: "true by default, automatically reconnect to the tunnel when disconnected"}, }, Description: `Create an SSH-encrypted connection to access your Scalingo database locally. @@ -54,7 +54,7 @@ var ( Example $ scalingo --app rails-app db-tunnel -i ~/.ssh/custom_key DATABASE_URL`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var sshIdentity string if c.String("identity") == "" && os.Getenv("SSH_AUTH_SOCK") != "" { @@ -64,22 +64,23 @@ var ( } else { sshIdentity = c.String("identity") } - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "db-tunnel") - return + return nil } err := db.Tunnel(db.TunnelOpts{ App: currentApp, - DBEnvVar: c.Args()[0], + DBEnvVar: c.Args().First(), Identity: sshIdentity, Port: c.Int("port"), Bind: c.String("bind"), - Reconnect: c.BoolT("reconnect"), + Reconnect: c.Bool("reconnect"), }) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "db-tunnel") diff --git a/cmd/deployments.go b/cmd/deployments.go index 5a9fa5fe6..2b29a0f07 100644 --- a/cmd/deployments.go +++ b/cmd/deployments.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/deployments" @@ -18,12 +18,12 @@ var ( Aliases: []string{"deployment-cache-delete"}, Category: "Deployment", Usage: "Reset deployment cache", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` Delete the deployment cache (in case of corruption mostly) $ scalingo -a myapp deployment-delete-cache `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "deployment-delete-cache") } else { currentApp := detect.CurrentApp(c) @@ -33,6 +33,7 @@ var ( } io.Status("Deployment cache successfully deleted") } + return nil }, } @@ -40,41 +41,43 @@ var ( Name: "deployments", Category: "Deployment", Usage: "List app deployments", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` List all of your previous app deployments $ scalingo -a myapp deployments `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) err := deployments.List(currentApp) if err != nil { errorQuit(err) } + return nil }, } deploymentLogCommand = cli.Command{ Name: "deployment-logs", Category: "Deployment", Usage: "View deployment logs", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` Get the logs of an app deployment $ scalingo -a myapp deployment-logs my-deployment `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) > 1 { + if c.Args().Len() > 1 { cli.ShowCommandHelp(c, "deployment-logs") } deploymentID := "" - if len(c.Args()) == 1 { - deploymentID = c.Args()[0] + if c.Args().Len() == 1 { + deploymentID = c.Args().First() } err := deployments.Logs(currentApp, deploymentID) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.DeploymentsAutoComplete(c) @@ -84,11 +87,11 @@ var ( Name: "deployment-follow", Category: "Deployment", Usage: "Follow deployment event stream", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` Get real-time deployment informations $ scalingo -a myapp deployment-follow `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) err := deployments.Stream(&deployments.StreamOpts{ AppName: currentApp, @@ -96,15 +99,16 @@ var ( if err != nil { errorQuit(err) } + return nil }, } deploymentDeployCommand = cli.Command{ Name: "deploy", Category: "Deployment", Usage: "Trigger a deployment by archive", - Flags: []cli.Flag{appFlag, - cli.BoolFlag{Name: "war, w", Usage: "Specify that you want to deploy a WAR file"}, - cli.BoolFlag{Name: "no-follow", Usage: "Return immediately after the deployment is triggered"}, + Flags: []cli.Flag{&appFlag, + &cli.BoolFlag{Name: "war", Aliases: []string{"w"}, Usage: "Specify that you want to deploy a WAR file"}, + &cli.BoolFlag{Name: "no-follow", Usage: "Return immediately after the deployment is triggered"}, }, Description: ` Trigger the deployment of a custom archive for your application @@ -123,16 +127,16 @@ var ( # See also commands 'deployments, deployment-follow' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { args := c.Args() - if len(args) != 1 && len(args) != 2 { + if args.Len() != 1 && args.Len() != 2 { cli.ShowCommandHelp(c, "deploy") - return + return nil } - archivePath := args[0] + archivePath := args.First() gitRef := "" - if len(args) == 2 { - gitRef = args[1] + if args.Len() == 2 { + gitRef = args.Slice()[1] } currentApp := detect.CurrentApp(c) opts := deployments.DeployOpts{NoFollow: c.Bool("no-follow")} @@ -149,6 +153,7 @@ var ( errorQuit(err) } } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "deploy") diff --git a/cmd/destroy.go b/cmd/destroy.go index 0bb639273..82ec47d09 100644 --- a/cmd/destroy.go +++ b/cmd/destroy.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -12,19 +12,19 @@ var ( DestroyCommand = cli.Command{ Name: "destroy", Category: "App Management", - Flags: []cli.Flag{appFlag, - cli.BoolFlag{Name: "force", Usage: "Force destroy without asking for a confirmation /!\\", EnvVar: ""}, + Flags: []cli.Flag{&appFlag, + &cli.BoolFlag{Name: "force", Usage: "Force destroy without asking for a confirmation /!\\"}, }, - Usage: "Destroy an app /!\\", + Usage: "Destroy an app /!\\", Description: "Destroy an app /!\\ It is not reversible\n Example:\n 'scalingo destroy my-app'\n 'scalingo -a my-app destroy --force'\n ", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { var currentApp string - if len(c.Args()) > 1 { + if c.Args().Len() > 1 { cli.ShowCommandHelp(c, "destroy") } else { - if len(c.Args()) != 0 { - currentApp = c.Args()[0] + if c.Args().Len() != 0 { + currentApp = c.Args().First() } else { currentApp = detect.CurrentApp(c) } @@ -34,6 +34,7 @@ var ( errorQuit(err) } } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "destroy") diff --git a/cmd/domains.go b/cmd/domains.go index 3b3f48efd..92ff2dd02 100644 --- a/cmd/domains.go +++ b/cmd/domains.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/detect" @@ -12,7 +12,7 @@ var ( DomainsListCommand = cli.Command{ Name: "domains", Category: "Custom Domains", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "List the domains of an application", Description: `List all the custom domains of an application: @@ -20,10 +20,10 @@ var ( # See also commands 'domains-add' and 'domains-remove'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err = domains.List(currentApp) } else { cli.ShowCommandHelp(c, "domains") @@ -32,6 +32,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "domains") @@ -42,9 +43,9 @@ var ( Name: "domains-add", Category: "Custom Domains", Usage: "Add a custom domain to an application", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "cert", Usage: "SSL Signed Certificate", Value: "domain.crt", EnvVar: ""}, - cli.StringFlag{Name: "key", Usage: "SSL Keypair", Value: "domain.key", EnvVar: ""}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "cert", Usage: "SSL Signed Certificate", Value: "domain.crt"}, + &cli.StringFlag{Name: "key", Usage: "SSL Keypair", Value: "domain.key"}, }, Description: `Add a custom domain to an application: @@ -52,10 +53,10 @@ var ( # See also commands 'domains' and 'domains-remove'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 1 { + if c.Args().Len() == 1 { cert := c.String("cert") if cert == "domain.crt" { cert = "" @@ -64,7 +65,7 @@ var ( if key == "domain.key" { key = "" } - err = domains.Add(currentApp, c.Args()[0], cert, key) + err = domains.Add(currentApp, c.Args().First(), cert, key) } else { cli.ShowCommandHelp(c, "domains-add") } @@ -72,6 +73,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "domains-add") @@ -81,7 +83,7 @@ var ( DomainsRemoveCommand = cli.Command{ Name: "domains-remove", Category: "Custom Domains", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Remove a custom domain from an application", Description: `Remove a custom domain from an application: @@ -89,11 +91,11 @@ var ( # See also commands 'domains' and 'domains-add'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 1 { - err = domains.Remove(currentApp, c.Args()[0]) + if c.Args().Len() == 1 { + err = domains.Remove(currentApp, c.Args().First()) } else { cli.ShowCommandHelp(c, "domains-remove") } @@ -101,6 +103,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "domains-remove") @@ -112,9 +115,9 @@ var ( Name: "domains-ssl", Category: "Custom Domains", Usage: "Enable or disable SSL for your custom domains", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "cert", Usage: "SSL Signed Certificate", Value: "domain.crt", EnvVar: ""}, - cli.StringFlag{Name: "key", Usage: "SSL Keypair", Value: "domain.key", EnvVar: ""}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "cert", Usage: "SSL Signed Certificate", Value: "domain.crt"}, + &cli.StringFlag{Name: "key", Usage: "SSL Keypair", Value: "domain.key"}, }, Description: `Enable or disable SSL for your custom domains: @@ -124,19 +127,20 @@ var ( # See also commands 'domains' and 'domains-add'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 2 && c.Args()[1] == "disable" { - err = domains.DisableSSL(currentApp, c.Args()[0]) - } else if len(c.Args()) == 1 { - err = domains.EnableSSL(currentApp, c.Args()[0], c.String("cert"), c.String("key")) + if c.Args().Len() == 2 && c.Args().Slice()[1] == "disable" { + err = domains.DisableSSL(currentApp, c.Args().First()) + } else if c.Args().Len() == 1 { + err = domains.EnableSSL(currentApp, c.Args().First(), c.String("cert"), c.String("key")) } else { cli.ShowCommandHelp(c, "domains-ssl") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "domains-ssl") @@ -146,7 +150,7 @@ var ( setCanonicalDomainCommand = cli.Command{ Name: "set-canonical-domain", Category: "App Management", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Set a canonical domain.", Description: `After defining multiple domains on an application, one can need to redirect all requests towards its application to a specific domain. This domain is called the canonical domain. This command sets the canonical domain: @@ -154,17 +158,18 @@ var ( # See also commands 'domains', 'domains-add' and 'unset-canonical-domain'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "set-canonical-domain") - return + return nil } - err := domains.SetCanonical(currentApp, c.Args()[0]) + err := domains.SetCanonical(currentApp, c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "set-canonical-domain") @@ -174,7 +179,7 @@ var ( unsetCanonicalDomainCommand = cli.Command{ Name: "unset-canonical-domain", Category: "App Management", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Unset a canonical domain.", Description: `Unset the canonical domain of this app: @@ -182,17 +187,18 @@ var ( # See also commands 'domains', 'domains-add' and 'set-canonical-domain'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "unset-canonical-domain") - return + return nil } err := domains.UnsetCanonical(currentApp) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "unset-canonical-domain") diff --git a/cmd/env.go b/cmd/env.go index d95c71ac9..3e212050b 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -3,7 +3,7 @@ package cmd import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/detect" @@ -14,7 +14,7 @@ var ( envCommand = cli.Command{ Name: "env", Category: "Environment", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Display the environment of your apps", Description: `List all the environment variables: @@ -22,10 +22,10 @@ var ( # See also commands 'env-get', 'env-set' and 'env-unset'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err = env.Display(currentApp) } else { cli.ShowCommandHelp(c, "env") @@ -34,6 +34,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "env") @@ -43,7 +44,7 @@ var ( envGetCommand = cli.Command{ Name: "env-get", Category: "Environment", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Get the requested environment variable from your app", Description: `Get the value of a specific environment variable: @@ -51,18 +52,19 @@ var ( # See also commands 'env', 'env-set' and 'env-unset'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "env") - return + return nil } currentApp := detect.CurrentApp(c) - variableValue, err := env.Get(currentApp, c.Args()[0]) + variableValue, err := env.Get(currentApp, c.Args().First()) if err != nil { errorQuit(err) } fmt.Println(variableValue) + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "env") @@ -72,7 +74,7 @@ var ( envSetCommand = cli.Command{ Name: "env-set", Category: "Environment", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Set the environment variables of your apps", Description: `Set variables: @@ -80,18 +82,19 @@ var ( # See also commands 'env', 'env-get' and 'env-unset'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) > 0 { - err = env.Add(currentApp, c.Args()) + if c.Args().Len() > 0 { + err = env.Add(currentApp, c.Args().Slice()) } else { cli.ShowCommandHelp(c, "env-set") - return + return nil } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "env-set") @@ -101,7 +104,7 @@ var ( envUnsetCommand = cli.Command{ Name: "env-unset", Category: "Environment", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Unset environment variables of your apps", Description: `Unset variables: @@ -109,17 +112,18 @@ var ( # See also commands 'env', 'env-get' and 'env-set'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) > 0 { - err = env.Delete(currentApp, c.Args()) + if c.Args().Len() > 0 { + err = env.Delete(currentApp, c.Args().Slice()) } else { cli.ShowCommandHelp(c, "env-unset") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "env-unset") diff --git a/cmd/flags.go b/cmd/flags.go index 7d9ecf813..f19d15a60 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -3,16 +3,17 @@ package cmd import ( "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/go-scalingo/v4/debug" ) var ( appFlag = cli.StringFlag{ - Name: "app, a", - Value: "", - Usage: "Name of the current app", + Name: "app", + Aliases: []string{"a"}, + Value: "", + Usage: "Name of the current app", } addonFlag = cli.StringFlag{ Name: "addon", @@ -23,9 +24,7 @@ var ( func addonNameFromFlags(c *cli.Context) string { var addonName string - if c.GlobalString("addon") != "" { - addonName = c.GlobalString("addon") - } else if c.String("addon") != "" { + if c.String("addon") != "" { addonName = c.String("addon") } else if os.Getenv("SCALINGO_ADDON") != "" { addonName = os.Getenv("SCALINGO_ADDON") diff --git a/cmd/git.go b/cmd/git.go index 2865949ca..b54bb79fe 100644 --- a/cmd/git.go +++ b/cmd/git.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/detect" @@ -13,23 +13,26 @@ var ( Name: "git-setup", Category: "Git", Usage: "Configure the Git remote for this application", - Flags: []cli.Flag{appFlag, - cli.StringFlag{ - Name: "remote, r", Value: "scalingo", - Usage: "Specify the remote name"}, - cli.BoolFlag{ - Name: "force, f", - Usage: "Replace remote url even if remote already exist"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{ + Name: "remote", + Aliases: []string{"r"}, + Value: "scalingo", + Usage: "Specify the remote name"}, + &cli.BoolFlag{ + Name: "force", + Aliases: []string{"f"}, + Usage: "Replace remote url even if remote already exist"}, }, Description: `Add a Git remote to the current folder. Example scalingo --app my-app git-setup --remote scalingo-staging `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "git-setup") - return + return nil } err := git.Setup(detect.CurrentApp(c), git.SetupParams{ @@ -39,6 +42,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "git-setup") @@ -48,22 +52,23 @@ var ( Name: "git-show", Category: "Git", Usage: "Display the Git remote URL for this application", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Display the Git remote URL for this application. Example scalingo --app my-app git-show `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "git-show") - return + return nil } err := git.Show(detect.CurrentApp(c)) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "git-show") diff --git a/cmd/help.go b/cmd/help.go index 11205cece..135b62e1a 100644 --- a/cmd/help.go +++ b/cmd/help.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" ) @@ -10,13 +10,14 @@ var ( HelpCommand = cli.Command{ Name: "help", Usage: "Shows a list of commands or help for one command", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { args := c.Args() if args.Present() { cli.ShowCommandHelp(c, args.First()) - return + return nil } cli.ShowAppHelp(c) + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "help") diff --git a/cmd/influxdb.go b/cmd/influxdb.go index 60af0ee7f..d9132a42c 100644 --- a/cmd/influxdb.go +++ b/cmd/influxdb.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/db" @@ -13,9 +13,9 @@ var ( Name: "influxdb-console", Category: "Databases", Usage: "Run an interactive console with your InfluxDB addon", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "size, s", Value: "", Usage: "Size of the container"}, - cli.StringFlag{Name: "env, e", Value: "", Usage: "Environment variable name to use for the connection to the database"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "size", Aliases: []string{"s"}, Value: "", Usage: "Size of the container"}, + &cli.StringFlag{Name: "env", Aliases: []string{"e"}, Value: "", Usage: "Environment variable name to use for the connection to the database"}, }, Description: ` Run an interactive console with your InfluxDB addon. @@ -31,10 +31,10 @@ var ( # See also 'mongo-console' and 'mysql-console' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "influxdb-console") - return + return nil } err := db.InfluxDBConsole(db.InfluxDBConsoleOpts{ @@ -45,6 +45,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "influxdb-console") diff --git a/cmd/integration_link.go b/cmd/integration_link.go index f45b14187..9e64888ae 100644 --- a/cmd/integration_link.go +++ b/cmd/integration_link.go @@ -7,7 +7,7 @@ import ( "os" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/AlecAivazis/survey.v1" "github.com/Scalingo/cli/cmd/autocomplete" @@ -26,15 +26,15 @@ var ( Name: "integration-link", Category: "Integration Link", Usage: "Show integration link of your app", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` Show integration link of your app: $ scalingo --app my-app integration-link # See also 'integration-link-create', 'integration-link-update', 'integration-link-delete', 'integration-link-manual-deploy', 'integration-link-manual-review-app'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "integration-link") - return + return nil } currentApp := detect.CurrentApp(c) @@ -42,6 +42,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integration-link") @@ -52,18 +53,18 @@ var ( Name: "integration-link-create", Category: "Integration Link", Flags: []cli.Flag{ - appFlag, - cli.StringFlag{Name: "branch", Usage: "Branch used in auto deploy"}, - cli.BoolFlag{Name: "auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, - cli.BoolFlag{Name: "deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, - cli.BoolFlag{Name: "destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, - cli.BoolFlag{Name: "no-auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, - cli.BoolFlag{Name: "no-deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, - cli.BoolFlag{Name: "no-destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, - cli.UintFlag{Name: "hours-before-destroy-on-close", Usage: "Time delay before auto destroying a review app when pull request is closed"}, - cli.BoolFlag{Name: "destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, - cli.BoolFlag{Name: "no-destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, - cli.UintFlag{Name: "hours-before-destroy-on-stale", Usage: "Time delay before auto destroying a review app when no deploy/commits has happened"}, + &appFlag, + &cli.StringFlag{Name: "branch", Usage: "Branch used in auto deploy"}, + &cli.BoolFlag{Name: "auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, + &cli.BoolFlag{Name: "deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, + &cli.BoolFlag{Name: "destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, + &cli.BoolFlag{Name: "no-auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, + &cli.BoolFlag{Name: "no-deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, + &cli.BoolFlag{Name: "no-destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, + &cli.UintFlag{Name: "hours-before-destroy-on-close", Usage: "Time delay before auto destroying a review app when pull request is closed"}, + &cli.BoolFlag{Name: "destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, + &cli.BoolFlag{Name: "no-destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, + &cli.UintFlag{Name: "hours-before-destroy-on-stale", Usage: "Time delay before auto destroying a review app when no deploy/commits has happened"}, }, Usage: "Link your Scalingo application to an integration", Description: ` Link your Scalingo application to an integration: @@ -82,14 +83,14 @@ var ( $ scalingo --app my-app integration-link-create https://ghe.example.org/test/frontend-app --branch master --auto-deploy # See also 'integration-link', 'integration-link-update', 'integration-link-delete', 'integration-link-manual-deploy' and 'integration-link-manual-review-app'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "integration-link-create") - return + return nil } currentApp := detect.CurrentApp(c) - integrationURL := c.Args()[0] + integrationURL := c.Args().First() integrationURLParsed, err := url.Parse(integrationURL) if err != nil { errorQuit(err) @@ -188,6 +189,7 @@ var ( } errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integration-link-create") @@ -198,18 +200,18 @@ var ( Name: "integration-link-update", Category: "Integration Link", Flags: []cli.Flag{ - appFlag, - cli.StringFlag{Name: "branch", Usage: "Branch used in auto deploy"}, - cli.BoolFlag{Name: "auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, - cli.BoolFlag{Name: "no-auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, - cli.BoolFlag{Name: "deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, - cli.BoolFlag{Name: "no-deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, - cli.BoolFlag{Name: "destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, - cli.BoolFlag{Name: "no-destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, - cli.UintFlag{Name: "hours-before-destroy-on-close", Usage: "Time delay before auto destroying a review app when pull request is closed"}, - cli.BoolFlag{Name: "destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, - cli.BoolFlag{Name: "no-destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, - cli.StringFlag{Name: "hours-before-destroy-on-stale", Usage: "Time delay before auto destroying a review app when no deploy/commits has happened"}, + &appFlag, + &cli.StringFlag{Name: "branch", Usage: "Branch used in auto deploy"}, + &cli.BoolFlag{Name: "auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, + &cli.BoolFlag{Name: "no-auto-deploy", Usage: "Enable auto deploy of application after each branch change"}, + &cli.BoolFlag{Name: "deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, + &cli.BoolFlag{Name: "no-deploy-review-apps", Usage: "Enable auto deploy of review app when new pull request is opened"}, + &cli.BoolFlag{Name: "destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, + &cli.BoolFlag{Name: "no-destroy-on-close", Usage: "Auto destroy review apps when pull request is closed"}, + &cli.UintFlag{Name: "hours-before-destroy-on-close", Usage: "Time delay before auto destroying a review app when pull request is closed"}, + &cli.BoolFlag{Name: "destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, + &cli.BoolFlag{Name: "no-destroy-on-stale", Usage: "Auto destroy review apps when no deploy/commits has happened"}, + &cli.StringFlag{Name: "hours-before-destroy-on-stale", Usage: "Time delay before auto destroying a review app when no deploy/commits has happened"}, }, Usage: "Update the integration link parameters", Description: ` Update the integration link parameters: @@ -222,10 +224,10 @@ var ( $ scalingo --app my-app integration-link-update --destroy-on-stale --hours-before-destroy-on-stale 2 # See also 'integration-link', 'integration-link-create', 'integration-link-delete', 'integration-link-manual-deploy' and 'integration-link-manual-review-app'`, - Action: func(c *cli.Context) { - if c.NumFlags() == 0 || len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.NumFlags() == 0 || c.Args().Len() != 0 { cli.ShowCommandHelp(c, "integration-link-update") - return + return nil } autoDeploy := c.Bool("auto-deploy") noAutoDeploy := c.Bool("no-auto-deploy") @@ -258,6 +260,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integration-link-update") @@ -267,17 +270,17 @@ var ( integrationLinkDeleteCommand = cli.Command{ Name: "integration-link-delete", Category: "Integration Link", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Delete the link between your Scalingo application and the integration", Description: `Delete the link between your Scalingo application and the integration: $ scalingo --app my-app integration-link-delete # See also 'integration-link', 'integration-link-create', 'integration-link-update', 'integration-link-manual-deploy' and 'integration-link-manual-review-app'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "integration-link-delete") - return + return nil } currentApp := detect.CurrentApp(c) @@ -285,6 +288,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integration-link-delete") @@ -294,25 +298,26 @@ var ( integrationLinkManualDeployCommand = cli.Command{ Name: "integration-link-manual-deploy", Category: "Integration Link", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Trigger a manual deployment of the specified branch", Description: `Trigger a manual deployment of the specified branch: $ scalingo --app my-app integration-link-manual-deploy mybranch # See also 'integration-link', 'integration-link-create', 'integration-link-update', 'integration-link-delete' and 'integration-link-manual-review-app'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "integration-link-manual-deploy") - return + return nil } currentApp := detect.CurrentApp(c) - branchName := c.Args()[0] + branchName := c.Args().First() err := integrationlink.ManualDeploy(currentApp, branchName) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integration-link-manual-deploy") @@ -322,7 +327,7 @@ var ( integrationLinkManualReviewAppCommand = cli.Command{ Name: "integration-link-manual-review-app", Category: "Integration Link", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Trigger a review app creation of the pull/merge request ID specified", Description: `Trigger a review app creation of the pull/merge request ID specified: @@ -333,18 +338,19 @@ var ( $ scalingo --app my-app integration-link-manual-review-app 42 # See also 'integration-link', 'integration-link-create', 'integration-link-update', 'integration-link-delete' and 'integration-link-manual-deploy'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "integration-link-manual-review-app") - return + return nil } currentApp := detect.CurrentApp(c) - pullRequestID := c.Args()[0] + pullRequestID := c.Args().First() err := integrationlink.ManualReviewApp(currentApp, pullRequestID) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integration-link-manual-review-app") diff --git a/cmd/keys.go b/cmd/keys.go index e84a8da09..ae94bbf6c 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/keys" @@ -18,11 +18,12 @@ var ( # See also commands 'keys-add' and 'keys-remove'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := keys.List() if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "keys") @@ -39,15 +40,16 @@ var ( # See also commands 'keys' and 'keys-remove'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 2 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 2 { cli.ShowCommandHelp(c, "keys-add") - return + return nil } - err := keys.Add(c.Args()[0], c.Args()[1]) + err := keys.Add(c.Args().First(), c.Args().Slice()[1]) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "keys-add") @@ -64,15 +66,16 @@ var ( # See also commands 'keys' and 'keys-add'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "keys-remove") - return + return nil } - err := keys.Remove(c.Args()[0]) + err := keys.Remove(c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "keys-remove") diff --git a/cmd/log_drains.go b/cmd/log_drains.go index cd8b6d03d..11e0502c9 100644 --- a/cmd/log_drains.go +++ b/cmd/log_drains.go @@ -3,7 +3,7 @@ package cmd import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/AlecAivazis/survey.v1" "github.com/Scalingo/cli/cmd/autocomplete" @@ -16,9 +16,9 @@ var ( logDrainsListCommand = cli.Command{ Name: "log-drains", Category: "Log drains", - Flags: []cli.Flag{appFlag, - addonFlag, - cli.BoolFlag{Name: "with-addons", Usage: "also list the log drains of all addons"}, + Flags: []cli.Flag{&appFlag, + &addonFlag, + &cli.BoolFlag{Name: "with-addons", Usage: "also list the log drains of all addons"}, }, Usage: "List the log drains of an application", Description: `List all the log drains of an application: @@ -32,17 +32,15 @@ var ( $ scalingo --app my-app log-drains --with-addons # See also commands 'log-drains-add', 'log-drains-remove'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "log-drains") - return + return nil } var addonID string - if c.GlobalString("addon") != "" { - addonID = c.GlobalString("addon") - } else if c.String("addon") != "" { + if c.String("addon") != "" { addonID = c.String("addon") } @@ -53,6 +51,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "log-drains") @@ -63,16 +62,16 @@ var ( Name: "log-drains-add", Category: "Log drains", Usage: "Add a log drain to an application", - Flags: []cli.Flag{appFlag, - addonFlag, - cli.BoolFlag{Name: "with-addons", Usage: "also add the log drains to all addons"}, - cli.BoolFlag{Name: "with-databases", Usage: "also add the log drains to all databases"}, - cli.StringFlag{Name: "type", Usage: "Communication protocol", Required: true}, - cli.StringFlag{Name: "url", Usage: "URL of self hosted ELK"}, - cli.StringFlag{Name: "host", Usage: "Host of logs management service"}, - cli.StringFlag{Name: "port", Usage: "Port of logs management service"}, - cli.StringFlag{Name: "token", Usage: "Used by certain vendor for authentication"}, - cli.StringFlag{Name: "drain-region", Usage: "Used by certain logs management service to identify the region of their servers"}, + Flags: []cli.Flag{&appFlag, + &addonFlag, + &cli.BoolFlag{Name: "with-addons", Usage: "also add the log drains to all addons"}, + &cli.BoolFlag{Name: "with-databases", Usage: "also add the log drains to all databases"}, + &cli.StringFlag{Name: "type", Usage: "Communication protocol", Required: true}, + &cli.StringFlag{Name: "url", Usage: "URL of self hosted ELK"}, + &cli.StringFlag{Name: "host", Usage: "Host of logs management service"}, + &cli.StringFlag{Name: "port", Usage: "Port of logs management service"}, + &cli.StringFlag{Name: "token", Usage: "Used by certain vendor for authentication"}, + &cli.StringFlag{Name: "drain-region", Usage: "Used by certain logs management service to identify the region of their servers"}, }, Description: `Add a log drain to an application: @@ -98,19 +97,17 @@ var ( # See also commands 'log-drains', 'log-drains-remove'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var addonID string - if c.GlobalString("addon") != "" { - addonID = c.GlobalString("addon") - } else if c.String("addon") != "" { + if c.String("addon") != "" { addonID = c.String("addon") } if addonID != "" && (c.Bool("with-addons") || c.Bool("with-databases")) { cli.ShowCommandHelp(c, "log-drains-add") - return + return nil } if c.Bool("with-addons") { @@ -133,6 +130,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "log-drains-add") @@ -143,9 +141,9 @@ var ( Name: "log-drains-remove", Category: "Log drains", Flags: []cli.Flag{ - appFlag, - addonFlag, - cli.BoolFlag{Name: "only-app", Usage: "remove the log drains for the application only"}, + &appFlag, + &addonFlag, + &cli.BoolFlag{Name: "only-app", Usage: "remove the log drains for the application only"}, }, Usage: "Remove a log drain from an application and its associated addons", Description: `Remove a log drain from an application and all its addons: @@ -164,24 +162,22 @@ var ( # See also commands 'log-drains-add', 'log-drains'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "log-drains-remove") - return + return nil } - drain := c.Args()[0] + drain := c.Args().First() var addonID string - if c.GlobalString("addon") != "" { - addonID = c.GlobalString("addon") - } else if c.String("addon") != "" { + if c.String("addon") != "" { addonID = c.String("addon") } if addonID != "" && c.Bool("only-app") { cli.ShowCommandHelp(c, "log-drains-remove") - return + return nil } message := "This operation will delete the log drain " + drain @@ -198,7 +194,7 @@ var ( result := askContinue(message) if !result { fmt.Println("Aborted") - return + return nil } err := log_drains.Remove(currentApp, log_drains.RemoveAddonOpts{ @@ -210,6 +206,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "log-drains-remove") diff --git a/cmd/login.go b/cmd/login.go index a04159167..2951eb98f 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -3,7 +3,7 @@ package cmd import ( "errors" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/session" @@ -14,16 +14,16 @@ var ( Name: "login", Category: "Global", Flags: []cli.Flag{ - cli.StringFlag{Name: "api-token", Usage: "Authenticate with a token instead of login/password or SSH"}, - cli.BoolFlag{Name: "ssh", Usage: "Login with you SSH identity instead of login/password"}, - cli.StringFlag{Name: "ssh-identity", Value: "ssh-agent", Usage: "Use a custom SSH key, only compatible if --ssh is set"}, - cli.BoolFlag{Name: "password-only", Usage: "Login with login/password without testing SSH connection"}, + &cli.StringFlag{Name: "api-token", Usage: "Authenticate with a token instead of login/password or SSH"}, + &cli.BoolFlag{Name: "ssh", Usage: "Login with you SSH identity instead of login/password"}, + &cli.StringFlag{Name: "ssh-identity", Value: "ssh-agent", Usage: "Use a custom SSH key, only compatible if --ssh is set"}, + &cli.BoolFlag{Name: "password-only", Usage: "Login with login/password without testing SSH connection"}, }, Usage: "Login to Scalingo platform", Description: ` Example 'scalingo login'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if c.Bool("ssh") && c.Bool("password-only") { errorQuit(errors.New("You cannot use both --ssh and --password-only at the same time")) } @@ -37,6 +37,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "login") diff --git a/cmd/logout.go b/cmd/logout.go index 35e008a7a..d4b5ec359 100644 --- a/cmd/logout.go +++ b/cmd/logout.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/config" @@ -15,19 +15,20 @@ var ( Category: "Global", Usage: "Logout from Scalingo", Description: "Destroy login information stored on your computer", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentUser, err := config.C.CurrentUser() if err != nil { errorQuit(err) } if currentUser == nil { io.Status("You are already logged out.") - return + return nil } if err := session.DestroyToken(); err != nil { panic(err) } io.Status("Scalingo credentials have been deleted.") + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "logout") diff --git a/cmd/logs.go b/cmd/logs.go index 932a8b71d..4edba4325 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -11,10 +11,10 @@ import ( var ( logsCommand = cli.Command{ - Name: "logs", - ShortName: "l", - Category: "App Management", - Usage: "Get the logs of your applications", + Name: "logs", + Aliases: []string{"l"}, + Category: "App Management", + Usage: "Get the logs of your applications", Description: `Get the logs of your applications Example: Get 100 lines: 'scalingo --app my-app logs -n 100' @@ -24,16 +24,16 @@ var ( 'scalingo --app my-app logs -F web' 'scalingo --app my-app logs -F web-1' 'scalingo --app my-app logs --follow -F "worker|clock"'`, - Flags: []cli.Flag{appFlag, addonFlag, - cli.IntFlag{Name: "lines, n", Value: 20, Usage: "Number of log lines to dump", EnvVar: ""}, - cli.BoolFlag{Name: "follow, f", Usage: "Stream logs of app, (as \"tail -f\")", EnvVar: ""}, - cli.StringFlag{Name: "filter, F", Usage: "Filter containers logs that will be displayed", EnvVar: ""}, + Flags: []cli.Flag{&appFlag, &addonFlag, + &cli.IntFlag{Name: "lines", Aliases: []string{"n"}, Value: 20, Usage: "Number of log lines to dump"}, + &cli.BoolFlag{Name: "follow", Aliases: []string{"f"}, Usage: "Stream logs of app, (as \"tail -f\")"}, + &cli.StringFlag{Name: "filter", Aliases: []string{"F"}, Usage: "Filter containers logs that will be displayed"}, }, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "logs") - return + return nil } addonName := addonNameFromFlags(c) @@ -51,6 +51,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "logs") diff --git a/cmd/logs_archives.go b/cmd/logs_archives.go index 8af838d82..aad290420 100644 --- a/cmd/logs_archives.go +++ b/cmd/logs_archives.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -11,23 +11,23 @@ import ( var ( logsArchivesCommand = cli.Command{ - Name: "logs-archives", - ShortName: "la", - Category: "App Management", - Usage: "Get the logs archives of your applications and databases", + Name: "logs-archives", + Aliases: []string{"la"}, + Category: "App Management", + Usage: "Get the logs archives of your applications and databases", Description: `Get the logs archives of your applications and databases Examples: Get most recents archives: 'scalingo --app my-app logs-archives' Get a specific page: 'scalingo --app my-app logs-archives -p 5' Addon logs archives: 'scalingo --app my-app logs-archives --addon addon-id'`, - Flags: []cli.Flag{appFlag, addonFlag, - cli.IntFlag{Name: "page, p", Usage: "Page number", EnvVar: ""}, + Flags: []cli.Flag{&appFlag, &addonFlag, + &cli.IntFlag{Name: "page", Aliases: []string{"p"}, Usage: "Page number"}, }, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "logs-archives") - return + return nil } addonName := addonNameFromFlags(c) @@ -42,6 +42,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "logs-archives") diff --git a/cmd/mongo.go b/cmd/mongo.go index 87a3ad5fc..ee4dc540d 100644 --- a/cmd/mongo.go +++ b/cmd/mongo.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/db" @@ -13,9 +13,9 @@ var ( Name: "mongo-console", Category: "Databases", Usage: "Run an interactive console with your MongoDB addon", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "size, s", Value: "", Usage: "Size of the container"}, - cli.StringFlag{Name: "env, e", Value: "", Usage: "Environment variable name to use for the connection to the database"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "size", Aliases: []string{"s"}, Value: "", Usage: "Size of the container"}, + &cli.StringFlag{Name: "env", Aliases: []string{"e"}, Value: "", Usage: "Environment variable name to use for the connection to the database"}, }, Description: ` Run an interactive console with your MongoDB addon. @@ -31,10 +31,10 @@ var ( # See also 'redis-console' and 'mysql-console' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "mongo-console") - return + return nil } err := db.MongoConsole(db.MongoConsoleOpts{ @@ -45,6 +45,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "mongo-console") diff --git a/cmd/mysql.go b/cmd/mysql.go index 2fea77156..09a8e35ac 100644 --- a/cmd/mysql.go +++ b/cmd/mysql.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/db" @@ -13,9 +13,9 @@ var ( Name: "mysql-console", Category: "Databases", Usage: "Run an interactive console with your MySQL addon", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "size, s", Value: "", Usage: "Size of the container"}, - cli.StringFlag{Name: "env, e", Value: "", Usage: "Environment variable name to use for the connection to the database"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "size", Aliases: []string{"s"}, Value: "", Usage: "Size of the container"}, + &cli.StringFlag{Name: "env", Aliases: []string{"e"}, Value: "", Usage: "Environment variable name to use for the connection to the database"}, }, Description: ` Run an interactive console with your MySQL addon. @@ -31,10 +31,10 @@ var ( # See also 'mongo-console' and 'pgsql-console' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "mysql-console") - return + return nil } err := db.MySQLConsole(db.MySQLConsoleOpts{ @@ -45,6 +45,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "mysql-console") diff --git a/cmd/notification_platforms.go b/cmd/notification_platforms.go index 5f0bd52b0..40e79ac4c 100644 --- a/cmd/notification_platforms.go +++ b/cmd/notification_platforms.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/notification_platforms" @@ -13,11 +13,12 @@ var ( Category: "Notifiers - Global", Description: "List all notification platforms you can use with a notifier.", Usage: "List all notification platforms", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := notification_platforms.List() if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "platforms-list") diff --git a/cmd/notifiers.go b/cmd/notifiers.go index 268ad7d5b..cd247b59d 100644 --- a/cmd/notifiers.go +++ b/cmd/notifiers.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/detect" @@ -14,16 +14,16 @@ var ( Name: "notifiers", Category: "Notifiers", Usage: "List your notifiers", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` List all notifiers of your app: $ scalingo -a myapp notifiers # See also 'notifiers-add' and 'notifiers-remove' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err = notifiers.List(currentApp) } else { cli.ShowCommandHelp(c, "notifiers") @@ -32,6 +32,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "notifiers") @@ -42,17 +43,17 @@ var ( Name: "notifiers-details", Category: "Notifiers", Usage: "Show details of your notifiers", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: ` Show details of your notifiers: $ scalingo -a myapp notifiers-details # See also 'notifiers' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 1 { - err = notifiers.Details(currentApp, c.Args()[0]) + if c.Args().Len() == 1 { + err = notifiers.Details(currentApp, c.Args().First()) } else { cli.ShowCommandHelp(c, "notifiers-details") } @@ -60,6 +61,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "notifiers-details") @@ -71,17 +73,17 @@ var ( Name: "notifiers-add", Category: "Notifiers", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "enable, e", Usage: "Enable the notifier (default)"}, - cli.BoolFlag{Name: "disable, d", Usage: "Disable the notifier"}, - cli.StringFlag{Name: "platform, p", Value: "", Usage: "The notifier platform"}, - cli.StringFlag{Name: "name, n", Value: "", Usage: "Name of the notifier"}, - cli.BoolFlag{Name: "send-all-events, sa", Usage: "If true the notifier will send all events. Default: false"}, - cli.StringFlag{Name: "webhook-url, u", Value: "", Usage: "The webhook url to send notification (if applicable)"}, - cli.StringFlag{Name: "phone", Value: "", Usage: "The phone number to send notifications (if applicable)"}, - cli.StringSliceFlag{Name: "event, ev", Value: &cli.StringSlice{}, Usage: "List of selected events. Default: []"}, - cli.StringSliceFlag{Name: "email", Value: &cli.StringSlice{}, Usage: "The emails (multiple option accepted) to send notifications (if applicable)"}, - cli.StringSliceFlag{Name: "collaborator", Value: &cli.StringSlice{}, Usage: "The usernames of the collaborators who will receive notifications"}, + &appFlag, + &cli.BoolFlag{Name: "enable", Aliases: []string{"e"}, Usage: "Enable the notifier (default)"}, + &cli.BoolFlag{Name: "disable", Aliases: []string{"d"}, Usage: "Disable the notifier"}, + &cli.StringFlag{Name: "platform", Aliases: []string{"p"}, Value: "", Usage: "The notifier platform"}, + &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: "", Usage: "Name of the notifier"}, + &cli.BoolFlag{Name: "send-all-events", Aliases: []string{"sa"}, Usage: "If true the notifier will send all events. Default: false"}, + &cli.StringFlag{Name: "webhook-url", Aliases: []string{"u"}, Value: "", Usage: "The webhook url to send notification (if applicable)"}, + &cli.StringFlag{Name: "phone", Value: "", Usage: "The phone number to send notifications (if applicable)"}, + &cli.StringSliceFlag{Name: "event", Aliases: []string{"ev"}, Value: cli.NewStringSlice(""), Usage: "List of selected events. Default: []"}, + &cli.StringSliceFlag{Name: "email", Value: cli.NewStringSlice(""), Usage: "The emails (multiple option accepted) to send notifications (if applicable)"}, + &cli.StringSliceFlag{Name: "collaborator", Value: cli.NewStringSlice(""), Usage: "The usernames of the collaborators who will receive notifications"}, }, Usage: "Add a notifier for your application", Description: `Add a notifier for your application: @@ -102,7 +104,7 @@ Examples # Use 'platforms-list' to see all available platforms # See also 'notifiers' and 'notifiers-remove' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) if c.String("platform") == "" { @@ -136,6 +138,7 @@ Examples if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "notifiers-add") @@ -146,15 +149,15 @@ Examples Name: "notifiers-update", Category: "Notifiers", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "enable, e", Usage: "Enable the notifier"}, - cli.BoolFlag{Name: "disable, d", Usage: "Disable the notifier"}, - cli.StringFlag{Name: "name, n", Value: "", Usage: "Name of the notifier"}, - cli.BoolFlag{Name: "send-all-events, sa", Usage: "If true the notifier will send all events. Default: false"}, - cli.StringFlag{Name: "webhook-url, u", Value: "", Usage: "The webhook url to send notification (if applicable)"}, - cli.StringFlag{Name: "phone", Value: "", Usage: "The phone number to send notifications (if applicable)"}, - cli.StringFlag{Name: "email", Value: "", Usage: "The email to send notifications (if applicable)"}, - cli.StringSliceFlag{Name: "event, ev", Value: &cli.StringSlice{}, Usage: "List of selected events. Default: []"}, + &appFlag, + &cli.BoolFlag{Name: "enable", Aliases: []string{"e"}, Usage: "Enable the notifier"}, + &cli.BoolFlag{Name: "disable", Aliases: []string{"d"}, Usage: "Disable the notifier"}, + &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: "", Usage: "Name of the notifier"}, + &cli.BoolFlag{Name: "send-all-events", Aliases: []string{"sa"}, Usage: "If true the notifier will send all events. Default: false"}, + &cli.StringFlag{Name: "webhook-url", Aliases: []string{"u"}, Value: "", Usage: "The webhook url to send notification (if applicable)"}, + &cli.StringFlag{Name: "phone", Value: "", Usage: "The phone number to send notifications (if applicable)"}, + &cli.StringFlag{Name: "email", Value: "", Usage: "The email to send notifications (if applicable)"}, + &cli.StringSliceFlag{Name: "event", Aliases: []string{"ev"}, Value: cli.NewStringSlice(""), Usage: "List of selected events. Default: []"}, }, Usage: "Update a notifier", Description: `Update a notifier: @@ -169,7 +172,7 @@ Examples # See also 'notifiers' and 'notifiers-remove' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error @@ -206,14 +209,15 @@ Examples WebhookURL: c.String("webhook-url"), }, } - if len(c.Args()) >= 1 { - err = notifiers.Update(currentApp, c.Args()[0], params) + if c.Args().Len() >= 1 { + err = notifiers.Update(currentApp, c.Args().First(), params) } else { cli.ShowCommandHelp(c, "notifiers-update") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "notifiers-update") @@ -224,24 +228,25 @@ Examples NotifiersRemoveCommand = cli.Command{ Name: "notifiers-remove", Category: "Notifiers", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Remove an existing notifier from your app", Description: `Remove an existing notifier from your app: $ scalingo -a myapp notifier-remove # See also 'notifiers' and 'notifiers-add' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 1 { - err = notifiers.Destroy(currentApp, c.Args()[0]) + if c.Args().Len() == 1 { + err = notifiers.Destroy(currentApp, c.Args().First()) } else { cli.ShowCommandHelp(c, "notifiers-remove") } if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "notifiers-remove") diff --git a/cmd/one_off_stop.go b/cmd/one_off_stop.go index adc4eb86c..395d24eb7 100644 --- a/cmd/one_off_stop.go +++ b/cmd/one_off_stop.go @@ -3,7 +3,7 @@ package cmd import ( "regexp" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -15,18 +15,18 @@ var ( Name: "one-off-stop", Category: "App Management", Usage: "Stop a running one-off container", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Stop a running one-off container Example 'scalingo --app my-app one-off-stop one-off-1234' 'scalingo --app my-app one-off-stop 1234'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "one-off-stop") - return + return nil } - oneOffLabel := c.Args()[0] + oneOffLabel := c.Args().First() // If oneOffLabel only contains digits, the client typed something like: // scalingo one-off-stop 1234 @@ -43,6 +43,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "one-off-stop") diff --git a/cmd/open.go b/cmd/open.go index 53083489e..104aa27ce 100644 --- a/cmd/open.go +++ b/cmd/open.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,14 +13,14 @@ var ( openCommand = cli.Command{ Name: "open", Category: "App Management", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Open app on default web browser", Description: `Open app on default web browser: $ scalingo --app my-app open`, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "open") - return + return nil } currentApp := detect.CurrentApp(c) @@ -30,6 +30,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "open") diff --git a/cmd/pgsql.go b/cmd/pgsql.go index 806e94b33..fd9778ca0 100644 --- a/cmd/pgsql.go +++ b/cmd/pgsql.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/db" @@ -14,9 +14,9 @@ var ( Aliases: []string{"psql-console", "postgresql-console"}, Category: "Databases", Usage: "Run an interactive console with your PostgreSQL addon", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "size, s", Value: "", Usage: "Size of the container"}, - cli.StringFlag{Name: "env, e", Value: "", Usage: "Environment variable name to use for the connection to the database"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "size", Aliases: []string{"s"}, Value: "", Usage: "Size of the container"}, + &cli.StringFlag{Name: "env", Aliases: []string{"e"}, Value: "", Usage: "Environment variable name to use for the connection to the database"}, }, Description: ` Run an interactive console with your PostgreSQL addon. @@ -32,10 +32,10 @@ var ( # See also 'mongo-console' and 'mysql-console' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "pgsql-console") - return + return nil } err := db.PgSQLConsole(db.PgSQLConsoleOpts{ @@ -46,6 +46,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "pgsql-console") diff --git a/cmd/ps.go b/cmd/ps.go index 635e35218..a4afe694c 100644 --- a/cmd/ps.go +++ b/cmd/ps.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,21 +13,22 @@ var ( Name: "ps", Category: "App Management", Usage: "Display your application containers", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Display your application containers Example 'scalingo --app my-app ps'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "ps") - return + return nil } err := apps.Ps(currentApp) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "ps") diff --git a/cmd/redis.go b/cmd/redis.go index b72878fae..e7c8b10df 100644 --- a/cmd/redis.go +++ b/cmd/redis.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/db" @@ -13,9 +13,9 @@ var ( Name: "redis-console", Category: "Databases", Usage: "Run an interactive console with your Redis addon", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "size, s", Value: "", Usage: "Size of the container"}, - cli.StringFlag{Name: "env, e", Value: "", Usage: "Environment variable name to use for the connection to the database"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "size", Aliases: []string{"s"}, Value: "", Usage: "Size of the container"}, + &cli.StringFlag{Name: "env", Aliases: []string{"e"}, Value: "", Usage: "Environment variable name to use for the connection to the database"}, }, Description: ` Run an interactive console with your Redis addon. @@ -31,10 +31,10 @@ var ( # See also 'mongo-console' and 'mysql-console' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "redis-console") - return + return nil } err := db.RedisConsole(db.RedisConsoleOpts{ @@ -45,6 +45,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "redis-console") diff --git a/cmd/region_migrations.go b/cmd/region_migrations.go index c073086ab..e457653b2 100644 --- a/cmd/region_migrations.go +++ b/cmd/region_migrations.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/detect" @@ -14,54 +14,55 @@ var ( Name: "migration-create", Category: "Region migrations", Flags: []cli.Flag{ - appFlag, - cli.StringFlag{Name: "to", Usage: "Select the destination region"}, - cli.StringFlag{Name: "new-name", Usage: "Name of the app in the destination region (same as origin by default)"}, + &appFlag, + &cli.StringFlag{Name: "to", Usage: "Select the destination region"}, + &cli.StringFlag{Name: "new-name", Usage: "Name of the app in the destination region (same as origin by default)"}, }, Usage: "Start migrating an app to another region", Description: `Migrate an app to another region. Example 'scalingo --app my-app migration-create --to osc-fr1' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "migration-create") - return + return nil } if c.String("to") == "" { cli.ShowCommandHelp(c, "migration-create") - return + return nil } err := region_migrations.Create(currentApp, c.String("to"), c.String("new-name")) if err != nil { errorQuit(err) } + return nil }, } migrationRunCommand = cli.Command{ Name: "migration-run", Category: "Region migrations", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "prepare", Usage: "Create an empty canvas on the new region"}, - cli.BoolFlag{Name: "data", Usage: "Import databases (and their data) to the new region"}, - cli.BoolFlag{Name: "finalize", Usage: "Stop the old app and start the new one"}, + &appFlag, + &cli.BoolFlag{Name: "prepare", Usage: "Create an empty canvas on the new region"}, + &cli.BoolFlag{Name: "data", Usage: "Import databases (and their data) to the new region"}, + &cli.BoolFlag{Name: "finalize", Usage: "Stop the old app and start the new one"}, }, Usage: "Run a specific migration step", Description: `Run a migration step: Example 'scalingo --app my-app migration-run --prepare migration-id' `, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "migration-run") - return + return nil } var step scalingo.RegionMigrationStep - migrationID := c.Args()[0] + migrationID := c.Args().First() currentApp := detect.CurrentApp(c) stepsFound := 0 if c.Bool("prepare") { @@ -78,88 +79,86 @@ var ( } if stepsFound != 1 { cli.ShowCommandHelp(c, "migration-run") - return + return nil } err := region_migrations.Run(currentApp, migrationID, step) if err != nil { errorQuit(err) } + return nil }, } migrationAbortCommand = cli.Command{ Name: "migration-abort", Category: "Region migrations", - Flags: []cli.Flag{ - appFlag, - }, - Usage: "Abort a migration", + Flags: []cli.Flag{&appFlag}, + Usage: "Abort a migration", Description: `Abort a running migration Example 'scalingo --app my-app migration-abort migration-id'`, - Action: func(c *cli.Context) { - if len(c.Args()) != 1 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "migration-run") - return + return nil } - migrationID := c.Args()[0] + migrationID := c.Args().First() currentApp := detect.CurrentApp(c) err := region_migrations.Abort(currentApp, migrationID) if err != nil { errorQuit(err) } + return nil }, } migrationListCommand = cli.Command{ Name: "migrations", Category: "Region migrations", - Flags: []cli.Flag{ - appFlag, - }, - Usage: "List all migrations linked to an app", + Flags: []cli.Flag{&appFlag}, + Usage: "List all migrations linked to an app", Description: `List all migrations linked to an app Example 'scalingo --app my-app migrations' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) err := region_migrations.List(currentApp) if err != nil { errorQuit(err) } + return nil }, } migrationFollowCommand = cli.Command{ Name: "migration-follow", Category: "Region migrations", - Flags: []cli.Flag{ - appFlag, - }, - Usage: "Follow a running migration", + Flags: []cli.Flag{&appFlag}, + Usage: "Follow a running migration", Description: `Listen for new events on a migration Example 'scalingo --app my-app migration-follow migration-id' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "migration-follow") - return + return nil } - migrationID := c.Args()[0] + migrationID := c.Args().First() err := region_migrations.Follow(currentApp, migrationID) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.RegionMigrationsAutoComplete(c) diff --git a/cmd/regions.go b/cmd/regions.go index f989f7ce0..e66a019ac 100644 --- a/cmd/regions.go +++ b/cmd/regions.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/regions" @@ -15,11 +15,12 @@ var ( Description: ` Example 'scalingo regions'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := regions.List() if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "regions") diff --git a/cmd/rename.go b/cmd/rename.go index 27b26f4c1..30cac3b4e 100644 --- a/cmd/rename.go +++ b/cmd/rename.go @@ -3,7 +3,7 @@ package cmd import ( "errors" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -15,16 +15,12 @@ var ( Name: "rename", Category: "App Management", Flags: []cli.Flag{ - appFlag, - cli.StringFlag{ - Name: "new-name", - Value: "", - Usage: "New name to give to the app", - }, + &appFlag, + &cli.StringFlag{Name: "new-name", Value: "", Usage: "New name to give to the app"}, }, Usage: "Rename an application", Description: "Rename an app\n Example:\n 'scalingo rename --app my-app --new-name my-app-production'", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) newName := c.String("new-name") if newName == "" { @@ -34,6 +30,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "rename") diff --git a/cmd/restart.go b/cmd/restart.go index 0f36d69fb..e963a1d86 100644 --- a/cmd/restart.go +++ b/cmd/restart.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -13,7 +13,9 @@ var ( Name: "restart", Category: "App Management", Usage: "Restart processes of your app", - Flags: []cli.Flag{appFlag, cli.BoolFlag{Name: "synchronous, s", Usage: "Do the restart synchronously", EnvVar: ""}}, + Flags: []cli.Flag{&appFlag, + &cli.BoolFlag{Name: "synchronous", Aliases: []string{"s"}, Usage: "Do the restart synchronously"}, + }, Description: `Restart one or several process or your application: Example ## Restart all the processes @@ -23,11 +25,12 @@ var ( ## Restart a specific container scalingo --app my-app restart web-1`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if err := apps.Restart(currentApp, c.Bool("s"), c.Args()); err != nil { + if err := apps.Restart(currentApp, c.Bool("s"), c.Args().Slice()); err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { diff --git a/cmd/review_apps.go b/cmd/review_apps.go index 28fa7fe23..83d416ba1 100644 --- a/cmd/review_apps.go +++ b/cmd/review_apps.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/review_apps" @@ -13,15 +13,15 @@ var ( reviewAppsShowCommand = cli.Command{ Name: "review-apps", Category: "Review Apps", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Usage: "Show review apps of the parent application", Description: `Show review apps of the parent application: $ scalingo --app my-app review-apps`, - Action: func(c *cli.Context) { - if len(c.Args()) != 0 { + Action: func(c *cli.Context) error { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "review-apps") - return + return nil } currentApp := detect.CurrentApp(c) @@ -29,6 +29,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "review-apps") diff --git a/cmd/routing_settings.go b/cmd/routing_settings.go index 3320aea7e..f7e6d6a09 100644 --- a/cmd/routing_settings.go +++ b/cmd/routing_settings.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -14,20 +14,20 @@ var ( Category: "App Management", Usage: "Enable/Disable automatic redirection of traffic to HTTPS for your application", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "enable, e", Usage: "Enable force HTTPS (default)"}, - cli.BoolFlag{Name: "disable, d", Usage: "Disable force HTTPS"}, + &appFlag, + &cli.BoolFlag{Name: "enable", Aliases: []string{"e"}, Usage: "Enable force HTTPS (default)"}, + &cli.BoolFlag{Name: "disable", Aliases: []string{"d"}, Usage: "Disable force HTTPS"}, }, Description: `When enabled, this feature will automatically redirect HTTP traffic to HTTPS for all domains associated with this application. Example scalingo --app my-app force-https --enable `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) > 1 { + if c.Args().Len() > 1 { cli.ShowCommandHelp(c, "force-https") - return + return nil } enable := true @@ -39,6 +39,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "force-https") @@ -50,20 +51,20 @@ var ( Category: "App Management", Usage: "Enable/Disable sticky sessions for your application", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "enable, e", Usage: "Enable sticky session (default)"}, - cli.BoolFlag{Name: "disable, d", Usage: "Disable sticky session"}, + &appFlag, + &cli.BoolFlag{Name: "enable", Aliases: []string{"e"}, Usage: "Enable sticky session (default)"}, + &cli.BoolFlag{Name: "disable", Aliases: []string{"d"}, Usage: "Disable sticky session"}, }, Description: `When enabled, application user sessions will be sticky: they will always return to the same container. Example scalingo --app my-app sticky-session --enable `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) > 1 { + if c.Args().Len() > 1 { cli.ShowCommandHelp(c, "sticky-session") - return + return nil } enable := true @@ -75,6 +76,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "sticky-session") @@ -86,20 +88,20 @@ var ( Category: "App Management", Usage: "Enable/disable router logs for your application", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "enable, e", Usage: "Enable router logs"}, - cli.BoolFlag{Name: "disable, d", Usage: "Disable router logs (default)"}, + &appFlag, + &cli.BoolFlag{Name: "enable", Aliases: []string{"e"}, Usage: "Enable router logs"}, + &cli.BoolFlag{Name: "disable", Aliases: []string{"d"}, Usage: "Disable router logs (default)"}, }, Description: `Enable/disable router logs for your application. Example scalingo --app my-app router-logs --enable `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) > 1 { + if c.Args().Len() > 1 { cli.ShowCommandHelp(c, "router-logs") - return + return nil } enable := false @@ -111,6 +113,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "router-logs") diff --git a/cmd/run.go b/cmd/run.go index b2c7dd782..1eca72c2a 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -10,20 +10,17 @@ import ( ) var ( - EnvFlag = cli.StringSlice([]string{}) - FilesFlag = cli.StringSlice([]string{}) runCommand = cli.Command{ - Name: "run", - ShortName: "r", - Category: "App Management", - Usage: "Run any command for your app", - Flags: []cli.Flag{appFlag, - cli.BoolFlag{Name: "detached, d", Usage: "Run a detached container"}, - cli.StringFlag{Name: "size, s", Value: "", Usage: "Size of the container"}, - cli.StringFlag{Name: "type, t", Value: "", Usage: "Procfile Type"}, - cli.StringSliceFlag{Name: "env, e", Value: &EnvFlag, Usage: "Environment variables"}, - cli.StringSliceFlag{Name: "file, f", Value: &FilesFlag, Usage: "Files to upload"}, - cli.BoolFlag{Name: "silent", Usage: "Do not output anything on stderr"}, + Name: "run", + Category: "App Management", + Usage: "Run any command for your app", + Flags: []cli.Flag{&appFlag, + &cli.BoolFlag{Name: "detached", Aliases: []string{"d"}, Usage: "Run a detached container"}, + &cli.StringFlag{Name: "size", Aliases: []string{"s"}, Value: "", Usage: "Size of the container"}, + &cli.StringFlag{Name: "type", Aliases: []string{"t"}, Value: "", Usage: "Procfile Type"}, + &cli.StringSliceFlag{Name: "env", Aliases: []string{"e"}, Usage: "Environment variables"}, + &cli.StringSliceFlag{Name: "file", Aliases: []string{"f"}, Usage: "Files to upload"}, + &cli.BoolFlag{Name: "silent", Usage: "Do not output anything on stderr"}, }, Description: `Run command in current app context, a one-off container will be start with your application environment loaded. @@ -76,11 +73,11 @@ var ( Example scalingo run --file mysqldump.sql rails dbconsole < /tmp/uploads/mysqldump.sql`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) opts := apps.RunOpts{ App: currentApp, - Cmd: c.Args(), + Cmd: c.Args().Slice(), Size: c.String("s"), Type: c.String("t"), CmdEnv: c.StringSlice("e"), @@ -88,20 +85,21 @@ var ( Silent: c.Bool("silent"), Detached: c.Bool("detached"), } - if (len(c.Args()) == 0 && c.String("t") == "") || (len(c.Args()) > 0 && c.String("t") != "") { + if (c.Args().Len() == 0 && c.String("t") == "") || (c.Args().Len() > 0 && c.String("t") != "") { cli.ShowCommandHelp(c, "run") - return + return nil } if opts.Detached && len(opts.Files) > 0 { io.Error("It is currently impossible to use detached one-off with an uploaded file. Please either remove the --detached or --file flags.") - return + return nil } err := apps.Run(opts) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "run") diff --git a/cmd/scale.go b/cmd/scale.go index 4ec5e2e64..704a7412a 100644 --- a/cmd/scale.go +++ b/cmd/scale.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -10,11 +10,10 @@ import ( var ( scaleCommand = cli.Command{ - Name: "scale", - ShortName: "s", - Category: "App Management", - Flags: []cli.Flag{appFlag, - cli.BoolFlag{Name: "synchronous, s", Usage: "Do the scaling synchronously", EnvVar: ""}, + Name: "scale", + Category: "App Management", + Flags: []cli.Flag{&appFlag, + &cli.BoolFlag{Name: "synchronous", Aliases: []string{"s"}, Usage: "Do the scaling synchronously"}, }, Usage: "Scale your application instantly", Description: `Scale your application processes. Without argument, this command lists the container types declared in your application. @@ -24,21 +23,22 @@ var ( 'scalingo --app my-app scale web:1:XL' 'scalingo --app my-app scale web:+1 worker:-1' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err := apps.ContainerTypes(currentApp) if err != nil { errorQuit(err) } - return + return nil } - err := apps.Scale(currentApp, c.Bool("s"), c.Args()) + err := apps.Scale(currentApp, c.Bool("s"), c.Args().Slice()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "scale") diff --git a/cmd/scm_integrations.go b/cmd/scm_integrations.go index 2a203524b..8afae6204 100644 --- a/cmd/scm_integrations.go +++ b/cmd/scm_integrations.go @@ -5,7 +5,7 @@ import ( "fmt" "net/url" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/scmintegrations" @@ -23,11 +23,12 @@ var ( # See also commands 'integrations-add', 'integrations-delete', 'integrations-import-keys'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := scmintegrations.List() if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integrations") @@ -37,9 +38,9 @@ var ( integrationsAddCommand = cli.Command{ Name: "integrations-add", Category: "Integrations", - Flags: []cli.Flag{appFlag, - cli.StringFlag{Name: "url", Usage: "URL of the integration"}, - cli.StringFlag{Name: "token", Usage: "Token of the integration"}, + Flags: []cli.Flag{&appFlag, + &cli.StringFlag{Name: "url", Usage: "URL of the integration"}, + &cli.StringFlag{Name: "token", Usage: "Token of the integration"}, }, Usage: "Link your Scalingo account with your account on a tool such as github.com", Description: `Link your Scalingo account with your account on a tool. After creating the link, you will be able to automatically deploy when pushing to your repository, or create Review Apps for all pull requests created. @@ -58,15 +59,15 @@ var ( # See also commands 'integrations', 'integrations-delete', 'integrations-import-keys'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if c.NArg() != 1 { _ = cli.ShowCommandHelp(c, "integrations-add") - return + return nil } integrationURL := c.String("url") token := c.String("token") - scmType := scalingo.SCMType(c.Args()[0]) + scmType := scalingo.SCMType(c.Args().First()) switch scmType { case scalingo.SCMGithubType, scalingo.SCMGitlabType: @@ -96,6 +97,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integrations-add") @@ -118,16 +120,17 @@ var ( # See also commands 'integrations', 'integrations-add', 'integrations-import-keys'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if c.NArg() != 1 { _ = cli.ShowCommandHelp(c, "integrations-delete") - return + return nil } - err := scmintegrations.Delete(c.Args()[0]) + err := scmintegrations.Delete(c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integrations-delete") @@ -150,16 +153,17 @@ var ( # See also commands 'integrations', 'integrations-add', 'integrations-delete'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { if c.NArg() != 1 { _ = cli.ShowCommandHelp(c, "integrations-import-keys") - return + return nil } - err := scmintegrations.ImportKeys(c.Args()[0]) + err := scmintegrations.ImportKeys(c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { _ = autocomplete.CmdFlagsAutoComplete(c, "integrations-import-keys") diff --git a/cmd/self.go b/cmd/self.go index f86929152..5d859405c 100644 --- a/cmd/self.go +++ b/cmd/self.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/user" ) @@ -13,11 +13,12 @@ var ( Category: "Global", Usage: "Get the logged in profile", Description: "Returns the logged in profile and print its username. Comes in handy when owning multiple accounts.", - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := user.Self() if err != nil { errorQuit(err) } + return nil }, } ) diff --git a/cmd/stacks.go b/cmd/stacks.go index e52db35b5..5a2b24865 100644 --- a/cmd/stacks.go +++ b/cmd/stacks.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/detect" @@ -20,11 +20,12 @@ var ( # See also 'stacks-set' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := stacks.List() if err != nil { errorQuit(err) } + return nil }, } @@ -32,7 +33,7 @@ var ( Name: "stacks-set", Category: "Runtime Stacks", Usage: "Set the runtime stack of an app", - Flags: []cli.Flag{appFlag}, + Flags: []cli.Flag{&appFlag}, Description: `Set the runtime stack of an app (deployment cache will be reset): Example: @@ -40,17 +41,18 @@ var ( # See also 'stacks' `, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 1 { + if c.Args().Len() != 1 { cli.ShowCommandHelp(c, "stacks-set") - return + return nil } - err := stacks.Set(currentApp, c.Args()[0]) + err := stacks.Set(currentApp, c.Args().First()) if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.StacksSetAutoComplete(c) diff --git a/cmd/stats.go b/cmd/stats.go index ac9dd3616..09a37cbdc 100644 --- a/cmd/stats.go +++ b/cmd/stats.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/detect" @@ -13,19 +13,20 @@ var ( Category: "Display metrics of the running containers", Usage: "Display metrics of the currently running containers", Flags: []cli.Flag{ - appFlag, - cli.BoolFlag{Name: "stream", Usage: "Stream metrics data"}, + &appFlag, + &cli.BoolFlag{Name: "stream", Usage: "Stream metrics data"}, }, Description: `Display metrics of you application running containers Example 'scalingo --app my-app stats'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) - if len(c.Args()) != 0 { + if c.Args().Len() != 0 { cli.ShowCommandHelp(c, "stats") } else if err := apps.Stats(currentApp, c.Bool("stream")); err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { return diff --git a/cmd/suggestions.go b/cmd/suggestions.go index 00b9baa99..d9f75ae8f 100644 --- a/cmd/suggestions.go +++ b/cmd/suggestions.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) func ShowSuggestions(c *cli.Context) { @@ -27,7 +27,7 @@ func ShowSuggestions(c *cli.Context) { } } - if len(c.Args()) > 0 && len(suggestions) > 0 { + if c.Args().Len() > 0 && len(suggestions) > 0 { fmt.Println("You might be looking for:") for _, s := range suggestions { fmt.Printf(" - '%s'\n", s) diff --git a/cmd/timeline.go b/cmd/timeline.go index 079ba9b82..e11bd09f8 100644 --- a/cmd/timeline.go +++ b/cmd/timeline.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/apps" "github.com/Scalingo/cli/cmd/autocomplete" @@ -14,18 +14,18 @@ var ( Name: "timeline", Category: "Events", Flags: []cli.Flag{ - appFlag, - cli.IntFlag{Name: "page", Usage: "Page to display", Value: 1}, - cli.IntFlag{Name: "per-page", Usage: "Number of events to display", Value: 30}, + &appFlag, + &cli.IntFlag{Name: "page", Usage: "Page to display", Value: 1}, + &cli.IntFlag{Name: "per-page", Usage: "Number of events to display", Value: 30}, }, Usage: "List the actions related to a given app", Description: `List the actions done by the owner and collaborators of an app: $ scalingo -a myapp timeline`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { currentApp := detect.CurrentApp(c) var err error - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err = apps.Events(currentApp, scalingo.PaginationOpts{ Page: c.Int("page"), PerPage: c.Int("per-page"), @@ -37,6 +37,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "timeline") diff --git a/cmd/update.go b/cmd/update.go index 08d3570c0..a56455c6a 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/update" @@ -15,11 +15,12 @@ var ( Description: `Update 'scalingo' SDK client Example 'scalingo update'`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { err := update.Check() if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "update") diff --git a/cmd/user-timeline.go b/cmd/user-timeline.go index 784232f0a..f6e5e928b 100644 --- a/cmd/user-timeline.go +++ b/cmd/user-timeline.go @@ -1,7 +1,7 @@ package cmd import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd/autocomplete" "github.com/Scalingo/cli/user" @@ -13,16 +13,16 @@ var ( Name: "user-timeline", Category: "Events", Flags: []cli.Flag{ - cli.IntFlag{Name: "page", Usage: "Page to display", Value: 1}, - cli.IntFlag{Name: "per-page", Usage: "Number of events to display", Value: 30}, + &cli.IntFlag{Name: "page", Usage: "Page to display", Value: 1}, + &cli.IntFlag{Name: "per-page", Usage: "Number of events to display", Value: 30}, }, Usage: "List the events you have done on the platform", Description: `List the events you have done on the platform: $ scalingo user-timeline`, - Action: func(c *cli.Context) { + Action: func(c *cli.Context) error { var err error - if len(c.Args()) == 0 { + if c.Args().Len() == 0 { err = user.Events(scalingo.PaginationOpts{ Page: c.Int("page"), PerPage: c.Int("per-page"), @@ -34,6 +34,7 @@ var ( if err != nil { errorQuit(err) } + return nil }, BashComplete: func(c *cli.Context) { autocomplete.CmdFlagsAutoComplete(c, "user-timeline") diff --git a/detect/app.go b/detect/app.go index aaa36b5ac..36ec7b7b8 100644 --- a/detect/app.go +++ b/detect/app.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/utils" @@ -20,14 +20,12 @@ func CurrentApp(c *cli.Context) string { var appName string var err error - if c.GlobalString("app") != "" { - appName = c.GlobalString("app") - } else if c.String("app") != "" { + if c.String("app") != "" { appName = c.String("app") } else if os.Getenv("SCALINGO_APP") != "" { appName = os.Getenv("SCALINGO_APP") } else if dir, ok := utils.DetectGit(); ok { - appName, err = GetAppNameFromGitRemote(dir, c.GlobalString("remote")) + appName, err = GetAppNameFromGitRemote(dir, c.String("remote")) if err != nil { debug.Println(err) } diff --git a/detect/region.go b/detect/region.go index 99c614315..abe330cc8 100644 --- a/detect/region.go +++ b/detect/region.go @@ -4,7 +4,7 @@ import ( "regexp" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "gopkg.in/errgo.v1" "github.com/Scalingo/cli/config" @@ -16,7 +16,7 @@ import ( // GetRegionFromGitRemote returns the region name extracted from remotes URL of the current Git repository // If not found it returns an empty string func GetRegionFromGitRemote(c *cli.Context, rc *config.RegionsCache) string { - remoteName := c.GlobalString("remote") + remoteName := c.String("remote") if dir, ok := utils.DetectGit(); ok { remotes, err := utils.ScalingoGitRemotes(dir) diff --git a/go.mod b/go.mod index d33daba5b..40f8543ac 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.0 github.com/stvp/rollbar v0.5.1 - github.com/urfave/cli v1.22.9 + github.com/urfave/cli/v2 v2.11.2 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d golang.org/x/net v0.0.0-20220607020251-c690dde0001d golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 @@ -34,7 +34,7 @@ require ( github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect github.com/emirpasic/gods v1.12.0 // indirect @@ -54,10 +54,10 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/russross/blackfriday/v2 v2.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 31ff609ca..2bc47b4c3 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -30,8 +30,8 @@ github.com/briandowns/spinner v1.19.0 h1:s8aq38H+Qju89yhp89b4iIiMzMm8YN3p6vGpwyh github.com/briandowns/spinner v1.19.0/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU= github.com/cheggaaa/pb/v3 v3.1.0 h1:3uouEsl32RL7gTiQsuaXD4Bzbfl5tGztXGUvXbs4O04= github.com/cheggaaa/pb/v3 v3.1.0/go.mod h1:YjrevcBqadFDaGQKRdmZxTY42pXEqda48Ea3lt0K/BE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -132,12 +132,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -153,10 +151,12 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stvp/rollbar v0.5.1 h1:qvyWbd0RNL5V27MBumqCXlcU7ohmHeEtKX+Czc8oeuw= github.com/stvp/rollbar v0.5.1/go.mod h1:/fyFC854GgkbHRz/rSsiYc6h84o0G5hxBezoQqRK7Ho= -github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= -github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.11.2 h1:FVfNg4m3vbjbBpLYxW//WjxUoHvJ9TlppXcqY9Q9ZfA= +github.com/urfave/cli/v2 v2.11.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/integrationlink/params.go b/integrationlink/params.go index 353e702ba..1362a9f4b 100644 --- a/integrationlink/params.go +++ b/integrationlink/params.go @@ -1,7 +1,7 @@ package integrationlink import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/go-scalingo/v4" ) diff --git a/scalingo/main.go b/scalingo/main.go index 8678e66de..08f02b6e6 100644 --- a/scalingo/main.go +++ b/scalingo/main.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/stvp/rollbar" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/Scalingo/cli/cmd" "github.com/Scalingo/cli/cmd/autocomplete" @@ -16,10 +16,10 @@ import ( ) var ( - completionFlag = "--" + cli.BashCompletionFlag.GetName() + completionFlag = "--" + cli.BashCompletionFlag.Names()[0] ) -func DefaultAction(c *cli.Context) { +func DefaultAction(c *cli.Context) error { completeMode := false for i := range os.Args { @@ -30,7 +30,7 @@ func DefaultAction(c *cli.Context) { } if !completeMode { - cmd.HelpCommand.Action.(func(*cli.Context))(c) + cmd.HelpCommand.Action(c) cmd.ShowSuggestions(c) } else { i := len(os.Args) - 2 @@ -38,6 +38,8 @@ func DefaultAction(c *cli.Context) { autocomplete.FlagsAutoComplete(c, os.Args[i]) } } + + return nil } func ScalingoAppComplete(c *cli.Context) { @@ -101,15 +103,14 @@ COPYRIGHT: func main() { app := cli.NewApp() app.Name = "Scalingo Client" - app.Author = "Scalingo Team" - app.Email = "hello@scalingo.com" + app.Authors = []*cli.Author{{Name: "Scalingo Team", Email: "hello@scalingo.com"}} app.Usage = "Manage your apps and containers" app.Version = config.Version app.Flags = []cli.Flag{ - cli.StringFlag{Name: "addon", Value: "", Usage: "ID of the current addon", EnvVar: "SCALINGO_ADDON"}, - cli.StringFlag{Name: "app, a", Value: "", Usage: "Name of the app", EnvVar: "SCALINGO_APP"}, - cli.StringFlag{Name: "remote, r", Value: "scalingo", Usage: "Name of the remote", EnvVar: ""}, - cli.StringFlag{Name: "region", Value: "", Usage: "Name of the region to use"}, + &cli.StringFlag{Name: "addon", Value: "", Usage: "ID of the current addon", EnvVars: []string{"SCALINGO_ADDON"}}, + &cli.StringFlag{Name: "app", Aliases: []string{"a"}, Value: "", Usage: "Name of the app", EnvVars: []string{"SCALINGO_APP"}}, + &cli.StringFlag{Name: "remote", Aliases: []string{"r"}, Value: "scalingo", Usage: "Name of the remote"}, + &cli.StringFlag{Name: "region", Value: "", Usage: "Name of the region to use"}, } app.EnableBashCompletion = true app.BashComplete = func(c *cli.Context) { diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go index 0668a66cf..be2b34360 100644 --- a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go @@ -15,7 +15,7 @@ type roffRenderer struct { extensions blackfriday.Extensions listCounters []int firstHeader bool - defineTerm bool + firstDD bool listDepth int } @@ -42,7 +42,8 @@ const ( quoteCloseTag = "\n.RE\n" listTag = "\n.RS\n" listCloseTag = "\n.RE\n" - arglistTag = "\n.TP\n" + dtTag = "\n.TP\n" + dd2Tag = "\n" tableStart = "\n.TS\nallbox;\n" tableEnd = ".TE\n" tableCellStart = "T{\n" @@ -90,7 +91,7 @@ func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering switch node.Type { case blackfriday.Text: - r.handleText(w, node, entering) + escapeSpecialChars(w, node.Literal) case blackfriday.Softbreak: out(w, crTag) case blackfriday.Hardbreak: @@ -150,40 +151,21 @@ func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering out(w, codeCloseTag) case blackfriday.Table: r.handleTable(w, node, entering) - case blackfriday.TableCell: - r.handleTableCell(w, node, entering) case blackfriday.TableHead: case blackfriday.TableBody: case blackfriday.TableRow: // no action as cell entries do all the nroff formatting return blackfriday.GoToNext + case blackfriday.TableCell: + r.handleTableCell(w, node, entering) + case blackfriday.HTMLSpan: + // ignore other HTML tags default: fmt.Fprintln(os.Stderr, "WARNING: go-md2man does not handle node type "+node.Type.String()) } return walkAction } -func (r *roffRenderer) handleText(w io.Writer, node *blackfriday.Node, entering bool) { - var ( - start, end string - ) - // handle special roff table cell text encapsulation - if node.Parent.Type == blackfriday.TableCell { - if len(node.Literal) > 30 { - start = tableCellStart - end = tableCellEnd - } else { - // end rows that aren't terminated by "tableCellEnd" with a cr if end of row - if node.Parent.Next == nil && !node.Parent.IsHeader { - end = crTag - } - } - } - out(w, start) - escapeSpecialChars(w, node.Literal) - out(w, end) -} - func (r *roffRenderer) handleHeading(w io.Writer, node *blackfriday.Node, entering bool) { if entering { switch node.Level { @@ -230,15 +212,20 @@ func (r *roffRenderer) handleItem(w io.Writer, node *blackfriday.Node, entering if node.ListFlags&blackfriday.ListTypeOrdered != 0 { out(w, fmt.Sprintf(".IP \"%3d.\" 5\n", r.listCounters[len(r.listCounters)-1])) r.listCounters[len(r.listCounters)-1]++ + } else if node.ListFlags&blackfriday.ListTypeTerm != 0 { + // DT (definition term): line just before DD (see below). + out(w, dtTag) + r.firstDD = true } else if node.ListFlags&blackfriday.ListTypeDefinition != 0 { - // state machine for handling terms and following definitions - // since blackfriday does not distinguish them properly, nor - // does it seperate them into separate lists as it should - if !r.defineTerm { - out(w, arglistTag) - r.defineTerm = true + // DD (definition description): line that starts with ": ". + // + // We have to distinguish between the first DD and the + // subsequent ones, as there should be no vertical + // whitespace between the DT and the first DD. + if r.firstDD { + r.firstDD = false } else { - r.defineTerm = false + out(w, dd2Tag) } } else { out(w, ".IP \\(bu 2\n") @@ -251,7 +238,7 @@ func (r *roffRenderer) handleItem(w io.Writer, node *blackfriday.Node, entering func (r *roffRenderer) handleTable(w io.Writer, node *blackfriday.Node, entering bool) { if entering { out(w, tableStart) - //call walker to count cells (and rows?) so format section can be produced + // call walker to count cells (and rows?) so format section can be produced columns := countColumns(node) out(w, strings.Repeat("l ", columns)+"\n") out(w, strings.Repeat("l ", columns)+".\n") @@ -261,28 +248,41 @@ func (r *roffRenderer) handleTable(w io.Writer, node *blackfriday.Node, entering } func (r *roffRenderer) handleTableCell(w io.Writer, node *blackfriday.Node, entering bool) { - var ( - start, end string - ) - if node.IsHeader { - start = codespanTag - end = codespanCloseTag - } if entering { + var start string if node.Prev != nil && node.Prev.Type == blackfriday.TableCell { - out(w, "\t"+start) - } else { - out(w, start) + start = "\t" + } + if node.IsHeader { + start += codespanTag + } else if nodeLiteralSize(node) > 30 { + start += tableCellStart } + out(w, start) } else { - // need to carriage return if we are at the end of the header row - if node.IsHeader && node.Next == nil { - end = end + crTag + var end string + if node.IsHeader { + end = codespanCloseTag + } else if nodeLiteralSize(node) > 30 { + end = tableCellEnd + } + if node.Next == nil && end != tableCellEnd { + // Last cell: need to carriage return if we are at the end of the + // header row and content isn't wrapped in a "tablecell" + end += crTag } out(w, end) } } +func nodeLiteralSize(node *blackfriday.Node) int { + total := 0 + for n := node.FirstChild; n != nil; n = n.FirstChild { + total += len(n.Literal) + } + return total +} + // because roff format requires knowing the column count before outputting any table // data we need to walk a table tree and count the columns func countColumns(node *blackfriday.Node) int { @@ -309,15 +309,6 @@ func out(w io.Writer, output string) { io.WriteString(w, output) // nolint: errcheck } -func needsBackslash(c byte) bool { - for _, r := range []byte("-_&\\~") { - if c == r { - return true - } - } - return false -} - func escapeSpecialChars(w io.Writer, text []byte) { for i := 0; i < len(text); i++ { // escape initial apostrophe or period @@ -328,7 +319,7 @@ func escapeSpecialChars(w io.Writer, text []byte) { // directly copy normal characters org := i - for i < len(text) && !needsBackslash(text[i]) { + for i < len(text) && text[i] != '\\' { i++ } if i > org { diff --git a/vendor/github.com/russross/blackfriday/v2/README.md b/vendor/github.com/russross/blackfriday/v2/README.md index d5a8649bd..d9c08a22f 100644 --- a/vendor/github.com/russross/blackfriday/v2/README.md +++ b/vendor/github.com/russross/blackfriday/v2/README.md @@ -1,4 +1,6 @@ -Blackfriday [![Build Status](https://travis-ci.org/russross/blackfriday.svg?branch=master)](https://travis-ci.org/russross/blackfriday) +Blackfriday +[![Build Status][BuildV2SVG]][BuildV2URL] +[![PkgGoDev][PkgGoDevV2SVG]][PkgGoDevV2URL] =========== Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It @@ -16,19 +18,21 @@ It started as a translation from C of [Sundown][3]. Installation ------------ -Blackfriday is compatible with any modern Go release. With Go 1.7 and git -installed: +Blackfriday is compatible with modern Go releases in module mode. +With Go installed: - go get gopkg.in/russross/blackfriday.v2 + go get github.com/russross/blackfriday/v2 -will download, compile, and install the package into your `$GOPATH` -directory hierarchy. Alternatively, you can achieve the same if you -import it into a project: +will resolve and add the package to the current development module, +then build and install it. Alternatively, you can achieve the same +if you import it in a package: - import "gopkg.in/russross/blackfriday.v2" + import "github.com/russross/blackfriday/v2" and `go get` without parameters. +Legacy GOPATH mode is unsupported. + Versions -------- @@ -36,13 +40,9 @@ Versions Currently maintained and recommended version of Blackfriday is `v2`. It's being developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the documentation is available at -https://godoc.org/gopkg.in/russross/blackfriday.v2. +https://pkg.go.dev/github.com/russross/blackfriday/v2. -It is `go get`-able via via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`, -but we highly recommend using package management tool like [dep][7] or -[Glide][8] and make use of semantic versioning. With package management you -should import `github.com/russross/blackfriday` and specify that you're using -version 2.0.0. +It is `go get`-able in module mode at `github.com/russross/blackfriday/v2`. Version 2 offers a number of improvements over v1: @@ -62,6 +62,11 @@ Potential drawbacks: v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for tracking. +If you are still interested in the legacy `v1`, you can import it from +`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found +here: https://pkg.go.dev/github.com/russross/blackfriday. + + Usage ----- @@ -91,7 +96,7 @@ Here's an example of simple usage of Blackfriday together with Bluemonday: ```go import ( "github.com/microcosm-cc/bluemonday" - "github.com/russross/blackfriday" + "github.com/russross/blackfriday/v2" ) // ... @@ -104,6 +109,8 @@ html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) If you want to customize the set of options, use `blackfriday.WithExtensions`, `blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. +### `blackfriday-tool` + You can also check out `blackfriday-tool` for a more complete example of how to use it. Download and install it using: @@ -114,7 +121,7 @@ markdown file using a standalone program. You can also browse the source directly on github if you are just looking for some example code: -* +* Note that if you have not already done so, installing `blackfriday-tool` will be sufficient to download and install @@ -123,6 +130,22 @@ installed in `$GOPATH/bin`. This is a statically-linked binary that can be copied to wherever you need it without worrying about dependencies and library versions. +### Sanitized anchor names + +Blackfriday includes an algorithm for creating sanitized anchor names +corresponding to a given input text. This algorithm is used to create +anchors for headings when `AutoHeadingIDs` extension is enabled. The +algorithm has a specification, so that other packages can create +compatible anchor names and links to those anchors. + +The specification is located at https://pkg.go.dev/github.com/russross/blackfriday/v2#hdr-Sanitized_Anchor_Names. + +[`SanitizedAnchorName`](https://pkg.go.dev/github.com/russross/blackfriday/v2#SanitizedAnchorName) exposes this functionality, and can be used to +create compatible links to the anchor names generated by blackfriday. +This algorithm is also implemented in a small standalone package at +[`github.com/shurcooL/sanitized_anchor_name`](https://pkg.go.dev/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients +that want a small package and don't need full functionality of blackfriday. + Features -------- @@ -199,6 +222,15 @@ implements the following extensions: You can use 3 or more backticks to mark the beginning of the block, and the same number to mark the end of the block. + To preserve classes of fenced code blocks while using the bluemonday + HTML sanitizer, use the following policy: + + ```go + p := bluemonday.UGCPolicy() + p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code") + html := p.SanitizeBytes(unsafe) + ``` + * **Definition lists**. A simple definition list is made of a single-line term followed by a colon and the definition for that term. @@ -250,7 +282,7 @@ Other renderers Blackfriday is structured to allow alternative rendering engines. Here are a few of note: -* [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown): +* [github_flavored_markdown](https://pkg.go.dev/github.com/shurcooL/github_flavored_markdown): provides a GitHub Flavored Markdown renderer with fenced code block highlighting, clickable heading anchor links. @@ -261,20 +293,28 @@ are a few of note: * [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, but for markdown. -* [LaTeX output](https://github.com/Ambrevar/Blackfriday-LaTeX): +* [LaTeX output](https://gitlab.com/ambrevar/blackfriday-latex): renders output as LaTeX. +* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience + integration with the [Chroma](https://github.com/alecthomas/chroma) code + highlighting library. bfchroma is only compatible with v2 of Blackfriday and + provides a drop-in renderer ready to use with Blackfriday, as well as + options and means for further customization. + * [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer. +* [Blackfriday-Slack](https://github.com/karriereat/blackfriday-slack): converts markdown to slack message style + -Todo +TODO ---- * More unit testing -* Improve unicode support. It does not understand all unicode +* Improve Unicode support. It does not understand all Unicode rules (about what constitutes a letter, a punctuation symbol, etc.), so it may fail to detect word boundaries correctly in - some instances. It is safe on all utf-8 input. + some instances. It is safe on all UTF-8 input. License @@ -286,6 +326,10 @@ License [1]: https://daringfireball.net/projects/markdown/ "Markdown" [2]: https://golang.org/ "Go Language" [3]: https://github.com/vmg/sundown "Sundown" - [4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func" + [4]: https://pkg.go.dev/github.com/russross/blackfriday/v2#Parse "Parse func" [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" - [6]: https://labix.org/gopkg.in "gopkg.in" + + [BuildV2SVG]: https://travis-ci.org/russross/blackfriday.svg?branch=v2 + [BuildV2URL]: https://travis-ci.org/russross/blackfriday + [PkgGoDevV2SVG]: https://pkg.go.dev/badge/github.com/russross/blackfriday/v2 + [PkgGoDevV2URL]: https://pkg.go.dev/github.com/russross/blackfriday/v2 diff --git a/vendor/github.com/russross/blackfriday/v2/block.go b/vendor/github.com/russross/blackfriday/v2/block.go index b8607474e..dcd61e6e3 100644 --- a/vendor/github.com/russross/blackfriday/v2/block.go +++ b/vendor/github.com/russross/blackfriday/v2/block.go @@ -18,8 +18,7 @@ import ( "html" "regexp" "strings" - - "github.com/shurcooL/sanitized_anchor_name" + "unicode" ) const ( @@ -259,7 +258,7 @@ func (p *Markdown) prefixHeading(data []byte) int { } if end > i { if id == "" && p.extensions&AutoHeadingIDs != 0 { - id = sanitized_anchor_name.Create(string(data[i:end])) + id = SanitizedAnchorName(string(data[i:end])) } block := p.addBlock(Heading, data[i:end]) block.HeadingID = id @@ -673,6 +672,7 @@ func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { if beg == 0 || beg >= len(data) { return 0 } + fenceLength := beg - 1 var work bytes.Buffer work.Write([]byte(info)) @@ -706,6 +706,7 @@ func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { if doRender { block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer block.IsFenced = true + block.FenceLength = fenceLength finalizeCodeBlock(block) } @@ -1503,7 +1504,7 @@ func (p *Markdown) paragraph(data []byte) int { id := "" if p.extensions&AutoHeadingIDs != 0 { - id = sanitized_anchor_name.Create(string(data[prev:eol])) + id = SanitizedAnchorName(string(data[prev:eol])) } block := p.addBlock(Heading, data[prev:eol]) @@ -1588,3 +1589,24 @@ func skipUntilChar(text []byte, start int, char byte) int { } return i } + +// SanitizedAnchorName returns a sanitized anchor name for the given text. +// +// It implements the algorithm specified in the package comment. +func SanitizedAnchorName(text string) string { + var anchorName []rune + futureDash := false + for _, r := range text { + switch { + case unicode.IsLetter(r) || unicode.IsNumber(r): + if futureDash && len(anchorName) > 0 { + anchorName = append(anchorName, '-') + } + futureDash = false + anchorName = append(anchorName, unicode.ToLower(r)) + default: + futureDash = true + } + } + return string(anchorName) +} diff --git a/vendor/github.com/russross/blackfriday/v2/doc.go b/vendor/github.com/russross/blackfriday/v2/doc.go index 5b3fa9876..57ff152a0 100644 --- a/vendor/github.com/russross/blackfriday/v2/doc.go +++ b/vendor/github.com/russross/blackfriday/v2/doc.go @@ -15,4 +15,32 @@ // // If you're interested in calling Blackfriday from command line, see // https://github.com/russross/blackfriday-tool. +// +// Sanitized Anchor Names +// +// Blackfriday includes an algorithm for creating sanitized anchor names +// corresponding to a given input text. This algorithm is used to create +// anchors for headings when AutoHeadingIDs extension is enabled. The +// algorithm is specified below, so that other packages can create +// compatible anchor names and links to those anchors. +// +// The algorithm iterates over the input text, interpreted as UTF-8, +// one Unicode code point (rune) at a time. All runes that are letters (category L) +// or numbers (category N) are considered valid characters. They are mapped to +// lower case, and included in the output. All other runes are considered +// invalid characters. Invalid characters that precede the first valid character, +// as well as invalid character that follow the last valid character +// are dropped completely. All other sequences of invalid characters +// between two valid characters are replaced with a single dash character '-'. +// +// SanitizedAnchorName exposes this functionality, and can be used to +// create compatible links to the anchor names generated by blackfriday. +// This algorithm is also implemented in a small standalone package at +// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients +// that want a small package and don't need full functionality of blackfriday. package blackfriday + +// NOTE: Keep Sanitized Anchor Name algorithm in sync with package +// github.com/shurcooL/sanitized_anchor_name. +// Otherwise, users of sanitized_anchor_name will get anchor names +// that are incompatible with those generated by blackfriday. diff --git a/vendor/github.com/russross/blackfriday/v2/entities.go b/vendor/github.com/russross/blackfriday/v2/entities.go new file mode 100644 index 000000000..a2c3edb69 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/entities.go @@ -0,0 +1,2236 @@ +package blackfriday + +// Extracted from https://html.spec.whatwg.org/multipage/entities.json +var entities = map[string]bool{ + "Æ": true, + "Æ": true, + "&": true, + "&": true, + "Á": true, + "Á": true, + "Ă": true, + "Â": true, + "Â": true, + "А": true, + "𝔄": true, + "À": true, + "À": true, + "Α": true, + "Ā": true, + "⩓": true, + "Ą": true, + "𝔸": true, + "⁡": true, + "Å": true, + "Å": true, + "𝒜": true, + "≔": true, + "Ã": true, + "Ã": true, + "Ä": true, + "Ä": true, + "∖": true, + "⫧": true, + "⌆": true, + "Б": true, + "∵": true, + "ℬ": true, + "Β": true, + "𝔅": true, + "𝔹": true, + "˘": true, + "ℬ": true, + "≎": true, + "Ч": true, + "©": true, + "©": true, + "Ć": true, + "⋒": true, + "ⅅ": true, + "ℭ": true, + "Č": true, + "Ç": true, + "Ç": true, + "Ĉ": true, + "∰": true, + "Ċ": true, + "¸": true, + "·": true, + "ℭ": true, + "Χ": true, + "⊙": true, + "⊖": true, + "⊕": true, + "⊗": true, + "∲": true, + "”": true, + "’": true, + "∷": true, + "⩴": true, + "≡": true, + "∯": true, + "∮": true, + "ℂ": true, + "∐": true, + "∳": true, + "⨯": true, + "𝒞": true, + "⋓": true, + "≍": true, + "ⅅ": true, + "⤑": true, + "Ђ": true, + "Ѕ": true, + "Џ": true, + "‡": true, + "↡": true, + "⫤": true, + "Ď": true, + "Д": true, + "∇": true, + "Δ": true, + "𝔇": true, + "´": true, + "˙": true, + "˝": true, + "`": true, + "˜": true, + "⋄": true, + "ⅆ": true, + "𝔻": true, + "¨": true, + "⃜": true, + "≐": true, + "∯": true, + "¨": true, + "⇓": true, + "⇐": true, + "⇔": true, + "⫤": true, + "⟸": true, + "⟺": true, + "⟹": true, + "⇒": true, + "⊨": true, + "⇑": true, + "⇕": true, + "∥": true, + "↓": true, + "⤓": true, + "⇵": true, + "̑": true, + "⥐": true, + "⥞": true, + "↽": true, + "⥖": true, + "⥟": true, + "⇁": true, + "⥗": true, + "⊤": true, + "↧": true, + "⇓": true, + "𝒟": true, + "Đ": true, + "Ŋ": true, + "Ð": true, + "Ð": true, + "É": true, + "É": true, + "Ě": true, + "Ê": true, + "Ê": true, + "Э": true, + "Ė": true, + "𝔈": true, + "È": true, + "È": true, + "∈": true, + "Ē": true, + "◻": true, + "▫": true, + "Ę": true, + "𝔼": true, + "Ε": true, + "⩵": true, + "≂": true, + "⇌": true, + "ℰ": true, + "⩳": true, + "Η": true, + "Ë": true, + "Ë": true, + "∃": true, + "ⅇ": true, + "Ф": true, + "𝔉": true, + "◼": true, + "▪": true, + "𝔽": true, + "∀": true, + "ℱ": true, + "ℱ": true, + "Ѓ": true, + ">": true, + ">": true, + "Γ": true, + "Ϝ": true, + "Ğ": true, + "Ģ": true, + "Ĝ": true, + "Г": true, + "Ġ": true, + "𝔊": true, + "⋙": true, + "𝔾": true, + "≥": true, + "⋛": true, + "≧": true, + "⪢": true, + "≷": true, + "⩾": true, + "≳": true, + "𝒢": true, + "≫": true, + "Ъ": true, + "ˇ": true, + "^": true, + "Ĥ": true, + "ℌ": true, + "ℋ": true, + "ℍ": true, + "─": true, + "ℋ": true, + "Ħ": true, + "≎": true, + "≏": true, + "Е": true, + "IJ": true, + "Ё": true, + "Í": true, + "Í": true, + "Î": true, + "Î": true, + "И": true, + "İ": true, + "ℑ": true, + "Ì": true, + "Ì": true, + "ℑ": true, + "Ī": true, + "ⅈ": true, + "⇒": true, + "∬": true, + "∫": true, + "⋂": true, + "⁣": true, + "⁢": true, + "Į": true, + "𝕀": true, + "Ι": true, + "ℐ": true, + "Ĩ": true, + "І": true, + "Ï": true, + "Ï": true, + "Ĵ": true, + "Й": true, + "𝔍": true, + "𝕁": true, + "𝒥": true, + "Ј": true, + "Є": true, + "Х": true, + "Ќ": true, + "Κ": true, + "Ķ": true, + "К": true, + "𝔎": true, + "𝕂": true, + "𝒦": true, + "Љ": true, + "<": true, + "<": true, + "Ĺ": true, + "Λ": true, + "⟪": true, + "ℒ": true, + "↞": true, + "Ľ": true, + "Ļ": true, + "Л": true, + "⟨": true, + "←": true, + "⇤": true, + "⇆": true, + "⌈": true, + "⟦": true, + "⥡": true, + "⇃": true, + "⥙": true, + "⌊": true, + "↔": true, + "⥎": true, + "⊣": true, + "↤": true, + "⥚": true, + "⊲": true, + "⧏": true, + "⊴": true, + "⥑": true, + "⥠": true, + "↿": true, + "⥘": true, + "↼": true, + "⥒": true, + "⇐": true, + "⇔": true, + "⋚": true, + "≦": true, + "≶": true, + "⪡": true, + "⩽": true, + "≲": true, + "𝔏": true, + "⋘": true, + "⇚": true, + "Ŀ": true, + "⟵": true, + "⟷": true, + "⟶": true, + "⟸": true, + "⟺": true, + "⟹": true, + "𝕃": true, + "↙": true, + "↘": true, + "ℒ": true, + "↰": true, + "Ł": true, + "≪": true, + "⤅": true, + "М": true, + " ": true, + "ℳ": true, + "𝔐": true, + "∓": true, + "𝕄": true, + "ℳ": true, + "Μ": true, + "Њ": true, + "Ń": true, + "Ň": true, + "Ņ": true, + "Н": true, + "​": true, + "​": true, + "​": true, + "​": true, + "≫": true, + "≪": true, + " ": true, + "𝔑": true, + "⁠": true, + " ": true, + "ℕ": true, + "⫬": true, + "≢": true, + "≭": true, + "∦": true, + "∉": true, + "≠": true, + "≂̸": true, + "∄": true, + "≯": true, + "≱": true, + "≧̸": true, + "≫̸": true, + "≹": true, + "⩾̸": true, + "≵": true, + "≎̸": true, + "≏̸": true, + "⋪": true, + "⧏̸": true, + "⋬": true, + "≮": true, + "≰": true, + "≸": true, + "≪̸": true, + "⩽̸": true, + "≴": true, + "⪢̸": true, + "⪡̸": true, + "⊀": true, + "⪯̸": true, + "⋠": true, + "∌": true, + "⋫": true, + "⧐̸": true, + "⋭": true, + "⊏̸": true, + "⋢": true, + "⊐̸": true, + "⋣": true, + "⊂⃒": true, + "⊈": true, + "⊁": true, + "⪰̸": true, + "⋡": true, + "≿̸": true, + "⊃⃒": true, + "⊉": true, + "≁": true, + "≄": true, + "≇": true, + "≉": true, + "∤": true, + "𝒩": true, + "Ñ": true, + "Ñ": true, + "Ν": true, + "Œ": true, + "Ó": true, + "Ó": true, + "Ô": true, + "Ô": true, + "О": true, + "Ő": true, + "𝔒": true, + "Ò": true, + "Ò": true, + "Ō": true, + "Ω": true, + "Ο": true, + "𝕆": true, + "“": true, + "‘": true, + "⩔": true, + "𝒪": true, + "Ø": true, + "Ø": true, + "Õ": true, + "Õ": true, + "⨷": true, + "Ö": true, + "Ö": true, + "‾": true, + "⏞": true, + "⎴": true, + "⏜": true, + "∂": true, + "П": true, + "𝔓": true, + "Φ": true, + "Π": true, + "±": true, + "ℌ": true, + "ℙ": true, + "⪻": true, + "≺": true, + "⪯": true, + "≼": true, + "≾": true, + "″": true, + "∏": true, + "∷": true, + "∝": true, + "𝒫": true, + "Ψ": true, + """: true, + """: true, + "𝔔": true, + "ℚ": true, + "𝒬": true, + "⤐": true, + "®": true, + "®": true, + "Ŕ": true, + "⟫": true, + "↠": true, + "⤖": true, + "Ř": true, + "Ŗ": true, + "Р": true, + "ℜ": true, + "∋": true, + "⇋": true, + "⥯": true, + "ℜ": true, + "Ρ": true, + "⟩": true, + "→": true, + "⇥": true, + "⇄": true, + "⌉": true, + "⟧": true, + "⥝": true, + "⇂": true, + "⥕": true, + "⌋": true, + "⊢": true, + "↦": true, + "⥛": true, + "⊳": true, + "⧐": true, + "⊵": true, + "⥏": true, + "⥜": true, + "↾": true, + "⥔": true, + "⇀": true, + "⥓": true, + "⇒": true, + "ℝ": true, + "⥰": true, + "⇛": true, + "ℛ": true, + "↱": true, + "⧴": true, + "Щ": true, + "Ш": true, + "Ь": true, + "Ś": true, + "⪼": true, + "Š": true, + "Ş": true, + "Ŝ": true, + "С": true, + "𝔖": true, + "↓": true, + "←": true, + "→": true, + "↑": true, + "Σ": true, + "∘": true, + "𝕊": true, + "√": true, + "□": true, + "⊓": true, + "⊏": true, + "⊑": true, + "⊐": true, + "⊒": true, + "⊔": true, + "𝒮": true, + "⋆": true, + "⋐": true, + "⋐": true, + "⊆": true, + "≻": true, + "⪰": true, + "≽": true, + "≿": true, + "∋": true, + "∑": true, + "⋑": true, + "⊃": true, + "⊇": true, + "⋑": true, + "Þ": true, + "Þ": true, + "™": true, + "Ћ": true, + "Ц": true, + " ": true, + "Τ": true, + "Ť": true, + "Ţ": true, + "Т": true, + "𝔗": true, + "∴": true, + "Θ": true, + "  ": true, + " ": true, + "∼": true, + "≃": true, + "≅": true, + "≈": true, + "𝕋": true, + "⃛": true, + "𝒯": true, + "Ŧ": true, + "Ú": true, + "Ú": true, + "↟": true, + "⥉": true, + "Ў": true, + "Ŭ": true, + "Û": true, + "Û": true, + "У": true, + "Ű": true, + "𝔘": true, + "Ù": true, + "Ù": true, + "Ū": true, + "_": true, + "⏟": true, + "⎵": true, + "⏝": true, + "⋃": true, + "⊎": true, + "Ų": true, + "𝕌": true, + "↑": true, + "⤒": true, + "⇅": true, + "↕": true, + "⥮": true, + "⊥": true, + "↥": true, + "⇑": true, + "⇕": true, + "↖": true, + "↗": true, + "ϒ": true, + "Υ": true, + "Ů": true, + "𝒰": true, + "Ũ": true, + "Ü": true, + "Ü": true, + "⊫": true, + "⫫": true, + "В": true, + "⊩": true, + "⫦": true, + "⋁": true, + "‖": true, + "‖": true, + "∣": true, + "|": true, + "❘": true, + "≀": true, + " ": true, + "𝔙": true, + "𝕍": true, + "𝒱": true, + "⊪": true, + "Ŵ": true, + "⋀": true, + "𝔚": true, + "𝕎": true, + "𝒲": true, + "𝔛": true, + "Ξ": true, + "𝕏": true, + "𝒳": true, + "Я": true, + "Ї": true, + "Ю": true, + "Ý": true, + "Ý": true, + "Ŷ": true, + "Ы": true, + "𝔜": true, + "𝕐": true, + "𝒴": true, + "Ÿ": true, + "Ж": true, + "Ź": true, + "Ž": true, + "З": true, + "Ż": true, + "​": true, + "Ζ": true, + "ℨ": true, + "ℤ": true, + "𝒵": true, + "á": true, + "á": true, + "ă": true, + "∾": true, + "∾̳": true, + "∿": true, + "â": true, + "â": true, + "´": true, + "´": true, + "а": true, + "æ": true, + "æ": true, + "⁡": true, + "𝔞": true, + "à": true, + "à": true, + "ℵ": true, + "ℵ": true, + "α": true, + "ā": true, + "⨿": true, + "&": true, + "&": true, + "∧": true, + "⩕": true, + "⩜": true, + "⩘": true, + "⩚": true, + "∠": true, + "⦤": true, + "∠": true, + "∡": true, + "⦨": true, + "⦩": true, + "⦪": true, + "⦫": true, + "⦬": true, + "⦭": true, + "⦮": true, + "⦯": true, + "∟": true, + "⊾": true, + "⦝": true, + "∢": true, + "Å": true, + "⍼": true, + "ą": true, + "𝕒": true, + "≈": true, + "⩰": true, + "⩯": true, + "≊": true, + "≋": true, + "'": true, + "≈": true, + "≊": true, + "å": true, + "å": true, + "𝒶": true, + "*": true, + "≈": true, + "≍": true, + "ã": true, + "ã": true, + "ä": true, + "ä": true, + "∳": true, + "⨑": true, + "⫭": true, + "≌": true, + "϶": true, + "‵": true, + "∽": true, + "⋍": true, + "⊽": true, + "⌅": true, + "⌅": true, + "⎵": true, + "⎶": true, + "≌": true, + "б": true, + "„": true, + "∵": true, + "∵": true, + "⦰": true, + "϶": true, + "ℬ": true, + "β": true, + "ℶ": true, + "≬": true, + "𝔟": true, + "⋂": true, + "◯": true, + "⋃": true, + "⨀": true, + "⨁": true, + "⨂": true, + "⨆": true, + "★": true, + "▽": true, + "△": true, + "⨄": true, + "⋁": true, + "⋀": true, + "⤍": true, + "⧫": true, + "▪": true, + "▴": true, + "▾": true, + "◂": true, + "▸": true, + "␣": true, + "▒": true, + "░": true, + "▓": true, + "█": true, + "=⃥": true, + "≡⃥": true, + "⌐": true, + "𝕓": true, + "⊥": true, + "⊥": true, + "⋈": true, + "╗": true, + "╔": true, + "╖": true, + "╓": true, + "═": true, + "╦": true, + "╩": true, + "╤": true, + "╧": true, + "╝": true, + "╚": true, + "╜": true, + "╙": true, + "║": true, + "╬": true, + "╣": true, + "╠": true, + "╫": true, + "╢": true, + "╟": true, + "⧉": true, + "╕": true, + "╒": true, + "┐": true, + "┌": true, + "─": true, + "╥": true, + "╨": true, + "┬": true, + "┴": true, + "⊟": true, + "⊞": true, + "⊠": true, + "╛": true, + "╘": true, + "┘": true, + "└": true, + "│": true, + "╪": true, + "╡": true, + "╞": true, + "┼": true, + "┤": true, + "├": true, + "‵": true, + "˘": true, + "¦": true, + "¦": true, + "𝒷": true, + "⁏": true, + "∽": true, + "⋍": true, + "\": true, + "⧅": true, + "⟈": true, + "•": true, + "•": true, + "≎": true, + "⪮": true, + "≏": true, + "≏": true, + "ć": true, + "∩": true, + "⩄": true, + "⩉": true, + "⩋": true, + "⩇": true, + "⩀": true, + "∩︀": true, + "⁁": true, + "ˇ": true, + "⩍": true, + "č": true, + "ç": true, + "ç": true, + "ĉ": true, + "⩌": true, + "⩐": true, + "ċ": true, + "¸": true, + "¸": true, + "⦲": true, + "¢": true, + "¢": true, + "·": true, + "𝔠": true, + "ч": true, + "✓": true, + "✓": true, + "χ": true, + "○": true, + "⧃": true, + "ˆ": true, + "≗": true, + "↺": true, + "↻": true, + "®": true, + "Ⓢ": true, + "⊛": true, + "⊚": true, + "⊝": true, + "≗": true, + "⨐": true, + "⫯": true, + "⧂": true, + "♣": true, + "♣": true, + ":": true, + "≔": true, + "≔": true, + ",": true, + "@": true, + "∁": true, + "∘": true, + "∁": true, + "ℂ": true, + "≅": true, + "⩭": true, + "∮": true, + "𝕔": true, + "∐": true, + "©": true, + "©": true, + "℗": true, + "↵": true, + "✗": true, + "𝒸": true, + "⫏": true, + "⫑": true, + "⫐": true, + "⫒": true, + "⋯": true, + "⤸": true, + "⤵": true, + "⋞": true, + "⋟": true, + "↶": true, + "⤽": true, + "∪": true, + "⩈": true, + "⩆": true, + "⩊": true, + "⊍": true, + "⩅": true, + "∪︀": true, + "↷": true, + "⤼": true, + "⋞": true, + "⋟": true, + "⋎": true, + "⋏": true, + "¤": true, + "¤": true, + "↶": true, + "↷": true, + "⋎": true, + "⋏": true, + "∲": true, + "∱": true, + "⌭": true, + "⇓": true, + "⥥": true, + "†": true, + "ℸ": true, + "↓": true, + "‐": true, + "⊣": true, + "⤏": true, + "˝": true, + "ď": true, + "д": true, + "ⅆ": true, + "‡": true, + "⇊": true, + "⩷": true, + "°": true, + "°": true, + "δ": true, + "⦱": true, + "⥿": true, + "𝔡": true, + "⇃": true, + "⇂": true, + "⋄": true, + "⋄": true, + "♦": true, + "♦": true, + "¨": true, + "ϝ": true, + "⋲": true, + "÷": true, + "÷": true, + "÷": true, + "⋇": true, + "⋇": true, + "ђ": true, + "⌞": true, + "⌍": true, + "$": true, + "𝕕": true, + "˙": true, + "≐": true, + "≑": true, + "∸": true, + "∔": true, + "⊡": true, + "⌆": true, + "↓": true, + "⇊": true, + "⇃": true, + "⇂": true, + "⤐": true, + "⌟": true, + "⌌": true, + "𝒹": true, + "ѕ": true, + "⧶": true, + "đ": true, + "⋱": true, + "▿": true, + "▾": true, + "⇵": true, + "⥯": true, + "⦦": true, + "џ": true, + "⟿": true, + "⩷": true, + "≑": true, + "é": true, + "é": true, + "⩮": true, + "ě": true, + "≖": true, + "ê": true, + "ê": true, + "≕": true, + "э": true, + "ė": true, + "ⅇ": true, + "≒": true, + "𝔢": true, + "⪚": true, + "è": true, + "è": true, + "⪖": true, + "⪘": true, + "⪙": true, + "⏧": true, + "ℓ": true, + "⪕": true, + "⪗": true, + "ē": true, + "∅": true, + "∅": true, + "∅": true, + " ": true, + " ": true, + " ": true, + "ŋ": true, + " ": true, + "ę": true, + "𝕖": true, + "⋕": true, + "⧣": true, + "⩱": true, + "ε": true, + "ε": true, + "ϵ": true, + "≖": true, + "≕": true, + "≂": true, + "⪖": true, + "⪕": true, + "=": true, + "≟": true, + "≡": true, + "⩸": true, + "⧥": true, + "≓": true, + "⥱": true, + "ℯ": true, + "≐": true, + "≂": true, + "η": true, + "ð": true, + "ð": true, + "ë": true, + "ë": true, + "€": true, + "!": true, + "∃": true, + "ℰ": true, + "ⅇ": true, + "≒": true, + "ф": true, + "♀": true, + "ffi": true, + "ff": true, + "ffl": true, + "𝔣": true, + "fi": true, + "fj": true, + "♭": true, + "fl": true, + "▱": true, + "ƒ": true, + "𝕗": true, + "∀": true, + "⋔": true, + "⫙": true, + "⨍": true, + "½": true, + "½": true, + "⅓": true, + "¼": true, + "¼": true, + "⅕": true, + "⅙": true, + "⅛": true, + "⅔": true, + "⅖": true, + "¾": true, + "¾": true, + "⅗": true, + "⅜": true, + "⅘": true, + "⅚": true, + "⅝": true, + "⅞": true, + "⁄": true, + "⌢": true, + "𝒻": true, + "≧": true, + "⪌": true, + "ǵ": true, + "γ": true, + "ϝ": true, + "⪆": true, + "ğ": true, + "ĝ": true, + "г": true, + "ġ": true, + "≥": true, + "⋛": true, + "≥": true, + "≧": true, + "⩾": true, + "⩾": true, + "⪩": true, + "⪀": true, + "⪂": true, + "⪄": true, + "⋛︀": true, + "⪔": true, + "𝔤": true, + "≫": true, + "⋙": true, + "ℷ": true, + "ѓ": true, + "≷": true, + "⪒": true, + "⪥": true, + "⪤": true, + "≩": true, + "⪊": true, + "⪊": true, + "⪈": true, + "⪈": true, + "≩": true, + "⋧": true, + "𝕘": true, + "`": true, + "ℊ": true, + "≳": true, + "⪎": true, + "⪐": true, + ">": true, + ">": true, + "⪧": true, + "⩺": true, + "⋗": true, + "⦕": true, + "⩼": true, + "⪆": true, + "⥸": true, + "⋗": true, + "⋛": true, + "⪌": true, + "≷": true, + "≳": true, + "≩︀": true, + "≩︀": true, + "⇔": true, + " ": true, + "½": true, + "ℋ": true, + "ъ": true, + "↔": true, + "⥈": true, + "↭": true, + "ℏ": true, + "ĥ": true, + "♥": true, + "♥": true, + "…": true, + "⊹": true, + "𝔥": true, + "⤥": true, + "⤦": true, + "⇿": true, + "∻": true, + "↩": true, + "↪": true, + "𝕙": true, + "―": true, + "𝒽": true, + "ℏ": true, + "ħ": true, + "⁃": true, + "‐": true, + "í": true, + "í": true, + "⁣": true, + "î": true, + "î": true, + "и": true, + "е": true, + "¡": true, + "¡": true, + "⇔": true, + "𝔦": true, + "ì": true, + "ì": true, + "ⅈ": true, + "⨌": true, + "∭": true, + "⧜": true, + "℩": true, + "ij": true, + "ī": true, + "ℑ": true, + "ℐ": true, + "ℑ": true, + "ı": true, + "⊷": true, + "Ƶ": true, + "∈": true, + "℅": true, + "∞": true, + "⧝": true, + "ı": true, + "∫": true, + "⊺": true, + "ℤ": true, + "⊺": true, + "⨗": true, + "⨼": true, + "ё": true, + "į": true, + "𝕚": true, + "ι": true, + "⨼": true, + "¿": true, + "¿": true, + "𝒾": true, + "∈": true, + "⋹": true, + "⋵": true, + "⋴": true, + "⋳": true, + "∈": true, + "⁢": true, + "ĩ": true, + "і": true, + "ï": true, + "ï": true, + "ĵ": true, + "й": true, + "𝔧": true, + "ȷ": true, + "𝕛": true, + "𝒿": true, + "ј": true, + "є": true, + "κ": true, + "ϰ": true, + "ķ": true, + "к": true, + "𝔨": true, + "ĸ": true, + "х": true, + "ќ": true, + "𝕜": true, + "𝓀": true, + "⇚": true, + "⇐": true, + "⤛": true, + "⤎": true, + "≦": true, + "⪋": true, + "⥢": true, + "ĺ": true, + "⦴": true, + "ℒ": true, + "λ": true, + "⟨": true, + "⦑": true, + "⟨": true, + "⪅": true, + "«": true, + "«": true, + "←": true, + "⇤": true, + "⤟": true, + "⤝": true, + "↩": true, + "↫": true, + "⤹": true, + "⥳": true, + "↢": true, + "⪫": true, + "⤙": true, + "⪭": true, + "⪭︀": true, + "⤌": true, + "❲": true, + "{": true, + "[": true, + "⦋": true, + "⦏": true, + "⦍": true, + "ľ": true, + "ļ": true, + "⌈": true, + "{": true, + "л": true, + "⤶": true, + "“": true, + "„": true, + "⥧": true, + "⥋": true, + "↲": true, + "≤": true, + "←": true, + "↢": true, + "↽": true, + "↼": true, + "⇇": true, + "↔": true, + "⇆": true, + "⇋": true, + "↭": true, + "⋋": true, + "⋚": true, + "≤": true, + "≦": true, + "⩽": true, + "⩽": true, + "⪨": true, + "⩿": true, + "⪁": true, + "⪃": true, + "⋚︀": true, + "⪓": true, + "⪅": true, + "⋖": true, + "⋚": true, + "⪋": true, + "≶": true, + "≲": true, + "⥼": true, + "⌊": true, + "𝔩": true, + "≶": true, + "⪑": true, + "↽": true, + "↼": true, + "⥪": true, + "▄": true, + "љ": true, + "≪": true, + "⇇": true, + "⌞": true, + "⥫": true, + "◺": true, + "ŀ": true, + "⎰": true, + "⎰": true, + "≨": true, + "⪉": true, + "⪉": true, + "⪇": true, + "⪇": true, + "≨": true, + "⋦": true, + "⟬": true, + "⇽": true, + "⟦": true, + "⟵": true, + "⟷": true, + "⟼": true, + "⟶": true, + "↫": true, + "↬": true, + "⦅": true, + "𝕝": true, + "⨭": true, + "⨴": true, + "∗": true, + "_": true, + "◊": true, + "◊": true, + "⧫": true, + "(": true, + "⦓": true, + "⇆": true, + "⌟": true, + "⇋": true, + "⥭": true, + "‎": true, + "⊿": true, + "‹": true, + "𝓁": true, + "↰": true, + "≲": true, + "⪍": true, + "⪏": true, + "[": true, + "‘": true, + "‚": true, + "ł": true, + "<": true, + "<": true, + "⪦": true, + "⩹": true, + "⋖": true, + "⋋": true, + "⋉": true, + "⥶": true, + "⩻": true, + "⦖": true, + "◃": true, + "⊴": true, + "◂": true, + "⥊": true, + "⥦": true, + "≨︀": true, + "≨︀": true, + "∺": true, + "¯": true, + "¯": true, + "♂": true, + "✠": true, + "✠": true, + "↦": true, + "↦": true, + "↧": true, + "↤": true, + "↥": true, + "▮": true, + "⨩": true, + "м": true, + "—": true, + "∡": true, + "𝔪": true, + "℧": true, + "µ": true, + "µ": true, + "∣": true, + "*": true, + "⫰": true, + "·": true, + "·": true, + "−": true, + "⊟": true, + "∸": true, + "⨪": true, + "⫛": true, + "…": true, + "∓": true, + "⊧": true, + "𝕞": true, + "∓": true, + "𝓂": true, + "∾": true, + "μ": true, + "⊸": true, + "⊸": true, + "⋙̸": true, + "≫⃒": true, + "≫̸": true, + "⇍": true, + "⇎": true, + "⋘̸": true, + "≪⃒": true, + "≪̸": true, + "⇏": true, + "⊯": true, + "⊮": true, + "∇": true, + "ń": true, + "∠⃒": true, + "≉": true, + "⩰̸": true, + "≋̸": true, + "ʼn": true, + "≉": true, + "♮": true, + "♮": true, + "ℕ": true, + " ": true, + " ": true, + "≎̸": true, + "≏̸": true, + "⩃": true, + "ň": true, + "ņ": true, + "≇": true, + "⩭̸": true, + "⩂": true, + "н": true, + "–": true, + "≠": true, + "⇗": true, + "⤤": true, + "↗": true, + "↗": true, + "≐̸": true, + "≢": true, + "⤨": true, + "≂̸": true, + "∄": true, + "∄": true, + "𝔫": true, + "≧̸": true, + "≱": true, + "≱": true, + "≧̸": true, + "⩾̸": true, + "⩾̸": true, + "≵": true, + "≯": true, + "≯": true, + "⇎": true, + "↮": true, + "⫲": true, + "∋": true, + "⋼": true, + "⋺": true, + "∋": true, + "њ": true, + "⇍": true, + "≦̸": true, + "↚": true, + "‥": true, + "≰": true, + "↚": true, + "↮": true, + "≰": true, + "≦̸": true, + "⩽̸": true, + "⩽̸": true, + "≮": true, + "≴": true, + "≮": true, + "⋪": true, + "⋬": true, + "∤": true, + "𝕟": true, + "¬": true, + "¬": true, + "∉": true, + "⋹̸": true, + "⋵̸": true, + "∉": true, + "⋷": true, + "⋶": true, + "∌": true, + "∌": true, + "⋾": true, + "⋽": true, + "∦": true, + "∦": true, + "⫽⃥": true, + "∂̸": true, + "⨔": true, + "⊀": true, + "⋠": true, + "⪯̸": true, + "⊀": true, + "⪯̸": true, + "⇏": true, + "↛": true, + "⤳̸": true, + "↝̸": true, + "↛": true, + "⋫": true, + "⋭": true, + "⊁": true, + "⋡": true, + "⪰̸": true, + "𝓃": true, + "∤": true, + "∦": true, + "≁": true, + "≄": true, + "≄": true, + "∤": true, + "∦": true, + "⋢": true, + "⋣": true, + "⊄": true, + "⫅̸": true, + "⊈": true, + "⊂⃒": true, + "⊈": true, + "⫅̸": true, + "⊁": true, + "⪰̸": true, + "⊅": true, + "⫆̸": true, + "⊉": true, + "⊃⃒": true, + "⊉": true, + "⫆̸": true, + "≹": true, + "ñ": true, + "ñ": true, + "≸": true, + "⋪": true, + "⋬": true, + "⋫": true, + "⋭": true, + "ν": true, + "#": true, + "№": true, + " ": true, + "⊭": true, + "⤄": true, + "≍⃒": true, + "⊬": true, + "≥⃒": true, + ">⃒": true, + "⧞": true, + "⤂": true, + "≤⃒": true, + "<⃒": true, + "⊴⃒": true, + "⤃": true, + "⊵⃒": true, + "∼⃒": true, + "⇖": true, + "⤣": true, + "↖": true, + "↖": true, + "⤧": true, + "Ⓢ": true, + "ó": true, + "ó": true, + "⊛": true, + "⊚": true, + "ô": true, + "ô": true, + "о": true, + "⊝": true, + "ő": true, + "⨸": true, + "⊙": true, + "⦼": true, + "œ": true, + "⦿": true, + "𝔬": true, + "˛": true, + "ò": true, + "ò": true, + "⧁": true, + "⦵": true, + "Ω": true, + "∮": true, + "↺": true, + "⦾": true, + "⦻": true, + "‾": true, + "⧀": true, + "ō": true, + "ω": true, + "ο": true, + "⦶": true, + "⊖": true, + "𝕠": true, + "⦷": true, + "⦹": true, + "⊕": true, + "∨": true, + "↻": true, + "⩝": true, + "ℴ": true, + "ℴ": true, + "ª": true, + "ª": true, + "º": true, + "º": true, + "⊶": true, + "⩖": true, + "⩗": true, + "⩛": true, + "ℴ": true, + "ø": true, + "ø": true, + "⊘": true, + "õ": true, + "õ": true, + "⊗": true, + "⨶": true, + "ö": true, + "ö": true, + "⌽": true, + "∥": true, + "¶": true, + "¶": true, + "∥": true, + "⫳": true, + "⫽": true, + "∂": true, + "п": true, + "%": true, + ".": true, + "‰": true, + "⊥": true, + "‱": true, + "𝔭": true, + "φ": true, + "ϕ": true, + "ℳ": true, + "☎": true, + "π": true, + "⋔": true, + "ϖ": true, + "ℏ": true, + "ℎ": true, + "ℏ": true, + "+": true, + "⨣": true, + "⊞": true, + "⨢": true, + "∔": true, + "⨥": true, + "⩲": true, + "±": true, + "±": true, + "⨦": true, + "⨧": true, + "±": true, + "⨕": true, + "𝕡": true, + "£": true, + "£": true, + "≺": true, + "⪳": true, + "⪷": true, + "≼": true, + "⪯": true, + "≺": true, + "⪷": true, + "≼": true, + "⪯": true, + "⪹": true, + "⪵": true, + "⋨": true, + "≾": true, + "′": true, + "ℙ": true, + "⪵": true, + "⪹": true, + "⋨": true, + "∏": true, + "⌮": true, + "⌒": true, + "⌓": true, + "∝": true, + "∝": true, + "≾": true, + "⊰": true, + "𝓅": true, + "ψ": true, + " ": true, + "𝔮": true, + "⨌": true, + "𝕢": true, + "⁗": true, + "𝓆": true, + "ℍ": true, + "⨖": true, + "?": true, + "≟": true, + """: true, + """: true, + "⇛": true, + "⇒": true, + "⤜": true, + "⤏": true, + "⥤": true, + "∽̱": true, + "ŕ": true, + "√": true, + "⦳": true, + "⟩": true, + "⦒": true, + "⦥": true, + "⟩": true, + "»": true, + "»": true, + "→": true, + "⥵": true, + "⇥": true, + "⤠": true, + "⤳": true, + "⤞": true, + "↪": true, + "↬": true, + "⥅": true, + "⥴": true, + "↣": true, + "↝": true, + "⤚": true, + "∶": true, + "ℚ": true, + "⤍": true, + "❳": true, + "}": true, + "]": true, + "⦌": true, + "⦎": true, + "⦐": true, + "ř": true, + "ŗ": true, + "⌉": true, + "}": true, + "р": true, + "⤷": true, + "⥩": true, + "”": true, + "”": true, + "↳": true, + "ℜ": true, + "ℛ": true, + "ℜ": true, + "ℝ": true, + "▭": true, + "®": true, + "®": true, + "⥽": true, + "⌋": true, + "𝔯": true, + "⇁": true, + "⇀": true, + "⥬": true, + "ρ": true, + "ϱ": true, + "→": true, + "↣": true, + "⇁": true, + "⇀": true, + "⇄": true, + "⇌": true, + "⇉": true, + "↝": true, + "⋌": true, + "˚": true, + "≓": true, + "⇄": true, + "⇌": true, + "‏": true, + "⎱": true, + "⎱": true, + "⫮": true, + "⟭": true, + "⇾": true, + "⟧": true, + "⦆": true, + "𝕣": true, + "⨮": true, + "⨵": true, + ")": true, + "⦔": true, + "⨒": true, + "⇉": true, + "›": true, + "𝓇": true, + "↱": true, + "]": true, + "’": true, + "’": true, + "⋌": true, + "⋊": true, + "▹": true, + "⊵": true, + "▸": true, + "⧎": true, + "⥨": true, + "℞": true, + "ś": true, + "‚": true, + "≻": true, + "⪴": true, + "⪸": true, + "š": true, + "≽": true, + "⪰": true, + "ş": true, + "ŝ": true, + "⪶": true, + "⪺": true, + "⋩": true, + "⨓": true, + "≿": true, + "с": true, + "⋅": true, + "⊡": true, + "⩦": true, + "⇘": true, + "⤥": true, + "↘": true, + "↘": true, + "§": true, + "§": true, + ";": true, + "⤩": true, + "∖": true, + "∖": true, + "✶": true, + "𝔰": true, + "⌢": true, + "♯": true, + "щ": true, + "ш": true, + "∣": true, + "∥": true, + "­": true, + "­": true, + "σ": true, + "ς": true, + "ς": true, + "∼": true, + "⩪": true, + "≃": true, + "≃": true, + "⪞": true, + "⪠": true, + "⪝": true, + "⪟": true, + "≆": true, + "⨤": true, + "⥲": true, + "←": true, + "∖": true, + "⨳": true, + "⧤": true, + "∣": true, + "⌣": true, + "⪪": true, + "⪬": true, + "⪬︀": true, + "ь": true, + "/": true, + "⧄": true, + "⌿": true, + "𝕤": true, + "♠": true, + "♠": true, + "∥": true, + "⊓": true, + "⊓︀": true, + "⊔": true, + "⊔︀": true, + "⊏": true, + "⊑": true, + "⊏": true, + "⊑": true, + "⊐": true, + "⊒": true, + "⊐": true, + "⊒": true, + "□": true, + "□": true, + "▪": true, + "▪": true, + "→": true, + "𝓈": true, + "∖": true, + "⌣": true, + "⋆": true, + "☆": true, + "★": true, + "ϵ": true, + "ϕ": true, + "¯": true, + "⊂": true, + "⫅": true, + "⪽": true, + "⊆": true, + "⫃": true, + "⫁": true, + "⫋": true, + "⊊": true, + "⪿": true, + "⥹": true, + "⊂": true, + "⊆": true, + "⫅": true, + "⊊": true, + "⫋": true, + "⫇": true, + "⫕": true, + "⫓": true, + "≻": true, + "⪸": true, + "≽": true, + "⪰": true, + "⪺": true, + "⪶": true, + "⋩": true, + "≿": true, + "∑": true, + "♪": true, + "¹": true, + "¹": true, + "²": true, + "²": true, + "³": true, + "³": true, + "⊃": true, + "⫆": true, + "⪾": true, + "⫘": true, + "⊇": true, + "⫄": true, + "⟉": true, + "⫗": true, + "⥻": true, + "⫂": true, + "⫌": true, + "⊋": true, + "⫀": true, + "⊃": true, + "⊇": true, + "⫆": true, + "⊋": true, + "⫌": true, + "⫈": true, + "⫔": true, + "⫖": true, + "⇙": true, + "⤦": true, + "↙": true, + "↙": true, + "⤪": true, + "ß": true, + "ß": true, + "⌖": true, + "τ": true, + "⎴": true, + "ť": true, + "ţ": true, + "т": true, + "⃛": true, + "⌕": true, + "𝔱": true, + "∴": true, + "∴": true, + "θ": true, + "ϑ": true, + "ϑ": true, + "≈": true, + "∼": true, + " ": true, + "≈": true, + "∼": true, + "þ": true, + "þ": true, + "˜": true, + "×": true, + "×": true, + "⊠": true, + "⨱": true, + "⨰": true, + "∭": true, + "⤨": true, + "⊤": true, + "⌶": true, + "⫱": true, + "𝕥": true, + "⫚": true, + "⤩": true, + "‴": true, + "™": true, + "▵": true, + "▿": true, + "◃": true, + "⊴": true, + "≜": true, + "▹": true, + "⊵": true, + "◬": true, + "≜": true, + "⨺": true, + "⨹": true, + "⧍": true, + "⨻": true, + "⏢": true, + "𝓉": true, + "ц": true, + "ћ": true, + "ŧ": true, + "≬": true, + "↞": true, + "↠": true, + "⇑": true, + "⥣": true, + "ú": true, + "ú": true, + "↑": true, + "ў": true, + "ŭ": true, + "û": true, + "û": true, + "у": true, + "⇅": true, + "ű": true, + "⥮": true, + "⥾": true, + "𝔲": true, + "ù": true, + "ù": true, + "↿": true, + "↾": true, + "▀": true, + "⌜": true, + "⌜": true, + "⌏": true, + "◸": true, + "ū": true, + "¨": true, + "¨": true, + "ų": true, + "𝕦": true, + "↑": true, + "↕": true, + "↿": true, + "↾": true, + "⊎": true, + "υ": true, + "ϒ": true, + "υ": true, + "⇈": true, + "⌝": true, + "⌝": true, + "⌎": true, + "ů": true, + "◹": true, + "𝓊": true, + "⋰": true, + "ũ": true, + "▵": true, + "▴": true, + "⇈": true, + "ü": true, + "ü": true, + "⦧": true, + "⇕": true, + "⫨": true, + "⫩": true, + "⊨": true, + "⦜": true, + "ϵ": true, + "ϰ": true, + "∅": true, + "ϕ": true, + "ϖ": true, + "∝": true, + "↕": true, + "ϱ": true, + "ς": true, + "⊊︀": true, + "⫋︀": true, + "⊋︀": true, + "⫌︀": true, + "ϑ": true, + "⊲": true, + "⊳": true, + "в": true, + "⊢": true, + "∨": true, + "⊻": true, + "≚": true, + "⋮": true, + "|": true, + "|": true, + "𝔳": true, + "⊲": true, + "⊂⃒": true, + "⊃⃒": true, + "𝕧": true, + "∝": true, + "⊳": true, + "𝓋": true, + "⫋︀": true, + "⊊︀": true, + "⫌︀": true, + "⊋︀": true, + "⦚": true, + "ŵ": true, + "⩟": true, + "∧": true, + "≙": true, + "℘": true, + "𝔴": true, + "𝕨": true, + "℘": true, + "≀": true, + "≀": true, + "𝓌": true, + "⋂": true, + "◯": true, + "⋃": true, + "▽": true, + "𝔵": true, + "⟺": true, + "⟷": true, + "ξ": true, + "⟸": true, + "⟵": true, + "⟼": true, + "⋻": true, + "⨀": true, + "𝕩": true, + "⨁": true, + "⨂": true, + "⟹": true, + "⟶": true, + "𝓍": true, + "⨆": true, + "⨄": true, + "△": true, + "⋁": true, + "⋀": true, + "ý": true, + "ý": true, + "я": true, + "ŷ": true, + "ы": true, + "¥": true, + "¥": true, + "𝔶": true, + "ї": true, + "𝕪": true, + "𝓎": true, + "ю": true, + "ÿ": true, + "ÿ": true, + "ź": true, + "ž": true, + "з": true, + "ż": true, + "ℨ": true, + "ζ": true, + "𝔷": true, + "ж": true, + "⇝": true, + "𝕫": true, + "𝓏": true, + "‍": true, + "‌": true, +} diff --git a/vendor/github.com/russross/blackfriday/v2/esc.go b/vendor/github.com/russross/blackfriday/v2/esc.go index 6385f27cb..6ab60102c 100644 --- a/vendor/github.com/russross/blackfriday/v2/esc.go +++ b/vendor/github.com/russross/blackfriday/v2/esc.go @@ -13,13 +13,27 @@ var htmlEscaper = [256][]byte{ } func escapeHTML(w io.Writer, s []byte) { + escapeEntities(w, s, false) +} + +func escapeAllHTML(w io.Writer, s []byte) { + escapeEntities(w, s, true) +} + +func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) { var start, end int for end < len(s) { escSeq := htmlEscaper[s[end]] if escSeq != nil { - w.Write(s[start:end]) - w.Write(escSeq) - start = end + 1 + isEntity, entityEnd := nodeIsEntity(s, end) + if isEntity && !escapeValidEntities { + w.Write(s[start : entityEnd+1]) + start = entityEnd + 1 + } else { + w.Write(s[start:end]) + w.Write(escSeq) + start = end + 1 + } } end++ } @@ -28,6 +42,28 @@ func escapeHTML(w io.Writer, s []byte) { } } +func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) { + isEntity = false + endEntityPos = end + 1 + + if s[end] == '&' { + for endEntityPos < len(s) { + if s[endEntityPos] == ';' { + if entities[string(s[end:endEntityPos+1])] { + isEntity = true + break + } + } + if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' { + break + } + endEntityPos++ + } + } + + return isEntity, endEntityPos +} + func escLink(w io.Writer, text []byte) { unesc := html.UnescapeString(string(text)) escapeHTML(w, []byte(unesc)) diff --git a/vendor/github.com/russross/blackfriday/v2/html.go b/vendor/github.com/russross/blackfriday/v2/html.go index 284c87184..cb4f26e30 100644 --- a/vendor/github.com/russross/blackfriday/v2/html.go +++ b/vendor/github.com/russross/blackfriday/v2/html.go @@ -132,7 +132,10 @@ func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer { } if params.FootnoteReturnLinkContents == "" { - params.FootnoteReturnLinkContents = `[return]` + // U+FE0E is VARIATION SELECTOR-15. + // It suppresses automatic emoji presentation of the preceding + // U+21A9 LEFTWARDS ARROW WITH HOOK on iOS and iPadOS. + params.FootnoteReturnLinkContents = "↩\ufe0e" } return &HTMLRenderer{ @@ -616,7 +619,7 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt } case Code: r.out(w, codeTag) - escapeHTML(w, node.Literal) + escapeAllHTML(w, node.Literal) r.out(w, codeCloseTag) case Document: break @@ -762,7 +765,7 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt r.cr(w) r.out(w, preTag) r.tag(w, codeTag[:len(codeTag)-1], attrs) - escapeHTML(w, node.Literal) + escapeAllHTML(w, node.Literal) r.out(w, codeCloseTag) r.out(w, preCloseTag) if node.Parent.Type != Item { diff --git a/vendor/github.com/russross/blackfriday/v2/inline.go b/vendor/github.com/russross/blackfriday/v2/inline.go index 4ed290792..d45bd9417 100644 --- a/vendor/github.com/russross/blackfriday/v2/inline.go +++ b/vendor/github.com/russross/blackfriday/v2/inline.go @@ -278,7 +278,7 @@ func link(p *Markdown, data []byte, offset int) (int, *Node) { case data[i] == '\n': textHasNl = true - case data[i-1] == '\\': + case isBackslashEscaped(data, i): continue case data[i] == '[': diff --git a/vendor/github.com/russross/blackfriday/v2/node.go b/vendor/github.com/russross/blackfriday/v2/node.go index 51b9e8c1b..04e6050ce 100644 --- a/vendor/github.com/russross/blackfriday/v2/node.go +++ b/vendor/github.com/russross/blackfriday/v2/node.go @@ -199,7 +199,8 @@ func (n *Node) InsertBefore(sibling *Node) { } } -func (n *Node) isContainer() bool { +// IsContainer returns true if 'n' can contain children. +func (n *Node) IsContainer() bool { switch n.Type { case Document: fallthrough @@ -238,6 +239,11 @@ func (n *Node) isContainer() bool { } } +// IsLeaf returns true if 'n' is a leaf node. +func (n *Node) IsLeaf() bool { + return !n.IsContainer() +} + func (n *Node) canContain(t NodeType) bool { if n.Type == List { return t == Item @@ -309,11 +315,11 @@ func newNodeWalker(root *Node) *nodeWalker { } func (nw *nodeWalker) next() { - if (!nw.current.isContainer() || !nw.entering) && nw.current == nw.root { + if (!nw.current.IsContainer() || !nw.entering) && nw.current == nw.root { nw.current = nil return } - if nw.entering && nw.current.isContainer() { + if nw.entering && nw.current.IsContainer() { if nw.current.FirstChild != nil { nw.current = nw.current.FirstChild nw.entering = true diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml b/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml deleted file mode 100644 index 93b1fcdb3..000000000 --- a/vendor/github.com/shurcooL/sanitized_anchor_name/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: false -language: go -go: - - 1.x - - master -matrix: - allow_failures: - - go: master - fast_finish: true -install: - - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d -s .) - - go tool vet . - - go test -v -race ./... diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/README.md b/vendor/github.com/shurcooL/sanitized_anchor_name/README.md deleted file mode 100644 index 670bf0fe6..000000000 --- a/vendor/github.com/shurcooL/sanitized_anchor_name/README.md +++ /dev/null @@ -1,36 +0,0 @@ -sanitized_anchor_name -===================== - -[![Build Status](https://travis-ci.org/shurcooL/sanitized_anchor_name.svg?branch=master)](https://travis-ci.org/shurcooL/sanitized_anchor_name) [![GoDoc](https://godoc.org/github.com/shurcooL/sanitized_anchor_name?status.svg)](https://godoc.org/github.com/shurcooL/sanitized_anchor_name) - -Package sanitized_anchor_name provides a func to create sanitized anchor names. - -Its logic can be reused by multiple packages to create interoperable anchor names -and links to those anchors. - -At this time, it does not try to ensure that generated anchor names -are unique, that responsibility falls on the caller. - -Installation ------------- - -```bash -go get -u github.com/shurcooL/sanitized_anchor_name -``` - -Example -------- - -```Go -anchorName := sanitized_anchor_name.Create("This is a header") - -fmt.Println(anchorName) - -// Output: -// this-is-a-header -``` - -License -------- - -- [MIT License](LICENSE) diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/main.go b/vendor/github.com/shurcooL/sanitized_anchor_name/main.go deleted file mode 100644 index 6a77d1243..000000000 --- a/vendor/github.com/shurcooL/sanitized_anchor_name/main.go +++ /dev/null @@ -1,29 +0,0 @@ -// Package sanitized_anchor_name provides a func to create sanitized anchor names. -// -// Its logic can be reused by multiple packages to create interoperable anchor names -// and links to those anchors. -// -// At this time, it does not try to ensure that generated anchor names -// are unique, that responsibility falls on the caller. -package sanitized_anchor_name // import "github.com/shurcooL/sanitized_anchor_name" - -import "unicode" - -// Create returns a sanitized anchor name for the given text. -func Create(text string) string { - var anchorName []rune - var futureDash = false - for _, r := range text { - switch { - case unicode.IsLetter(r) || unicode.IsNumber(r): - if futureDash && len(anchorName) > 0 { - anchorName = append(anchorName, '-') - } - futureDash = false - anchorName = append(anchorName, unicode.ToLower(r)) - default: - futureDash = true - } - } - return string(anchorName) -} diff --git a/vendor/github.com/urfave/cli/.gitignore b/vendor/github.com/urfave/cli/.gitignore deleted file mode 100644 index 8ae196fee..000000000 --- a/vendor/github.com/urfave/cli/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.coverprofile -coverage.txt -node_modules/ -vendor -.idea diff --git a/vendor/github.com/urfave/cli/LICENSE b/vendor/github.com/urfave/cli/LICENSE deleted file mode 100644 index 42a597e29..000000000 --- a/vendor/github.com/urfave/cli/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 Jeremy Saenz & Contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/urfave/cli/README.md b/vendor/github.com/urfave/cli/README.md deleted file mode 100644 index 9c2cf851a..000000000 --- a/vendor/github.com/urfave/cli/README.md +++ /dev/null @@ -1,80 +0,0 @@ -cli -=== - -[![Build Status](https://travis-ci.org/urfave/cli.svg?branch=master)](https://travis-ci.org/urfave/cli) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli) - -[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli) -[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) -[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) -[![codecov](https://codecov.io/gh/urfave/cli/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/cli) - -cli is a simple, fast, and fun package for building command line apps in Go. The -goal is to enable developers to write fast and distributable command line -applications in an expressive way. - -## Usage Documentation - -Usage documentation exists for each major version - -- `v1` - [./docs/v1/manual.md](./docs/v1/manual.md) -- `v2` - 🚧 documentation for `v2` is WIP 🚧 - -## Installation - -Make sure you have a working Go environment. Go version 1.10+ is supported. [See -the install instructions for Go](http://golang.org/doc/install.html). - -### GOPATH - -Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can -be easily used: -``` -export PATH=$PATH:$GOPATH/bin -``` - -### Supported platforms - -cli is tested against multiple versions of Go on Linux, and against the latest -released version of Go on OS X and Windows. For full details, see -[`./.travis.yml`](./.travis.yml) and [`./appveyor.yml`](./appveyor.yml). - -### Build tags - -You can use the following build tags: - -#### `urfave_cli_no_docs` - -When set, this removes `ToMarkdown` and `ToMan` methods, so your application -won't be able to call those. This reduces the resulting binary size by about -300-400 KB (measured using Go 1.18.1 on Linux/amd64), due to less dependencies. - -### Using `v1` releases - -``` -$ go get github.com/urfave/cli -``` - -```go -... -import ( - "github.com/urfave/cli" -) -... -``` - -### Using `v2` releases - -**Warning**: `v2` is in a pre-release state. - -``` -$ go get github.com/urfave/cli.v2 -``` - -```go -... -import ( - "github.com/urfave/cli.v2" // imports as package "cli" -) -... -``` diff --git a/vendor/github.com/urfave/cli/appveyor.yml b/vendor/github.com/urfave/cli/appveyor.yml deleted file mode 100644 index 8ef2fea1a..000000000 --- a/vendor/github.com/urfave/cli/appveyor.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: "{build}" - -os: Windows Server 2016 - -image: Visual Studio 2017 - -clone_folder: c:\gopath\src\github.com\urfave\cli - -cache: - - node_modules - -environment: - GOPATH: C:\gopath - GOVERSION: 1.11.x - GO111MODULE: on - GOPROXY: https://proxy.golang.org - -install: - - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% - - go version - - go env - - go get github.com/urfave/gfmrun/cmd/gfmrun - - go mod vendor - -build_script: - - go run build.go vet - - go run build.go test - - go run build.go gfmrun docs/v1/manual.md diff --git a/vendor/github.com/urfave/cli/category.go b/vendor/github.com/urfave/cli/category.go deleted file mode 100644 index bf3c73c55..000000000 --- a/vendor/github.com/urfave/cli/category.go +++ /dev/null @@ -1,44 +0,0 @@ -package cli - -// CommandCategories is a slice of *CommandCategory. -type CommandCategories []*CommandCategory - -// CommandCategory is a category containing commands. -type CommandCategory struct { - Name string - Commands Commands -} - -func (c CommandCategories) Less(i, j int) bool { - return lexicographicLess(c[i].Name, c[j].Name) -} - -func (c CommandCategories) Len() int { - return len(c) -} - -func (c CommandCategories) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -// AddCommand adds a command to a category. -func (c CommandCategories) AddCommand(category string, command Command) CommandCategories { - for _, commandCategory := range c { - if commandCategory.Name == category { - commandCategory.Commands = append(commandCategory.Commands, command) - return c - } - } - return append(c, &CommandCategory{Name: category, Commands: []Command{command}}) -} - -// VisibleCommands returns a slice of the Commands with Hidden=false -func (c *CommandCategory) VisibleCommands() []Command { - ret := []Command{} - for _, command := range c.Commands { - if !command.Hidden { - ret = append(ret, command) - } - } - return ret -} diff --git a/vendor/github.com/urfave/cli/command.go b/vendor/github.com/urfave/cli/command.go deleted file mode 100644 index 09fda1642..000000000 --- a/vendor/github.com/urfave/cli/command.go +++ /dev/null @@ -1,384 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "sort" - "strings" -) - -// Command is a subcommand for a cli.App. -type Command struct { - // The name of the command - Name string - // short name of the command. Typically one character (deprecated, use `Aliases`) - ShortName string - // A list of aliases for the command - Aliases []string - // A short description of the usage of this command - Usage string - // Custom text to show on USAGE section of help - UsageText string - // A longer explanation of how the command works - Description string - // A short description of the arguments of this command - ArgsUsage string - // The category the command is part of - Category string - // The function to call when checking for bash command completions - BashComplete BashCompleteFunc - // An action to execute before any sub-subcommands are run, but after the context is ready - // If a non-nil error is returned, no sub-subcommands are run - Before BeforeFunc - // An action to execute after any subcommands are run, but after the subcommand has finished - // It is run even if Action() panics - After AfterFunc - // The function to call when this command is invoked - Action interface{} - // TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind - // of deprecation period has passed, maybe? - - // Execute this function if a usage error occurs. - OnUsageError OnUsageErrorFunc - // List of child commands - Subcommands Commands - // List of flags to parse - Flags []Flag - // Treat all flags as normal arguments if true - SkipFlagParsing bool - // Skip argument reordering which attempts to move flags before arguments, - // but only works if all flags appear after all arguments. This behavior was - // removed n version 2 since it only works under specific conditions so we - // backport here by exposing it as an option for compatibility. - SkipArgReorder bool - // Boolean to hide built-in help command - HideHelp bool - // Boolean to hide this command from help or completion - Hidden bool - // Boolean to enable short-option handling so user can combine several - // single-character bool arguments into one - // i.e. foobar -o -v -> foobar -ov - UseShortOptionHandling bool - - // Full name of command for help, defaults to full command name, including parent commands. - HelpName string - commandNamePath []string - - // CustomHelpTemplate the text template for the command help topic. - // cli.go uses text/template to render templates. You can - // render custom help text by setting this variable. - CustomHelpTemplate string -} - -type CommandsByName []Command - -func (c CommandsByName) Len() int { - return len(c) -} - -func (c CommandsByName) Less(i, j int) bool { - return lexicographicLess(c[i].Name, c[j].Name) -} - -func (c CommandsByName) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -// FullName returns the full name of the command. -// For subcommands this ensures that parent commands are part of the command path -func (c Command) FullName() string { - if c.commandNamePath == nil { - return c.Name - } - return strings.Join(c.commandNamePath, " ") -} - -// Commands is a slice of Command -type Commands []Command - -// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c Command) Run(ctx *Context) (err error) { - if len(c.Subcommands) > 0 { - return c.startApp(ctx) - } - - if !c.HideHelp && (HelpFlag != BoolFlag{}) { - // append help to flags - c.Flags = append( - c.Flags, - HelpFlag, - ) - } - - if ctx.App.UseShortOptionHandling { - c.UseShortOptionHandling = true - } - - set, err := c.parseFlags(ctx.Args().Tail(), ctx.shellComplete) - - context := NewContext(ctx.App, set, ctx) - context.Command = c - if checkCommandCompletions(context, c.Name) { - return nil - } - - if err != nil { - if c.OnUsageError != nil { - err := c.OnUsageError(context, err, false) - context.App.handleExitCoder(context, err) - return err - } - _, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) - _, _ = fmt.Fprintln(context.App.Writer) - _ = ShowCommandHelp(context, c.Name) - return err - } - - if checkCommandHelp(context, c.Name) { - return nil - } - - cerr := checkRequiredFlags(c.Flags, context) - if cerr != nil { - _ = ShowCommandHelp(context, c.Name) - return cerr - } - - if c.After != nil { - defer func() { - afterErr := c.After(context) - if afterErr != nil { - context.App.handleExitCoder(context, err) - if err != nil { - err = NewMultiError(err, afterErr) - } else { - err = afterErr - } - } - }() - } - - if c.Before != nil { - err = c.Before(context) - if err != nil { - context.App.handleExitCoder(context, err) - return err - } - } - - if c.Action == nil { - c.Action = helpSubcommand.Action - } - - err = HandleAction(c.Action, context) - - if err != nil { - context.App.handleExitCoder(context, err) - } - return err -} - -func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { - if c.SkipFlagParsing { - set, err := c.newFlagSet() - if err != nil { - return nil, err - } - - return set, set.Parse(append([]string{"--"}, args...)) - } - - if !c.SkipArgReorder { - args = reorderArgs(c.Flags, args) - } - - set, err := c.newFlagSet() - if err != nil { - return nil, err - } - - err = parseIter(set, c, args, shellComplete) - if err != nil { - return nil, err - } - - err = normalizeFlags(c.Flags, set) - if err != nil { - return nil, err - } - - return set, nil -} - -func (c *Command) newFlagSet() (*flag.FlagSet, error) { - return flagSet(c.Name, c.Flags) -} - -func (c *Command) useShortOptionHandling() bool { - return c.UseShortOptionHandling -} - -// reorderArgs moves all flags (via reorderedArgs) before the rest of -// the arguments (remainingArgs) as this is what flag expects. -func reorderArgs(commandFlags []Flag, args []string) []string { - var remainingArgs, reorderedArgs []string - - nextIndexMayContainValue := false - for i, arg := range args { - - // if we're expecting an option-value, check if this arg is a value, in - // which case it should be re-ordered next to its associated flag - if nextIndexMayContainValue && !argIsFlag(commandFlags, arg) { - nextIndexMayContainValue = false - reorderedArgs = append(reorderedArgs, arg) - } else if arg == "--" { - // don't reorder any args after the -- delimiter As described in the POSIX spec: - // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02 - // > Guideline 10: - // > The first -- argument that is not an option-argument should be accepted - // > as a delimiter indicating the end of options. Any following arguments - // > should be treated as operands, even if they begin with the '-' character. - - // make sure the "--" delimiter itself is at the start - remainingArgs = append([]string{"--"}, remainingArgs...) - remainingArgs = append(remainingArgs, args[i+1:]...) - break - // checks if this is an arg that should be re-ordered - } else if argIsFlag(commandFlags, arg) { - // we have determined that this is a flag that we should re-order - reorderedArgs = append(reorderedArgs, arg) - // if this arg does not contain a "=", then the next index may contain the value for this flag - nextIndexMayContainValue = !strings.Contains(arg, "=") - - // simply append any remaining args - } else { - remainingArgs = append(remainingArgs, arg) - } - } - - return append(reorderedArgs, remainingArgs...) -} - -// argIsFlag checks if an arg is one of our command flags -func argIsFlag(commandFlags []Flag, arg string) bool { - if arg == "-" || arg == "--"{ - // `-` is never a flag - // `--` is an option-value when following a flag, and a delimiter indicating the end of options in other cases. - return false - } - // flags always start with a - - if !strings.HasPrefix(arg, "-") { - return false - } - // this line turns `--flag` into `flag` - if strings.HasPrefix(arg, "--") { - arg = strings.Replace(arg, "-", "", 2) - } - // this line turns `-flag` into `flag` - if strings.HasPrefix(arg, "-") { - arg = strings.Replace(arg, "-", "", 1) - } - // this line turns `flag=value` into `flag` - arg = strings.Split(arg, "=")[0] - // look through all the flags, to see if the `arg` is one of our flags - for _, flag := range commandFlags { - for _, key := range strings.Split(flag.GetName(), ",") { - key := strings.TrimSpace(key) - if key == arg { - return true - } - } - } - // return false if this arg was not one of our flags - return false -} - -// Names returns the names including short names and aliases. -func (c Command) Names() []string { - names := []string{c.Name} - - if c.ShortName != "" { - names = append(names, c.ShortName) - } - - return append(names, c.Aliases...) -} - -// HasName returns true if Command.Name or Command.ShortName matches given name -func (c Command) HasName(name string) bool { - for _, n := range c.Names() { - if n == name { - return true - } - } - return false -} - -func (c Command) startApp(ctx *Context) error { - app := NewApp() - app.Metadata = ctx.App.Metadata - app.ExitErrHandler = ctx.App.ExitErrHandler - // set the name and usage - app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) - if c.HelpName == "" { - app.HelpName = c.HelpName - } else { - app.HelpName = app.Name - } - - app.Usage = c.Usage - app.Description = c.Description - app.ArgsUsage = c.ArgsUsage - - // set CommandNotFound - app.CommandNotFound = ctx.App.CommandNotFound - app.CustomAppHelpTemplate = c.CustomHelpTemplate - - // set the flags and commands - app.Commands = c.Subcommands - app.Flags = c.Flags - app.HideHelp = c.HideHelp - - app.Version = ctx.App.Version - app.HideVersion = ctx.App.HideVersion - app.Compiled = ctx.App.Compiled - app.Author = ctx.App.Author - app.Email = ctx.App.Email - app.Writer = ctx.App.Writer - app.ErrWriter = ctx.App.ErrWriter - app.UseShortOptionHandling = ctx.App.UseShortOptionHandling - - app.categories = CommandCategories{} - for _, command := range c.Subcommands { - app.categories = app.categories.AddCommand(command.Category, command) - } - - sort.Sort(app.categories) - - // bash completion - app.EnableBashCompletion = ctx.App.EnableBashCompletion - if c.BashComplete != nil { - app.BashComplete = c.BashComplete - } - - // set the actions - app.Before = c.Before - app.After = c.After - if c.Action != nil { - app.Action = c.Action - } else { - app.Action = helpSubcommand.Action - } - app.OnUsageError = c.OnUsageError - - for index, cc := range app.Commands { - app.Commands[index].commandNamePath = []string{c.Name, cc.Name} - } - - return app.RunAsSubcommand(ctx) -} - -// VisibleFlags returns a slice of the Flags with Hidden=false -func (c Command) VisibleFlags() []Flag { - return visibleFlags(c.Flags) -} diff --git a/vendor/github.com/urfave/cli/context.go b/vendor/github.com/urfave/cli/context.go deleted file mode 100644 index 3adf37e7b..000000000 --- a/vendor/github.com/urfave/cli/context.go +++ /dev/null @@ -1,348 +0,0 @@ -package cli - -import ( - "errors" - "flag" - "fmt" - "os" - "reflect" - "strings" - "syscall" -) - -// Context is a type that is passed through to -// each Handler action in a cli application. Context -// can be used to retrieve context-specific Args and -// parsed command-line options. -type Context struct { - App *App - Command Command - shellComplete bool - flagSet *flag.FlagSet - setFlags map[string]bool - parentContext *Context -} - -// NewContext creates a new context. For use in when invoking an App or Command action. -func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { - c := &Context{App: app, flagSet: set, parentContext: parentCtx} - - if parentCtx != nil { - c.shellComplete = parentCtx.shellComplete - } - - return c -} - -// NumFlags returns the number of flags set -func (c *Context) NumFlags() int { - return c.flagSet.NFlag() -} - -// Set sets a context flag to a value. -func (c *Context) Set(name, value string) error { - c.setFlags = nil - return c.flagSet.Set(name, value) -} - -// GlobalSet sets a context flag to a value on the global flagset -func (c *Context) GlobalSet(name, value string) error { - globalContext(c).setFlags = nil - return globalContext(c).flagSet.Set(name, value) -} - -// IsSet determines if the flag was actually set -func (c *Context) IsSet(name string) bool { - if c.setFlags == nil { - c.setFlags = make(map[string]bool) - - c.flagSet.Visit(func(f *flag.Flag) { - c.setFlags[f.Name] = true - }) - - c.flagSet.VisitAll(func(f *flag.Flag) { - if _, ok := c.setFlags[f.Name]; ok { - return - } - c.setFlags[f.Name] = false - }) - - // XXX hack to support IsSet for flags with EnvVar - // - // There isn't an easy way to do this with the current implementation since - // whether a flag was set via an environment variable is very difficult to - // determine here. Instead, we intend to introduce a backwards incompatible - // change in version 2 to add `IsSet` to the Flag interface to push the - // responsibility closer to where the information required to determine - // whether a flag is set by non-standard means such as environment - // variables is available. - // - // See https://github.com/urfave/cli/issues/294 for additional discussion - flags := c.Command.Flags - if c.Command.Name == "" { // cannot == Command{} since it contains slice types - if c.App != nil { - flags = c.App.Flags - } - } - for _, f := range flags { - eachName(f.GetName(), func(name string) { - if isSet, ok := c.setFlags[name]; isSet || !ok { - // Check if a flag is set - if isSet { - // If the flag is set, also set its other aliases - eachName(f.GetName(), func(name string) { - c.setFlags[name] = true - }) - } - - return - } - - val := reflect.ValueOf(f) - if val.Kind() == reflect.Ptr { - val = val.Elem() - } - - filePathValue := val.FieldByName("FilePath") - if filePathValue.IsValid() { - eachName(filePathValue.String(), func(filePath string) { - if _, err := os.Stat(filePath); err == nil { - c.setFlags[name] = true - return - } - }) - } - - envVarValue := val.FieldByName("EnvVar") - if envVarValue.IsValid() { - eachName(envVarValue.String(), func(envVar string) { - envVar = strings.TrimSpace(envVar) - if _, ok := syscall.Getenv(envVar); ok { - c.setFlags[name] = true - return - } - }) - } - }) - } - } - - return c.setFlags[name] -} - -// GlobalIsSet determines if the global flag was actually set -func (c *Context) GlobalIsSet(name string) bool { - ctx := c - if ctx.parentContext != nil { - ctx = ctx.parentContext - } - - for ; ctx != nil; ctx = ctx.parentContext { - if ctx.IsSet(name) { - return true - } - } - return false -} - -// FlagNames returns a slice of flag names used in this context. -func (c *Context) FlagNames() (names []string) { - for _, f := range c.Command.Flags { - name := strings.Split(f.GetName(), ",")[0] - if name == "help" { - continue - } - names = append(names, name) - } - return -} - -// GlobalFlagNames returns a slice of global flag names used by the app. -func (c *Context) GlobalFlagNames() (names []string) { - for _, f := range c.App.Flags { - name := strings.Split(f.GetName(), ",")[0] - if name == "help" || name == "version" { - continue - } - names = append(names, name) - } - return -} - -// Parent returns the parent context, if any -func (c *Context) Parent() *Context { - return c.parentContext -} - -// value returns the value of the flag coressponding to `name` -func (c *Context) value(name string) interface{} { - return c.flagSet.Lookup(name).Value.(flag.Getter).Get() -} - -// Args contains apps console arguments -type Args []string - -// Args returns the command line arguments associated with the context. -func (c *Context) Args() Args { - args := Args(c.flagSet.Args()) - return args -} - -// NArg returns the number of the command line arguments. -func (c *Context) NArg() int { - return len(c.Args()) -} - -// Get returns the nth argument, or else a blank string -func (a Args) Get(n int) string { - if len(a) > n { - return a[n] - } - return "" -} - -// First returns the first argument, or else a blank string -func (a Args) First() string { - return a.Get(0) -} - -// Tail returns the rest of the arguments (not the first one) -// or else an empty string slice -func (a Args) Tail() []string { - if len(a) >= 2 { - return []string(a)[1:] - } - return []string{} -} - -// Present checks if there are any arguments present -func (a Args) Present() bool { - return len(a) != 0 -} - -// Swap swaps arguments at the given indexes -func (a Args) Swap(from, to int) error { - if from >= len(a) || to >= len(a) { - return errors.New("index out of range") - } - a[from], a[to] = a[to], a[from] - return nil -} - -func globalContext(ctx *Context) *Context { - if ctx == nil { - return nil - } - - for { - if ctx.parentContext == nil { - return ctx - } - ctx = ctx.parentContext - } -} - -func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet { - if ctx.parentContext != nil { - ctx = ctx.parentContext - } - for ; ctx != nil; ctx = ctx.parentContext { - if f := ctx.flagSet.Lookup(name); f != nil { - return ctx.flagSet - } - } - return nil -} - -func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { - switch ff.Value.(type) { - case *StringSlice: - default: - _ = set.Set(name, ff.Value.String()) - } -} - -func normalizeFlags(flags []Flag, set *flag.FlagSet) error { - visited := make(map[string]bool) - set.Visit(func(f *flag.Flag) { - visited[f.Name] = true - }) - for _, f := range flags { - parts := strings.Split(f.GetName(), ",") - if len(parts) == 1 { - continue - } - var ff *flag.Flag - for _, name := range parts { - name = strings.Trim(name, " ") - if visited[name] { - if ff != nil { - return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) - } - ff = set.Lookup(name) - } - } - if ff == nil { - continue - } - for _, name := range parts { - name = strings.Trim(name, " ") - if !visited[name] { - copyFlag(name, ff, set) - } - } - } - return nil -} - -type requiredFlagsErr interface { - error - getMissingFlags() []string -} - -type errRequiredFlags struct { - missingFlags []string -} - -func (e *errRequiredFlags) Error() string { - numberOfMissingFlags := len(e.missingFlags) - if numberOfMissingFlags == 1 { - return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) - } - joinedMissingFlags := strings.Join(e.missingFlags, ", ") - return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) -} - -func (e *errRequiredFlags) getMissingFlags() []string { - return e.missingFlags -} - -func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr { - var missingFlags []string - for _, f := range flags { - if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { - var flagPresent bool - var flagName string - for _, key := range strings.Split(f.GetName(), ",") { - key = strings.TrimSpace(key) - if len(key) > 1 { - flagName = key - } - - if context.IsSet(key) { - flagPresent = true - } - } - - if !flagPresent && flagName != "" { - missingFlags = append(missingFlags, flagName) - } - } - } - - if len(missingFlags) != 0 { - return &errRequiredFlags{missingFlags: missingFlags} - } - - return nil -} diff --git a/vendor/github.com/urfave/cli/errors.go b/vendor/github.com/urfave/cli/errors.go deleted file mode 100644 index 562b2953c..000000000 --- a/vendor/github.com/urfave/cli/errors.go +++ /dev/null @@ -1,115 +0,0 @@ -package cli - -import ( - "fmt" - "io" - "os" - "strings" -) - -// OsExiter is the function used when the app exits. If not set defaults to os.Exit. -var OsExiter = os.Exit - -// ErrWriter is used to write errors to the user. This can be anything -// implementing the io.Writer interface and defaults to os.Stderr. -var ErrWriter io.Writer = os.Stderr - -// MultiError is an error that wraps multiple errors. -type MultiError struct { - Errors []error -} - -// NewMultiError creates a new MultiError. Pass in one or more errors. -func NewMultiError(err ...error) MultiError { - return MultiError{Errors: err} -} - -// Error implements the error interface. -func (m MultiError) Error() string { - errs := make([]string, len(m.Errors)) - for i, err := range m.Errors { - errs[i] = err.Error() - } - - return strings.Join(errs, "\n") -} - -type ErrorFormatter interface { - Format(s fmt.State, verb rune) -} - -// ExitCoder is the interface checked by `App` and `Command` for a custom exit -// code -type ExitCoder interface { - error - ExitCode() int -} - -// ExitError fulfills both the builtin `error` interface and `ExitCoder` -type ExitError struct { - exitCode int - message interface{} -} - -// NewExitError makes a new *ExitError -func NewExitError(message interface{}, exitCode int) *ExitError { - return &ExitError{ - exitCode: exitCode, - message: message, - } -} - -// Error returns the string message, fulfilling the interface required by -// `error` -func (ee *ExitError) Error() string { - return fmt.Sprintf("%v", ee.message) -} - -// ExitCode returns the exit code, fulfilling the interface required by -// `ExitCoder` -func (ee *ExitError) ExitCode() int { - return ee.exitCode -} - -// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if -// so prints the error to stderr (if it is non-empty) and calls OsExiter with the -// given exit code. If the given error is a MultiError, then this func is -// called on all members of the Errors slice and calls OsExiter with the last exit code. -func HandleExitCoder(err error) { - if err == nil { - return - } - - if exitErr, ok := err.(ExitCoder); ok { - if err.Error() != "" { - if _, ok := exitErr.(ErrorFormatter); ok { - fmt.Fprintf(ErrWriter, "%+v\n", err) - } else { - fmt.Fprintln(ErrWriter, err) - } - } - OsExiter(exitErr.ExitCode()) - return - } - - if multiErr, ok := err.(MultiError); ok { - code := handleMultiError(multiErr) - OsExiter(code) - return - } -} - -func handleMultiError(multiErr MultiError) int { - code := 1 - for _, merr := range multiErr.Errors { - if multiErr2, ok := merr.(MultiError); ok { - code = handleMultiError(multiErr2) - } else { - fmt.Fprintln(ErrWriter, merr) - if exitErr, ok := merr.(ExitCoder); ok { - code = exitErr.ExitCode() - } - } - } - return code -} diff --git a/vendor/github.com/urfave/cli/flag.go b/vendor/github.com/urfave/cli/flag.go deleted file mode 100644 index 5b7ae6c3f..000000000 --- a/vendor/github.com/urfave/cli/flag.go +++ /dev/null @@ -1,348 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "io/ioutil" - "reflect" - "runtime" - "strconv" - "strings" - "syscall" -) - -const defaultPlaceholder = "value" - -// BashCompletionFlag enables bash-completion for all commands and subcommands -var BashCompletionFlag Flag = BoolFlag{ - Name: "generate-bash-completion", - Hidden: true, -} - -// VersionFlag prints the version for the application -var VersionFlag Flag = BoolFlag{ - Name: "version, v", - Usage: "print the version", -} - -// HelpFlag prints the help for all commands and subcommands -// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand -// unless HideHelp is set to true) -var HelpFlag Flag = BoolFlag{ - Name: "help, h", - Usage: "show help", -} - -// FlagStringer converts a flag definition to a string. This is used by help -// to display a flag. -var FlagStringer FlagStringFunc = stringifyFlag - -// FlagNamePrefixer converts a full flag name and its placeholder into the help -// message flag prefix. This is used by the default FlagStringer. -var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames - -// FlagEnvHinter annotates flag help message with the environment variable -// details. This is used by the default FlagStringer. -var FlagEnvHinter FlagEnvHintFunc = withEnvHint - -// FlagFileHinter annotates flag help message with the environment variable -// details. This is used by the default FlagStringer. -var FlagFileHinter FlagFileHintFunc = withFileHint - -// FlagsByName is a slice of Flag. -type FlagsByName []Flag - -func (f FlagsByName) Len() int { - return len(f) -} - -func (f FlagsByName) Less(i, j int) bool { - return lexicographicLess(f[i].GetName(), f[j].GetName()) -} - -func (f FlagsByName) Swap(i, j int) { - f[i], f[j] = f[j], f[i] -} - -// Flag is a common interface related to parsing flags in cli. -// For more advanced flag parsing techniques, it is recommended that -// this interface be implemented. -type Flag interface { - fmt.Stringer - // Apply Flag settings to the given flag set - Apply(*flag.FlagSet) - GetName() string -} - -// RequiredFlag is an interface that allows us to mark flags as required -// it allows flags required flags to be backwards compatible with the Flag interface -type RequiredFlag interface { - Flag - - IsRequired() bool -} - -// DocGenerationFlag is an interface that allows documentation generation for the flag -type DocGenerationFlag interface { - Flag - - // TakesValue returns true if the flag takes a value, otherwise false - TakesValue() bool - - // GetUsage returns the usage string for the flag - GetUsage() string - - // GetValue returns the flags value as string representation and an empty - // string if the flag takes no value at all. - GetValue() string -} - -// errorableFlag is an interface that allows us to return errors during apply -// it allows flags defined in this library to return errors in a fashion backwards compatible -// TODO remove in v2 and modify the existing Flag interface to return errors -type errorableFlag interface { - Flag - - ApplyWithError(*flag.FlagSet) error -} - -func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { - set := flag.NewFlagSet(name, flag.ContinueOnError) - - for _, f := range flags { - //TODO remove in v2 when errorableFlag is removed - if ef, ok := f.(errorableFlag); ok { - if err := ef.ApplyWithError(set); err != nil { - return nil, err - } - } else { - f.Apply(set) - } - } - set.SetOutput(ioutil.Discard) - return set, nil -} - -func eachName(longName string, fn func(string)) { - parts := strings.Split(longName, ",") - for _, name := range parts { - name = strings.Trim(name, " ") - fn(name) - } -} - -func visibleFlags(fl []Flag) []Flag { - var visible []Flag - for _, f := range fl { - field := flagValue(f).FieldByName("Hidden") - if !field.IsValid() || !field.Bool() { - visible = append(visible, f) - } - } - return visible -} - -func prefixFor(name string) (prefix string) { - if len(name) == 1 { - prefix = "-" - } else { - prefix = "--" - } - - return -} - -// Returns the placeholder, if any, and the unquoted usage string. -func unquoteUsage(usage string) (string, string) { - for i := 0; i < len(usage); i++ { - if usage[i] == '`' { - for j := i + 1; j < len(usage); j++ { - if usage[j] == '`' { - name := usage[i+1 : j] - usage = usage[:i] + name + usage[j+1:] - return name, usage - } - } - break - } - } - return "", usage -} - -func prefixedNames(fullName, placeholder string) string { - var prefixed string - parts := strings.Split(fullName, ",") - for i, name := range parts { - name = strings.Trim(name, " ") - prefixed += prefixFor(name) + name - if placeholder != "" { - prefixed += " " + placeholder - } - if i < len(parts)-1 { - prefixed += ", " - } - } - return prefixed -} - -func withEnvHint(envVar, str string) string { - envText := "" - if envVar != "" { - prefix := "$" - suffix := "" - sep := ", $" - if runtime.GOOS == "windows" { - prefix = "%" - suffix = "%" - sep = "%, %" - } - envText = " [" + prefix + strings.Join(strings.Split(envVar, ","), sep) + suffix + "]" - } - return str + envText -} - -func withFileHint(filePath, str string) string { - fileText := "" - if filePath != "" { - fileText = fmt.Sprintf(" [%s]", filePath) - } - return str + fileText -} - -func flagValue(f Flag) reflect.Value { - fv := reflect.ValueOf(f) - for fv.Kind() == reflect.Ptr { - fv = reflect.Indirect(fv) - } - return fv -} - -func stringifyFlag(f Flag) string { - fv := flagValue(f) - - switch f.(type) { - case IntSliceFlag: - return FlagFileHinter( - fv.FieldByName("FilePath").String(), - FlagEnvHinter( - fv.FieldByName("EnvVar").String(), - stringifyIntSliceFlag(f.(IntSliceFlag)), - ), - ) - case Int64SliceFlag: - return FlagFileHinter( - fv.FieldByName("FilePath").String(), - FlagEnvHinter( - fv.FieldByName("EnvVar").String(), - stringifyInt64SliceFlag(f.(Int64SliceFlag)), - ), - ) - case StringSliceFlag: - return FlagFileHinter( - fv.FieldByName("FilePath").String(), - FlagEnvHinter( - fv.FieldByName("EnvVar").String(), - stringifyStringSliceFlag(f.(StringSliceFlag)), - ), - ) - } - - placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) - - needsPlaceholder := false - defaultValueString := "" - - if val := fv.FieldByName("Value"); val.IsValid() { - needsPlaceholder = true - defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface()) - - if val.Kind() == reflect.String && val.String() != "" { - defaultValueString = fmt.Sprintf(" (default: %q)", val.String()) - } - } - - if defaultValueString == " (default: )" { - defaultValueString = "" - } - - if needsPlaceholder && placeholder == "" { - placeholder = defaultPlaceholder - } - - usageWithDefault := strings.TrimSpace(usage + defaultValueString) - - return FlagFileHinter( - fv.FieldByName("FilePath").String(), - FlagEnvHinter( - fv.FieldByName("EnvVar").String(), - FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder)+"\t"+usageWithDefault, - ), - ) -} - -func stringifyIntSliceFlag(f IntSliceFlag) string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.Itoa(i)) - } - } - - return stringifySliceFlag(f.Usage, f.Name, defaultVals) -} - -func stringifyInt64SliceFlag(f Int64SliceFlag) string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) - } - } - - return stringifySliceFlag(f.Usage, f.Name, defaultVals) -} - -func stringifyStringSliceFlag(f StringSliceFlag) string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, s := range f.Value.Value() { - if len(s) > 0 { - defaultVals = append(defaultVals, strconv.Quote(s)) - } - } - } - - return stringifySliceFlag(f.Usage, f.Name, defaultVals) -} - -func stringifySliceFlag(usage, name string, defaultVals []string) string { - placeholder, usage := unquoteUsage(usage) - if placeholder == "" { - placeholder = defaultPlaceholder - } - - defaultVal := "" - if len(defaultVals) > 0 { - defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", ")) - } - - usageWithDefault := strings.TrimSpace(usage + defaultVal) - return FlagNamePrefixer(name, placeholder) + "\t" + usageWithDefault -} - -func flagFromFileEnv(filePath, envName string) (val string, ok bool) { - for _, envVar := range strings.Split(envName, ",") { - envVar = strings.TrimSpace(envVar) - if envVal, ok := syscall.Getenv(envVar); ok { - return envVal, true - } - } - for _, fileVar := range strings.Split(filePath, ",") { - if fileVar != "" { - if data, err := ioutil.ReadFile(fileVar); err == nil { - return string(data), true - } - } - } - return "", false -} diff --git a/vendor/github.com/urfave/cli/flag_bool.go b/vendor/github.com/urfave/cli/flag_bool.go deleted file mode 100644 index 2499b0b52..000000000 --- a/vendor/github.com/urfave/cli/flag_bool.go +++ /dev/null @@ -1,109 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// BoolFlag is a flag with type bool -type BoolFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Destination *bool -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f BoolFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f BoolFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f BoolFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f BoolFlag) TakesValue() bool { - return false -} - -// GetUsage returns the usage string for the flag -func (f BoolFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f BoolFlag) GetValue() string { - return "" -} - -// Bool looks up the value of a local BoolFlag, returns -// false if not found -func (c *Context) Bool(name string) bool { - return lookupBool(name, c.flagSet) -} - -// GlobalBool looks up the value of a global BoolFlag, returns -// false if not found -func (c *Context) GlobalBool(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBool(name, fs) - } - return false -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f BoolFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error { - val := false - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - if envVal == "" { - val = false - } else { - envValBool, err := strconv.ParseBool(envVal) - if err != nil { - return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) - } - val = envValBool - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.BoolVar(f.Destination, name, val, f.Usage) - return - } - set.Bool(name, val, f.Usage) - }) - - return nil -} - -func lookupBool(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return parsed - } - return false -} diff --git a/vendor/github.com/urfave/cli/flag_bool_t.go b/vendor/github.com/urfave/cli/flag_bool_t.go deleted file mode 100644 index cd0888fa2..000000000 --- a/vendor/github.com/urfave/cli/flag_bool_t.go +++ /dev/null @@ -1,110 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// BoolTFlag is a flag with type bool that is true by default -type BoolTFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Destination *bool -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f BoolTFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f BoolTFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f BoolTFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f BoolTFlag) TakesValue() bool { - return false -} - -// GetUsage returns the usage string for the flag -func (f BoolTFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f BoolTFlag) GetValue() string { - return "" -} - -// BoolT looks up the value of a local BoolTFlag, returns -// false if not found -func (c *Context) BoolT(name string) bool { - return lookupBoolT(name, c.flagSet) -} - -// GlobalBoolT looks up the value of a global BoolTFlag, returns -// false if not found -func (c *Context) GlobalBoolT(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBoolT(name, fs) - } - return false -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f BoolTFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error { - val := true - - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - if envVal == "" { - val = false - } else { - envValBool, err := strconv.ParseBool(envVal) - if err != nil { - return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) - } - val = envValBool - } - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.BoolVar(f.Destination, name, val, f.Usage) - return - } - set.Bool(name, val, f.Usage) - }) - - return nil -} - -func lookupBoolT(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return parsed - } - return false -} diff --git a/vendor/github.com/urfave/cli/flag_duration.go b/vendor/github.com/urfave/cli/flag_duration.go deleted file mode 100644 index df4ade589..000000000 --- a/vendor/github.com/urfave/cli/flag_duration.go +++ /dev/null @@ -1,106 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "time" -) - -// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) -type DurationFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value time.Duration - Destination *time.Duration -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f DurationFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f DurationFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f DurationFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f DurationFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f DurationFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f DurationFlag) GetValue() string { - return f.Value.String() -} - -// Duration looks up the value of a local DurationFlag, returns -// 0 if not found -func (c *Context) Duration(name string) time.Duration { - return lookupDuration(name, c.flagSet) -} - -// GlobalDuration looks up the value of a global DurationFlag, returns -// 0 if not found -func (c *Context) GlobalDuration(name string) time.Duration { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupDuration(name, fs) - } - return 0 -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f DurationFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - envValDuration, err := time.ParseDuration(envVal) - if err != nil { - return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err) - } - - f.Value = envValDuration - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.DurationVar(f.Destination, name, f.Value, f.Usage) - return - } - set.Duration(name, f.Value, f.Usage) - }) - - return nil -} - -func lookupDuration(name string, set *flag.FlagSet) time.Duration { - f := set.Lookup(name) - if f != nil { - parsed, err := time.ParseDuration(f.Value.String()) - if err != nil { - return 0 - } - return parsed - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/flag_float64.go b/vendor/github.com/urfave/cli/flag_float64.go deleted file mode 100644 index 65398d3b5..000000000 --- a/vendor/github.com/urfave/cli/flag_float64.go +++ /dev/null @@ -1,106 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// Float64Flag is a flag with type float64 -type Float64Flag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value float64 - Destination *float64 -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Float64Flag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Float64Flag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f Float64Flag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f Float64Flag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f Float64Flag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Float64Flag) GetValue() string { - return fmt.Sprintf("%f", f.Value) -} - -// Float64 looks up the value of a local Float64Flag, returns -// 0 if not found -func (c *Context) Float64(name string) float64 { - return lookupFloat64(name, c.flagSet) -} - -// GlobalFloat64 looks up the value of a global Float64Flag, returns -// 0 if not found -func (c *Context) GlobalFloat64(name string) float64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupFloat64(name, fs) - } - return 0 -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Float64Flag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - envValFloat, err := strconv.ParseFloat(envVal, 10) - if err != nil { - return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = envValFloat - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.Float64Var(f.Destination, name, f.Value, f.Usage) - return - } - set.Float64(name, f.Value, f.Usage) - }) - - return nil -} - -func lookupFloat64(name string, set *flag.FlagSet) float64 { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseFloat(f.Value.String(), 64) - if err != nil { - return 0 - } - return parsed - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/flag_generic.go b/vendor/github.com/urfave/cli/flag_generic.go deleted file mode 100644 index c43dae7d0..000000000 --- a/vendor/github.com/urfave/cli/flag_generic.go +++ /dev/null @@ -1,110 +0,0 @@ -package cli - -import ( - "flag" - "fmt" -) - -// Generic is a generic parseable type identified by a specific flag -type Generic interface { - Set(value string) error - String() string -} - -// GenericFlag is a flag with type Generic -type GenericFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value Generic -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f GenericFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f GenericFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f GenericFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f GenericFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f GenericFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f GenericFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() - } - return "" -} - -// Apply takes the flagset and calls Set on the generic flag with the value -// provided by the user for parsing by the flag -// Ignores parsing errors -func (f GenericFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError takes the flagset and calls Set on the generic flag with the value -// provided by the user for parsing by the flag -func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error { - val := f.Value - if fileEnvVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - if err := val.Set(fileEnvVal); err != nil { - return fmt.Errorf("could not parse %s as value for flag %s: %s", fileEnvVal, f.Name, err) - } - } - - eachName(f.Name, func(name string) { - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// Generic looks up the value of a local GenericFlag, returns -// nil if not found -func (c *Context) Generic(name string) interface{} { - return lookupGeneric(name, c.flagSet) -} - -// GlobalGeneric looks up the value of a global GenericFlag, returns -// nil if not found -func (c *Context) GlobalGeneric(name string) interface{} { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupGeneric(name, fs) - } - return nil -} - -func lookupGeneric(name string, set *flag.FlagSet) interface{} { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value, error(nil) - if err != nil { - return nil - } - return parsed - } - return nil -} diff --git a/vendor/github.com/urfave/cli/flag_int.go b/vendor/github.com/urfave/cli/flag_int.go deleted file mode 100644 index bae32e281..000000000 --- a/vendor/github.com/urfave/cli/flag_int.go +++ /dev/null @@ -1,105 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// IntFlag is a flag with type int -type IntFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value int - Destination *int -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f IntFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f IntFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f IntFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f IntFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f IntFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f IntFlag) GetValue() string { - return fmt.Sprintf("%d", f.Value) -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f IntFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f IntFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) - } - f.Value = int(envValInt) - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.IntVar(f.Destination, name, f.Value, f.Usage) - return - } - set.Int(name, f.Value, f.Usage) - }) - - return nil -} - -// Int looks up the value of a local IntFlag, returns -// 0 if not found -func (c *Context) Int(name string) int { - return lookupInt(name, c.flagSet) -} - -// GlobalInt looks up the value of a global IntFlag, returns -// 0 if not found -func (c *Context) GlobalInt(name string) int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt(name, fs) - } - return 0 -} - -func lookupInt(name string, set *flag.FlagSet) int { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return int(parsed) - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/flag_int64.go b/vendor/github.com/urfave/cli/flag_int64.go deleted file mode 100644 index aaafbe9d6..000000000 --- a/vendor/github.com/urfave/cli/flag_int64.go +++ /dev/null @@ -1,106 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// Int64Flag is a flag with type int64 -type Int64Flag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value int64 - Destination *int64 -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Int64Flag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Int64Flag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f Int64Flag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f Int64Flag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f Int64Flag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Int64Flag) GetValue() string { - return fmt.Sprintf("%d", f.Value) -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Int64Flag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = envValInt - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.Int64Var(f.Destination, name, f.Value, f.Usage) - return - } - set.Int64(name, f.Value, f.Usage) - }) - - return nil -} - -// Int64 looks up the value of a local Int64Flag, returns -// 0 if not found -func (c *Context) Int64(name string) int64 { - return lookupInt64(name, c.flagSet) -} - -// GlobalInt64 looks up the value of a global Int64Flag, returns -// 0 if not found -func (c *Context) GlobalInt64(name string) int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64(name, fs) - } - return 0 -} - -func lookupInt64(name string, set *flag.FlagSet) int64 { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return parsed - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/flag_int64_slice.go b/vendor/github.com/urfave/cli/flag_int64_slice.go deleted file mode 100644 index 80772e7c2..000000000 --- a/vendor/github.com/urfave/cli/flag_int64_slice.go +++ /dev/null @@ -1,199 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" - "strings" -) - -// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter -type Int64Slice []int64 - -// Set parses the value into an integer and appends it to the list of values -func (f *Int64Slice) Set(value string) error { - tmp, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return err - } - *f = append(*f, tmp) - return nil -} - -// String returns a readable representation of this value (for usage defaults) -func (f *Int64Slice) String() string { - slice := make([]string, len(*f)) - for i, v := range *f { - slice[i] = strconv.FormatInt(v, 10) - } - - return strings.Join(slice, ",") -} - -// Value returns the slice of ints set by this flag -func (f *Int64Slice) Value() []int64 { - return *f -} - -// Get returns the slice of ints set by this flag -func (f *Int64Slice) Get() interface{} { - return *f -} - -// Int64SliceFlag is a flag with type *Int64Slice -type Int64SliceFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value *Int64Slice -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Int64SliceFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Int64SliceFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f Int64SliceFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f Int64SliceFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f Int64SliceFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Int64SliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() - } - return "" -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Int64SliceFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - newVal := &Int64Slice{} - for _, s := range strings.Split(envVal, ",") { - s = strings.TrimSpace(s) - if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err) - } - } - if f.Value == nil { - f.Value = newVal - } else { - *f.Value = *newVal - } - } - - eachName(f.Name, func(name string) { - if f.Value == nil { - f.Value = &Int64Slice{} - } - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// Int64Slice looks up the value of a local Int64SliceFlag, returns -// nil if not found -func (c *Context) Int64Slice(name string) []int64 { - return lookupInt64Slice(name, c.flagSet) -} - -// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns -// nil if not found -func (c *Context) GlobalInt64Slice(name string) []int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64Slice(name, fs) - } - return nil -} - -func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { - f := set.Lookup(name) - if f != nil { - value, ok := f.Value.(*Int64Slice) - if !ok { - return nil - } - - // extract the slice from asserted value - parsed := value.Value() - - // extract default value from the flag - var defaultVal []int64 - for _, v := range strings.Split(f.DefValue, ",") { - if v != "" { - int64Value, err := strconv.ParseInt(v, 10, 64) - if err != nil { - panic(err) - } - defaultVal = append(defaultVal, int64Value) - } - } - // if the current value is not equal to the default value - // remove the default values from the flag - if !isInt64SliceEqual(parsed, defaultVal) { - for _, v := range defaultVal { - parsed = removeFromInt64Slice(parsed, v) - } - } - return parsed - } - return nil -} - -func removeFromInt64Slice(slice []int64, val int64) []int64 { - for i, v := range slice { - if v == val { - ret := append([]int64{}, slice[:i]...) - ret = append(ret, slice[i+1:]...) - return ret - } - } - return slice -} - -func isInt64SliceEqual(newValue, defaultValue []int64) bool { - // If one is nil, the other must also be nil. - if (newValue == nil) != (defaultValue == nil) { - return false - } - - if len(newValue) != len(defaultValue) { - return false - } - - for i, v := range newValue { - if v != defaultValue[i] { - return false - } - } - - return true -} diff --git a/vendor/github.com/urfave/cli/flag_int_slice.go b/vendor/github.com/urfave/cli/flag_int_slice.go deleted file mode 100644 index af6d582de..000000000 --- a/vendor/github.com/urfave/cli/flag_int_slice.go +++ /dev/null @@ -1,198 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" - "strings" -) - -// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter -type IntSlice []int - -// Set parses the value into an integer and appends it to the list of values -func (f *IntSlice) Set(value string) error { - tmp, err := strconv.Atoi(value) - if err != nil { - return err - } - *f = append(*f, tmp) - return nil -} - -// String returns a readable representation of this value (for usage defaults) -func (f *IntSlice) String() string { - slice := make([]string, len(*f)) - for i, v := range *f { - slice[i] = strconv.Itoa(v) - } - - return strings.Join(slice, ",") -} - -// Value returns the slice of ints set by this flag -func (f *IntSlice) Value() []int { - return *f -} - -// Get returns the slice of ints set by this flag -func (f *IntSlice) Get() interface{} { - return *f -} - -// IntSliceFlag is a flag with type *IntSlice -type IntSliceFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value *IntSlice -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f IntSliceFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f IntSliceFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f IntSliceFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f IntSliceFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f IntSliceFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f IntSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() - } - return "" -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f IntSliceFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - newVal := &IntSlice{} - for _, s := range strings.Split(envVal, ",") { - s = strings.TrimSpace(s) - if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err) - } - } - if f.Value == nil { - f.Value = newVal - } else { - *f.Value = *newVal - } - } - - eachName(f.Name, func(name string) { - if f.Value == nil { - f.Value = &IntSlice{} - } - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// IntSlice looks up the value of a local IntSliceFlag, returns -// nil if not found -func (c *Context) IntSlice(name string) []int { - return lookupIntSlice(name, c.flagSet) -} - -// GlobalIntSlice looks up the value of a global IntSliceFlag, returns -// nil if not found -func (c *Context) GlobalIntSlice(name string) []int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupIntSlice(name, fs) - } - return nil -} - -func lookupIntSlice(name string, set *flag.FlagSet) []int { - f := set.Lookup(name) - if f != nil { - value, ok := f.Value.(*IntSlice) - if !ok { - return nil - } - // extract the slice from asserted value - slice := value.Value() - - // extract default value from the flag - var defaultVal []int - for _, v := range strings.Split(f.DefValue, ",") { - if v != "" { - intValue, err := strconv.Atoi(v) - if err != nil { - panic(err) - } - defaultVal = append(defaultVal, intValue) - } - } - // if the current value is not equal to the default value - // remove the default values from the flag - if !isIntSliceEqual(slice, defaultVal) { - for _, v := range defaultVal { - slice = removeFromIntSlice(slice, v) - } - } - return slice - } - return nil -} - -func removeFromIntSlice(slice []int, val int) []int { - for i, v := range slice { - if v == val { - ret := append([]int{}, slice[:i]...) - ret = append(ret, slice[i+1:]...) - return ret - } - } - return slice -} - -func isIntSliceEqual(newValue, defaultValue []int) bool { - // If one is nil, the other must also be nil. - if (newValue == nil) != (defaultValue == nil) { - return false - } - - if len(newValue) != len(defaultValue) { - return false - } - - for i, v := range newValue { - if v != defaultValue[i] { - return false - } - } - - return true -} diff --git a/vendor/github.com/urfave/cli/flag_string.go b/vendor/github.com/urfave/cli/flag_string.go deleted file mode 100644 index 9f29da40b..000000000 --- a/vendor/github.com/urfave/cli/flag_string.go +++ /dev/null @@ -1,98 +0,0 @@ -package cli - -import "flag" - -// StringFlag is a flag with type string -type StringFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value string - Destination *string -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f StringFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f StringFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f StringFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f StringFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f StringFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f StringFlag) GetValue() string { - return f.Value -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f StringFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f StringFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - f.Value = envVal - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.StringVar(f.Destination, name, f.Value, f.Usage) - return - } - set.String(name, f.Value, f.Usage) - }) - - return nil -} - -// String looks up the value of a local StringFlag, returns -// "" if not found -func (c *Context) String(name string) string { - return lookupString(name, c.flagSet) -} - -// GlobalString looks up the value of a global StringFlag, returns -// "" if not found -func (c *Context) GlobalString(name string) string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupString(name, fs) - } - return "" -} - -func lookupString(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value.String(), error(nil) - if err != nil { - return "" - } - return parsed - } - return "" -} diff --git a/vendor/github.com/urfave/cli/flag_string_slice.go b/vendor/github.com/urfave/cli/flag_string_slice.go deleted file mode 100644 index a7c71e9dc..000000000 --- a/vendor/github.com/urfave/cli/flag_string_slice.go +++ /dev/null @@ -1,184 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strings" -) - -// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter -type StringSlice []string - -// Set appends the string value to the list of values -func (f *StringSlice) Set(value string) error { - *f = append(*f, value) - return nil -} - -// String returns a readable representation of this value (for usage defaults) -func (f *StringSlice) String() string { - return strings.Join(*f, ",") -} - -// Value returns the slice of strings set by this flag -func (f *StringSlice) Value() []string { - return *f -} - -// Get returns the slice of strings set by this flag -func (f *StringSlice) Get() interface{} { - return *f -} - -// StringSliceFlag is a flag with type *StringSlice -type StringSliceFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value *StringSlice -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f StringSliceFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f StringSliceFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f StringSliceFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f StringSliceFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f StringSliceFlag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f StringSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() - } - return "" -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f StringSliceFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - newVal := &StringSlice{} - for _, s := range strings.Split(envVal, ",") { - s = strings.TrimSpace(s) - if err := newVal.Set(s); err != nil { - return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err) - } - } - if f.Value == nil { - f.Value = newVal - } else { - *f.Value = *newVal - } - } - - eachName(f.Name, func(name string) { - if f.Value == nil { - f.Value = &StringSlice{} - } - set.Var(f.Value, name, f.Usage) - }) - - return nil -} - -// StringSlice looks up the value of a local StringSliceFlag, returns -// nil if not found -func (c *Context) StringSlice(name string) []string { - return lookupStringSlice(name, c.flagSet) -} - -// GlobalStringSlice looks up the value of a global StringSliceFlag, returns -// nil if not found -func (c *Context) GlobalStringSlice(name string) []string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupStringSlice(name, fs) - } - return nil -} - -func lookupStringSlice(name string, set *flag.FlagSet) []string { - f := set.Lookup(name) - if f != nil { - value, ok := f.Value.(*StringSlice) - if !ok { - return nil - } - // extract the slice from asserted value - slice := value.Value() - - // extract default value from the flag - var defaultVal []string - for _, v := range strings.Split(f.DefValue, ",") { - defaultVal = append(defaultVal, v) - } - - // if the current value is not equal to the default value - // remove the default values from the flag - if !isStringSliceEqual(slice, defaultVal) { - for _, v := range defaultVal { - slice = removeFromStringSlice(slice, v) - } - } - return slice - } - return nil -} - -func removeFromStringSlice(slice []string, val string) []string { - for i, v := range slice { - if v == val { - ret := append([]string{}, slice[:i]...) - ret = append(ret, slice[i+1:]...) - return ret - } - } - return slice -} - -func isStringSliceEqual(newValue, defaultValue []string) bool { - // If one is nil, the other must also be nil. - if (newValue == nil) != (defaultValue == nil) { - return false - } - - if len(newValue) != len(defaultValue) { - return false - } - - for i, v := range newValue { - if v != defaultValue[i] { - return false - } - } - - return true -} diff --git a/vendor/github.com/urfave/cli/flag_uint.go b/vendor/github.com/urfave/cli/flag_uint.go deleted file mode 100644 index d6a04f408..000000000 --- a/vendor/github.com/urfave/cli/flag_uint.go +++ /dev/null @@ -1,106 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// UintFlag is a flag with type uint -type UintFlag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value uint - Destination *uint -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f UintFlag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f UintFlag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f UintFlag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f UintFlag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f UintFlag) GetUsage() string { - return f.Usage -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f UintFlag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f UintFlag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = uint(envValInt) - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.UintVar(f.Destination, name, f.Value, f.Usage) - return - } - set.Uint(name, f.Value, f.Usage) - }) - - return nil -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f UintFlag) GetValue() string { - return fmt.Sprintf("%d", f.Value) -} - -// Uint looks up the value of a local UintFlag, returns -// 0 if not found -func (c *Context) Uint(name string) uint { - return lookupUint(name, c.flagSet) -} - -// GlobalUint looks up the value of a global UintFlag, returns -// 0 if not found -func (c *Context) GlobalUint(name string) uint { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint(name, fs) - } - return 0 -} - -func lookupUint(name string, set *flag.FlagSet) uint { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return uint(parsed) - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/flag_uint64.go b/vendor/github.com/urfave/cli/flag_uint64.go deleted file mode 100644 index ea6493a8b..000000000 --- a/vendor/github.com/urfave/cli/flag_uint64.go +++ /dev/null @@ -1,106 +0,0 @@ -package cli - -import ( - "flag" - "fmt" - "strconv" -) - -// Uint64Flag is a flag with type uint64 -type Uint64Flag struct { - Name string - Usage string - EnvVar string - FilePath string - Required bool - Hidden bool - Value uint64 - Destination *uint64 -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f Uint64Flag) String() string { - return FlagStringer(f) -} - -// GetName returns the name of the flag -func (f Uint64Flag) GetName() string { - return f.Name -} - -// IsRequired returns whether or not the flag is required -func (f Uint64Flag) IsRequired() bool { - return f.Required -} - -// TakesValue returns true of the flag takes a value, otherwise false -func (f Uint64Flag) TakesValue() bool { - return true -} - -// GetUsage returns the usage string for the flag -func (f Uint64Flag) GetUsage() string { - return f.Usage -} - -// GetValue returns the flags value as string representation and an empty -// string if the flag takes no value at all. -func (f Uint64Flag) GetValue() string { - return fmt.Sprintf("%d", f.Value) -} - -// Apply populates the flag given the flag set and environment -// Ignores errors -func (f Uint64Flag) Apply(set *flag.FlagSet) { - _ = f.ApplyWithError(set) -} - -// ApplyWithError populates the flag given the flag set and environment -func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error { - if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok { - envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err != nil { - return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err) - } - - f.Value = envValInt - } - - eachName(f.Name, func(name string) { - if f.Destination != nil { - set.Uint64Var(f.Destination, name, f.Value, f.Usage) - return - } - set.Uint64(name, f.Value, f.Usage) - }) - - return nil -} - -// Uint64 looks up the value of a local Uint64Flag, returns -// 0 if not found -func (c *Context) Uint64(name string) uint64 { - return lookupUint64(name, c.flagSet) -} - -// GlobalUint64 looks up the value of a global Uint64Flag, returns -// 0 if not found -func (c *Context) GlobalUint64(name string) uint64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint64(name, fs) - } - return 0 -} - -func lookupUint64(name string, set *flag.FlagSet) uint64 { - f := set.Lookup(name) - if f != nil { - parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return parsed - } - return 0 -} diff --git a/vendor/github.com/urfave/cli/.flake8 b/vendor/github.com/urfave/cli/v2/.flake8 similarity index 100% rename from vendor/github.com/urfave/cli/.flake8 rename to vendor/github.com/urfave/cli/v2/.flake8 diff --git a/vendor/github.com/urfave/cli/v2/.gitignore b/vendor/github.com/urfave/cli/v2/.gitignore new file mode 100644 index 000000000..c04fcc538 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/.gitignore @@ -0,0 +1,10 @@ +*.coverprofile +*.orig +vendor +.idea +internal/*/built-example +coverage.txt +/.local/ +/site/ + +*.exe diff --git a/vendor/github.com/urfave/cli/CODE_OF_CONDUCT.md b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md similarity index 87% rename from vendor/github.com/urfave/cli/CODE_OF_CONDUCT.md rename to vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md index 41ba294f6..9fee14807 100644 --- a/vendor/github.com/urfave/cli/CODE_OF_CONDUCT.md +++ b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md @@ -55,11 +55,12 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting Dan Buch at dan@meatballhat.com. All complaints will be -reviewed and investigated and will result in a response that is deemed necessary -and appropriate to the circumstances. The project team is obligated to maintain -confidentiality with regard to the reporter of an incident. Further details of -specific enforcement policies may be posted separately. +reported by contacting urfave-governance@googlegroups.com, a members-only group +that is world-postable. All complaints will be reviewed and investigated and +will result in a response that is deemed necessary and appropriate to the +circumstances. The project team is obligated to maintain confidentiality with +regard to the reporter of an incident. Further details of specific enforcement +policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE b/vendor/github.com/urfave/cli/v2/LICENSE similarity index 96% rename from vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE rename to vendor/github.com/urfave/cli/v2/LICENSE index c35c17af9..2c84c78a1 100644 --- a/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE +++ b/vendor/github.com/urfave/cli/v2/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2015 Dmitri Shuralyov +Copyright (c) 2022 urfave/cli maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/urfave/cli/v2/Makefile b/vendor/github.com/urfave/cli/v2/Makefile new file mode 100644 index 000000000..3b0e5e0bb --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/Makefile @@ -0,0 +1,40 @@ +# NOTE: this Makefile is meant to provide a simplified entry point for humans to +# run all of the critical steps to verify one's changes are harmonious in +# nature. Keeping target bodies to one line each and abstaining from make magic +# are very important so that maintainers and contributors can focus their +# attention on files that are primarily Go. + +.PHONY: all +all: generate vet tag-test test check-binary-size tag-check-binary-size gfmrun v2diff + +# NOTE: this is a special catch-all rule to run any of the commands +# defined in internal/build/build.go with optional arguments passed +# via GFLAGS (global flags) and FLAGS (command-specific flags), e.g.: +# +# $ make test GFLAGS='--packages cli' +%: + go run internal/build/build.go $(GFLAGS) $* $(FLAGS) + +.PHONY: tag-test +tag-test: + go run internal/build/build.go -tags urfave_cli_no_docs test + +.PHONY: tag-check-binary-size +tag-check-binary-size: + go run internal/build/build.go -tags urfave_cli_no_docs check-binary-size + +.PHONY: gfmrun +gfmrun: + go run internal/build/build.go gfmrun docs/v2/manual.md + +.PHONY: docs +docs: + mkdocs build + +.PHONY: docs-deps +docs-deps: + pip install -r mkdocs-requirements.txt + +.PHONY: serve-docs +serve-docs: + mkdocs serve diff --git a/vendor/github.com/urfave/cli/v2/README.md b/vendor/github.com/urfave/cli/v2/README.md new file mode 100644 index 000000000..eaed35630 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/README.md @@ -0,0 +1,19 @@ +# cli + +[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://pkg.go.dev/github.com/urfave/cli/v2) +[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) +[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) +[![codecov](https://codecov.io/gh/urfave/cli/branch/main/graph/badge.svg)](https://codecov.io/gh/urfave/cli) + +cli is a simple, fast, and fun package for building command line apps in Go. The +goal is to enable developers to write fast and distributable command line +applications in an expressive way. + +## Documentation + +More documentation is available in [`./docs`](./docs) or the hosted +documentation site at . + +## License + +See [`LICENSE`](./LICENSE) diff --git a/vendor/github.com/urfave/cli/app.go b/vendor/github.com/urfave/cli/v2/app.go similarity index 52% rename from vendor/github.com/urfave/cli/app.go rename to vendor/github.com/urfave/cli/v2/app.go index 382f238f4..0b3f45cfd 100644 --- a/vendor/github.com/urfave/cli/app.go +++ b/vendor/github.com/urfave/cli/v2/app.go @@ -1,26 +1,30 @@ package cli import ( + "context" "flag" "fmt" "io" "os" "path/filepath" + "reflect" "sort" "time" ) +const suggestDidYouMeanTemplate = "Did you mean %q?" + var ( - changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md" + changeLogURL = "https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md" appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL) - // unused variable. commented for now. will remove in future if agreed upon by everyone - //runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL) - - contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." - - errInvalidActionType = NewExitError("ERROR invalid Action type. "+ + contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." + errInvalidActionType = NewExitError("ERROR invalid Action type. "+ fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ fmt.Sprintf("See %s", appActionDeprecationURL), 2) + + SuggestFlag SuggestFlagFunc = suggestFlag + SuggestCommand SuggestCommandFunc = suggestCommand + SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate ) // App is the main structure of a cli application. It is recommended that @@ -40,19 +44,27 @@ type App struct { Version string // Description of the program Description string + // DefaultCommand is the (optional) name of a command + // to run if no command names are passed as CLI arguments. + DefaultCommand string // List of commands to execute - Commands []Command + Commands []*Command // List of flags to parse Flags []Flag // Boolean to enable bash completion commands EnableBashCompletion bool - // Boolean to hide built-in help command + // Boolean to hide built-in help command and help flag HideHelp bool + // Boolean to hide built-in help command but keep help flag. + // Ignored if HideHelp is true. + HideHelpCommand bool // Boolean to hide built-in version flag and the VERSION section of help HideVersion bool - // Populate on app startup, only gettable through method Categories() + // categories contains the categorized commands and is populated on app startup categories CommandCategories - // An action to execute when the bash-completion flag is set + // flagCategories contains the categorized flags and is populated on app startup + flagCategories FlagCategories + // An action to execute when the shell completion flag is set BashComplete BashCompleteFunc // An action to execute before any subcommands are run, but after the context is ready // If a non-nil error is returned, no subcommands are run @@ -60,32 +72,27 @@ type App struct { // An action to execute after any subcommands are run, but after the subcommand has finished // It is run even if Action() panics After AfterFunc - // The action to execute when no subcommands are specified - // Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}` - // *Note*: support for the deprecated `Action` signature will be removed in a future version - Action interface{} - + Action ActionFunc // Execute this function if the proper command cannot be found CommandNotFound CommandNotFoundFunc - // Execute this function if an usage error occurs + // Execute this function if a usage error occurs OnUsageError OnUsageErrorFunc // Compilation date Compiled time.Time // List of all authors who contributed - Authors []Author + Authors []*Author // Copyright of the binary if any Copyright string - // Name of Author (Note: Use App.Authors, this is deprecated) - Author string - // Email of Author (Note: Use App.Authors, this is deprecated) - Email string + // Reader reader to write input to (useful for tests) + Reader io.Reader // Writer writer to write output to Writer io.Writer // ErrWriter writes error output ErrWriter io.Writer - // Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to - // function as a default, so this is optional. + // ExitErrHandler processes any error encountered while running an App before + // it is returned to the caller. If no function is provided, HandleExitCoder + // is used as the default behavior. ExitErrHandler ExitErrHandlerFunc // Other custom info Metadata map[string]interface{} @@ -96,13 +103,19 @@ type App struct { // render custom help text by setting this variable. CustomAppHelpTemplate string // Boolean to enable short-option handling so user can combine several - // single-character bool arguements into one + // single-character bool arguments into one // i.e. foobar -o -v -> foobar -ov UseShortOptionHandling bool + // Enable suggestions for commands and flags + Suggest bool didSetup bool } +type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string + +type SuggestCommandFunc func(commands []*Command, provided string) string + // Tries to find out when this binary was compiled. // Returns the current time if it fails to find it. func compileTime() time.Time { @@ -124,7 +137,9 @@ func NewApp() *App { BashComplete: DefaultAppComplete, Action: helpCommand.Action, Compiled: compileTime(), + Reader: os.Stdin, Writer: os.Stdout, + ErrWriter: os.Stderr, } } @@ -138,46 +153,87 @@ func (a *App) Setup() { a.didSetup = true - if a.Author != "" || a.Email != "" { - a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) + if a.Name == "" { + a.Name = filepath.Base(os.Args[0]) + } + + if a.HelpName == "" { + a.HelpName = a.Name + } + + if a.Usage == "" { + a.Usage = "A new cli application" + } + + if a.Version == "" { + a.HideVersion = true + } + + if a.BashComplete == nil { + a.BashComplete = DefaultAppComplete + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + if a.Compiled == (time.Time{}) { + a.Compiled = compileTime() + } + + if a.Reader == nil { + a.Reader = os.Stdin + } + + if a.Writer == nil { + a.Writer = os.Stdout + } + + if a.ErrWriter == nil { + a.ErrWriter = os.Stderr } - var newCmds []Command + var newCommands []*Command + for _, c := range a.Commands { if c.HelpName == "" { c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) } - newCmds = append(newCmds, c) + + c.flagCategories = newFlagCategoriesFromFlags(c.Flags) + newCommands = append(newCommands, c) } - a.Commands = newCmds + a.Commands = newCommands if a.Command(helpCommand.Name) == nil && !a.HideHelp { - a.Commands = append(a.Commands, helpCommand) - if (HelpFlag != BoolFlag{}) { - a.appendFlag(HelpFlag) + if !a.HideHelpCommand { + a.appendCommand(helpCommand) } - } - if a.Version == "" { - a.HideVersion = true + if HelpFlag != nil { + a.appendFlag(HelpFlag) + } } if !a.HideVersion { a.appendFlag(VersionFlag) } - a.categories = CommandCategories{} + a.categories = newCommandCategories() for _, command := range a.Commands { - a.categories = a.categories.AddCommand(command.Category, command) + a.categories.AddCommand(command.Category, command) } - sort.Sort(a.categories) + sort.Sort(a.categories.(*commandCategories)) - if a.Metadata == nil { - a.Metadata = make(map[string]interface{}) + a.flagCategories = newFlagCategories() + for _, fl := range a.Flags { + if cf, ok := fl.(CategorizableFlag); ok { + a.flagCategories.AddFlag(cf.GetCategory(), cf) + } } - if a.Writer == nil { - a.Writer = os.Stdout + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) } } @@ -192,6 +248,13 @@ func (a *App) useShortOptionHandling() bool { // Run is the entry point to the cli app. Parses the arguments slice and routes // to the proper flag/args combination func (a *App) Run(arguments []string) (err error) { + return a.RunContext(context.Background(), arguments) +} + +// RunContext is like Run except it takes a Context that will be +// passed to its commands and sub-commands. Through this, you can +// propagate timeouts and cancellation requests +func (a *App) RunContext(ctx context.Context, arguments []string) (err error) { a.Setup() // handle the completion flag separately from the flagset since @@ -209,50 +272,43 @@ func (a *App) Run(arguments []string) (err error) { err = parseIter(set, a, arguments[1:], shellComplete) nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, nil) + cCtx := NewContext(a, set, &Context{Context: ctx}) if nerr != nil { _, _ = fmt.Fprintln(a.Writer, nerr) - _ = ShowAppHelp(context) + if !a.HideHelp { + _ = ShowAppHelp(cCtx) + } return nerr } - context.shellComplete = shellComplete + cCtx.shellComplete = shellComplete - if checkCompletions(context) { + if checkCompletions(cCtx) { return nil } if err != nil { if a.OnUsageError != nil { - err := a.OnUsageError(context, err, false) - a.handleExitCoder(context, err) + err := a.OnUsageError(cCtx, err, false) + a.handleExitCoder(cCtx, err) return err } _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - _ = ShowAppHelp(context) + if a.Suggest { + if suggestion, err := a.suggestFlagFromError(err, ""); err == nil { + fmt.Fprintf(a.Writer, suggestion) + } + } + if !a.HideHelp { + _ = ShowAppHelp(cCtx) + } return err } - if !a.HideHelp && checkHelp(context) { - _ = ShowAppHelp(context) - return nil - } - - if !a.HideVersion && checkVersion(context) { - ShowVersion(context) - return nil - } - - cerr := checkRequiredFlags(a.Flags, context) - if cerr != nil { - _ = ShowAppHelp(context) - return cerr - } - if a.After != nil { defer func() { - if afterErr := a.After(context); afterErr != nil { + if afterErr := a.After(cCtx); afterErr != nil { if err != nil { - err = NewMultiError(err, afterErr) + err = newMultiError(err, afterErr) } else { err = afterErr } @@ -260,22 +316,70 @@ func (a *App) Run(arguments []string) (err error) { }() } + if !a.HideHelp && checkHelp(cCtx) { + _ = ShowAppHelp(cCtx) + return nil + } + + if !a.HideVersion && checkVersion(cCtx) { + ShowVersion(cCtx) + return nil + } + + cerr := cCtx.checkRequiredFlags(a.Flags) + if cerr != nil { + _ = ShowAppHelp(cCtx) + return cerr + } + if a.Before != nil { - beforeErr := a.Before(context) + beforeErr := a.Before(cCtx) if beforeErr != nil { - a.handleExitCoder(context, beforeErr) + a.handleExitCoder(cCtx, beforeErr) err = beforeErr return err } } - args := context.Args() + var c *Command + args := cCtx.Args() if args.Present() { name := args.First() - c := a.Command(name) - if c != nil { - return c.Run(context) + if a.validCommandName(name) { + c = a.Command(name) + } else { + hasDefault := a.DefaultCommand != "" + isFlagName := checkStringSliceIncludes(name, cCtx.FlagNames()) + + var ( + isDefaultSubcommand = false + defaultHasSubcommands = false + ) + + if hasDefault { + dc := a.Command(a.DefaultCommand) + defaultHasSubcommands = len(dc.Subcommands) > 0 + for _, dcSub := range dc.Subcommands { + if checkStringSliceIncludes(name, dcSub.Names()) { + isDefaultSubcommand = true + break + } + } + } + + if isFlagName || (hasDefault && (defaultHasSubcommands && isDefaultSubcommand)) { + argsWithDefault := a.argsWithDefaultCommand(args) + if !reflect.DeepEqual(args, argsWithDefault) { + c = a.Command(argsWithDefault.First()) + } + } } + } else if a.DefaultCommand != "" { + c = a.Command(a.DefaultCommand) + } + + if c != nil { + return c.Run(cCtx) } if a.Action == nil { @@ -283,20 +387,43 @@ func (a *App) Run(arguments []string) (err error) { } // Run default Action - err = HandleAction(a.Action, context) + err = a.Action(cCtx) - a.handleExitCoder(context, err) + a.handleExitCoder(cCtx, err) return err } +func (a *App) suggestFlagFromError(err error, command string) (string, error) { + flag, parseErr := flagFromError(err) + if parseErr != nil { + return "", err + } + + flags := a.Flags + if command != "" { + cmd := a.Command(command) + if cmd == nil { + return "", err + } + flags = cmd.Flags + } + + suggestion := SuggestFlag(flags, flag, a.HideHelp) + if len(suggestion) == 0 { + return "", err + } + + return fmt.Sprintf(SuggestDidYouMeanTemplate+"\n\n", suggestion), nil +} + // RunAndExitOnError calls .Run() and exits non-zero if an error was returned // // Deprecated: instead you should return an error that fulfills cli.ExitCoder -// to cli.App.Run. This will cause the application to exit with the given eror +// to cli.App.Run. This will cause the application to exit with the given error // code in the cli.ExitCoder func (a *App) RunAndExitOnError() { if err := a.Run(os.Args); err != nil { - _, _ = fmt.Fprintln(a.errWriter(), err) + _, _ = fmt.Fprintln(a.ErrWriter, err) OsExiter(1) } } @@ -304,17 +431,10 @@ func (a *App) RunAndExitOnError() { // RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to // generate command-specific flags func (a *App) RunAsSubcommand(ctx *Context) (err error) { - // append help to commands - if len(a.Commands) > 0 { - if a.Command(helpCommand.Name) == nil && !a.HideHelp { - a.Commands = append(a.Commands, helpCommand) - if (HelpFlag != BoolFlag{}) { - a.appendFlag(HelpFlag) - } - } - } + // Setup also handles HideHelp and HideHelpCommand + a.Setup() - newCmds := []Command{} + var newCmds []*Command for _, c := range a.Commands { if c.HelpName == "" { c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) @@ -330,57 +450,62 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, ctx) + cCtx := NewContext(a, set, ctx) if nerr != nil { _, _ = fmt.Fprintln(a.Writer, nerr) _, _ = fmt.Fprintln(a.Writer) if len(a.Commands) > 0 { - _ = ShowSubcommandHelp(context) + _ = ShowSubcommandHelp(cCtx) } else { - _ = ShowCommandHelp(ctx, context.Args().First()) + _ = ShowCommandHelp(ctx, cCtx.Args().First()) } return nerr } - if checkCompletions(context) { + if checkCompletions(cCtx) { return nil } if err != nil { if a.OnUsageError != nil { - err = a.OnUsageError(context, err, true) - a.handleExitCoder(context, err) + err = a.OnUsageError(cCtx, err, true) + a.handleExitCoder(cCtx, err) return err } _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - _ = ShowSubcommandHelp(context) + if a.Suggest { + if suggestion, err := a.suggestFlagFromError(err, cCtx.Command.Name); err == nil { + fmt.Fprintf(a.Writer, suggestion) + } + } + _ = ShowSubcommandHelp(cCtx) return err } if len(a.Commands) > 0 { - if checkSubcommandHelp(context) { + if checkSubcommandHelp(cCtx) { return nil } } else { - if checkCommandHelp(ctx, context.Args().First()) { + if checkCommandHelp(ctx, cCtx.Args().First()) { return nil } } - cerr := checkRequiredFlags(a.Flags, context) + cerr := cCtx.checkRequiredFlags(a.Flags) if cerr != nil { - _ = ShowSubcommandHelp(context) + _ = ShowSubcommandHelp(cCtx) return cerr } if a.After != nil { defer func() { - afterErr := a.After(context) + afterErr := a.After(cCtx) if afterErr != nil { - a.handleExitCoder(context, err) + a.handleExitCoder(cCtx, err) if err != nil { - err = NewMultiError(err, afterErr) + err = newMultiError(err, afterErr) } else { err = afterErr } @@ -389,27 +514,27 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } if a.Before != nil { - beforeErr := a.Before(context) + beforeErr := a.Before(cCtx) if beforeErr != nil { - a.handleExitCoder(context, beforeErr) + a.handleExitCoder(cCtx, beforeErr) err = beforeErr return err } } - args := context.Args() + args := cCtx.Args() if args.Present() { name := args.First() c := a.Command(name) if c != nil { - return c.Run(context) + return c.Run(cCtx) } } // Run default Action - err = HandleAction(a.Action, context) + err = a.Action(cCtx) - a.handleExitCoder(context, err) + a.handleExitCoder(cCtx, err) return err } @@ -417,28 +542,21 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { func (a *App) Command(name string) *Command { for _, c := range a.Commands { if c.HasName(name) { - return &c + return c } } return nil } -// Categories returns a slice containing all the categories with the commands they contain -func (a *App) Categories() CommandCategories { - return a.categories -} - // VisibleCategories returns a slice of categories and commands that are // Hidden=false -func (a *App) VisibleCategories() []*CommandCategory { - ret := []*CommandCategory{} - for _, category := range a.categories { - if visible := func() *CommandCategory { - for _, command := range category.Commands { - if !command.Hidden { - return category - } +func (a *App) VisibleCategories() []CommandCategory { + ret := []CommandCategory{} + for _, category := range a.categories.Categories() { + if visible := func() CommandCategory { + if len(category.VisibleCommands()) > 0 { + return category } return nil }(); visible != nil { @@ -449,8 +567,8 @@ func (a *App) VisibleCategories() []*CommandCategory { } // VisibleCommands returns a slice of the Commands with Hidden=false -func (a *App) VisibleCommands() []Command { - var ret []Command +func (a *App) VisibleCommands() []*Command { + var ret []*Command for _, command := range a.Commands { if !command.Hidden { ret = append(ret, command) @@ -459,42 +577,72 @@ func (a *App) VisibleCommands() []Command { return ret } +// VisibleFlagCategories returns a slice containing all the categories with the flags they contain +func (a *App) VisibleFlagCategories() []VisibleFlagCategory { + if a.flagCategories == nil { + return []VisibleFlagCategory{} + } + return a.flagCategories.VisibleCategories() +} + // VisibleFlags returns a slice of the Flags with Hidden=false func (a *App) VisibleFlags() []Flag { return visibleFlags(a.Flags) } -func (a *App) hasFlag(flag Flag) bool { - for _, f := range a.Flags { - if flag == f { - return true - } +func (a *App) appendFlag(fl Flag) { + if !hasFlag(a.Flags, fl) { + a.Flags = append(a.Flags, fl) } +} - return false +func (a *App) appendCommand(c *Command) { + if !hasCommand(a.Commands, c) { + a.Commands = append(a.Commands, c) + } } -func (a *App) errWriter() io.Writer { - // When the app ErrWriter is nil use the package level one. - if a.ErrWriter == nil { - return ErrWriter +func (a *App) handleExitCoder(cCtx *Context, err error) { + if a.ExitErrHandler != nil { + a.ExitErrHandler(cCtx, err) + } else { + HandleExitCoder(err) } +} - return a.ErrWriter +func (a *App) commandNames() []string { + var cmdNames []string + + for _, cmd := range a.Commands { + cmdNames = append(cmdNames, cmd.Names()...) + } + + return cmdNames } -func (a *App) appendFlag(flag Flag) { - if !a.hasFlag(flag) { - a.Flags = append(a.Flags, flag) +func (a *App) validCommandName(checkCmdName string) bool { + valid := false + allCommandNames := a.commandNames() + + for _, cmdName := range allCommandNames { + if checkCmdName == cmdName { + valid = true + break + } } + + return valid } -func (a *App) handleExitCoder(context *Context, err error) { - if a.ExitErrHandler != nil { - a.ExitErrHandler(context, err) - } else { - HandleExitCoder(err) +func (a *App) argsWithDefaultCommand(oldArgs Args) Args { + if a.DefaultCommand != "" { + rawArgs := append([]string{a.DefaultCommand}, oldArgs.Slice()...) + newArgs := args(rawArgs) + + return &newArgs } + + return oldArgs } // Author represents someone who has contributed to a cli project. @@ -504,7 +652,7 @@ type Author struct { } // String makes Author comply to the Stringer interface, to allow an easy print in the templating process -func (a Author) String() string { +func (a *Author) String() string { e := "" if a.Email != "" { e = " <" + a.Email + ">" @@ -516,16 +664,28 @@ func (a Author) String() string { // HandleAction attempts to figure out which Action signature was used. If // it's an ActionFunc or a func with the legacy signature for Action, the func // is run! -func HandleAction(action interface{}, context *Context) (err error) { +func HandleAction(action interface{}, cCtx *Context) (err error) { switch a := action.(type) { case ActionFunc: - return a(context) + return a(cCtx) case func(*Context) error: - return a(context) + return a(cCtx) case func(*Context): // deprecated function signature - a(context) + a(cCtx) return nil } return errInvalidActionType } + +func checkStringSliceIncludes(want string, sSlice []string) bool { + found := false + for _, s := range sSlice { + if want == s { + found = true + break + } + } + + return found +} diff --git a/vendor/github.com/urfave/cli/v2/args.go b/vendor/github.com/urfave/cli/v2/args.go new file mode 100644 index 000000000..bd65c17bd --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/args.go @@ -0,0 +1,54 @@ +package cli + +type Args interface { + // Get returns the nth argument, or else a blank string + Get(n int) string + // First returns the first argument, or else a blank string + First() string + // Tail returns the rest of the arguments (not the first one) + // or else an empty string slice + Tail() []string + // Len returns the length of the wrapped slice + Len() int + // Present checks if there are any arguments present + Present() bool + // Slice returns a copy of the internal slice + Slice() []string +} + +type args []string + +func (a *args) Get(n int) string { + if len(*a) > n { + return (*a)[n] + } + return "" +} + +func (a *args) First() string { + return a.Get(0) +} + +func (a *args) Tail() []string { + if a.Len() >= 2 { + tail := []string((*a)[1:]) + ret := make([]string, len(tail)) + copy(ret, tail) + return ret + } + return []string{} +} + +func (a *args) Len() int { + return len(*a) +} + +func (a *args) Present() bool { + return a.Len() != 0 +} + +func (a *args) Slice() []string { + ret := make([]string, len(*a)) + copy(ret, *a) + return ret +} diff --git a/vendor/github.com/urfave/cli/v2/category.go b/vendor/github.com/urfave/cli/v2/category.go new file mode 100644 index 000000000..8bf325e20 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/category.go @@ -0,0 +1,171 @@ +package cli + +import "sort" + +// CommandCategories interface allows for category manipulation +type CommandCategories interface { + // AddCommand adds a command to a category, creating a new category if necessary. + AddCommand(category string, command *Command) + // Categories returns a slice of categories sorted by name + Categories() []CommandCategory +} + +type commandCategories []*commandCategory + +func newCommandCategories() CommandCategories { + ret := commandCategories([]*commandCategory{}) + return &ret +} + +func (c *commandCategories) Less(i, j int) bool { + return lexicographicLess((*c)[i].Name(), (*c)[j].Name()) +} + +func (c *commandCategories) Len() int { + return len(*c) +} + +func (c *commandCategories) Swap(i, j int) { + (*c)[i], (*c)[j] = (*c)[j], (*c)[i] +} + +func (c *commandCategories) AddCommand(category string, command *Command) { + for _, commandCategory := range []*commandCategory(*c) { + if commandCategory.name == category { + commandCategory.commands = append(commandCategory.commands, command) + return + } + } + newVal := append(*c, + &commandCategory{name: category, commands: []*Command{command}}) + *c = newVal +} + +func (c *commandCategories) Categories() []CommandCategory { + ret := make([]CommandCategory, len(*c)) + for i, cat := range *c { + ret[i] = cat + } + return ret +} + +// CommandCategory is a category containing commands. +type CommandCategory interface { + // Name returns the category name string + Name() string + // VisibleCommands returns a slice of the Commands with Hidden=false + VisibleCommands() []*Command +} + +type commandCategory struct { + name string + commands []*Command +} + +func (c *commandCategory) Name() string { + return c.name +} + +func (c *commandCategory) VisibleCommands() []*Command { + if c.commands == nil { + c.commands = []*Command{} + } + + var ret []*Command + for _, command := range c.commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} + +// FlagCategories interface allows for category manipulation +type FlagCategories interface { + // AddFlags adds a flag to a category, creating a new category if necessary. + AddFlag(category string, fl Flag) + // VisibleCategories returns a slice of visible flag categories sorted by name + VisibleCategories() []VisibleFlagCategory +} + +type defaultFlagCategories struct { + m map[string]*defaultVisibleFlagCategory +} + +func newFlagCategories() FlagCategories { + return &defaultFlagCategories{ + m: map[string]*defaultVisibleFlagCategory{}, + } +} + +func newFlagCategoriesFromFlags(fs []Flag) FlagCategories { + fc := newFlagCategories() + for _, fl := range fs { + if cf, ok := fl.(CategorizableFlag); ok { + fc.AddFlag(cf.GetCategory(), cf) + } + } + + return fc +} + +func (f *defaultFlagCategories) AddFlag(category string, fl Flag) { + if _, ok := f.m[category]; !ok { + f.m[category] = &defaultVisibleFlagCategory{name: category, m: map[string]Flag{}} + } + + f.m[category].m[fl.String()] = fl +} + +func (f *defaultFlagCategories) VisibleCategories() []VisibleFlagCategory { + catNames := []string{} + for name := range f.m { + catNames = append(catNames, name) + } + + sort.Strings(catNames) + + ret := make([]VisibleFlagCategory, len(catNames)) + for i, name := range catNames { + ret[i] = f.m[name] + } + + return ret +} + +// VisibleFlagCategory is a category containing flags. +type VisibleFlagCategory interface { + // Name returns the category name string + Name() string + // Flags returns a slice of VisibleFlag sorted by name + Flags() []VisibleFlag +} + +type defaultVisibleFlagCategory struct { + name string + m map[string]Flag +} + +func (fc *defaultVisibleFlagCategory) Name() string { + return fc.name +} + +func (fc *defaultVisibleFlagCategory) Flags() []VisibleFlag { + vfNames := []string{} + for flName, fl := range fc.m { + if vf, ok := fl.(VisibleFlag); ok { + if vf.IsVisible() { + vfNames = append(vfNames, flName) + } + } + } + + sort.Strings(vfNames) + + ret := make([]VisibleFlag, len(vfNames)) + for i, flName := range vfNames { + ret[i] = fc.m[flName].(VisibleFlag) + } + + return ret +} diff --git a/vendor/github.com/urfave/cli/cli.go b/vendor/github.com/urfave/cli/v2/cli.go similarity index 57% rename from vendor/github.com/urfave/cli/cli.go rename to vendor/github.com/urfave/cli/v2/cli.go index 4bd250839..2a11c5ad4 100644 --- a/vendor/github.com/urfave/cli/cli.go +++ b/vendor/github.com/urfave/cli/v2/cli.go @@ -2,21 +2,22 @@ // Go applications. cli is designed to be easy to understand and write, the most simple // cli application can be written as follows: // func main() { -// cli.NewApp().Run(os.Args) +// (&cli.App{}).Run(os.Args) // } // // Of course this application does not do much, so let's make this an actual application: // func main() { -// app := cli.NewApp() -// app.Name = "greet" -// app.Usage = "say a greeting" -// app.Action = func(c *cli.Context) error { -// println("Greetings") -// return nil -// } +// app := &cli.App{ +// Name: "greet", +// Usage: "say a greeting", +// Action: func(c *cli.Context) error { +// fmt.Println("Greetings") +// return nil +// }, +// } // // app.Run(os.Args) // } package cli -//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go +//go:generate go run internal/genflags/cmd/genflags/main.go diff --git a/vendor/github.com/urfave/cli/v2/command.go b/vendor/github.com/urfave/cli/v2/command.go new file mode 100644 index 000000000..13b79de46 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/command.go @@ -0,0 +1,321 @@ +package cli + +import ( + "flag" + "fmt" + "sort" + "strings" +) + +// Command is a subcommand for a cli.App. +type Command struct { + // The name of the command + Name string + // A list of aliases for the command + Aliases []string + // A short description of the usage of this command + Usage string + // Custom text to show on USAGE section of help + UsageText string + // A longer explanation of how the command works + Description string + // A short description of the arguments of this command + ArgsUsage string + // The category the command is part of + Category string + // The function to call when checking for bash command completions + BashComplete BashCompleteFunc + // An action to execute before any sub-subcommands are run, but after the context is ready + // If a non-nil error is returned, no sub-subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The function to call when this command is invoked + Action ActionFunc + // Execute this function if a usage error occurs. + OnUsageError OnUsageErrorFunc + // List of child commands + Subcommands []*Command + // List of flags to parse + Flags []Flag + flagCategories FlagCategories + // Treat all flags as normal arguments if true + SkipFlagParsing bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide this command from help or completion + Hidden bool + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + // Full name of command for help, defaults to full command name, including parent commands. + HelpName string + commandNamePath []string + + // CustomHelpTemplate the text template for the command help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomHelpTemplate string +} + +type Commands []*Command + +type CommandsByName []*Command + +func (c CommandsByName) Len() int { + return len(c) +} + +func (c CommandsByName) Less(i, j int) bool { + return lexicographicLess(c[i].Name, c[j].Name) +} + +func (c CommandsByName) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} + +// FullName returns the full name of the command. +// For subcommands this ensures that parent commands are part of the command path +func (c *Command) FullName() string { + if c.commandNamePath == nil { + return c.Name + } + return strings.Join(c.commandNamePath, " ") +} + +// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags +func (c *Command) Run(ctx *Context) (err error) { + if len(c.Subcommands) > 0 { + return c.startApp(ctx) + } + + if !c.HideHelp && HelpFlag != nil { + // append help to flags + c.appendFlag(HelpFlag) + } + + if ctx.App.UseShortOptionHandling { + c.UseShortOptionHandling = true + } + + set, err := c.parseFlags(ctx.Args(), ctx.shellComplete) + + cCtx := NewContext(ctx.App, set, ctx) + cCtx.Command = c + if checkCommandCompletions(cCtx, c.Name) { + return nil + } + + if err != nil { + if c.OnUsageError != nil { + err = c.OnUsageError(cCtx, err, false) + cCtx.App.handleExitCoder(cCtx, err) + return err + } + _, _ = fmt.Fprintln(cCtx.App.Writer, "Incorrect Usage:", err.Error()) + _, _ = fmt.Fprintln(cCtx.App.Writer) + if ctx.App.Suggest { + if suggestion, err := ctx.App.suggestFlagFromError(err, c.Name); err == nil { + fmt.Fprintf(cCtx.App.Writer, suggestion) + } + } + if !c.HideHelp { + _ = ShowCommandHelp(cCtx, c.Name) + } + return err + } + + if checkCommandHelp(cCtx, c.Name) { + return nil + } + + cerr := cCtx.checkRequiredFlags(c.Flags) + if cerr != nil { + if !c.HideHelp { + _ = ShowCommandHelp(cCtx, c.Name) + } + return cerr + } + + if c.After != nil { + defer func() { + afterErr := c.After(cCtx) + if afterErr != nil { + cCtx.App.handleExitCoder(cCtx, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if c.Before != nil { + err = c.Before(cCtx) + if err != nil { + cCtx.App.handleExitCoder(cCtx, err) + return err + } + } + + if c.Action == nil { + c.Action = helpSubcommand.Action + } + + cCtx.Command = c + err = c.Action(cCtx) + + if err != nil { + cCtx.App.handleExitCoder(cCtx, err) + } + return err +} + +func (c *Command) newFlagSet() (*flag.FlagSet, error) { + return flagSet(c.Name, c.Flags) +} + +func (c *Command) useShortOptionHandling() bool { + return c.UseShortOptionHandling +} + +func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { + set, err := c.newFlagSet() + if err != nil { + return nil, err + } + + if c.SkipFlagParsing { + return set, set.Parse(append([]string{"--"}, args.Tail()...)) + } + + err = parseIter(set, c, args.Tail(), shellComplete) + if err != nil { + return nil, err + } + + err = normalizeFlags(c.Flags, set) + if err != nil { + return nil, err + } + + return set, nil +} + +// Names returns the names including short names and aliases. +func (c *Command) Names() []string { + return append([]string{c.Name}, c.Aliases...) +} + +// HasName returns true if Command.Name matches given name +func (c *Command) HasName(name string) bool { + for _, n := range c.Names() { + if n == name { + return true + } + } + return false +} + +func (c *Command) startApp(ctx *Context) error { + app := &App{ + Metadata: ctx.App.Metadata, + Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name), + } + + if c.HelpName == "" { + app.HelpName = c.HelpName + } else { + app.HelpName = app.Name + } + + app.Usage = c.Usage + app.UsageText = c.UsageText + app.Description = c.Description + app.ArgsUsage = c.ArgsUsage + + // set CommandNotFound + app.CommandNotFound = ctx.App.CommandNotFound + app.CustomAppHelpTemplate = c.CustomHelpTemplate + + // set the flags and commands + app.Commands = c.Subcommands + app.Flags = c.Flags + app.HideHelp = c.HideHelp + app.HideHelpCommand = c.HideHelpCommand + + app.Version = ctx.App.Version + app.HideVersion = true + app.Compiled = ctx.App.Compiled + app.Reader = ctx.App.Reader + app.Writer = ctx.App.Writer + app.ErrWriter = ctx.App.ErrWriter + app.ExitErrHandler = ctx.App.ExitErrHandler + app.UseShortOptionHandling = ctx.App.UseShortOptionHandling + app.Suggest = ctx.App.Suggest + + app.categories = newCommandCategories() + for _, command := range c.Subcommands { + app.categories.AddCommand(command.Category, command) + } + + sort.Sort(app.categories.(*commandCategories)) + + // bash completion + app.EnableBashCompletion = ctx.App.EnableBashCompletion + if c.BashComplete != nil { + app.BashComplete = c.BashComplete + } + + // set the actions + app.Before = c.Before + app.After = c.After + if c.Action != nil { + app.Action = c.Action + } else { + app.Action = helpSubcommand.Action + } + app.OnUsageError = c.OnUsageError + + for index, cc := range app.Commands { + app.Commands[index].commandNamePath = []string{c.Name, cc.Name} + } + + return app.RunAsSubcommand(ctx) +} + +// VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain +func (c *Command) VisibleFlagCategories() []VisibleFlagCategory { + if c.flagCategories == nil { + return []VisibleFlagCategory{} + } + return c.flagCategories.VisibleCategories() +} + +// VisibleFlags returns a slice of the Flags with Hidden=false +func (c *Command) VisibleFlags() []Flag { + return visibleFlags(c.Flags) +} + +func (c *Command) appendFlag(fl Flag) { + if !hasFlag(c.Flags, fl) { + c.Flags = append(c.Flags, fl) + } +} + +func hasCommand(commands []*Command, command *Command) bool { + for _, existing := range commands { + if command == existing { + return true + } + } + + return false +} diff --git a/vendor/github.com/urfave/cli/v2/context.go b/vendor/github.com/urfave/cli/v2/context.go new file mode 100644 index 000000000..6b497ed20 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/context.go @@ -0,0 +1,211 @@ +package cli + +import ( + "context" + "flag" + "strings" +) + +// Context is a type that is passed through to +// each Handler action in a cli application. Context +// can be used to retrieve context-specific args and +// parsed command-line options. +type Context struct { + context.Context + App *App + Command *Command + shellComplete bool + flagSet *flag.FlagSet + parentContext *Context +} + +// NewContext creates a new context. For use in when invoking an App or Command action. +func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { + c := &Context{App: app, flagSet: set, parentContext: parentCtx} + if parentCtx != nil { + c.Context = parentCtx.Context + c.shellComplete = parentCtx.shellComplete + if parentCtx.flagSet == nil { + parentCtx.flagSet = &flag.FlagSet{} + } + } + + c.Command = &Command{} + + if c.Context == nil { + c.Context = context.Background() + } + + return c +} + +// NumFlags returns the number of flags set +func (cCtx *Context) NumFlags() int { + return cCtx.flagSet.NFlag() +} + +// Set sets a context flag to a value. +func (cCtx *Context) Set(name, value string) error { + return cCtx.flagSet.Set(name, value) +} + +// IsSet determines if the flag was actually set +func (cCtx *Context) IsSet(name string) bool { + if fs := cCtx.lookupFlagSet(name); fs != nil { + isSet := false + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + isSet = true + } + }) + if isSet { + return true + } + + f := cCtx.lookupFlag(name) + if f == nil { + return false + } + + return f.IsSet() + } + + return false +} + +// LocalFlagNames returns a slice of flag names used in this context. +func (cCtx *Context) LocalFlagNames() []string { + var names []string + cCtx.flagSet.Visit(makeFlagNameVisitor(&names)) + return names +} + +// FlagNames returns a slice of flag names used by the this context and all of +// its parent contexts. +func (cCtx *Context) FlagNames() []string { + var names []string + for _, pCtx := range cCtx.Lineage() { + pCtx.flagSet.Visit(makeFlagNameVisitor(&names)) + } + return names +} + +// Lineage returns *this* context and all of its ancestor contexts in order from +// child to parent +func (cCtx *Context) Lineage() []*Context { + var lineage []*Context + + for cur := cCtx; cur != nil; cur = cur.parentContext { + lineage = append(lineage, cur) + } + + return lineage +} + +// Value returns the value of the flag corresponding to `name` +func (cCtx *Context) Value(name string) interface{} { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return fs.Lookup(name).Value.(flag.Getter).Get() + } + return nil +} + +// Args returns the command line arguments associated with the context. +func (cCtx *Context) Args() Args { + ret := args(cCtx.flagSet.Args()) + return &ret +} + +// NArg returns the number of the command line arguments. +func (cCtx *Context) NArg() int { + return cCtx.Args().Len() +} + +func (cCtx *Context) lookupFlag(name string) Flag { + for _, c := range cCtx.Lineage() { + if c.Command == nil { + continue + } + + for _, f := range c.Command.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + if cCtx.App != nil { + for _, f := range cCtx.App.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + return nil +} + +func (cCtx *Context) lookupFlagSet(name string) *flag.FlagSet { + for _, c := range cCtx.Lineage() { + if c.flagSet == nil { + continue + } + if f := c.flagSet.Lookup(name); f != nil { + return c.flagSet + } + } + + return nil +} + +func (cCtx *Context) checkRequiredFlags(flags []Flag) requiredFlagsErr { + var missingFlags []string + for _, f := range flags { + if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { + var flagPresent bool + var flagName string + + for _, key := range f.Names() { + if len(key) > 1 { + flagName = key + } + + if cCtx.IsSet(strings.TrimSpace(key)) { + flagPresent = true + } + } + + if !flagPresent && flagName != "" { + missingFlags = append(missingFlags, flagName) + } + } + } + + if len(missingFlags) != 0 { + return &errRequiredFlags{missingFlags: missingFlags} + } + + return nil +} + +func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { + return func(f *flag.Flag) { + nameParts := strings.Split(f.Name, ",") + name := strings.TrimSpace(nameParts[0]) + + for _, part := range nameParts { + part = strings.TrimSpace(part) + if len(part) > len(name) { + name = part + } + } + + if name != "" { + *names = append(*names, name) + } + } +} diff --git a/vendor/github.com/urfave/cli/docs.go b/vendor/github.com/urfave/cli/v2/docs.go similarity index 58% rename from vendor/github.com/urfave/cli/docs.go rename to vendor/github.com/urfave/cli/v2/docs.go index 725fa7ff2..8b1c9c8a2 100644 --- a/vendor/github.com/urfave/cli/docs.go +++ b/vendor/github.com/urfave/cli/v2/docs.go @@ -18,31 +18,39 @@ import ( // The function errors if either parsing or writing of the string fails. func (a *App) ToMarkdown() (string, error) { var w bytes.Buffer - if err := a.writeDocTemplate(&w); err != nil { + if err := a.writeDocTemplate(&w, 0); err != nil { return "", err } return w.String(), nil } -// ToMan creates a man page string for the `*App` +// ToMan creates a man page string with section number for the `*App` // The function errors if either parsing or writing of the string fails. -func (a *App) ToMan() (string, error) { +func (a *App) ToManWithSection(sectionNumber int) (string, error) { var w bytes.Buffer - if err := a.writeDocTemplate(&w); err != nil { + if err := a.writeDocTemplate(&w, sectionNumber); err != nil { return "", err } man := md2man.Render(w.Bytes()) return string(man), nil } +// ToMan creates a man page string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMan() (string, error) { + man, err := a.ToManWithSection(8) + return man, err +} + type cliTemplate struct { App *App + SectionNum int Commands []string GlobalArgs []string SynopsisArgs []string } -func (a *App) writeDocTemplate(w io.Writer) error { +func (a *App) writeDocTemplate(w io.Writer, sectionNum int) error { const name = "cli" t, err := template.New(name).Parse(MarkdownDocTemplate) if err != nil { @@ -50,38 +58,39 @@ func (a *App) writeDocTemplate(w io.Writer) error { } return t.ExecuteTemplate(w, name, &cliTemplate{ App: a, + SectionNum: sectionNum, Commands: prepareCommands(a.Commands, 0), - GlobalArgs: prepareArgsWithValues(a.Flags), - SynopsisArgs: prepareArgsSynopsis(a.Flags), + GlobalArgs: prepareArgsWithValues(a.VisibleFlags()), + SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()), }) } -func prepareCommands(commands []Command, level int) []string { - coms := []string{} - for i := range commands { - command := &commands[i] +func prepareCommands(commands []*Command, level int) []string { + var coms []string + for _, command := range commands { if command.Hidden { continue } - usage := "" - if command.Usage != "" { - usage = command.Usage - } - prepared := fmt.Sprintf("%s %s\n\n%s\n", + usageText := prepareUsageText(command) + + usage := prepareUsage(command, usageText) + + prepared := fmt.Sprintf("%s %s\n\n%s%s", strings.Repeat("#", level+2), strings.Join(command.Names(), ", "), usage, + usageText, ) - flags := prepareArgsWithValues(command.Flags) + flags := prepareArgsWithValues(command.VisibleFlags()) if len(flags) > 0 { prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n")) } coms = append(coms, prepared) - // recursevly iterate subcommands + // recursively iterate subcommands if len(command.Subcommands) > 0 { coms = append( coms, @@ -113,7 +122,8 @@ func prepareFlags( continue } modifiedArg := opener - for _, s := range strings.Split(flag.GetName(), ",") { + + for _, s := range flag.Names() { trimmed := strings.TrimSpace(s) if len(modifiedArg) > len(opener) { modifiedArg += sep @@ -149,3 +159,40 @@ func flagDetails(flag DocGenerationFlag) string { } return ": " + description } + +func prepareUsageText(command *Command) string { + if command.UsageText == "" { + return "" + } + + // Remove leading and trailing newlines + preparedUsageText := strings.Trim(command.UsageText, "\n") + + var usageText string + if strings.Contains(preparedUsageText, "\n") { + // Format multi-line string as a code block using the 4 space schema to allow for embedded markdown such + // that it will not break the continuous code block. + for _, ln := range strings.Split(preparedUsageText, "\n") { + usageText += fmt.Sprintf(" %s\n", ln) + } + } else { + // Style a single line as a note + usageText = fmt.Sprintf(">%s\n", preparedUsageText) + } + + return usageText +} + +func prepareUsage(command *Command, usageText string) string { + if command.Usage == "" { + return "" + } + + usage := command.Usage + "\n" + // Add a newline to the Usage IFF there is a UsageText + if usageText != "" { + usage += "\n" + } + + return usage +} diff --git a/vendor/github.com/urfave/cli/v2/errors.go b/vendor/github.com/urfave/cli/v2/errors.go new file mode 100644 index 000000000..8f641fb64 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/errors.go @@ -0,0 +1,163 @@ +package cli + +import ( + "fmt" + "io" + "os" + "strings" +) + +// OsExiter is the function used when the app exits. If not set defaults to os.Exit. +var OsExiter = os.Exit + +// ErrWriter is used to write errors to the user. This can be anything +// implementing the io.Writer interface and defaults to os.Stderr. +var ErrWriter io.Writer = os.Stderr + +// MultiError is an error that wraps multiple errors. +type MultiError interface { + error + Errors() []error +} + +// newMultiError creates a new MultiError. Pass in one or more errors. +func newMultiError(err ...error) MultiError { + ret := multiError(err) + return &ret +} + +type multiError []error + +// Error implements the error interface. +func (m *multiError) Error() string { + errs := make([]string, len(*m)) + for i, err := range *m { + errs[i] = err.Error() + } + + return strings.Join(errs, "\n") +} + +// Errors returns a copy of the errors slice +func (m *multiError) Errors() []error { + errs := make([]error, len(*m)) + for _, err := range *m { + errs = append(errs, err) + } + return errs +} + +type requiredFlagsErr interface { + error + getMissingFlags() []string +} + +type errRequiredFlags struct { + missingFlags []string +} + +func (e *errRequiredFlags) Error() string { + numberOfMissingFlags := len(e.missingFlags) + if numberOfMissingFlags == 1 { + return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) + } + joinedMissingFlags := strings.Join(e.missingFlags, ", ") + return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) +} + +func (e *errRequiredFlags) getMissingFlags() []string { + return e.missingFlags +} + +// ErrorFormatter is the interface that will suitably format the error output +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + +// ExitCoder is the interface checked by `App` and `Command` for a custom exit +// code +type ExitCoder interface { + error + ExitCode() int +} + +type exitError struct { + exitCode int + message interface{} +} + +// NewExitError calls Exit to create a new ExitCoder. +// +// Deprecated: This function is a duplicate of Exit and will eventually be removed. +func NewExitError(message interface{}, exitCode int) ExitCoder { + return Exit(message, exitCode) +} + +// Exit wraps a message and exit code into an error, which by default is +// handled with a call to os.Exit during default error handling. +// +// This is the simplest way to trigger a non-zero exit code for an App without +// having to call os.Exit manually. During testing, this behavior can be avoided +// by overiding the ExitErrHandler function on an App or the package-global +// OsExiter function. +func Exit(message interface{}, exitCode int) ExitCoder { + return &exitError{ + message: message, + exitCode: exitCode, + } +} + +func (ee *exitError) Error() string { + return fmt.Sprintf("%v", ee.message) +} + +func (ee *exitError) ExitCode() int { + return ee.exitCode +} + +// HandleExitCoder handles errors implementing ExitCoder by printing their +// message and calling OsExiter with the given exit code. +// +// If the given error instead implements MultiError, each error will be checked +// for the ExitCoder interface, and OsExiter will be called with the last exit +// code found, or exit code 1 if no ExitCoder is found. +// +// This function is the default error-handling behavior for an App. +func HandleExitCoder(err error) { + if err == nil { + return + } + + if exitErr, ok := err.(ExitCoder); ok { + if err.Error() != "" { + if _, ok := exitErr.(ErrorFormatter); ok { + _, _ = fmt.Fprintf(ErrWriter, "%+v\n", err) + } else { + _, _ = fmt.Fprintln(ErrWriter, err) + } + } + OsExiter(exitErr.ExitCode()) + return + } + + if multiErr, ok := err.(MultiError); ok { + code := handleMultiError(multiErr) + OsExiter(code) + return + } +} + +func handleMultiError(multiErr MultiError) int { + code := 1 + for _, merr := range multiErr.Errors() { + if multiErr2, ok := merr.(MultiError); ok { + code = handleMultiError(multiErr2) + } else if merr != nil { + fmt.Fprintln(ErrWriter, merr) + if exitErr, ok := merr.(ExitCoder); ok { + code = exitErr.ExitCode() + } + } + } + return code +} diff --git a/vendor/github.com/urfave/cli/fish.go b/vendor/github.com/urfave/cli/v2/fish.go similarity index 91% rename from vendor/github.com/urfave/cli/fish.go rename to vendor/github.com/urfave/cli/v2/fish.go index cf183af61..eec3253cd 100644 --- a/vendor/github.com/urfave/cli/fish.go +++ b/vendor/github.com/urfave/cli/v2/fish.go @@ -64,11 +64,9 @@ func (a *App) writeFishCompletionTemplate(w io.Writer) error { }) } -func (a *App) prepareFishCommands(commands []Command, allCommands *[]string, previousCommands []string) []string { +func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, previousCommands []string) []string { completions := []string{} - for i := range commands { - command := &commands[i] - + for _, command := range commands { if command.Hidden { continue } @@ -97,7 +95,7 @@ func (a *App) prepareFishCommands(commands []Command, allCommands *[]string, pre completions = append(completions, completion.String()) completions = append( completions, - a.prepareFishFlags(command.Flags, command.Names())..., + a.prepareFishFlags(command.VisibleFlags(), command.Names())..., ) // recursevly iterate subcommands @@ -131,7 +129,7 @@ func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string fishAddFileFlag(f, completion) - for idx, opt := range strings.Split(flag.GetName(), ",") { + for idx, opt := range flag.Names() { if idx == 0 { completion.WriteString(fmt.Sprintf( " -l %s", strings.TrimSpace(opt), @@ -161,15 +159,19 @@ func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string func fishAddFileFlag(flag Flag, completion *strings.Builder) { switch f := flag.(type) { - case GenericFlag: + case *GenericFlag: + if f.TakesFile { + return + } + case *StringFlag: if f.TakesFile { return } - case StringFlag: + case *StringSliceFlag: if f.TakesFile { return } - case StringSliceFlag: + case *PathFlag: if f.TakesFile { return } diff --git a/vendor/github.com/urfave/cli/v2/flag-spec.yaml b/vendor/github.com/urfave/cli/v2/flag-spec.yaml new file mode 100644 index 000000000..45f054d6e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag-spec.yaml @@ -0,0 +1,51 @@ +# NOTE: this file is used by the tool defined in +# ./internal/genflags/cmd/genflags/main.go which uses the +# `genflags.Spec` type that maps to this file structure. + +flag_types: + bool: {} + float64: {} + int64: {} + int: {} + time.Duration: {} + uint64: {} + uint: {} + + string: + struct_fields: + - { name: TakesFile, type: bool } + Generic: + struct_fields: + - { name: TakesFile, type: bool } + Path: + struct_fields: + - { name: TakesFile, type: bool } + + Float64Slice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + Int64Slice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + IntSlice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + StringSlice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - { name: TakesFile, type: bool } + Timestamp: + value_pointer: true + struct_fields: + - { name: Layout, type: string } + - { name: Timezone, type: "*time.Location" } + + # TODO: enable UintSlice + # UintSlice: {} + # TODO: enable Uint64Slice once #1334 lands + # Uint64Slice: {} diff --git a/vendor/github.com/urfave/cli/v2/flag.go b/vendor/github.com/urfave/cli/v2/flag.go new file mode 100644 index 000000000..dbed577cd --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag.go @@ -0,0 +1,419 @@ +package cli + +import ( + "errors" + "flag" + "fmt" + "io/ioutil" + "regexp" + "runtime" + "strconv" + "strings" + "syscall" + "time" +) + +const defaultPlaceholder = "value" + +var ( + slPfx = fmt.Sprintf("sl:::%d:::", time.Now().UTC().UnixNano()) + + commaWhitespace = regexp.MustCompile("[, ]+.*") +) + +// BashCompletionFlag enables bash-completion for all commands and subcommands +var BashCompletionFlag Flag = &BoolFlag{ + Name: "generate-bash-completion", + Hidden: true, +} + +// VersionFlag prints the version for the application +var VersionFlag Flag = &BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "print the version", +} + +// HelpFlag prints the help for all commands and subcommands. +// Set to nil to disable the flag. The subcommand +// will still be added unless HideHelp or HideHelpCommand is set to true. +var HelpFlag Flag = &BoolFlag{ + Name: "help", + Aliases: []string{"h"}, + Usage: "show help", +} + +// FlagStringer converts a flag definition to a string. This is used by help +// to display a flag. +var FlagStringer FlagStringFunc = stringifyFlag + +// Serializer is used to circumvent the limitations of flag.FlagSet.Set +type Serializer interface { + Serialize() string +} + +// FlagNamePrefixer converts a full flag name and its placeholder into the help +// message flag prefix. This is used by the default FlagStringer. +var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames + +// FlagEnvHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagEnvHinter FlagEnvHintFunc = withEnvHint + +// FlagFileHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagFileHinter FlagFileHintFunc = withFileHint + +// FlagsByName is a slice of Flag. +type FlagsByName []Flag + +func (f FlagsByName) Len() int { + return len(f) +} + +func (f FlagsByName) Less(i, j int) bool { + if len(f[j].Names()) == 0 { + return false + } else if len(f[i].Names()) == 0 { + return true + } + return lexicographicLess(f[i].Names()[0], f[j].Names()[0]) +} + +func (f FlagsByName) Swap(i, j int) { + f[i], f[j] = f[j], f[i] +} + +// Flag is a common interface related to parsing flags in cli. +// For more advanced flag parsing techniques, it is recommended that +// this interface be implemented. +type Flag interface { + fmt.Stringer + // Apply Flag settings to the given flag set + Apply(*flag.FlagSet) error + Names() []string + IsSet() bool +} + +// RequiredFlag is an interface that allows us to mark flags as required +// it allows flags required flags to be backwards compatible with the Flag interface +type RequiredFlag interface { + Flag + + IsRequired() bool +} + +// DocGenerationFlag is an interface that allows documentation generation for the flag +type DocGenerationFlag interface { + Flag + + // TakesValue returns true if the flag takes a value, otherwise false + TakesValue() bool + + // GetUsage returns the usage string for the flag + GetUsage() string + + // GetValue returns the flags value as string representation and an empty + // string if the flag takes no value at all. + GetValue() string + + // GetDefaultText returns the default text for this flag + GetDefaultText() string + + // GetEnvVars returns the env vars for this flag + GetEnvVars() []string +} + +// VisibleFlag is an interface that allows to check if a flag is visible +type VisibleFlag interface { + Flag + + // IsVisible returns true if the flag is not hidden, otherwise false + IsVisible() bool +} + +// CategorizableFlag is an interface that allows us to potentially +// use a flag in a categorized representation. +type CategorizableFlag interface { + VisibleFlag + + GetCategory() string +} + +func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { + set := flag.NewFlagSet(name, flag.ContinueOnError) + + for _, f := range flags { + if err := f.Apply(set); err != nil { + return nil, err + } + } + set.SetOutput(ioutil.Discard) + return set, nil +} + +func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { + switch ff.Value.(type) { + case Serializer: + _ = set.Set(name, ff.Value.(Serializer).Serialize()) + default: + _ = set.Set(name, ff.Value.String()) + } +} + +func normalizeFlags(flags []Flag, set *flag.FlagSet) error { + visited := make(map[string]bool) + set.Visit(func(f *flag.Flag) { + visited[f.Name] = true + }) + for _, f := range flags { + parts := f.Names() + if len(parts) == 1 { + continue + } + var ff *flag.Flag + for _, name := range parts { + name = strings.Trim(name, " ") + if visited[name] { + if ff != nil { + return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) + } + ff = set.Lookup(name) + } + } + if ff == nil { + continue + } + for _, name := range parts { + name = strings.Trim(name, " ") + if !visited[name] { + copyFlag(name, ff, set) + } + } + } + return nil +} + +func visibleFlags(fl []Flag) []Flag { + var visible []Flag + for _, f := range fl { + if vf, ok := f.(VisibleFlag); ok && vf.IsVisible() { + visible = append(visible, f) + } + } + return visible +} + +func prefixFor(name string) (prefix string) { + if len(name) == 1 { + prefix = "-" + } else { + prefix = "--" + } + + return +} + +// Returns the placeholder, if any, and the unquoted usage string. +func unquoteUsage(usage string) (string, string) { + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name := usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break + } + } + return "", usage +} + +func prefixedNames(names []string, placeholder string) string { + var prefixed string + for i, name := range names { + if name == "" { + continue + } + + prefixed += prefixFor(name) + name + if placeholder != "" { + prefixed += " " + placeholder + } + if i < len(names)-1 { + prefixed += ", " + } + } + return prefixed +} + +func withEnvHint(envVars []string, str string) string { + envText := "" + if len(envVars) > 0 { + prefix := "$" + suffix := "" + sep := ", $" + if runtime.GOOS == "windows" { + prefix = "%" + suffix = "%" + sep = "%, %" + } + + envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix) + } + return str + envText +} + +func FlagNames(name string, aliases []string) []string { + var ret []string + + for _, part := range append([]string{name}, aliases...) { + // v1 -> v2 migration warning zone: + // Strip off anything after the first found comma or space, which + // *hopefully* makes it a tiny bit more obvious that unexpected behavior is + // caused by using the v1 form of stringly typed "Name". + ret = append(ret, commaWhitespace.ReplaceAllString(part, "")) + } + + return ret +} + +func withFileHint(filePath, str string) string { + fileText := "" + if filePath != "" { + fileText = fmt.Sprintf(" [%s]", filePath) + } + return str + fileText +} + +func formatDefault(format string) string { + return " (default: " + format + ")" +} + +func stringifyFlag(f Flag) string { + // enforce DocGeneration interface on flags to avoid reflection + df, ok := f.(DocGenerationFlag) + if !ok { + return "" + } + + placeholder, usage := unquoteUsage(df.GetUsage()) + needsPlaceholder := df.TakesValue() + + if needsPlaceholder && placeholder == "" { + placeholder = defaultPlaceholder + } + + defaultValueString := "" + + if s := df.GetDefaultText(); s != "" { + defaultValueString = fmt.Sprintf(formatDefault("%s"), s) + } + + usageWithDefault := strings.TrimSpace(usage + defaultValueString) + + return withEnvHint(df.GetEnvVars(), + fmt.Sprintf("%s\t%s", prefixedNames(df.Names(), placeholder), usageWithDefault)) +} + +func stringifyIntSliceFlag(f *IntSliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.Itoa(i)) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyInt64SliceFlag(f *Int64SliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyFloat64SliceFlag(f *Float64SliceFlag) string { + var defaultVals []string + + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyStringSliceFlag(f *StringSliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, s := range f.Value.Value() { + if len(s) > 0 { + defaultVals = append(defaultVals, strconv.Quote(s)) + } + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifySliceFlag(usage string, names, defaultVals []string) string { + placeholder, usage := unquoteUsage(usage) + if placeholder == "" { + placeholder = defaultPlaceholder + } + + defaultVal := "" + if len(defaultVals) > 0 { + defaultVal = fmt.Sprintf(formatDefault("%s"), strings.Join(defaultVals, ", ")) + } + + usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal)) + multiInputString := "(accepts multiple inputs)" + if usageWithDefault != "" { + multiInputString = "\t" + multiInputString + } + return fmt.Sprintf("%s\t%s%s", prefixedNames(names, placeholder), usageWithDefault, multiInputString) +} + +func hasFlag(flags []Flag, fl Flag) bool { + for _, existing := range flags { + if fl == existing { + return true + } + } + + return false +} + +// Return the first value from a list of environment variables and files +// (which may or may not exist), a description of where the value was found, +// and a boolean which is true if a value was found. +func flagFromEnvOrFile(envVars []string, filePath string) (value string, fromWhere string, found bool) { + for _, envVar := range envVars { + envVar = strings.TrimSpace(envVar) + if value, found := syscall.Getenv(envVar); found { + return value, fmt.Sprintf("environment variable %q", envVar), true + } + } + for _, fileVar := range strings.Split(filePath, ",") { + if fileVar != "" { + if data, err := ioutil.ReadFile(fileVar); err == nil { + return string(data), fmt.Sprintf("file %q", filePath), true + } + } + } + return "", "", false +} + +func flagSplitMultiValues(val string) []string { + return strings.Split(val, ",") +} diff --git a/vendor/github.com/urfave/cli/v2/flag_bool.go b/vendor/github.com/urfave/cli/v2/flag_bool.go new file mode 100644 index 000000000..b21d5163c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_bool.go @@ -0,0 +1,93 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *BoolFlag) TakesValue() bool { + return false +} + +// GetUsage returns the usage string for the flag +func (f *BoolFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *BoolFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *BoolFlag) GetValue() string { + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *BoolFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return fmt.Sprintf("%v", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *BoolFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *BoolFlag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valBool, err := strconv.ParseBool(val) + + if err != nil { + return fmt.Errorf("could not parse %q as bool value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = valBool + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.BoolVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Bool(name, f.Value, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *BoolFlag) Get(ctx *Context) bool { + return ctx.Bool(f.Name) +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (cCtx *Context) Bool(name string) bool { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupBool(name, fs) + } + return false +} + +func lookupBool(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} diff --git a/vendor/github.com/urfave/cli/v2/flag_duration.go b/vendor/github.com/urfave/cli/v2/flag_duration.go new file mode 100644 index 000000000..5178c6ae1 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_duration.go @@ -0,0 +1,92 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *DurationFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *DurationFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *DurationFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *DurationFlag) GetValue() string { + return f.Value.String() +} + +// GetDefaultText returns the default text for this flag +func (f *DurationFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *DurationFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *DurationFlag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valDuration, err := time.ParseDuration(val) + + if err != nil { + return fmt.Errorf("could not parse %q as duration value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = valDuration + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.DurationVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Duration(name, f.Value, f.Usage) + } + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *DurationFlag) Get(ctx *Context) time.Duration { + return ctx.Duration(f.Name) +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (cCtx *Context) Duration(name string) time.Duration { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupDuration(name, fs) + } + return 0 +} + +func lookupDuration(name string, set *flag.FlagSet) time.Duration { + f := set.Lookup(name) + if f != nil { + parsed, err := time.ParseDuration(f.Value.String()) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64.go b/vendor/github.com/urfave/cli/v2/flag_float64.go new file mode 100644 index 000000000..2d31739bc --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64.go @@ -0,0 +1,92 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Float64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Float64Flag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *Float64Flag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Float64Flag) GetValue() string { + return fmt.Sprintf("%v", f.Value) +} + +// GetDefaultText returns the default text for this flag +func (f *Float64Flag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Float64Flag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *Float64Flag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valFloat, err := strconv.ParseFloat(val, 64) + if err != nil { + return fmt.Errorf("could not parse %q as float64 value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = valFloat + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Float64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Float64(name, f.Value, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *Float64Flag) Get(ctx *Context) float64 { + return ctx.Float64(f.Name) +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (cCtx *Context) Float64(name string) float64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupFloat64(name, fs) + } + return 0 +} + +func lookupFloat64(name string, set *flag.FlagSet) float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseFloat(f.Value.String(), 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64_slice.go b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go new file mode 100644 index 000000000..031ec1d1a --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go @@ -0,0 +1,189 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Float64Slice wraps []float64 to satisfy flag.Value +type Float64Slice struct { + slice []float64 + hasBeenSet bool +} + +// NewFloat64Slice makes a *Float64Slice with default values +func NewFloat64Slice(defaults ...float64) *Float64Slice { + return &Float64Slice{slice: append([]float64{}, defaults...)} +} + +// clone allocate a copy of self object +func (f *Float64Slice) clone() *Float64Slice { + n := &Float64Slice{ + slice: make([]float64, len(f.slice)), + hasBeenSet: f.hasBeenSet, + } + copy(n.slice, f.slice) + return n +} + +// Set parses the value into a float64 and appends it to the list of values +func (f *Float64Slice) Set(value string) error { + if !f.hasBeenSet { + f.slice = []float64{} + f.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &f.slice) + f.hasBeenSet = true + return nil + } + + for _, s := range flagSplitMultiValues(value) { + tmp, err := strconv.ParseFloat(strings.TrimSpace(s), 64) + if err != nil { + return err + } + + f.slice = append(f.slice, tmp) + } + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Float64Slice) String() string { + v := f.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]float64, 0) + } + return fmt.Sprintf("%#v", v) +} + +// Serialize allows Float64Slice to fulfill Serializer +func (f *Float64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(f.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of float64s set by this flag +func (f *Float64Slice) Value() []float64 { + return f.slice +} + +// Get returns the slice of float64s set by this flag +func (f *Float64Slice) Get() interface{} { + return *f +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64SliceFlag) String() string { + return withEnvHint(f.GetEnvVars(), stringifyFloat64SliceFlag(f)) +} + +// TakesValue returns true if the flag takes a value, otherwise false +func (f *Float64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Float64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *Float64SliceFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Float64SliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *Float64SliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Float64SliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]float64, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *Float64Slice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(Float64Slice) + } + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + for _, s := range flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as float64 slice value from %s for flag %s: %s", val, source, f.Name, err) + } + } + + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + set.Var(setValue, name, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *Float64SliceFlag) Get(ctx *Context) []float64 { + return ctx.Float64Slice(f.Name) +} + +// Float64Slice looks up the value of a local Float64SliceFlag, returns +// nil if not found +func (cCtx *Context) Float64Slice(name string) []float64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupFloat64Slice(name, fs) + } + return nil +} + +func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 { + f := set.Lookup(name) + if f != nil { + if slice, ok := unwrapFlagValue(f.Value).(*Float64Slice); ok { + return slice.Value() + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_generic.go b/vendor/github.com/urfave/cli/v2/flag_generic.go new file mode 100644 index 000000000..680eeb9d7 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_generic.go @@ -0,0 +1,95 @@ +package cli + +import ( + "flag" + "fmt" +) + +// Generic is a generic parseable type identified by a specific flag +type Generic interface { + Set(value string) error + String() string +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *GenericFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *GenericFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *GenericFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *GenericFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *GenericFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *GenericFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply takes the flagset and calls Set on the generic flag with the value +// provided by the user for parsing by the flag +func (f GenericFlag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q from %s as value for flag %s: %s", val, source, f.Name, err) + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *GenericFlag) Get(ctx *Context) interface{} { + return ctx.Generic(f.Name) +} + +// Generic looks up the value of a local GenericFlag, returns +// nil if not found +func (cCtx *Context) Generic(name string) interface{} { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupGeneric(name, fs) + } + return nil +} + +func lookupGeneric(name string, set *flag.FlagSet) interface{} { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value, error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int.go b/vendor/github.com/urfave/cli/v2/flag_int.go new file mode 100644 index 000000000..c70b88985 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int.go @@ -0,0 +1,93 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *IntFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *IntFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *IntFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *IntFlag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// GetDefaultText returns the default text for this flag +func (f *IntFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *IntFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *IntFlag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = int(valInt) + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.IntVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Int(name, f.Value, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *IntFlag) Get(ctx *Context) int { + return ctx.Int(f.Name) +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (cCtx *Context) Int(name string) int { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupInt(name, fs) + } + return 0 +} + +func lookupInt(name string, set *flag.FlagSet) int { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return int(parsed) + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int64.go b/vendor/github.com/urfave/cli/v2/flag_int64.go new file mode 100644 index 000000000..5e7038cfb --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64.go @@ -0,0 +1,92 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Int64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Int64Flag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *Int64Flag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Int64Flag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// GetDefaultText returns the default text for this flag +func (f *Int64Flag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Int64Flag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *Int64Flag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = valInt + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Int64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Int64(name, f.Value, f.Usage) + } + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *Int64Flag) Get(ctx *Context) int64 { + return ctx.Int64(f.Name) +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (cCtx *Context) Int64(name string) int64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupInt64(name, fs) + } + return 0 +} + +func lookupInt64(name string, set *flag.FlagSet) int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int64_slice.go b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go new file mode 100644 index 000000000..657aaaaf3 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go @@ -0,0 +1,188 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Int64Slice wraps []int64 to satisfy flag.Value +type Int64Slice struct { + slice []int64 + hasBeenSet bool +} + +// NewInt64Slice makes an *Int64Slice with default values +func NewInt64Slice(defaults ...int64) *Int64Slice { + return &Int64Slice{slice: append([]int64{}, defaults...)} +} + +// clone allocate a copy of self object +func (i *Int64Slice) clone() *Int64Slice { + n := &Int64Slice{ + slice: make([]int64, len(i.slice)), + hasBeenSet: i.hasBeenSet, + } + copy(n.slice, i.slice) + return n +} + +// Set parses the value into an integer and appends it to the list of values +func (i *Int64Slice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []int64{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + for _, s := range flagSplitMultiValues(value) { + tmp, err := strconv.ParseInt(strings.TrimSpace(s), 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, tmp) + } + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (i *Int64Slice) String() string { + v := i.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]int64, 0) + } + return fmt.Sprintf("%#v", v) +} + +// Serialize allows Int64Slice to fulfill Serializer +func (i *Int64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *Int64Slice) Value() []int64 { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *Int64Slice) Get() interface{} { + return *i +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64SliceFlag) String() string { + return withEnvHint(f.GetEnvVars(), stringifyInt64SliceFlag(f)) +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Int64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Int64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *Int64SliceFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Int64SliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *Int64SliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Int64SliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]int64, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *Int64Slice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(Int64Slice) + } + + if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" { + for _, s := range flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int64 slice value from %s for flag %s: %s", val, source, f.Name, err) + } + } + + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(setValue, name, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *Int64SliceFlag) Get(ctx *Context) []int64 { + return ctx.Int64Slice(f.Name) +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// nil if not found +func (cCtx *Context) Int64Slice(name string) []int64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupInt64Slice(name, fs) + } + return nil +} + +func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { + f := set.Lookup(name) + if f != nil { + if slice, ok := unwrapFlagValue(f.Value).(*Int64Slice); ok { + return slice.Value() + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int_slice.go b/vendor/github.com/urfave/cli/v2/flag_int_slice.go new file mode 100644 index 000000000..7c383935a --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int_slice.go @@ -0,0 +1,199 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// IntSlice wraps []int to satisfy flag.Value +type IntSlice struct { + slice []int + hasBeenSet bool +} + +// NewIntSlice makes an *IntSlice with default values +func NewIntSlice(defaults ...int) *IntSlice { + return &IntSlice{slice: append([]int{}, defaults...)} +} + +// clone allocate a copy of self object +func (i *IntSlice) clone() *IntSlice { + n := &IntSlice{ + slice: make([]int, len(i.slice)), + hasBeenSet: i.hasBeenSet, + } + copy(n.slice, i.slice) + return n +} + +// TODO: Consistently have specific Set function for Int64 and Float64 ? +// SetInt directly adds an integer to the list of values +func (i *IntSlice) SetInt(value int) { + if !i.hasBeenSet { + i.slice = []int{} + i.hasBeenSet = true + } + + i.slice = append(i.slice, value) +} + +// Set parses the value into an integer and appends it to the list of values +func (i *IntSlice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []int{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + for _, s := range flagSplitMultiValues(value) { + tmp, err := strconv.ParseInt(strings.TrimSpace(s), 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, int(tmp)) + } + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (i *IntSlice) String() string { + v := i.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]int, 0) + } + return fmt.Sprintf("%#v", v) +} + +// Serialize allows IntSlice to fulfill Serializer +func (i *IntSlice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *IntSlice) Value() []int { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *IntSlice) Get() interface{} { + return *i +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntSliceFlag) String() string { + return withEnvHint(f.GetEnvVars(), stringifyIntSliceFlag(f)) +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *IntSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *IntSliceFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *IntSliceFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *IntSliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *IntSliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *IntSliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]int, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *IntSlice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(IntSlice) + } + + if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" { + for _, s := range flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int slice value from %s for flag %s: %s", val, source, f.Name, err) + } + } + + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(setValue, name, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *IntSliceFlag) Get(ctx *Context) []int { + return ctx.IntSlice(f.Name) +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// nil if not found +func (cCtx *Context) IntSlice(name string) []int { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupIntSlice(name, fs) + } + return nil +} + +func lookupIntSlice(name string, set *flag.FlagSet) []int { + f := set.Lookup(name) + if f != nil { + if slice, ok := unwrapFlagValue(f.Value).(*IntSlice); ok { + return slice.Value() + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_path.go b/vendor/github.com/urfave/cli/v2/flag_path.go new file mode 100644 index 000000000..7c87a8900 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_path.go @@ -0,0 +1,90 @@ +package cli + +import ( + "flag" + "fmt" +) + +type Path = string + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *PathFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *PathFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *PathFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *PathFlag) GetValue() string { + return f.Value +} + +// GetDefaultText returns the default text for this flag +func (f *PathFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.Value == "" { + return f.Value + } + return fmt.Sprintf("%q", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *PathFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *PathFlag) Apply(set *flag.FlagSet) error { + if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + f.Value = val + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.StringVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.String(name, f.Value, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *PathFlag) Get(ctx *Context) string { + return ctx.Path(f.Name) +} + +// Path looks up the value of a local PathFlag, returns +// "" if not found +func (cCtx *Context) Path(name string) string { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupPath(name, fs) + } + + return "" +} + +func lookupPath(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value.String(), error(nil) + if err != nil { + return "" + } + return parsed + } + return "" +} diff --git a/vendor/github.com/urfave/cli/v2/flag_string.go b/vendor/github.com/urfave/cli/v2/flag_string.go new file mode 100644 index 000000000..c8da38f92 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string.go @@ -0,0 +1,84 @@ +package cli + +import ( + "flag" + "fmt" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *StringFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *StringFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *StringFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *StringFlag) GetValue() string { + return f.Value +} + +// GetDefaultText returns the default text for this flag +func (f *StringFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.Value == "" { + return f.Value + } + return fmt.Sprintf("%q", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *StringFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *StringFlag) Apply(set *flag.FlagSet) error { + if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + f.Value = val + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.StringVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.String(name, f.Value, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *StringFlag) Get(ctx *Context) string { + return ctx.String(f.Name) +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (cCtx *Context) String(name string) string { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupString(name, fs) + } + return "" +} + +func lookupString(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed := f.Value.String() + return parsed + } + return "" +} diff --git a/vendor/github.com/urfave/cli/v2/flag_string_slice.go b/vendor/github.com/urfave/cli/v2/flag_string_slice.go new file mode 100644 index 000000000..bcdfd4c55 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string_slice.go @@ -0,0 +1,177 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strings" +) + +// StringSlice wraps a []string to satisfy flag.Value +type StringSlice struct { + slice []string + hasBeenSet bool +} + +// NewStringSlice creates a *StringSlice with default values +func NewStringSlice(defaults ...string) *StringSlice { + return &StringSlice{slice: append([]string{}, defaults...)} +} + +// clone allocate a copy of self object +func (s *StringSlice) clone() *StringSlice { + n := &StringSlice{ + slice: make([]string, len(s.slice)), + hasBeenSet: s.hasBeenSet, + } + copy(n.slice, s.slice) + return n +} + +// Set appends the string value to the list of values +func (s *StringSlice) Set(value string) error { + if !s.hasBeenSet { + s.slice = []string{} + s.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &s.slice) + s.hasBeenSet = true + return nil + } + + for _, t := range flagSplitMultiValues(value) { + s.slice = append(s.slice, strings.TrimSpace(t)) + } + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (s *StringSlice) String() string { + return fmt.Sprintf("%s", s.slice) +} + +// Serialize allows StringSlice to fulfill Serializer +func (s *StringSlice) Serialize() string { + jsonBytes, _ := json.Marshal(s.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of strings set by this flag +func (s *StringSlice) Value() []string { + return s.slice +} + +// Get returns the slice of strings set by this flag +func (s *StringSlice) Get() interface{} { + return *s +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringSliceFlag) String() string { + return withEnvHint(f.GetEnvVars(), stringifyStringSliceFlag(f)) +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *StringSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *StringSliceFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *StringSliceFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *StringSliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *StringSliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *StringSliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]string, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *StringSlice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(StringSlice) + } + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + for _, s := range flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as string value from %s for flag %s: %s", val, source, f.Name, err) + } + } + + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(setValue, name, f.Usage) + } + + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *StringSliceFlag) Get(ctx *Context) []string { + return ctx.StringSlice(f.Name) +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// nil if not found +func (cCtx *Context) StringSlice(name string) []string { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupStringSlice(name, fs) + } + return nil +} + +func lookupStringSlice(name string, set *flag.FlagSet) []string { + f := set.Lookup(name) + if f != nil { + if slice, ok := unwrapFlagValue(f.Value).(*StringSlice); ok { + return slice.Value() + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_timestamp.go b/vendor/github.com/urfave/cli/v2/flag_timestamp.go new file mode 100644 index 000000000..16f42dd01 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_timestamp.go @@ -0,0 +1,166 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// Timestamp wrap to satisfy golang's flag interface. +type Timestamp struct { + timestamp *time.Time + hasBeenSet bool + layout string + location *time.Location +} + +// Timestamp constructor +func NewTimestamp(timestamp time.Time) *Timestamp { + return &Timestamp{timestamp: ×tamp} +} + +// Set the timestamp value directly +func (t *Timestamp) SetTimestamp(value time.Time) { + if !t.hasBeenSet { + t.timestamp = &value + t.hasBeenSet = true + } +} + +// Set the timestamp string layout for future parsing +func (t *Timestamp) SetLayout(layout string) { + t.layout = layout +} + +// Set perceived timezone of the to-be parsed time string +func (t *Timestamp) SetLocation(loc *time.Location) { + t.location = loc +} + +// Parses the string value to timestamp +func (t *Timestamp) Set(value string) error { + var timestamp time.Time + var err error + + if t.location != nil { + timestamp, err = time.ParseInLocation(t.layout, value, t.location) + } else { + timestamp, err = time.Parse(t.layout, value) + } + + if err != nil { + return err + } + + t.timestamp = ×tamp + t.hasBeenSet = true + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (t *Timestamp) String() string { + return fmt.Sprintf("%#v", t.timestamp) +} + +// Value returns the timestamp value stored in the flag +func (t *Timestamp) Value() *time.Time { + return t.timestamp +} + +// Get returns the flag structure +func (t *Timestamp) Get() interface{} { + return *t +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *TimestampFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *TimestampFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *TimestampFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *TimestampFlag) GetValue() string { + if f.Value != nil && f.Value.timestamp != nil { + return f.Value.timestamp.String() + } + return "" +} + +// GetDefaultText returns the default text for this flag +func (f *TimestampFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *TimestampFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Apply populates the flag given the flag set and environment +func (f *TimestampFlag) Apply(set *flag.FlagSet) error { + if f.Layout == "" { + return fmt.Errorf("timestamp Layout is required") + } + if f.Value == nil { + f.Value = &Timestamp{} + } + f.Value.SetLayout(f.Layout) + f.Value.SetLocation(f.Timezone) + + if f.Destination != nil { + f.Destination.SetLayout(f.Layout) + f.Destination.SetLocation(f.Timezone) + } + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as timestamp value from %s for flag %s: %s", val, source, f.Name, err) + } + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Var(f.Destination, name, f.Usage) + continue + } + + set.Var(f.Value, name, f.Usage) + } + return nil +} + +// Get returns the flag’s value in the given Context. +func (f *TimestampFlag) Get(ctx *Context) *time.Time { + return ctx.Timestamp(f.Name) +} + +// Timestamp gets the timestamp from a flag name +func (cCtx *Context) Timestamp(name string) *time.Time { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupTimestamp(name, fs) + } + return nil +} + +// Fetches the timestamp value from the local timestampWrap +func lookupTimestamp(name string, set *flag.FlagSet) *time.Time { + f := set.Lookup(name) + if f != nil { + return (f.Value.(*Timestamp)).Value() + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint.go b/vendor/github.com/urfave/cli/v2/flag_uint.go new file mode 100644 index 000000000..6092b1ad6 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint.go @@ -0,0 +1,92 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *UintFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *UintFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *UintFlag) GetCategory() string { + return f.Category +} + +// Apply populates the flag given the flag set and environment +func (f *UintFlag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = uint(valInt) + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.UintVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Uint(name, f.Value, f.Usage) + } + + return nil +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *UintFlag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// GetDefaultText returns the default text for this flag +func (f *UintFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *UintFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Get returns the flag’s value in the given Context. +func (f *UintFlag) Get(ctx *Context) uint { + return ctx.Uint(f.Name) +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (cCtx *Context) Uint(name string) uint { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupUint(name, fs) + } + return 0 +} + +func lookupUint(name string, set *flag.FlagSet) uint { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return uint(parsed) + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint64.go b/vendor/github.com/urfave/cli/v2/flag_uint64.go new file mode 100644 index 000000000..a37f30d9f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint64.go @@ -0,0 +1,92 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Uint64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Uint64Flag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *Uint64Flag) GetCategory() string { + return f.Category +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64Flag) Apply(set *flag.FlagSet) error { + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint64 value from %s for flag %s: %s", val, source, f.Name, err) + } + + f.Value = valInt + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Uint64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Uint64(name, f.Value, f.Usage) + } + + return nil +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Uint64Flag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// GetDefaultText returns the default text for this flag +func (f *Uint64Flag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Uint64Flag) GetEnvVars() []string { + return f.EnvVars +} + +// Get returns the flag’s value in the given Context. +func (f *Uint64Flag) Get(ctx *Context) uint64 { + return ctx.Uint64(f.Name) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (cCtx *Context) Uint64(name string) uint64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupUint64(name, fs) + } + return 0 +} + +func lookupUint64(name string, set *flag.FlagSet) uint64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/funcs.go b/vendor/github.com/urfave/cli/v2/funcs.go similarity index 76% rename from vendor/github.com/urfave/cli/funcs.go rename to vendor/github.com/urfave/cli/v2/funcs.go index 0036b1130..0a9b22c94 100644 --- a/vendor/github.com/urfave/cli/funcs.go +++ b/vendor/github.com/urfave/cli/v2/funcs.go @@ -1,6 +1,6 @@ package cli -// BashCompleteFunc is an action to execute when the bash-completion flag is set +// BashCompleteFunc is an action to execute when the shell completion flag is set type BashCompleteFunc func(*Context) // BeforeFunc is an action to execute before any subcommands are run, but after @@ -17,15 +17,15 @@ type ActionFunc func(*Context) error // CommandNotFoundFunc is executed if the proper command cannot be found type CommandNotFoundFunc func(*Context, string) -// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying +// OnUsageErrorFunc is executed if a usage error occurs. This is useful for displaying // customized usage error messages. This function is able to replace the // original error messages. If this function is not set, the "Incorrect usage" // is displayed and the execution is interrupted. -type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error +type OnUsageErrorFunc func(cCtx *Context, err error, isSubcommand bool) error -// ExitErrHandlerFunc is executed if provided in order to handle ExitError values +// ExitErrHandlerFunc is executed if provided in order to handle exitError values // returned by Actions and Before/After functions. -type ExitErrHandlerFunc func(context *Context, err error) +type ExitErrHandlerFunc func(cCtx *Context, err error) // FlagStringFunc is used by the help generation to display a flag, which is // expected to be a single line. @@ -33,11 +33,11 @@ type FlagStringFunc func(Flag) string // FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix // text for a flag's full name. -type FlagNamePrefixFunc func(fullName, placeholder string) string +type FlagNamePrefixFunc func(fullName []string, placeholder string) string // FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help // with the environment variable details. -type FlagEnvHintFunc func(envVar, str string) string +type FlagEnvHintFunc func(envVars []string, str string) string // FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help // with the file path details. diff --git a/vendor/github.com/urfave/cli/v2/godoc-current.txt b/vendor/github.com/urfave/cli/v2/godoc-current.txt new file mode 100644 index 000000000..1ba48cc65 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/godoc-current.txt @@ -0,0 +1,2318 @@ +package cli // import "github.com/urfave/cli/v2" + +Package cli provides a minimal framework for creating and organizing command +line Go applications. cli is designed to be easy to understand and write, +the most simple cli application can be written as follows: + + func main() { + (&cli.App{}).Run(os.Args) + } + +Of course this application does not do much, so let's make this an actual +application: + + func main() { + app := &cli.App{ + Name: "greet", + Usage: "say a greeting", + Action: func(c *cli.Context) error { + fmt.Println("Greetings") + return nil + }, + } + + app.Run(os.Args) + } + +VARIABLES + +var ( + SuggestFlag SuggestFlagFunc = suggestFlag + SuggestCommand SuggestCommandFunc = suggestCommand + SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate +) +var AppHelpTemplate = `NAME: + {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + +USAGE: + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{wrap .Description 3}}{{end}}{{if len .Authors}} + +AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} + +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + +GLOBAL OPTIONS:{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} + +GLOBAL OPTIONS: + {{range $index, $option := .VisibleFlags}}{{if $index}} + {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} + +COPYRIGHT: + {{wrap .Copyright 3}}{{end}} +` + AppHelpTemplate is the text template for the Default help topic. cli.go uses + text/template to render templates. You can render custom help text by + setting this variable. + +var CommandHelpTemplate = `NAME: + {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + +USAGE: + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + +CATEGORY: + {{.Category}}{{end}}{{if .Description}} + +DESCRIPTION: + {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}}{{end}} +` + CommandHelpTemplate is the text template for the command help topic. cli.go + uses text/template to render templates. You can render custom help text by + setting this variable. + +var ErrWriter io.Writer = os.Stderr + ErrWriter is used to write errors to the user. This can be anything + implementing the io.Writer interface and defaults to os.Stderr. + +var FishCompletionTemplate = `# {{ .App.Name }} fish shell completion + +function __fish_{{ .App.Name }}_no_subcommand --description 'Test if there has been any subcommand yet' + for i in (commandline -opc) + if contains -- $i{{ range $v := .AllCommands }} {{ $v }}{{ end }} + return 1 + end + end + return 0 +end + +{{ range $v := .Completions }}{{ $v }} +{{ end }}` +var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} + +{{end}}# NAME + +{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} + +# SYNOPSIS + +{{ .App.Name }} +{{ if .SynopsisArgs }} +` + "```" + ` +{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` +{{ end }}{{ if .App.Description }} +# DESCRIPTION + +{{ .App.Description }} +{{ end }} +**Usage**: + +` + "```" + `{{ if .App.UsageText }} +{{ .App.UsageText }} +{{ else }} +{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +{{ end }}` + "```" + ` +{{ if .GlobalArgs }} +# GLOBAL OPTIONS +{{ range $v := .GlobalArgs }} +{{ $v }}{{ end }} +{{ end }}{{ if .Commands }} +# COMMANDS +{{ range $v := .Commands }} +{{ $v }}{{ end }}{{ end }}` +var OsExiter = os.Exit + OsExiter is the function used when the app exits. If not set defaults to + os.Exit. + +var SubcommandHelpTemplate = `NAME: + {{.HelpName}} - {{.Usage}} + +USAGE: + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{wrap .Description 3}}{{end}} + +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}} +` + SubcommandHelpTemplate is the text template for the subcommand help topic. + cli.go uses text/template to render templates. You can render custom help + text by setting this variable. + +var VersionPrinter = printVersion + VersionPrinter prints the version for the App + +var HelpPrinter helpPrinter = printHelp + HelpPrinter is a function that writes the help output. If not set + explicitly, this calls HelpPrinterCustom using only the default template + functions. + + If custom logic for printing help is required, this function can be + overridden. If the ExtraInfo field is defined on an App, this function + should not be modified, as HelpPrinterCustom will be used directly in order + to capture the extra information. + +var HelpPrinterCustom helpPrinterCustom = printHelpCustom + HelpPrinterCustom is a function that writes the help output. It is used as + the default implementation of HelpPrinter, and may be called directly if the + ExtraInfo field is set on an App. + + In the default implementation, if the customFuncs argument contains a + "wrapAt" key, which is a function which takes no arguments and returns an + int, this int value will be used to produce a "wrap" function used by the + default template to wrap long lines. + + +FUNCTIONS + +func DefaultAppComplete(cCtx *Context) + DefaultAppComplete prints the list of subcommands as the default app + completion method + +func DefaultCompleteWithFlags(cmd *Command) func(cCtx *Context) +func FlagNames(name string, aliases []string) []string +func HandleAction(action interface{}, cCtx *Context) (err error) + HandleAction attempts to figure out which Action signature was used. If it's + an ActionFunc or a func with the legacy signature for Action, the func is + run! + +func HandleExitCoder(err error) + HandleExitCoder handles errors implementing ExitCoder by printing their + message and calling OsExiter with the given exit code. + + If the given error instead implements MultiError, each error will be checked + for the ExitCoder interface, and OsExiter will be called with the last exit + code found, or exit code 1 if no ExitCoder is found. + + This function is the default error-handling behavior for an App. + +func ShowAppHelp(cCtx *Context) error + ShowAppHelp is an action that displays the help. + +func ShowAppHelpAndExit(c *Context, exitCode int) + ShowAppHelpAndExit - Prints the list of subcommands for the app and exits + with exit code. + +func ShowCommandCompletions(ctx *Context, command string) + ShowCommandCompletions prints the custom completions for a given command + +func ShowCommandHelp(ctx *Context, command string) error + ShowCommandHelp prints help for the given command + +func ShowCommandHelpAndExit(c *Context, command string, code int) + ShowCommandHelpAndExit - exits with code after showing help + +func ShowCompletions(cCtx *Context) + ShowCompletions prints the lists of commands within a given context + +func ShowSubcommandHelp(cCtx *Context) error + ShowSubcommandHelp prints help for the given subcommand + +func ShowSubcommandHelpAndExit(c *Context, exitCode int) + ShowSubcommandHelpAndExit - Prints help for the given subcommand and exits + with exit code. + +func ShowVersion(cCtx *Context) + ShowVersion prints the version number of the App + + +TYPES + +type ActionFunc func(*Context) error + ActionFunc is the action to execute when no subcommands are specified + +type AfterFunc func(*Context) error + AfterFunc is an action to execute after any subcommands are run, but after + the subcommand has finished it is run even if Action() panics + +type App struct { + // The name of the program. Defaults to path.Base(os.Args[0]) + Name string + // Full name of command for help, defaults to Name + HelpName string + // Description of the program. + Usage string + // Text to override the USAGE section of help + UsageText string + // Description of the program argument format. + ArgsUsage string + // Version of the program + Version string + // Description of the program + Description string + // DefaultCommand is the (optional) name of a command + // to run if no command names are passed as CLI arguments. + DefaultCommand string + // List of commands to execute + Commands []*Command + // List of flags to parse + Flags []Flag + // Boolean to enable bash completion commands + EnableBashCompletion bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag. + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide built-in version flag and the VERSION section of help + HideVersion bool + + // An action to execute when the shell completion flag is set + BashComplete BashCompleteFunc + // An action to execute before any subcommands are run, but after the context is ready + // If a non-nil error is returned, no subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The action to execute when no subcommands are specified + Action ActionFunc + // Execute this function if the proper command cannot be found + CommandNotFound CommandNotFoundFunc + // Execute this function if a usage error occurs + OnUsageError OnUsageErrorFunc + // Compilation date + Compiled time.Time + // List of all authors who contributed + Authors []*Author + // Copyright of the binary if any + Copyright string + // Reader reader to write input to (useful for tests) + Reader io.Reader + // Writer writer to write output to + Writer io.Writer + // ErrWriter writes error output + ErrWriter io.Writer + // ExitErrHandler processes any error encountered while running an App before + // it is returned to the caller. If no function is provided, HandleExitCoder + // is used as the default behavior. + ExitErrHandler ExitErrHandlerFunc + // Other custom info + Metadata map[string]interface{} + // Carries a function which returns app specific info. + ExtraInfo func() map[string]string + // CustomAppHelpTemplate the text template for app help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomAppHelpTemplate string + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + // Enable suggestions for commands and flags + Suggest bool + + // Has unexported fields. +} + App is the main structure of a cli application. It is recommended that an + app be created with the cli.NewApp() function + +func NewApp() *App + NewApp creates a new cli Application with some reasonable defaults for Name, + Usage, Version and Action. + +func (a *App) Command(name string) *Command + Command returns the named command on App. Returns nil if the command does + not exist + +func (a *App) Run(arguments []string) (err error) + Run is the entry point to the cli app. Parses the arguments slice and routes + to the proper flag/args combination + +func (a *App) RunAndExitOnError() + RunAndExitOnError calls .Run() and exits non-zero if an error was returned + + Deprecated: instead you should return an error that fulfills cli.ExitCoder + to cli.App.Run. This will cause the application to exit with the given error + code in the cli.ExitCoder + +func (a *App) RunAsSubcommand(ctx *Context) (err error) + RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() + to generate command-specific flags + +func (a *App) RunContext(ctx context.Context, arguments []string) (err error) + RunContext is like Run except it takes a Context that will be passed to its + commands and sub-commands. Through this, you can propagate timeouts and + cancellation requests + +func (a *App) Setup() + Setup runs initialization code to ensure all data structures are ready for + `Run` or inspection prior to `Run`. It is internally called by `Run`, but + will return early if setup has already happened. + +func (a *App) ToFishCompletion() (string, error) + ToFishCompletion creates a fish completion string for the `*App` The + function errors if either parsing or writing of the string fails. + +func (a *App) ToMan() (string, error) + ToMan creates a man page string for the `*App` The function errors if either + parsing or writing of the string fails. + +func (a *App) ToManWithSection(sectionNumber int) (string, error) + ToMan creates a man page string with section number for the `*App` The + function errors if either parsing or writing of the string fails. + +func (a *App) ToMarkdown() (string, error) + ToMarkdown creates a markdown string for the `*App` The function errors if + either parsing or writing of the string fails. + +func (a *App) VisibleCategories() []CommandCategory + VisibleCategories returns a slice of categories and commands that are + Hidden=false + +func (a *App) VisibleCommands() []*Command + VisibleCommands returns a slice of the Commands with Hidden=false + +func (a *App) VisibleFlagCategories() []VisibleFlagCategory + VisibleFlagCategories returns a slice containing all the categories with the + flags they contain + +func (a *App) VisibleFlags() []Flag + VisibleFlags returns a slice of the Flags with Hidden=false + +type Args interface { + // Get returns the nth argument, or else a blank string + Get(n int) string + // First returns the first argument, or else a blank string + First() string + // Tail returns the rest of the arguments (not the first one) + // or else an empty string slice + Tail() []string + // Len returns the length of the wrapped slice + Len() int + // Present checks if there are any arguments present + Present() bool + // Slice returns a copy of the internal slice + Slice() []string +} + +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + Author represents someone who has contributed to a cli project. + +func (a *Author) String() string + String makes Author comply to the Stringer interface, to allow an easy print + in the templating process + +type BashCompleteFunc func(*Context) + BashCompleteFunc is an action to execute when the shell completion flag is + set + +type BeforeFunc func(*Context) error + BeforeFunc is an action to execute before any subcommands are run, but after + the context is ready if a non-nil error is returned, no subcommands are run + +type BoolFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value bool + Destination *bool + + Aliases []string + EnvVars []string +} + BoolFlag is a flag with type bool + +func (f *BoolFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *BoolFlag) Get(ctx *Context) bool + Get returns the flag’s value in the given Context. + +func (f *BoolFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *BoolFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *BoolFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *BoolFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *BoolFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *BoolFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *BoolFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *BoolFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *BoolFlag) Names() []string + Names returns the names of the flag + +func (f *BoolFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *BoolFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type CategorizableFlag interface { + VisibleFlag + + GetCategory() string +} + CategorizableFlag is an interface that allows us to potentially use a flag + in a categorized representation. + +type Command struct { + // The name of the command + Name string + // A list of aliases for the command + Aliases []string + // A short description of the usage of this command + Usage string + // Custom text to show on USAGE section of help + UsageText string + // A longer explanation of how the command works + Description string + // A short description of the arguments of this command + ArgsUsage string + // The category the command is part of + Category string + // The function to call when checking for bash command completions + BashComplete BashCompleteFunc + // An action to execute before any sub-subcommands are run, but after the context is ready + // If a non-nil error is returned, no sub-subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The function to call when this command is invoked + Action ActionFunc + // Execute this function if a usage error occurs. + OnUsageError OnUsageErrorFunc + // List of child commands + Subcommands []*Command + // List of flags to parse + Flags []Flag + + // Treat all flags as normal arguments if true + SkipFlagParsing bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide this command from help or completion + Hidden bool + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + // Full name of command for help, defaults to full command name, including parent commands. + HelpName string + + // CustomHelpTemplate the text template for the command help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomHelpTemplate string + // Has unexported fields. +} + Command is a subcommand for a cli.App. + +func (c *Command) FullName() string + FullName returns the full name of the command. For subcommands this ensures + that parent commands are part of the command path + +func (c *Command) HasName(name string) bool + HasName returns true if Command.Name matches given name + +func (c *Command) Names() []string + Names returns the names including short names and aliases. + +func (c *Command) Run(ctx *Context) (err error) + Run invokes the command given the context, parses ctx.Args() to generate + command-specific flags + +func (c *Command) VisibleFlagCategories() []VisibleFlagCategory + VisibleFlagCategories returns a slice containing all the visible flag + categories with the flags they contain + +func (c *Command) VisibleFlags() []Flag + VisibleFlags returns a slice of the Flags with Hidden=false + +type CommandCategories interface { + // AddCommand adds a command to a category, creating a new category if necessary. + AddCommand(category string, command *Command) + // Categories returns a slice of categories sorted by name + Categories() []CommandCategory +} + CommandCategories interface allows for category manipulation + +type CommandCategory interface { + // Name returns the category name string + Name() string + // VisibleCommands returns a slice of the Commands with Hidden=false + VisibleCommands() []*Command +} + CommandCategory is a category containing commands. + +type CommandNotFoundFunc func(*Context, string) + CommandNotFoundFunc is executed if the proper command cannot be found + +type Commands []*Command + +type CommandsByName []*Command + +func (c CommandsByName) Len() int + +func (c CommandsByName) Less(i, j int) bool + +func (c CommandsByName) Swap(i, j int) + +type Context struct { + context.Context + App *App + Command *Command + + // Has unexported fields. +} + Context is a type that is passed through to each Handler action in a cli + application. Context can be used to retrieve context-specific args and + parsed command-line options. + +func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context + NewContext creates a new context. For use in when invoking an App or Command + action. + +func (cCtx *Context) Args() Args + Args returns the command line arguments associated with the context. + +func (cCtx *Context) Bool(name string) bool + Bool looks up the value of a local BoolFlag, returns false if not found + +func (cCtx *Context) Duration(name string) time.Duration + Duration looks up the value of a local DurationFlag, returns 0 if not found + +func (cCtx *Context) FlagNames() []string + FlagNames returns a slice of flag names used by the this context and all of + its parent contexts. + +func (cCtx *Context) Float64(name string) float64 + Float64 looks up the value of a local Float64Flag, returns 0 if not found + +func (cCtx *Context) Float64Slice(name string) []float64 + Float64Slice looks up the value of a local Float64SliceFlag, returns nil if + not found + +func (cCtx *Context) Generic(name string) interface{} + Generic looks up the value of a local GenericFlag, returns nil if not found + +func (cCtx *Context) Int(name string) int + Int looks up the value of a local IntFlag, returns 0 if not found + +func (cCtx *Context) Int64(name string) int64 + Int64 looks up the value of a local Int64Flag, returns 0 if not found + +func (cCtx *Context) Int64Slice(name string) []int64 + Int64Slice looks up the value of a local Int64SliceFlag, returns nil if not + found + +func (cCtx *Context) IntSlice(name string) []int + IntSlice looks up the value of a local IntSliceFlag, returns nil if not + found + +func (cCtx *Context) IsSet(name string) bool + IsSet determines if the flag was actually set + +func (cCtx *Context) Lineage() []*Context + Lineage returns *this* context and all of its ancestor contexts in order + from child to parent + +func (cCtx *Context) LocalFlagNames() []string + LocalFlagNames returns a slice of flag names used in this context. + +func (cCtx *Context) NArg() int + NArg returns the number of the command line arguments. + +func (cCtx *Context) NumFlags() int + NumFlags returns the number of flags set + +func (cCtx *Context) Path(name string) string + Path looks up the value of a local PathFlag, returns "" if not found + +func (cCtx *Context) Set(name, value string) error + Set sets a context flag to a value. + +func (cCtx *Context) String(name string) string + String looks up the value of a local StringFlag, returns "" if not found + +func (cCtx *Context) StringSlice(name string) []string + StringSlice looks up the value of a local StringSliceFlag, returns nil if + not found + +func (cCtx *Context) Timestamp(name string) *time.Time + Timestamp gets the timestamp from a flag name + +func (cCtx *Context) Uint(name string) uint + Uint looks up the value of a local UintFlag, returns 0 if not found + +func (cCtx *Context) Uint64(name string) uint64 + Uint64 looks up the value of a local Uint64Flag, returns 0 if not found + +func (cCtx *Context) Value(name string) interface{} + Value returns the value of the flag corresponding to `name` + +type DocGenerationFlag interface { + Flag + + // TakesValue returns true if the flag takes a value, otherwise false + TakesValue() bool + + // GetUsage returns the usage string for the flag + GetUsage() string + + // GetValue returns the flags value as string representation and an empty + // string if the flag takes no value at all. + GetValue() string + + // GetDefaultText returns the default text for this flag + GetDefaultText() string + + // GetEnvVars returns the env vars for this flag + GetEnvVars() []string +} + DocGenerationFlag is an interface that allows documentation generation for + the flag + +type DurationFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value time.Duration + Destination *time.Duration + + Aliases []string + EnvVars []string +} + DurationFlag is a flag with type time.Duration + +func (f *DurationFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *DurationFlag) Get(ctx *Context) time.Duration + Get returns the flag’s value in the given Context. + +func (f *DurationFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *DurationFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *DurationFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *DurationFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *DurationFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *DurationFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *DurationFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *DurationFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *DurationFlag) Names() []string + Names returns the names of the flag + +func (f *DurationFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *DurationFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + ErrorFormatter is the interface that will suitably format the error output + +type ExitCoder interface { + error + ExitCode() int +} + ExitCoder is the interface checked by `App` and `Command` for a custom exit + code + +func Exit(message interface{}, exitCode int) ExitCoder + Exit wraps a message and exit code into an error, which by default is + handled with a call to os.Exit during default error handling. + + This is the simplest way to trigger a non-zero exit code for an App without + having to call os.Exit manually. During testing, this behavior can be + avoided by overiding the ExitErrHandler function on an App or the + package-global OsExiter function. + +func NewExitError(message interface{}, exitCode int) ExitCoder + NewExitError calls Exit to create a new ExitCoder. + + Deprecated: This function is a duplicate of Exit and will eventually be + removed. + +type ExitErrHandlerFunc func(cCtx *Context, err error) + ExitErrHandlerFunc is executed if provided in order to handle exitError + values returned by Actions and Before/After functions. + +type Flag interface { + fmt.Stringer + // Apply Flag settings to the given flag set + Apply(*flag.FlagSet) error + Names() []string + IsSet() bool +} + Flag is a common interface related to parsing flags in cli. For more + advanced flag parsing techniques, it is recommended that this interface be + implemented. + +var BashCompletionFlag Flag = &BoolFlag{ + Name: "generate-bash-completion", + Hidden: true, +} + BashCompletionFlag enables bash-completion for all commands and subcommands + +var HelpFlag Flag = &BoolFlag{ + Name: "help", + Aliases: []string{"h"}, + Usage: "show help", +} + HelpFlag prints the help for all commands and subcommands. Set to nil to + disable the flag. The subcommand will still be added unless HideHelp or + HideHelpCommand is set to true. + +var VersionFlag Flag = &BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "print the version", +} + VersionFlag prints the version for the application + +type FlagCategories interface { + // AddFlags adds a flag to a category, creating a new category if necessary. + AddFlag(category string, fl Flag) + // VisibleCategories returns a slice of visible flag categories sorted by name + VisibleCategories() []VisibleFlagCategory +} + FlagCategories interface allows for category manipulation + +type FlagEnvHintFunc func(envVars []string, str string) string + FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help + with the environment variable details. + +var FlagEnvHinter FlagEnvHintFunc = withEnvHint + FlagEnvHinter annotates flag help message with the environment variable + details. This is used by the default FlagStringer. + +type FlagFileHintFunc func(filePath, str string) string + FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help + with the file path details. + +var FlagFileHinter FlagFileHintFunc = withFileHint + FlagFileHinter annotates flag help message with the environment variable + details. This is used by the default FlagStringer. + +type FlagNamePrefixFunc func(fullName []string, placeholder string) string + FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix + text for a flag's full name. + +var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames + FlagNamePrefixer converts a full flag name and its placeholder into the help + message flag prefix. This is used by the default FlagStringer. + +type FlagStringFunc func(Flag) string + FlagStringFunc is used by the help generation to display a flag, which is + expected to be a single line. + +var FlagStringer FlagStringFunc = stringifyFlag + FlagStringer converts a flag definition to a string. This is used by help to + display a flag. + +type FlagsByName []Flag + FlagsByName is a slice of Flag. + +func (f FlagsByName) Len() int + +func (f FlagsByName) Less(i, j int) bool + +func (f FlagsByName) Swap(i, j int) + +type Float64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value float64 + Destination *float64 + + Aliases []string + EnvVars []string +} + Float64Flag is a flag with type float64 + +func (f *Float64Flag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Float64Flag) Get(ctx *Context) float64 + Get returns the flag’s value in the given Context. + +func (f *Float64Flag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Float64Flag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Float64Flag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Float64Flag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Float64Flag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Float64Flag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Float64Flag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Float64Flag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Float64Flag) Names() []string + Names returns the names of the flag + +func (f *Float64Flag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Float64Flag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Float64Slice struct { + // Has unexported fields. +} + Float64Slice wraps []float64 to satisfy flag.Value + +func NewFloat64Slice(defaults ...float64) *Float64Slice + NewFloat64Slice makes a *Float64Slice with default values + +func (f *Float64Slice) Get() interface{} + Get returns the slice of float64s set by this flag + +func (f *Float64Slice) Serialize() string + Serialize allows Float64Slice to fulfill Serializer + +func (f *Float64Slice) Set(value string) error + Set parses the value into a float64 and appends it to the list of values + +func (f *Float64Slice) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Float64Slice) Value() []float64 + Value returns the slice of float64s set by this flag + +type Float64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Float64Slice + Destination *Float64Slice + + Aliases []string + EnvVars []string +} + Float64SliceFlag is a flag with type *Float64Slice + +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Float64SliceFlag) Get(ctx *Context) []float64 + Get returns the flag’s value in the given Context. + +func (f *Float64SliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Float64SliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Float64SliceFlag) GetDestination() []float64 + +func (f *Float64SliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Float64SliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Float64SliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Float64SliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Float64SliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Float64SliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Float64SliceFlag) Names() []string + Names returns the names of the flag + +func (f *Float64SliceFlag) SetDestination(slice []float64) + +func (f *Float64SliceFlag) SetValue(slice []float64) + +func (f *Float64SliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Float64SliceFlag) TakesValue() bool + TakesValue returns true if the flag takes a value, otherwise false + +type Generic interface { + Set(value string) error + String() string +} + Generic is a generic parseable type identified by a specific flag + +type GenericFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Generic + Destination *Generic + + Aliases []string + EnvVars []string + + TakesFile bool +} + GenericFlag is a flag with type Generic + +func (f GenericFlag) Apply(set *flag.FlagSet) error + Apply takes the flagset and calls Set on the generic flag with the value + provided by the user for parsing by the flag + +func (f *GenericFlag) Get(ctx *Context) interface{} + Get returns the flag’s value in the given Context. + +func (f *GenericFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *GenericFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *GenericFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *GenericFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *GenericFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *GenericFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *GenericFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *GenericFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *GenericFlag) Names() []string + Names returns the names of the flag + +func (f *GenericFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *GenericFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Int64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int64 + Destination *int64 + + Aliases []string + EnvVars []string +} + Int64Flag is a flag with type int64 + +func (f *Int64Flag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Int64Flag) Get(ctx *Context) int64 + Get returns the flag’s value in the given Context. + +func (f *Int64Flag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Int64Flag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Int64Flag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Int64Flag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Int64Flag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Int64Flag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Int64Flag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Int64Flag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Int64Flag) Names() []string + Names returns the names of the flag + +func (f *Int64Flag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Int64Flag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Int64Slice struct { + // Has unexported fields. +} + Int64Slice wraps []int64 to satisfy flag.Value + +func NewInt64Slice(defaults ...int64) *Int64Slice + NewInt64Slice makes an *Int64Slice with default values + +func (i *Int64Slice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *Int64Slice) Serialize() string + Serialize allows Int64Slice to fulfill Serializer + +func (i *Int64Slice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *Int64Slice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *Int64Slice) Value() []int64 + Value returns the slice of ints set by this flag + +type Int64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Int64Slice + Destination *Int64Slice + + Aliases []string + EnvVars []string +} + Int64SliceFlag is a flag with type *Int64Slice + +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Int64SliceFlag) Get(ctx *Context) []int64 + Get returns the flag’s value in the given Context. + +func (f *Int64SliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Int64SliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Int64SliceFlag) GetDestination() []int64 + +func (f *Int64SliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Int64SliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Int64SliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Int64SliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Int64SliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Int64SliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Int64SliceFlag) Names() []string + Names returns the names of the flag + +func (f *Int64SliceFlag) SetDestination(slice []int64) + +func (f *Int64SliceFlag) SetValue(slice []int64) + +func (f *Int64SliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Int64SliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type IntFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int + Destination *int + + Aliases []string + EnvVars []string +} + IntFlag is a flag with type int + +func (f *IntFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *IntFlag) Get(ctx *Context) int + Get returns the flag’s value in the given Context. + +func (f *IntFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *IntFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *IntFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *IntFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *IntFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *IntFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *IntFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *IntFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *IntFlag) Names() []string + Names returns the names of the flag + +func (f *IntFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *IntFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type IntSlice struct { + // Has unexported fields. +} + IntSlice wraps []int to satisfy flag.Value + +func NewIntSlice(defaults ...int) *IntSlice + NewIntSlice makes an *IntSlice with default values + +func (i *IntSlice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *IntSlice) Serialize() string + Serialize allows IntSlice to fulfill Serializer + +func (i *IntSlice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *IntSlice) SetInt(value int) + TODO: Consistently have specific Set function for Int64 and Float64 ? SetInt + directly adds an integer to the list of values + +func (i *IntSlice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *IntSlice) Value() []int + Value returns the slice of ints set by this flag + +type IntSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *IntSlice + Destination *IntSlice + + Aliases []string + EnvVars []string +} + IntSliceFlag is a flag with type *IntSlice + +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *IntSliceFlag) Get(ctx *Context) []int + Get returns the flag’s value in the given Context. + +func (f *IntSliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *IntSliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *IntSliceFlag) GetDestination() []int + +func (f *IntSliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *IntSliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *IntSliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *IntSliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *IntSliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *IntSliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *IntSliceFlag) Names() []string + Names returns the names of the flag + +func (f *IntSliceFlag) SetDestination(slice []int) + +func (f *IntSliceFlag) SetValue(slice []int) + +func (f *IntSliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *IntSliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type MultiError interface { + error + Errors() []error +} + MultiError is an error that wraps multiple errors. + +type MultiFloat64Flag = SliceFlag[*Float64SliceFlag, []float64, float64] + MultiFloat64Flag extends Float64SliceFlag with support for using slices + directly, as Value and/or Destination. See also SliceFlag. + +type MultiInt64Flag = SliceFlag[*Int64SliceFlag, []int64, int64] + MultiInt64Flag extends Int64SliceFlag with support for using slices + directly, as Value and/or Destination. See also SliceFlag. + +type MultiIntFlag = SliceFlag[*IntSliceFlag, []int, int] + MultiIntFlag extends IntSliceFlag with support for using slices directly, as + Value and/or Destination. See also SliceFlag. + +type MultiStringFlag = SliceFlag[*StringSliceFlag, []string, string] + MultiStringFlag extends StringSliceFlag with support for using slices + directly, as Value and/or Destination. See also SliceFlag. + +type OnUsageErrorFunc func(cCtx *Context, err error, isSubcommand bool) error + OnUsageErrorFunc is executed if a usage error occurs. This is useful for + displaying customized usage error messages. This function is able to replace + the original error messages. If this function is not set, the "Incorrect + usage" is displayed and the execution is interrupted. + +type Path = string + +type PathFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Path + Destination *Path + + Aliases []string + EnvVars []string + + TakesFile bool +} + PathFlag is a flag with type Path + +func (f *PathFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *PathFlag) Get(ctx *Context) string + Get returns the flag’s value in the given Context. + +func (f *PathFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *PathFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *PathFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *PathFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *PathFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *PathFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *PathFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *PathFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *PathFlag) Names() []string + Names returns the names of the flag + +func (f *PathFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *PathFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type RequiredFlag interface { + Flag + + IsRequired() bool +} + RequiredFlag is an interface that allows us to mark flags as required it + allows flags required flags to be backwards compatible with the Flag + interface + +type Serializer interface { + Serialize() string +} + Serializer is used to circumvent the limitations of flag.FlagSet.Set + +type SliceFlag[T SliceFlagTarget[E], S ~[]E, E any] struct { + Target T + Value S + Destination *S +} + SliceFlag extends implementations like StringSliceFlag and IntSliceFlag with + support for using slices directly, as Value and/or Destination. See also + SliceFlagTarget, MultiStringFlag, MultiFloat64Flag, MultiInt64Flag, + MultiIntFlag. + +func (x *SliceFlag[T, S, E]) Apply(set *flag.FlagSet) error + +func (x *SliceFlag[T, S, E]) GetCategory() string + +func (x *SliceFlag[T, S, E]) GetDefaultText() string + +func (x *SliceFlag[T, S, E]) GetDestination() S + +func (x *SliceFlag[T, S, E]) GetEnvVars() []string + +func (x *SliceFlag[T, S, E]) GetUsage() string + +func (x *SliceFlag[T, S, E]) GetValue() string + +func (x *SliceFlag[T, S, E]) IsRequired() bool + +func (x *SliceFlag[T, S, E]) IsSet() bool + +func (x *SliceFlag[T, S, E]) IsVisible() bool + +func (x *SliceFlag[T, S, E]) Names() []string + +func (x *SliceFlag[T, S, E]) SetDestination(slice S) + +func (x *SliceFlag[T, S, E]) SetValue(slice S) + +func (x *SliceFlag[T, S, E]) String() string + +func (x *SliceFlag[T, S, E]) TakesValue() bool + +type SliceFlagTarget[E any] interface { + Flag + RequiredFlag + DocGenerationFlag + VisibleFlag + CategorizableFlag + + // SetValue should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~[]E). + SetValue(slice []E) + // SetDestination should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~*[]E). + SetDestination(slice []E) + // GetDestination should return the current value referenced by any destination, or nil if nil/unset. + GetDestination() []E +} + SliceFlagTarget models a target implementation for use with SliceFlag. The + three methods, SetValue, SetDestination, and GetDestination, are necessary + to propagate Value and Destination, where Value is propagated inwards + (initially), and Destination is propagated outwards (on every update). + +type StringFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value string + Destination *string + + Aliases []string + EnvVars []string + + TakesFile bool +} + StringFlag is a flag with type string + +func (f *StringFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *StringFlag) Get(ctx *Context) string + Get returns the flag’s value in the given Context. + +func (f *StringFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *StringFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *StringFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *StringFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *StringFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *StringFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *StringFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *StringFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *StringFlag) Names() []string + Names returns the names of the flag + +func (f *StringFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *StringFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type StringSlice struct { + // Has unexported fields. +} + StringSlice wraps a []string to satisfy flag.Value + +func NewStringSlice(defaults ...string) *StringSlice + NewStringSlice creates a *StringSlice with default values + +func (s *StringSlice) Get() interface{} + Get returns the slice of strings set by this flag + +func (s *StringSlice) Serialize() string + Serialize allows StringSlice to fulfill Serializer + +func (s *StringSlice) Set(value string) error + Set appends the string value to the list of values + +func (s *StringSlice) String() string + String returns a readable representation of this value (for usage defaults) + +func (s *StringSlice) Value() []string + Value returns the slice of strings set by this flag + +type StringSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *StringSlice + Destination *StringSlice + + Aliases []string + EnvVars []string + + TakesFile bool +} + StringSliceFlag is a flag with type *StringSlice + +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *StringSliceFlag) Get(ctx *Context) []string + Get returns the flag’s value in the given Context. + +func (f *StringSliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *StringSliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *StringSliceFlag) GetDestination() []string + +func (f *StringSliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *StringSliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *StringSliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *StringSliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *StringSliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *StringSliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *StringSliceFlag) Names() []string + Names returns the names of the flag + +func (f *StringSliceFlag) SetDestination(slice []string) + +func (f *StringSliceFlag) SetValue(slice []string) + +func (f *StringSliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *StringSliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type SuggestCommandFunc func(commands []*Command, provided string) string + +type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string + +type Timestamp struct { + // Has unexported fields. +} + Timestamp wrap to satisfy golang's flag interface. + +func NewTimestamp(timestamp time.Time) *Timestamp + Timestamp constructor + +func (t *Timestamp) Get() interface{} + Get returns the flag structure + +func (t *Timestamp) Set(value string) error + Parses the string value to timestamp + +func (t *Timestamp) SetLayout(layout string) + Set the timestamp string layout for future parsing + +func (t *Timestamp) SetLocation(loc *time.Location) + Set perceived timezone of the to-be parsed time string + +func (t *Timestamp) SetTimestamp(value time.Time) + Set the timestamp value directly + +func (t *Timestamp) String() string + String returns a readable representation of this value (for usage defaults) + +func (t *Timestamp) Value() *time.Time + Value returns the timestamp value stored in the flag + +type TimestampFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Timestamp + Destination *Timestamp + + Aliases []string + EnvVars []string + + Layout string + + Timezone *time.Location +} + TimestampFlag is a flag with type *Timestamp + +func (f *TimestampFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *TimestampFlag) Get(ctx *Context) *time.Time + Get returns the flag’s value in the given Context. + +func (f *TimestampFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *TimestampFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *TimestampFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *TimestampFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *TimestampFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *TimestampFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *TimestampFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *TimestampFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *TimestampFlag) Names() []string + Names returns the names of the flag + +func (f *TimestampFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *TimestampFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Uint64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint64 + Destination *uint64 + + Aliases []string + EnvVars []string +} + Uint64Flag is a flag with type uint64 + +func (f *Uint64Flag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Uint64Flag) Get(ctx *Context) uint64 + Get returns the flag’s value in the given Context. + +func (f *Uint64Flag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Uint64Flag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Uint64Flag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Uint64Flag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Uint64Flag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Uint64Flag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Uint64Flag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Uint64Flag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Uint64Flag) Names() []string + Names returns the names of the flag + +func (f *Uint64Flag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Uint64Flag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type UintFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint + Destination *uint + + Aliases []string + EnvVars []string +} + UintFlag is a flag with type uint + +func (f *UintFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *UintFlag) Get(ctx *Context) uint + Get returns the flag’s value in the given Context. + +func (f *UintFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *UintFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *UintFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *UintFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *UintFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *UintFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *UintFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *UintFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *UintFlag) Names() []string + Names returns the names of the flag + +func (f *UintFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *UintFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type VisibleFlag interface { + Flag + + // IsVisible returns true if the flag is not hidden, otherwise false + IsVisible() bool +} + VisibleFlag is an interface that allows to check if a flag is visible + +type VisibleFlagCategory interface { + // Name returns the category name string + Name() string + // Flags returns a slice of VisibleFlag sorted by name + Flags() []VisibleFlag +} + VisibleFlagCategory is a category containing flags. + +package altsrc // import "github.com/urfave/cli/v2/altsrc" + + +FUNCTIONS + +func ApplyInputSourceValues(cCtx *cli.Context, inputSourceContext InputSourceContext, flags []cli.Flag) error + ApplyInputSourceValues iterates over all provided flags and executes + ApplyInputSourceValue on flags implementing the FlagInputSourceExtension + interface to initialize these flags to an alternate input source. + +func InitInputSource(flags []cli.Flag, createInputSource func() (InputSourceContext, error)) cli.BeforeFunc + InitInputSource is used to to setup an InputSourceContext on a cli.Command + Before method. It will create a new input source based on the func provided. + If there is no error it will then apply the new input source to any flags + that are supported by the input source + +func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(cCtx *cli.Context) (InputSourceContext, error)) cli.BeforeFunc + InitInputSourceWithContext is used to to setup an InputSourceContext on a + cli.Command Before method. It will create a new input source based on the + func provided with potentially using existing cli.Context values to + initialize itself. If there is no error it will then apply the new input + source to any flags that are supported by the input source + +func NewJSONSourceFromFlagFunc(flag string) func(c *cli.Context) (InputSourceContext, error) + NewJSONSourceFromFlagFunc returns a func that takes a cli.Context and + returns an InputSourceContext suitable for retrieving config variables from + a file containing JSON data with the file name defined by the given flag. + +func NewTomlSourceFromFlagFunc(flagFileName string) func(cCtx *cli.Context) (InputSourceContext, error) + NewTomlSourceFromFlagFunc creates a new TOML InputSourceContext from a + provided flag name and source context. + +func NewYamlSourceFromFlagFunc(flagFileName string) func(cCtx *cli.Context) (InputSourceContext, error) + NewYamlSourceFromFlagFunc creates a new Yaml InputSourceContext from a + provided flag name and source context. + + +TYPES + +type BoolFlag struct { + *cli.BoolFlag + // Has unexported fields. +} + BoolFlag is the flag type that wraps cli.BoolFlag to allow for other values + to be specified + +func NewBoolFlag(fl *cli.BoolFlag) *BoolFlag + NewBoolFlag creates a new BoolFlag + +func (f *BoolFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + BoolFlag.Apply + +func (f *BoolFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Bool value to the flagSet if required + +type DurationFlag struct { + *cli.DurationFlag + // Has unexported fields. +} + DurationFlag is the flag type that wraps cli.DurationFlag to allow for other + values to be specified + +func NewDurationFlag(fl *cli.DurationFlag) *DurationFlag + NewDurationFlag creates a new DurationFlag + +func (f *DurationFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + DurationFlag.Apply + +func (f *DurationFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Duration value to the flagSet if required + +type FlagInputSourceExtension interface { + cli.Flag + ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error +} + FlagInputSourceExtension is an extension interface of cli.Flag that allows a + value to be set on the existing parsed flags. + +type Float64Flag struct { + *cli.Float64Flag + // Has unexported fields. +} + Float64Flag is the flag type that wraps cli.Float64Flag to allow for other + values to be specified + +func NewFloat64Flag(fl *cli.Float64Flag) *Float64Flag + NewFloat64Flag creates a new Float64Flag + +func (f *Float64Flag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Float64Flag.Apply + +func (f *Float64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Float64 value to the flagSet if required + +type Float64SliceFlag struct { + *cli.Float64SliceFlag + // Has unexported fields. +} + Float64SliceFlag is the flag type that wraps cli.Float64SliceFlag to allow + for other values to be specified + +func NewFloat64SliceFlag(fl *cli.Float64SliceFlag) *Float64SliceFlag + NewFloat64SliceFlag creates a new Float64SliceFlag + +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Float64SliceFlag.Apply + +type GenericFlag struct { + *cli.GenericFlag + // Has unexported fields. +} + GenericFlag is the flag type that wraps cli.GenericFlag to allow for other + values to be specified + +func NewGenericFlag(fl *cli.GenericFlag) *GenericFlag + NewGenericFlag creates a new GenericFlag + +func (f *GenericFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + GenericFlag.Apply + +func (f *GenericFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a generic value to the flagSet if required + +type InputSourceContext interface { + Source() string + + Int(name string) (int, error) + Duration(name string) (time.Duration, error) + Float64(name string) (float64, error) + String(name string) (string, error) + StringSlice(name string) ([]string, error) + IntSlice(name string) ([]int, error) + Generic(name string) (cli.Generic, error) + Bool(name string) (bool, error) + + // Has unexported methods. +} + InputSourceContext is an interface used to allow other input sources to be + implemented as needed. + + Source returns an identifier for the input source. In case of file source it + should return path to the file. + +func NewJSONSource(data []byte) (InputSourceContext, error) + NewJSONSource returns an InputSourceContext suitable for retrieving config + variables from raw JSON data. + +func NewJSONSourceFromFile(f string) (InputSourceContext, error) + NewJSONSourceFromFile returns an InputSourceContext suitable for retrieving + config variables from a file (or url) containing JSON data. + +func NewJSONSourceFromReader(r io.Reader) (InputSourceContext, error) + NewJSONSourceFromReader returns an InputSourceContext suitable for + retrieving config variables from an io.Reader that returns JSON data. + +func NewTomlSourceFromFile(file string) (InputSourceContext, error) + NewTomlSourceFromFile creates a new TOML InputSourceContext from a filepath. + +func NewYamlSourceFromFile(file string) (InputSourceContext, error) + NewYamlSourceFromFile creates a new Yaml InputSourceContext from a filepath. + +type Int64Flag struct { + *cli.Int64Flag + // Has unexported fields. +} + Int64Flag is the flag type that wraps cli.Int64Flag to allow for other + values to be specified + +func NewInt64Flag(fl *cli.Int64Flag) *Int64Flag + NewInt64Flag creates a new Int64Flag + +func (f *Int64Flag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Int64Flag.Apply + +type Int64SliceFlag struct { + *cli.Int64SliceFlag + // Has unexported fields. +} + Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow for + other values to be specified + +func NewInt64SliceFlag(fl *cli.Int64SliceFlag) *Int64SliceFlag + NewInt64SliceFlag creates a new Int64SliceFlag + +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Int64SliceFlag.Apply + +type IntFlag struct { + *cli.IntFlag + // Has unexported fields. +} + IntFlag is the flag type that wraps cli.IntFlag to allow for other values to + be specified + +func NewIntFlag(fl *cli.IntFlag) *IntFlag + NewIntFlag creates a new IntFlag + +func (f *IntFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + IntFlag.Apply + +func (f *IntFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a int value to the flagSet if required + +type IntSliceFlag struct { + *cli.IntSliceFlag + // Has unexported fields. +} + IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow for other + values to be specified + +func NewIntSliceFlag(fl *cli.IntSliceFlag) *IntSliceFlag + NewIntSliceFlag creates a new IntSliceFlag + +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + IntSliceFlag.Apply + +func (f *IntSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a IntSlice value if required + +type MapInputSource struct { + // Has unexported fields. +} + MapInputSource implements InputSourceContext to return data from the map + that is loaded. + +func NewMapInputSource(file string, valueMap map[interface{}]interface{}) *MapInputSource + NewMapInputSource creates a new MapInputSource for implementing custom input + sources. + +func (fsm *MapInputSource) Bool(name string) (bool, error) + Bool returns an bool from the map otherwise returns false + +func (fsm *MapInputSource) Duration(name string) (time.Duration, error) + Duration returns a duration from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Float64(name string) (float64, error) + Float64 returns an float64 from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) + Generic returns an cli.Generic from the map if it exists otherwise returns + nil + +func (fsm *MapInputSource) Int(name string) (int, error) + Int returns an int from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) IntSlice(name string) ([]int, error) + IntSlice returns an []int from the map if it exists otherwise returns nil + +func (fsm *MapInputSource) Source() string + Source returns the path of the source file + +func (fsm *MapInputSource) String(name string) (string, error) + String returns a string from the map if it exists otherwise returns an empty + string + +func (fsm *MapInputSource) StringSlice(name string) ([]string, error) + StringSlice returns an []string from the map if it exists otherwise returns + nil + +type PathFlag struct { + *cli.PathFlag + // Has unexported fields. +} + PathFlag is the flag type that wraps cli.PathFlag to allow for other values + to be specified + +func NewPathFlag(fl *cli.PathFlag) *PathFlag + NewPathFlag creates a new PathFlag + +func (f *PathFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + PathFlag.Apply + +func (f *PathFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Path value to the flagSet if required + +type StringFlag struct { + *cli.StringFlag + // Has unexported fields. +} + StringFlag is the flag type that wraps cli.StringFlag to allow for other + values to be specified + +func NewStringFlag(fl *cli.StringFlag) *StringFlag + NewStringFlag creates a new StringFlag + +func (f *StringFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + StringFlag.Apply + +func (f *StringFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a String value to the flagSet if required + +type StringSliceFlag struct { + *cli.StringSliceFlag + // Has unexported fields. +} + StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow for + other values to be specified + +func NewStringSliceFlag(fl *cli.StringSliceFlag) *StringSliceFlag + NewStringSliceFlag creates a new StringSliceFlag + +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + StringSliceFlag.Apply + +func (f *StringSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a StringSlice value to the flagSet if required + +type Uint64Flag struct { + *cli.Uint64Flag + // Has unexported fields. +} + Uint64Flag is the flag type that wraps cli.Uint64Flag to allow for other + values to be specified + +func NewUint64Flag(fl *cli.Uint64Flag) *Uint64Flag + NewUint64Flag creates a new Uint64Flag + +func (f *Uint64Flag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Uint64Flag.Apply + +type UintFlag struct { + *cli.UintFlag + // Has unexported fields. +} + UintFlag is the flag type that wraps cli.UintFlag to allow for other values + to be specified + +func NewUintFlag(fl *cli.UintFlag) *UintFlag + NewUintFlag creates a new UintFlag + +func (f *UintFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + UintFlag.Apply + diff --git a/vendor/github.com/urfave/cli/help.go b/vendor/github.com/urfave/cli/v2/help.go similarity index 57% rename from vendor/github.com/urfave/cli/help.go rename to vendor/github.com/urfave/cli/v2/help.go index 2280e338e..9a8d2437d 100644 --- a/vendor/github.com/urfave/cli/help.go +++ b/vendor/github.com/urfave/cli/v2/help.go @@ -10,34 +10,39 @@ import ( "unicode/utf8" ) -var helpCommand = Command{ - Name: "help", - Aliases: []string{"h"}, +const ( + helpName = "help" + helpAlias = "h" +) + +var helpCommand = &Command{ + Name: helpName, + Aliases: []string{helpAlias}, Usage: "Shows a list of commands or help for one command", ArgsUsage: "[command]", - Action: func(c *Context) error { - args := c.Args() + Action: func(cCtx *Context) error { + args := cCtx.Args() if args.Present() { - return ShowCommandHelp(c, args.First()) + return ShowCommandHelp(cCtx, args.First()) } - _ = ShowAppHelp(c) + _ = ShowAppHelp(cCtx) return nil }, } -var helpSubcommand = Command{ - Name: "help", - Aliases: []string{"h"}, +var helpSubcommand = &Command{ + Name: helpName, + Aliases: []string{helpAlias}, Usage: "Shows a list of commands or help for one command", ArgsUsage: "[command]", - Action: func(c *Context) error { - args := c.Args() + Action: func(cCtx *Context) error { + args := cCtx.Args() if args.Present() { - return ShowCommandHelp(c, args.First()) + return ShowCommandHelp(cCtx, args.First()) } - return ShowSubcommandHelp(c) + return ShowSubcommandHelp(cCtx) }, } @@ -59,6 +64,11 @@ var HelpPrinter helpPrinter = printHelp // HelpPrinterCustom is a function that writes the help output. It is used as // the default implementation of HelpPrinter, and may be called directly if // the ExtraInfo field is set on an App. +// +// In the default implementation, if the customFuncs argument contains a +// "wrapAt" key, which is a function which takes no arguments and returns +// an int, this int value will be used to produce a "wrap" function used +// by the default template to wrap long lines. var HelpPrinterCustom helpPrinterCustom = printHelpCustom // VersionPrinter prints the version for the App @@ -71,38 +81,38 @@ func ShowAppHelpAndExit(c *Context, exitCode int) { } // ShowAppHelp is an action that displays the help. -func ShowAppHelp(c *Context) error { - template := c.App.CustomAppHelpTemplate - if template == "" { - template = AppHelpTemplate +func ShowAppHelp(cCtx *Context) error { + tpl := cCtx.App.CustomAppHelpTemplate + if tpl == "" { + tpl = AppHelpTemplate } - if c.App.ExtraInfo == nil { - HelpPrinter(c.App.Writer, template, c.App) + if cCtx.App.ExtraInfo == nil { + HelpPrinter(cCtx.App.Writer, tpl, cCtx.App) return nil } customAppData := func() map[string]interface{} { return map[string]interface{}{ - "ExtraInfo": c.App.ExtraInfo, + "ExtraInfo": cCtx.App.ExtraInfo, } } - HelpPrinterCustom(c.App.Writer, template, c.App, customAppData()) + HelpPrinterCustom(cCtx.App.Writer, tpl, cCtx.App, customAppData()) return nil } // DefaultAppComplete prints the list of subcommands as the default app completion method -func DefaultAppComplete(c *Context) { - DefaultCompleteWithFlags(nil)(c) +func DefaultAppComplete(cCtx *Context) { + DefaultCompleteWithFlags(nil)(cCtx) } -func printCommandSuggestions(commands []Command, writer io.Writer) { +func printCommandSuggestions(commands []*Command, writer io.Writer) { for _, command := range commands { if command.Hidden { continue } - if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + if strings.HasSuffix(os.Getenv("SHELL"), "zsh") { for _, name := range command.Names() { _, _ = fmt.Fprintf(writer, "%s:%s\n", name, command.Usage) } @@ -135,10 +145,10 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { cur := strings.TrimPrefix(lastArg, "-") cur = strings.TrimPrefix(cur, "-") for _, flag := range flags { - if bflag, ok := flag.(BoolFlag); ok && bflag.Hidden { + if bflag, ok := flag.(*BoolFlag); ok && bflag.Hidden { continue } - for _, name := range strings.Split(flag.GetName(), ",") { + for _, name := range flag.Names() { name = strings.TrimSpace(name) // this will get total count utf8 letters in flag name count := utf8.RuneCountInString(name) @@ -151,7 +161,7 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { continue } // match if last argument matches this flag and it is not repeated - if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(flag.GetName()) { + if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(name) { flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) _, _ = fmt.Fprintln(writer, flagCompletion) } @@ -159,23 +169,30 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { } } -func DefaultCompleteWithFlags(cmd *Command) func(c *Context) { - return func(c *Context) { +func DefaultCompleteWithFlags(cmd *Command) func(cCtx *Context) { + return func(cCtx *Context) { if len(os.Args) > 2 { lastArg := os.Args[len(os.Args)-2] + if strings.HasPrefix(lastArg, "-") { - printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer) if cmd != nil { - printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer) + printFlagSuggestions(lastArg, cmd.Flags, cCtx.App.Writer) + + return } + + printFlagSuggestions(lastArg, cCtx.App.Flags, cCtx.App.Writer) + return } } + if cmd != nil { - printCommandSuggestions(cmd.Subcommands, c.App.Writer) - } else { - printCommandSuggestions(c.App.Commands, c.App.Writer) + printCommandSuggestions(cmd.Subcommands, cCtx.App.Writer) + return } + + printCommandSuggestions(cCtx.App.Commands, cCtx.App.Writer) } } @@ -207,32 +224,52 @@ func ShowCommandHelp(ctx *Context, command string) error { } if ctx.App.CommandNotFound == nil { - return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3) + errMsg := fmt.Sprintf("No help topic for '%v'", command) + if ctx.App.Suggest { + if suggestion := SuggestCommand(ctx.App.Commands, command); suggestion != "" { + errMsg += ". " + suggestion + } + } + return Exit(errMsg, 3) } ctx.App.CommandNotFound(ctx, command) return nil } +// ShowSubcommandHelpAndExit - Prints help for the given subcommand and exits with exit code. +func ShowSubcommandHelpAndExit(c *Context, exitCode int) { + _ = ShowSubcommandHelp(c) + os.Exit(exitCode) +} + // ShowSubcommandHelp prints help for the given subcommand -func ShowSubcommandHelp(c *Context) error { - return ShowCommandHelp(c, c.Command.Name) +func ShowSubcommandHelp(cCtx *Context) error { + if cCtx == nil { + return nil + } + + if cCtx.Command != nil { + return ShowCommandHelp(cCtx, cCtx.Command.Name) + } + + return ShowCommandHelp(cCtx, "") } // ShowVersion prints the version number of the App -func ShowVersion(c *Context) { - VersionPrinter(c) +func ShowVersion(cCtx *Context) { + VersionPrinter(cCtx) } -func printVersion(c *Context) { - _, _ = fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) +func printVersion(cCtx *Context) { + _, _ = fmt.Fprintf(cCtx.App.Writer, "%v version %v\n", cCtx.App.Name, cCtx.App.Version) } // ShowCompletions prints the lists of commands within a given context -func ShowCompletions(c *Context) { - a := c.App +func ShowCompletions(cCtx *Context) { + a := cCtx.App if a != nil && a.BashComplete != nil { - a.BashComplete(c) + a.BashComplete(cCtx) } } @@ -254,15 +291,36 @@ func ShowCommandCompletions(ctx *Context, command string) { // The customFuncs map will be combined with a default template.FuncMap to // allow using arbitrary functions in template rendering. func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { + + const maxLineLength = 10000 + funcMap := template.FuncMap{ - "join": strings.Join, + "join": strings.Join, + "indent": indent, + "nindent": nindent, + "trim": strings.TrimSpace, + "wrap": func(input string, offset int) string { return wrap(input, offset, maxLineLength) }, + "offset": offset, } + + if customFuncs["wrapAt"] != nil { + if wa, ok := customFuncs["wrapAt"]; ok { + if waf, ok := wa.(func() int); ok { + wrapAt := waf() + customFuncs["wrap"] = func(input string, offset int) string { + return wrap(input, offset, wrapAt) + } + } + } + } + for key, value := range customFuncs { funcMap[key] = value } w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + err := t.Execute(w, data) if err != nil { // If the writer is closed, t.Execute will fail, and there's nothing @@ -279,26 +337,22 @@ func printHelp(out io.Writer, templ string, data interface{}) { HelpPrinterCustom(out, templ, data, nil) } -func checkVersion(c *Context) bool { +func checkVersion(cCtx *Context) bool { found := false - if VersionFlag.GetName() != "" { - eachName(VersionFlag.GetName(), func(name string) { - if c.GlobalBool(name) || c.Bool(name) { - found = true - } - }) + for _, name := range VersionFlag.Names() { + if cCtx.Bool(name) { + found = true + } } return found } -func checkHelp(c *Context) bool { +func checkHelp(cCtx *Context) bool { found := false - if HelpFlag.GetName() != "" { - eachName(HelpFlag.GetName(), func(name string) { - if c.GlobalBool(name) || c.Bool(name) { - found = true - } - }) + for _, name := range HelpFlag.Names() { + if cCtx.Bool(name) { + found = true + } } return found } @@ -312,9 +366,9 @@ func checkCommandHelp(c *Context, name string) bool { return false } -func checkSubcommandHelp(c *Context) bool { - if c.Bool("h") || c.Bool("help") { - _ = ShowSubcommandHelp(c) +func checkSubcommandHelp(cCtx *Context) bool { + if cCtx.Bool("h") || cCtx.Bool("help") { + _ = ShowSubcommandHelp(cCtx) return true } @@ -329,27 +383,27 @@ func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { pos := len(arguments) - 1 lastArg := arguments[pos] - if lastArg != "--"+BashCompletionFlag.GetName() { + if lastArg != "--generate-bash-completion" { return false, arguments } return true, arguments[:pos] } -func checkCompletions(c *Context) bool { - if !c.shellComplete { +func checkCompletions(cCtx *Context) bool { + if !cCtx.shellComplete { return false } - if args := c.Args(); args.Present() { + if args := cCtx.Args(); args.Present() { name := args.First() - if cmd := c.App.Command(name); cmd != nil { + if cmd := cCtx.App.Command(name); cmd != nil { // let the command handle the completion return false } } - ShowCompletions(c) + ShowCompletions(cCtx) return true } @@ -361,3 +415,64 @@ func checkCommandCompletions(c *Context, name string) bool { ShowCommandCompletions(c, name) return true } + +func indent(spaces int, v string) string { + pad := strings.Repeat(" ", spaces) + return pad + strings.Replace(v, "\n", "\n"+pad, -1) +} + +func nindent(spaces int, v string) string { + return "\n" + indent(spaces, v) +} + +func wrap(input string, offset int, wrapAt int) string { + var sb strings.Builder + + lines := strings.Split(input, "\n") + + padding := strings.Repeat(" ", offset) + + for i, line := range lines { + if i != 0 { + sb.WriteString(padding) + } + + sb.WriteString(wrapLine(line, offset, wrapAt, padding)) + + if i != len(lines)-1 { + sb.WriteString("\n") + } + } + + return sb.String() +} + +func wrapLine(input string, offset int, wrapAt int, padding string) string { + if wrapAt <= offset || len(input) <= wrapAt-offset { + return input + } + + lineWidth := wrapAt - offset + words := strings.Fields(input) + if len(words) == 0 { + return input + } + + wrapped := words[0] + spaceLeft := lineWidth - len(wrapped) + for _, word := range words[1:] { + if len(word)+1 > spaceLeft { + wrapped += "\n" + padding + word + spaceLeft = lineWidth - len(word) + } else { + wrapped += " " + word + spaceLeft -= 1 + len(word) + } + } + + return wrapped +} + +func offset(input string, fixed int) int { + return len(input) + fixed +} diff --git a/vendor/github.com/urfave/cli/v2/mkdocs-requirements.txt b/vendor/github.com/urfave/cli/v2/mkdocs-requirements.txt new file mode 100644 index 000000000..482ad0622 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/mkdocs-requirements.txt @@ -0,0 +1,5 @@ +mkdocs-git-revision-date-localized-plugin~=1.0 +mkdocs-material-extensions~=1.0 +mkdocs-material~=8.2 +mkdocs~=1.3 +pygments~=2.12 diff --git a/vendor/github.com/urfave/cli/v2/mkdocs.yml b/vendor/github.com/urfave/cli/v2/mkdocs.yml new file mode 100644 index 000000000..73b88c509 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/mkdocs.yml @@ -0,0 +1,62 @@ +# NOTE: the mkdocs dependencies will need to be installed out of +# band until this whole thing gets more automated: +# +# pip install -r mkdocs-requirements.txt +# + +site_name: urfave/cli +site_url: https://cli.urfave.org/ +repo_url: https://github.com/urfave/cli +edit_uri: edit/main/docs/ +nav: + - Home: index.md + - v2 Manual: v2/index.md + - v1 Manual: v1/index.md +theme: + name: material + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-4 + name: dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-7 + name: light mode +plugins: + - git-revision-date-localized + - search +# NOTE: this is the recommended configuration from +# https://squidfunk.github.io/mkdocs-material/setup/extensions/#recommended-configuration +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - meta + - md_in_html + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + - pymdownx.highlight + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde diff --git a/vendor/github.com/urfave/cli/parse.go b/vendor/github.com/urfave/cli/v2/parse.go similarity index 82% rename from vendor/github.com/urfave/cli/parse.go rename to vendor/github.com/urfave/cli/v2/parse.go index 7df17296a..a2db306e1 100644 --- a/vendor/github.com/urfave/cli/parse.go +++ b/vendor/github.com/urfave/cli/v2/parse.go @@ -26,9 +26,8 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple return err } - errStr := err.Error() - trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") - if errStr == trimmed { + trimmed, trimErr := flagFromError(err) + if trimErr != nil { return err } @@ -67,6 +66,19 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple } } +const providedButNotDefinedErrMsg = "flag provided but not defined: -" + +// flagFromError tries to parse a provided flag from an error message. If the +// parsing fials, it returns the input error and an empty string +func flagFromError(err error) (string, error) { + errStr := err.Error() + trimmed := strings.TrimPrefix(errStr, providedButNotDefinedErrMsg) + if errStr == trimmed { + return "", err + } + return trimmed, nil +} + func splitShortOptions(set *flag.FlagSet, arg string) []string { shortFlagsExist := func(s string) bool { for _, c := range s[1:] { diff --git a/vendor/github.com/urfave/cli/v2/sliceflag.go b/vendor/github.com/urfave/cli/v2/sliceflag.go new file mode 100644 index 000000000..7dea3576a --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/sliceflag.go @@ -0,0 +1,293 @@ +//go:build go1.18 +// +build go1.18 + +package cli + +import ( + "flag" + "reflect" +) + +type ( + // SliceFlag extends implementations like StringSliceFlag and IntSliceFlag with support for using slices directly, + // as Value and/or Destination. + // See also SliceFlagTarget, MultiStringFlag, MultiFloat64Flag, MultiInt64Flag, MultiIntFlag. + SliceFlag[T SliceFlagTarget[E], S ~[]E, E any] struct { + Target T + Value S + Destination *S + } + + // SliceFlagTarget models a target implementation for use with SliceFlag. + // The three methods, SetValue, SetDestination, and GetDestination, are necessary to propagate Value and + // Destination, where Value is propagated inwards (initially), and Destination is propagated outwards (on every + // update). + SliceFlagTarget[E any] interface { + Flag + RequiredFlag + DocGenerationFlag + VisibleFlag + CategorizableFlag + + // SetValue should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~[]E). + SetValue(slice []E) + // SetDestination should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~*[]E). + SetDestination(slice []E) + // GetDestination should return the current value referenced by any destination, or nil if nil/unset. + GetDestination() []E + } + + // MultiStringFlag extends StringSliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiStringFlag = SliceFlag[*StringSliceFlag, []string, string] + + // MultiFloat64Flag extends Float64SliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiFloat64Flag = SliceFlag[*Float64SliceFlag, []float64, float64] + + // MultiInt64Flag extends Int64SliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiInt64Flag = SliceFlag[*Int64SliceFlag, []int64, int64] + + // MultiIntFlag extends IntSliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiIntFlag = SliceFlag[*IntSliceFlag, []int, int] + + flagValueHook struct { + value Generic + hook func() + } +) + +var ( + // compile time assertions + + _ SliceFlagTarget[string] = (*StringSliceFlag)(nil) + _ SliceFlagTarget[string] = (*SliceFlag[*StringSliceFlag, []string, string])(nil) + _ SliceFlagTarget[string] = (*MultiStringFlag)(nil) + _ SliceFlagTarget[float64] = (*MultiFloat64Flag)(nil) + _ SliceFlagTarget[int64] = (*MultiInt64Flag)(nil) + _ SliceFlagTarget[int] = (*MultiIntFlag)(nil) + + _ Generic = (*flagValueHook)(nil) + _ Serializer = (*flagValueHook)(nil) +) + +func (x *SliceFlag[T, S, E]) Apply(set *flag.FlagSet) error { + x.Target.SetValue(x.convertSlice(x.Value)) + + destination := x.Destination + if destination == nil { + x.Target.SetDestination(nil) + + return x.Target.Apply(set) + } + + x.Target.SetDestination(x.convertSlice(*destination)) + + return applyFlagValueHook(set, x.Target.Apply, func() { + *destination = x.Target.GetDestination() + }) +} + +func (x *SliceFlag[T, S, E]) convertSlice(slice S) []E { + result := make([]E, len(slice)) + copy(result, slice) + return result +} + +func (x *SliceFlag[T, S, E]) SetValue(slice S) { + x.Value = slice +} + +func (x *SliceFlag[T, S, E]) SetDestination(slice S) { + if slice != nil { + x.Destination = &slice + } else { + x.Destination = nil + } +} + +func (x *SliceFlag[T, S, E]) GetDestination() S { + if destination := x.Destination; destination != nil { + return *destination + } + return nil +} + +func (x *SliceFlag[T, S, E]) String() string { return x.Target.String() } +func (x *SliceFlag[T, S, E]) Names() []string { return x.Target.Names() } +func (x *SliceFlag[T, S, E]) IsSet() bool { return x.Target.IsSet() } +func (x *SliceFlag[T, S, E]) IsRequired() bool { return x.Target.IsRequired() } +func (x *SliceFlag[T, S, E]) TakesValue() bool { return x.Target.TakesValue() } +func (x *SliceFlag[T, S, E]) GetUsage() string { return x.Target.GetUsage() } +func (x *SliceFlag[T, S, E]) GetValue() string { return x.Target.GetValue() } +func (x *SliceFlag[T, S, E]) GetDefaultText() string { return x.Target.GetDefaultText() } +func (x *SliceFlag[T, S, E]) GetEnvVars() []string { return x.Target.GetEnvVars() } +func (x *SliceFlag[T, S, E]) IsVisible() bool { return x.Target.IsVisible() } +func (x *SliceFlag[T, S, E]) GetCategory() string { return x.Target.GetCategory() } + +func (x *flagValueHook) Set(value string) error { + if err := x.value.Set(value); err != nil { + return err + } + x.hook() + return nil +} + +func (x *flagValueHook) String() string { + // note: this is necessary due to the way Go's flag package handles defaults + isZeroValue := func(f flag.Value, v string) bool { + /* + https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/flag/flag.go;drc=2580d0e08d5e9f979b943758d3c49877fb2324cb;l=453 + + Copyright (c) 2009 The Go Authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + // Build a zero value of the flag's Value type, and see if the + // result of calling its String method equals the value passed in. + // This works unless the Value type is itself an interface type. + typ := reflect.TypeOf(f) + var z reflect.Value + if typ.Kind() == reflect.Pointer { + z = reflect.New(typ.Elem()) + } else { + z = reflect.Zero(typ) + } + return v == z.Interface().(flag.Value).String() + } + if x.value != nil { + // only return non-empty if not the same string as returned by the zero value + if s := x.value.String(); !isZeroValue(x.value, s) { + return s + } + } + return `` +} + +func (x *flagValueHook) Serialize() string { + if value, ok := x.value.(Serializer); ok { + return value.Serialize() + } + return x.String() +} + +// applyFlagValueHook wraps calls apply then wraps flags to call a hook function on update and after initial apply. +func applyFlagValueHook(set *flag.FlagSet, apply func(set *flag.FlagSet) error, hook func()) error { + if apply == nil || set == nil || hook == nil { + panic(`invalid input`) + } + var tmp flag.FlagSet + if err := apply(&tmp); err != nil { + return err + } + tmp.VisitAll(func(f *flag.Flag) { set.Var(&flagValueHook{value: f.Value, hook: hook}, f.Name, f.Usage) }) + hook() + return nil +} + +// newSliceFlagValue is for implementing SliceFlagTarget.SetValue and SliceFlagTarget.SetDestination. +// It's e.g. as part of StringSliceFlag.SetValue, using the factory NewStringSlice. +func newSliceFlagValue[R any, S ~[]E, E any](factory func(defaults ...E) *R, defaults S) *R { + if defaults == nil { + return nil + } + return factory(defaults...) +} + +// unwrapFlagValue strips any/all *flagValueHook wrappers. +func unwrapFlagValue(v flag.Value) flag.Value { + for { + h, ok := v.(*flagValueHook) + if !ok { + return v + } + v = h.value + } +} + +// NOTE: the methods below are in this file to make use of the build constraint + +func (f *Float64SliceFlag) SetValue(slice []float64) { + f.Value = newSliceFlagValue(NewFloat64Slice, slice) +} + +func (f *Float64SliceFlag) SetDestination(slice []float64) { + f.Destination = newSliceFlagValue(NewFloat64Slice, slice) +} + +func (f *Float64SliceFlag) GetDestination() []float64 { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} + +func (f *Int64SliceFlag) SetValue(slice []int64) { + f.Value = newSliceFlagValue(NewInt64Slice, slice) +} + +func (f *Int64SliceFlag) SetDestination(slice []int64) { + f.Destination = newSliceFlagValue(NewInt64Slice, slice) +} + +func (f *Int64SliceFlag) GetDestination() []int64 { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} + +func (f *IntSliceFlag) SetValue(slice []int) { + f.Value = newSliceFlagValue(NewIntSlice, slice) +} + +func (f *IntSliceFlag) SetDestination(slice []int) { + f.Destination = newSliceFlagValue(NewIntSlice, slice) +} + +func (f *IntSliceFlag) GetDestination() []int { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} + +func (f *StringSliceFlag) SetValue(slice []string) { + f.Value = newSliceFlagValue(NewStringSlice, slice) +} + +func (f *StringSliceFlag) SetDestination(slice []string) { + f.Destination = newSliceFlagValue(NewStringSlice, slice) +} + +func (f *StringSliceFlag) GetDestination() []string { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/sliceflag_pre18.go b/vendor/github.com/urfave/cli/v2/sliceflag_pre18.go new file mode 100644 index 000000000..1173ae740 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/sliceflag_pre18.go @@ -0,0 +1,10 @@ +//go:build !go1.18 +// +build !go1.18 + +package cli + +import ( + "flag" +) + +func unwrapFlagValue(v flag.Value) flag.Value { return v } diff --git a/vendor/github.com/urfave/cli/sort.go b/vendor/github.com/urfave/cli/v2/sort.go similarity index 100% rename from vendor/github.com/urfave/cli/sort.go rename to vendor/github.com/urfave/cli/v2/sort.go diff --git a/vendor/github.com/urfave/cli/v2/suggestions.go b/vendor/github.com/urfave/cli/v2/suggestions.go new file mode 100644 index 000000000..87fa905dd --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/suggestions.go @@ -0,0 +1,60 @@ +package cli + +import ( + "fmt" + + "github.com/xrash/smetrics" +) + +func jaroWinkler(a, b string) float64 { + // magic values are from https://github.com/xrash/smetrics/blob/039620a656736e6ad994090895784a7af15e0b80/jaro-winkler.go#L8 + const ( + boostThreshold = 0.7 + prefixSize = 4 + ) + return smetrics.JaroWinkler(a, b, boostThreshold, prefixSize) +} + +func suggestFlag(flags []Flag, provided string, hideHelp bool) string { + distance := 0.0 + suggestion := "" + + for _, flag := range flags { + flagNames := flag.Names() + if !hideHelp { + flagNames = append(flagNames, HelpFlag.Names()...) + } + for _, name := range flagNames { + newDistance := jaroWinkler(name, provided) + if newDistance > distance { + distance = newDistance + suggestion = name + } + } + } + + if len(suggestion) == 1 { + suggestion = "-" + suggestion + } else if len(suggestion) > 1 { + suggestion = "--" + suggestion + } + + return suggestion +} + +// suggestCommand takes a list of commands and a provided string to suggest a +// command name +func suggestCommand(commands []*Command, provided string) (suggestion string) { + distance := 0.0 + for _, command := range commands { + for _, name := range append(command.Names(), helpName, helpAlias) { + newDistance := jaroWinkler(name, provided) + if newDistance > distance { + distance = newDistance + suggestion = name + } + } + } + + return fmt.Sprintf(SuggestDidYouMeanTemplate, suggestion) +} diff --git a/vendor/github.com/urfave/cli/template.go b/vendor/github.com/urfave/cli/v2/template.go similarity index 61% rename from vendor/github.com/urfave/cli/template.go rename to vendor/github.com/urfave/cli/v2/template.go index c631fb97d..f3116fd2c 100644 --- a/vendor/github.com/urfave/cli/template.go +++ b/vendor/github.com/urfave/cli/v2/template.go @@ -4,66 +4,77 @@ package cli // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var AppHelpTemplate = `NAME: - {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} + {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{.Description}}{{end}}{{if len .Authors}} + {{wrap .Description 3}}{{end}}{{if len .Authors}} AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: {{range $index, $author := .Authors}}{{if $index}} {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + +GLOBAL OPTIONS:{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} GLOBAL OPTIONS: {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} + {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} COPYRIGHT: - {{.Copyright}}{{end}} + {{wrap .Copyright 3}}{{end}} ` // CommandHelpTemplate is the text template for the command help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{.Description}}{{end}}{{if .VisibleFlags}} + {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} OPTIONS: {{range .VisibleFlags}}{{.}} - {{end}}{{end}} + {{end}}{{end}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}} + {{.HelpName}} - {{.Usage}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} +DESCRIPTION: + {{wrap .Description 3}}{{end}} +COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} @@ -73,11 +84,9 @@ OPTIONS: {{end}}{{end}} ` -var MarkdownDocTemplate = `% {{ .App.Name }}(8) {{ .App.Description }} +var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} -% {{ .App.Author }} - -# NAME +{{end}}# NAME {{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} @@ -87,16 +96,18 @@ var MarkdownDocTemplate = `% {{ .App.Name }}(8) {{ .App.Description }} {{ if .SynopsisArgs }} ` + "```" + ` {{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` -{{ end }}{{ if .App.UsageText }} +{{ end }}{{ if .App.Description }} # DESCRIPTION -{{ .App.UsageText }} +{{ .App.Description }} {{ end }} **Usage**: -` + "```" + ` +` + "```" + `{{ if .App.UsageText }} +{{ .App.UsageText }} +{{ else }} {{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] -` + "```" + ` +{{ end }}` + "```" + ` {{ if .GlobalArgs }} # GLOBAL OPTIONS {{ range $v := .GlobalArgs }} diff --git a/vendor/github.com/urfave/cli/v2/zz_generated.flags.go b/vendor/github.com/urfave/cli/v2/zz_generated.flags.go new file mode 100644 index 000000000..b89566f90 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/zz_generated.flags.go @@ -0,0 +1,674 @@ +// WARNING: this file is generated. DO NOT EDIT + +package cli + +import "time" + +// Float64SliceFlag is a flag with type *Float64Slice +type Float64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Float64Slice + Destination *Float64Slice + + Aliases []string + EnvVars []string +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Float64SliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64SliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Float64SliceFlag) IsVisible() bool { + return !f.Hidden +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Generic + Destination *Generic + + Aliases []string + EnvVars []string + + TakesFile bool +} + +// String returns a readable representation of this value (for usage defaults) +func (f *GenericFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *GenericFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *GenericFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *GenericFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *GenericFlag) IsVisible() bool { + return !f.Hidden +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Int64Slice + Destination *Int64Slice + + Aliases []string + EnvVars []string +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Int64SliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64SliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Int64SliceFlag) IsVisible() bool { + return !f.Hidden +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *IntSlice + Destination *IntSlice + + Aliases []string + EnvVars []string +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *IntSliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *IntSliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *IntSliceFlag) IsVisible() bool { + return !f.Hidden +} + +// PathFlag is a flag with type Path +type PathFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Path + Destination *Path + + Aliases []string + EnvVars []string + + TakesFile bool +} + +// String returns a readable representation of this value (for usage defaults) +func (f *PathFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *PathFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *PathFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *PathFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *PathFlag) IsVisible() bool { + return !f.Hidden +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *StringSlice + Destination *StringSlice + + Aliases []string + EnvVars []string + + TakesFile bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *StringSliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *StringSliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *StringSliceFlag) IsVisible() bool { + return !f.Hidden +} + +// TimestampFlag is a flag with type *Timestamp +type TimestampFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Timestamp + Destination *Timestamp + + Aliases []string + EnvVars []string + + Layout string + + Timezone *time.Location +} + +// String returns a readable representation of this value (for usage defaults) +func (f *TimestampFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *TimestampFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *TimestampFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *TimestampFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *TimestampFlag) IsVisible() bool { + return !f.Hidden +} + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value bool + Destination *bool + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *BoolFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *BoolFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *BoolFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *BoolFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *BoolFlag) IsVisible() bool { + return !f.Hidden +} + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value float64 + Destination *float64 + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Float64Flag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64Flag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Float64Flag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64Flag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Float64Flag) IsVisible() bool { + return !f.Hidden +} + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int + Destination *int + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *IntFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *IntFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *IntFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *IntFlag) IsVisible() bool { + return !f.Hidden +} + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int64 + Destination *int64 + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Int64Flag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64Flag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Int64Flag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64Flag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Int64Flag) IsVisible() bool { + return !f.Hidden +} + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value string + Destination *string + + Aliases []string + EnvVars []string + + TakesFile bool +} + +// String returns a readable representation of this value (for usage defaults) +func (f *StringFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *StringFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *StringFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *StringFlag) IsVisible() bool { + return !f.Hidden +} + +// DurationFlag is a flag with type time.Duration +type DurationFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value time.Duration + Destination *time.Duration + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *DurationFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *DurationFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *DurationFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *DurationFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *DurationFlag) IsVisible() bool { + return !f.Hidden +} + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint + Destination *uint + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *UintFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *UintFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *UintFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *UintFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *UintFlag) IsVisible() bool { + return !f.Hidden +} + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint64 + Destination *uint64 + + Aliases []string + EnvVars []string +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Uint64Flag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Uint64Flag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Uint64Flag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Uint64Flag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Uint64Flag) IsVisible() bool { + return !f.Hidden +} + +// vim:ro diff --git a/vendor/github.com/xrash/smetrics/.travis.yml b/vendor/github.com/xrash/smetrics/.travis.yml new file mode 100644 index 000000000..d1cd67ff9 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.11 + - 1.12 + - 1.13 + - 1.14.x + - master +script: + - cd tests && make diff --git a/vendor/github.com/xrash/smetrics/LICENSE b/vendor/github.com/xrash/smetrics/LICENSE new file mode 100644 index 000000000..80445682f --- /dev/null +++ b/vendor/github.com/xrash/smetrics/LICENSE @@ -0,0 +1,21 @@ +Copyright (C) 2016 Felipe da Cunha Gonçalves +All Rights Reserved. + +MIT LICENSE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/xrash/smetrics/README.md b/vendor/github.com/xrash/smetrics/README.md new file mode 100644 index 000000000..5e0c1a463 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/README.md @@ -0,0 +1,49 @@ +[![Build Status](https://travis-ci.org/xrash/smetrics.svg?branch=master)](http://travis-ci.org/xrash/smetrics) + +# smetrics + +`smetrics` is "string metrics". + +Package smetrics provides a bunch of algorithms for calculating the distance between strings. + +There are implementations for calculating the popular Levenshtein distance (aka Edit Distance or Wagner-Fischer), as well as the Jaro distance, the Jaro-Winkler distance, and more. + +# How to import + +```go +import "github.com/xrash/smetrics" +``` + +# Documentation + +Go to [https://pkg.go.dev/github.com/xrash/smetrics](https://pkg.go.dev/github.com/xrash/smetrics) for complete documentation. + +# Example + +```go +package main + +import ( + "github.com/xrash/smetrics" +) + +func main() { + smetrics.WagnerFischer("POTATO", "POTATTO", 1, 1, 2) + smetrics.WagnerFischer("MOUSE", "HOUSE", 2, 2, 4) + + smetrics.Ukkonen("POTATO", "POTATTO", 1, 1, 2) + smetrics.Ukkonen("MOUSE", "HOUSE", 2, 2, 4) + + smetrics.Jaro("AL", "AL") + smetrics.Jaro("MARTHA", "MARHTA") + + smetrics.JaroWinkler("AL", "AL", 0.7, 4) + smetrics.JaroWinkler("MARTHA", "MARHTA", 0.7, 4) + + smetrics.Soundex("Euler") + smetrics.Soundex("Ellery") + + smetrics.Hamming("aaa", "aaa") + smetrics.Hamming("aaa", "aab") +} +``` diff --git a/vendor/github.com/xrash/smetrics/doc.go b/vendor/github.com/xrash/smetrics/doc.go new file mode 100644 index 000000000..21bc986c9 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/doc.go @@ -0,0 +1,19 @@ +/* +Package smetrics provides a bunch of algorithms for calculating +the distance between strings. + +There are implementations for calculating the popular Levenshtein +distance (aka Edit Distance or Wagner-Fischer), as well as the Jaro +distance, the Jaro-Winkler distance, and more. + +For the Levenshtein distance, you can use the functions WagnerFischer() +and Ukkonen(). Read the documentation on these functions. + +For the Jaro and Jaro-Winkler algorithms, check the functions +Jaro() and JaroWinkler(). Read the documentation on these functions. + +For the Soundex algorithm, check the function Soundex(). + +For the Hamming distance algorithm, check the function Hamming(). +*/ +package smetrics diff --git a/vendor/github.com/xrash/smetrics/hamming.go b/vendor/github.com/xrash/smetrics/hamming.go new file mode 100644 index 000000000..505d3e5da --- /dev/null +++ b/vendor/github.com/xrash/smetrics/hamming.go @@ -0,0 +1,25 @@ +package smetrics + +import ( + "fmt" +) + +// The Hamming distance is the minimum number of substitutions required to change string A into string B. Both strings must have the same size. If the strings have different sizes, the function returns an error. +func Hamming(a, b string) (int, error) { + al := len(a) + bl := len(b) + + if al != bl { + return -1, fmt.Errorf("strings are not equal (len(a)=%d, len(b)=%d)", al, bl) + } + + var difference = 0 + + for i := range a { + if a[i] != b[i] { + difference = difference + 1 + } + } + + return difference, nil +} diff --git a/vendor/github.com/xrash/smetrics/jaro-winkler.go b/vendor/github.com/xrash/smetrics/jaro-winkler.go new file mode 100644 index 000000000..abdb28883 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/jaro-winkler.go @@ -0,0 +1,28 @@ +package smetrics + +import ( + "math" +) + +// The Jaro-Winkler distance. The result is 1 for equal strings, and 0 for completely different strings. It is commonly used on Record Linkage stuff, thus it tries to be accurate for common typos when writing real names such as person names and street names. +// Jaro-Winkler is a modification of the Jaro algorithm. It works by first running Jaro, then boosting the score of exact matches at the beginning of the strings. Because of that, it introduces two more parameters: the boostThreshold and the prefixSize. These are commonly set to 0.7 and 4, respectively. +func JaroWinkler(a, b string, boostThreshold float64, prefixSize int) float64 { + j := Jaro(a, b) + + if j <= boostThreshold { + return j + } + + prefixSize = int(math.Min(float64(len(a)), math.Min(float64(prefixSize), float64(len(b))))) + + var prefixMatch float64 + for i := 0; i < prefixSize; i++ { + if a[i] == b[i] { + prefixMatch++ + } else { + break + } + } + + return j + 0.1*prefixMatch*(1.0-j) +} diff --git a/vendor/github.com/xrash/smetrics/jaro.go b/vendor/github.com/xrash/smetrics/jaro.go new file mode 100644 index 000000000..75f924e11 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/jaro.go @@ -0,0 +1,86 @@ +package smetrics + +import ( + "math" +) + +// The Jaro distance. The result is 1 for equal strings, and 0 for completely different strings. +func Jaro(a, b string) float64 { + // If both strings are zero-length, they are completely equal, + // therefore return 1. + if len(a) == 0 && len(b) == 0 { + return 1 + } + + // If one string is zero-length, strings are completely different, + // therefore return 0. + if len(a) == 0 || len(b) == 0 { + return 0 + } + + // Define the necessary variables for the algorithm. + la := float64(len(a)) + lb := float64(len(b)) + matchRange := int(math.Max(0, math.Floor(math.Max(la, lb)/2.0)-1)) + matchesA := make([]bool, len(a)) + matchesB := make([]bool, len(b)) + var matches float64 = 0 + + // Step 1: Matches + // Loop through each character of the first string, + // looking for a matching character in the second string. + for i := 0; i < len(a); i++ { + start := int(math.Max(0, float64(i-matchRange))) + end := int(math.Min(lb-1, float64(i+matchRange))) + + for j := start; j <= end; j++ { + if matchesB[j] { + continue + } + + if a[i] == b[j] { + matchesA[i] = true + matchesB[j] = true + matches++ + break + } + } + } + + // If there are no matches, strings are completely different, + // therefore return 0. + if matches == 0 { + return 0 + } + + // Step 2: Transpositions + // Loop through the matches' arrays, looking for + // unaligned matches. Count the number of unaligned matches. + unaligned := 0 + j := 0 + for i := 0; i < len(a); i++ { + if !matchesA[i] { + continue + } + + for !matchesB[j] { + j++ + } + + if a[i] != b[j] { + unaligned++ + } + + j++ + } + + // The number of unaligned matches divided by two, is the number of _transpositions_. + transpositions := math.Floor(float64(unaligned / 2)) + + // Jaro distance is the average between these three numbers: + // 1. matches / length of string A + // 2. matches / length of string B + // 3. (matches - transpositions/matches) + // So, all that divided by three is the final result. + return ((matches / la) + (matches / lb) + ((matches - transpositions) / matches)) / 3.0 +} diff --git a/vendor/github.com/xrash/smetrics/soundex.go b/vendor/github.com/xrash/smetrics/soundex.go new file mode 100644 index 000000000..a2ad034d5 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/soundex.go @@ -0,0 +1,41 @@ +package smetrics + +import ( + "strings" +) + +// The Soundex encoding. It is a phonetic algorithm that considers how the words sound in English. Soundex maps a string to a 4-byte code consisting of the first letter of the original string and three numbers. Strings that sound similar should map to the same code. +func Soundex(s string) string { + m := map[byte]string{ + 'B': "1", 'P': "1", 'F': "1", 'V': "1", + 'C': "2", 'S': "2", 'K': "2", 'G': "2", 'J': "2", 'Q': "2", 'X': "2", 'Z': "2", + 'D': "3", 'T': "3", + 'L': "4", + 'M': "5", 'N': "5", + 'R': "6", + } + + s = strings.ToUpper(s) + + r := string(s[0]) + p := s[0] + for i := 1; i < len(s) && len(r) < 4; i++ { + c := s[i] + + if (c < 'A' || c > 'Z') || (c == p) { + continue + } + + p = c + + if n, ok := m[c]; ok { + r += n + } + } + + for i := len(r); i < 4; i++ { + r += "0" + } + + return r +} diff --git a/vendor/github.com/xrash/smetrics/ukkonen.go b/vendor/github.com/xrash/smetrics/ukkonen.go new file mode 100644 index 000000000..3c5579cd9 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/ukkonen.go @@ -0,0 +1,94 @@ +package smetrics + +import ( + "math" +) + +// The Ukkonen algorithm for calculating the Levenshtein distance. The algorithm is described in http://www.cs.helsinki.fi/u/ukkonen/InfCont85.PDF, or in docs/InfCont85.PDF. It runs on O(t . min(m, n)) where t is the actual distance between strings a and b. It needs O(min(t, m, n)) space. This function might be preferred over WagnerFischer() for *very* similar strings. But test it out yourself. +// The first two parameters are the two strings to be compared. The last three parameters are the insertion cost, the deletion cost and the substitution cost. These are normally defined as 1, 1 and 2 respectively. +func Ukkonen(a, b string, icost, dcost, scost int) int { + var lowerCost int + + if icost < dcost && icost < scost { + lowerCost = icost + } else if dcost < scost { + lowerCost = dcost + } else { + lowerCost = scost + } + + infinite := math.MaxInt32 / 2 + + var r []int + var k, kprime, p, t int + var ins, del, sub int + + if len(a) > len(b) { + t = (len(a) - len(b) + 1) * lowerCost + } else { + t = (len(b) - len(a) + 1) * lowerCost + } + + for { + if (t / lowerCost) < (len(b) - len(a)) { + continue + } + + // This is the right damn thing since the original Ukkonen + // paper minimizes the expression result only, but the uncommented version + // doesn't need to deal with floats so it's faster. + // p = int(math.Floor(0.5*((float64(t)/float64(lowerCost)) - float64(len(b) - len(a))))) + p = ((t / lowerCost) - (len(b) - len(a))) / 2 + + k = -p + kprime = k + + rowlength := (len(b) - len(a)) + (2 * p) + + r = make([]int, rowlength+2) + + for i := 0; i < rowlength+2; i++ { + r[i] = infinite + } + + for i := 0; i <= len(a); i++ { + for j := 0; j <= rowlength; j++ { + if i == j+k && i == 0 { + r[j] = 0 + } else { + if j-1 < 0 { + ins = infinite + } else { + ins = r[j-1] + icost + } + + del = r[j+1] + dcost + sub = r[j] + scost + + if i-1 < 0 || i-1 >= len(a) || j+k-1 >= len(b) || j+k-1 < 0 { + sub = infinite + } else if a[i-1] == b[j+k-1] { + sub = r[j] + } + + if ins < del && ins < sub { + r[j] = ins + } else if del < sub { + r[j] = del + } else { + r[j] = sub + } + } + } + k++ + } + + if r[(len(b)-len(a))+(2*p)+kprime] <= t { + break + } else { + t *= 2 + } + } + + return r[(len(b)-len(a))+(2*p)+kprime] +} diff --git a/vendor/github.com/xrash/smetrics/wagner-fischer.go b/vendor/github.com/xrash/smetrics/wagner-fischer.go new file mode 100644 index 000000000..9883aea04 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/wagner-fischer.go @@ -0,0 +1,48 @@ +package smetrics + +// The Wagner-Fischer algorithm for calculating the Levenshtein distance. +// The first two parameters are the two strings to be compared. The last three parameters are the insertion cost, the deletion cost and the substitution cost. These are normally defined as 1, 1 and 2 respectively. +func WagnerFischer(a, b string, icost, dcost, scost int) int { + + // Allocate both rows. + row1 := make([]int, len(b)+1) + row2 := make([]int, len(b)+1) + var tmp []int + + // Initialize the first row. + for i := 1; i <= len(b); i++ { + row1[i] = i * icost + } + + // For each row... + for i := 1; i <= len(a); i++ { + row2[0] = i * dcost + + // For each column... + for j := 1; j <= len(b); j++ { + if a[i-1] == b[j-1] { + row2[j] = row1[j-1] + } else { + ins := row2[j-1] + icost + del := row1[j] + dcost + sub := row1[j-1] + scost + + if ins < del && ins < sub { + row2[j] = ins + } else if del < sub { + row2[j] = del + } else { + row2[j] = sub + } + } + } + + // Swap the rows at the end of each row. + tmp = row1 + row1 = row2 + row2 = tmp + } + + // Because we swapped the rows, the final result is in row1 instead of row2. + return row1[len(row1)-1] +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9496be42c..39bf37fa5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -53,8 +53,8 @@ github.com/briandowns/spinner ## explicit; go 1.12 github.com/cheggaaa/pb/v3 github.com/cheggaaa/pb/v3/termutil -# github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d -## explicit; go 1.12 +# github.com/cpuguy83/go-md2man/v2 v2.0.2 +## explicit; go 1.11 github.com/cpuguy83/go-md2man/v2/md2man # github.com/davecgh/go-spew v1.1.1 ## explicit @@ -140,8 +140,6 @@ github.com/golang-jwt/jwt/v4 # github.com/golang/mock v1.6.0 ## explicit; go 1.11 github.com/golang/mock/gomock -# github.com/google/go-github/v45 v45.2.0 -## explicit; go 1.17 # github.com/google/go-github/v47 v47.0.0 ## explicit; go 1.17 github.com/google/go-github/v47/github @@ -196,7 +194,7 @@ github.com/pmezard/go-difflib/difflib # github.com/rivo/uniseg v0.2.0 ## explicit; go 1.12 github.com/rivo/uniseg -# github.com/russross/blackfriday/v2 v2.0.1 +# github.com/russross/blackfriday/v2 v2.1.0 ## explicit github.com/russross/blackfriday/v2 # github.com/sergi/go-diff v1.1.0 @@ -204,7 +202,6 @@ github.com/russross/blackfriday/v2 github.com/sergi/go-diff/diffmatchpatch # github.com/shurcooL/sanitized_anchor_name v1.0.0 ## explicit -github.com/shurcooL/sanitized_anchor_name # github.com/stretchr/testify v1.8.0 ## explicit; go 1.13 github.com/stretchr/testify/assert @@ -214,10 +211,15 @@ github.com/stretchr/testify/require github.com/stvp/rollbar # github.com/urfave/cli v1.22.9 ## explicit; go 1.11 -github.com/urfave/cli +# github.com/urfave/cli/v2 v2.11.2 +## explicit; go 1.18 +github.com/urfave/cli/v2 # github.com/xanzy/ssh-agent v0.3.0 ## explicit github.com/xanzy/ssh-agent +# github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 +## explicit +github.com/xrash/smetrics # golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d ## explicit; go 1.17 golang.org/x/crypto/blowfish