diff --git a/cli/build/build.go b/cli/build/build.go index 287f0ea4f..35ab51501 100644 --- a/cli/build/build.go +++ b/cli/build/build.go @@ -1,12 +1,17 @@ package build -import "github.com/urfave/cli" +import ( + "github.com/urfave/cli/v2" + + "github.com/woodpecker-ci/woodpecker/cli/common" +) // Command exports the build command set. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "build", Usage: "manage builds", - Subcommands: []cli.Command{ + Flags: common.GlobalFlags, + Subcommands: []*cli.Command{ buildListCmd, buildLastCmd, buildLogsCmd, diff --git a/cli/build/build_approve.go b/cli/build/build_approve.go index 2f10702e0..5f5b7da24 100644 --- a/cli/build/build_approve.go +++ b/cli/build/build_approve.go @@ -4,16 +4,18 @@ import ( "fmt" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildApproveCmd = cli.Command{ +var buildApproveCmd = &cli.Command{ Name: "approve", Usage: "approve a build", ArgsUsage: " ", Action: buildApprove, + Flags: common.GlobalFlags, } func buildApprove(c *cli.Context) (err error) { diff --git a/cli/build/build_decline.go b/cli/build/build_decline.go index 525a398a0..ea8a3df13 100644 --- a/cli/build/build_decline.go +++ b/cli/build/build_decline.go @@ -4,16 +4,18 @@ import ( "fmt" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildDeclineCmd = cli.Command{ +var buildDeclineCmd = &cli.Command{ Name: "decline", Usage: "decline a build", ArgsUsage: " ", Action: buildDecline, + Flags: common.GlobalFlags, } func buildDecline(c *cli.Context) (err error) { diff --git a/cli/build/build_info.go b/cli/build/build_info.go index 150eed371..a5e8e3a39 100644 --- a/cli/build/build_info.go +++ b/cli/build/build_info.go @@ -5,23 +5,20 @@ import ( "strconv" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildInfoCmd = cli.Command{ +var buildInfoCmd = &cli.Command{ Name: "info", Usage: "show build details", ArgsUsage: " [build]", Action: buildInfo, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplBuildInfo, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplBuildInfo), + ), } func buildInfo(c *cli.Context) error { diff --git a/cli/build/build_kill.go b/cli/build/build_kill.go index 01b66c1a4..742061896 100644 --- a/cli/build/build_kill.go +++ b/cli/build/build_kill.go @@ -4,17 +4,19 @@ import ( "fmt" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildKillCmd = cli.Command{ +var buildKillCmd = &cli.Command{ Name: "kill", Usage: "force kill a build", ArgsUsage: " ", Action: buildKill, Hidden: true, + Flags: common.GlobalFlags, } func buildKill(c *cli.Context) (err error) { diff --git a/cli/build/build_last.go b/cli/build/build_last.go index c7918bef5..3638e15ec 100644 --- a/cli/build/build_last.go +++ b/cli/build/build_last.go @@ -4,28 +4,25 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildLastCmd = cli.Command{ +var buildLastCmd = &cli.Command{ Name: "last", Usage: "show latest build details", ArgsUsage: "", Action: buildLast, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplBuildInfo, - }, - cli.StringFlag{ + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplBuildInfo), + &cli.StringFlag{ Name: "branch", Usage: "branch name", Value: "master", }, - }, + ), } func buildLast(c *cli.Context) error { diff --git a/cli/build/build_list.go b/cli/build/build_list.go index eeb9b6dab..c8fe6af77 100644 --- a/cli/build/build_list.go +++ b/cli/build/build_list.go @@ -4,40 +4,37 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildListCmd = cli.Command{ +var buildListCmd = &cli.Command{ Name: "ls", Usage: "show build history", ArgsUsage: "", Action: buildList, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplBuildList, - }, - cli.StringFlag{ + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplBuildList), + &cli.StringFlag{ Name: "branch", Usage: "branch filter", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "event", Usage: "event filter", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "status", Usage: "status filter", }, - cli.IntFlag{ + &cli.IntFlag{ Name: "limit", Usage: "limit the list size", Value: 25, }, - }, + ), } func buildList(c *cli.Context) error { diff --git a/cli/build/build_logs.go b/cli/build/build_logs.go index 232779a02..444ed2697 100644 --- a/cli/build/build_logs.go +++ b/cli/build/build_logs.go @@ -3,14 +3,17 @@ package build import ( "fmt" - "github.com/urfave/cli" + "github.com/woodpecker-ci/woodpecker/cli/common" + + "github.com/urfave/cli/v2" ) -var buildLogsCmd = cli.Command{ +var buildLogsCmd = &cli.Command{ Name: "logs", Usage: "show build logs", ArgsUsage: " [build] [job]", Action: buildLogs, + Flags: common.GlobalFlags, } func buildLogs(c *cli.Context) error { diff --git a/cli/build/build_ps.go b/cli/build/build_ps.go index 533c0490f..5c9b9aecd 100644 --- a/cli/build/build_ps.go +++ b/cli/build/build_ps.go @@ -5,23 +5,20 @@ import ( "strconv" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildPsCmd = cli.Command{ +var buildPsCmd = &cli.Command{ Name: "ps", Usage: "show build steps", ArgsUsage: " [build]", Action: buildPs, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplBuildPs, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplBuildPs), + ), } func buildPs(c *cli.Context) error { diff --git a/cli/build/build_queue.go b/cli/build/build_queue.go index 663467a71..9b212f13f 100644 --- a/cli/build/build_queue.go +++ b/cli/build/build_queue.go @@ -5,23 +5,20 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildQueueCmd = cli.Command{ +var buildQueueCmd = &cli.Command{ Name: "queue", Usage: "show build queue", ArgsUsage: " ", Action: buildQueue, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplBuildQueue, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplBuildQueue), + ), } func buildQueue(c *cli.Context) error { diff --git a/cli/build/build_start.go b/cli/build/build_start.go index c90440a7d..1cc3578aa 100644 --- a/cli/build/build_start.go +++ b/cli/build/build_start.go @@ -5,22 +5,24 @@ import ( "fmt" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildStartCmd = cli.Command{ +var buildStartCmd = &cli.Command{ Name: "start", Usage: "start a build", ArgsUsage: " [build]", Action: buildStart, - Flags: []cli.Flag{ - cli.StringSliceFlag{ - Name: "param, p", - Usage: "custom parameters to be injected into the job environment. Format: KEY=value", + Flags: append(common.GlobalFlags, + &cli.StringSliceFlag{ + Name: "param", + Aliases: []string{"p"}, + Usage: "custom parameters to be injected into the job environment. Format: KEY=value", }, - }, + ), } func buildStart(c *cli.Context) (err error) { diff --git a/cli/build/build_stop.go b/cli/build/build_stop.go index bdd25762c..e2134875b 100644 --- a/cli/build/build_stop.go +++ b/cli/build/build_stop.go @@ -4,15 +4,17 @@ import ( "fmt" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var buildStopCmd = cli.Command{ +var buildStopCmd = &cli.Command{ Name: "stop", Usage: "stop a build", ArgsUsage: " [build] [job]", + Flags: common.GlobalFlags, Action: buildStop, } diff --git a/cli/common/flags.go b/cli/common/flags.go new file mode 100644 index 000000000..9fbf469da --- /dev/null +++ b/cli/common/flags.go @@ -0,0 +1,61 @@ +// Copyright 2021 Woodpecker Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import "github.com/urfave/cli/v2" + +var GlobalFlags = []cli.Flag{ + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_TOKEN"}, + Name: "token", + Aliases: []string{"t"}, + Usage: "server auth token", + }, + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SERVER"}, + Name: "server", + Aliases: []string{"s"}, + Usage: "server address", + }, + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_SKIP_VERIFY"}, + Name: "skip-verify", + Usage: "skip ssl verification", + Hidden: true, + }, + &cli.StringFlag{ + EnvVars: []string{"SOCKS_PROXY"}, + Name: "socks-proxy", + Usage: "socks proxy address", + Hidden: true, + }, + &cli.BoolFlag{ + EnvVars: []string{"SOCKS_PROXY_OFF"}, + Name: "socks-proxy-off", + Usage: "socks proxy ignored", + Hidden: true, + }, +} + +// FormatFlag return format flag with value set based on template +// if hidden value is set, flag will be hidden +func FormatFlag(tmpl string, hidden ...bool) *cli.StringFlag { + return &cli.StringFlag{ + Name: "format", + Usage: "format output", + Value: tmpl, + Hidden: len(hidden) != 0, + } +} diff --git a/cli/deploy/deploy.go b/cli/deploy/deploy.go index 757a32505..b48c156a2 100644 --- a/cli/deploy/deploy.go +++ b/cli/deploy/deploy.go @@ -6,44 +6,42 @@ import ( "os" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) // Command exports the deploy command. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "deploy", Usage: "deploy code", ArgsUsage: " ", Action: deploy, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplDeployInfo, - }, - cli.StringFlag{ + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplDeployInfo), + &cli.StringFlag{ Name: "branch", Usage: "branch filter", Value: "master", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "event", Usage: "event filter", Value: woodpecker.EventPush, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "status", Usage: "status filter", Value: woodpecker.StatusSuccess, }, - cli.StringSliceFlag{ - Name: "param, p", - Usage: "custom parameters to be injected into the job environment. Format: KEY=value", + &cli.StringSliceFlag{ + Name: "param", + Aliases: []string{"p"}, + Usage: "custom parameters to be injected into the job environment. Format: KEY=value", }, - }, + ), } func deploy(c *cli.Context) error { diff --git a/cli/exec/exec.go b/cli/exec/exec.go index 105a87de2..3fcff7fa6 100644 --- a/cli/exec/exec.go +++ b/cli/exec/exec.go @@ -11,9 +11,9 @@ import ( "strings" "github.com/drone/envsubst" - "github.com/rs/zerolog/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/pipeline" "github.com/woodpecker-ci/woodpecker/pipeline/backend" "github.com/woodpecker-ci/woodpecker/pipeline/backend/docker" @@ -27,16 +27,12 @@ import ( ) // Command exports the exec command. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "exec", Usage: "execute a local build", ArgsUsage: "[path/to/.woodpecker.yml]", - Action: func(c *cli.Context) { - if err := exec(c); err != nil { - log.Fatal().Err(err).Msg("") - } - }, - Flags: flags, + Action: exec, + Flags: append(common.GlobalFlags, flags...), } func exec(c *cli.Context) error { diff --git a/cli/exec/flags.go b/cli/exec/flags.go index b8e89fbd9..e670b5b2f 100644 --- a/cli/exec/flags.go +++ b/cli/exec/flags.go @@ -17,46 +17,47 @@ package exec import ( "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var flags = []cli.Flag{ - cli.BoolTFlag{ - EnvVar: "WOODPECKER_LOCAL", - Name: "local", - Usage: "build from local directory", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_LOCAL"}, + Name: "local", + Usage: "build from local directory", + Value: true, }, - cli.DurationFlag{ - EnvVar: "WOODPECKER_TIMEOUT", - Name: "timeout", - Usage: "build timeout", - Value: time.Hour, + &cli.DurationFlag{ + EnvVars: []string{"WOODPECKER_TIMEOUT"}, + Name: "timeout", + Usage: "build timeout", + Value: time.Hour, }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_VOLUMES", - Name: "volumes", - Usage: "build volumes", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_VOLUMES"}, + Name: "volumes", + Usage: "build volumes", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_NETWORKS", - Name: "network", - Usage: "external networks", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_NETWORKS"}, + Name: "network", + Usage: "external networks", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_DOCKER_PREFIX", - Name: "prefix", - Value: "woodpecker", - Usage: "prefix containers created by woodpecker", - Hidden: true, + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_DOCKER_PREFIX"}, + Name: "prefix", + Value: "woodpecker", + Usage: "prefix containers created by woodpecker", + Hidden: true, }, - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: "privileged", Usage: "privileged plugins", - Value: &cli.StringSlice{ + Value: cli.NewStringSlice( "plugins/docker", "plugins/gcr", "plugins/ecr", - }, + ), }, // @@ -67,199 +68,199 @@ var flags = []cli.Flag{ // // workspace default // - cli.StringFlag{ - EnvVar: "WOODPECKER_WORKSPACE_BASE", - Name: "workspace-base", - Value: "/woodpecker", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_WORKSPACE_BASE"}, + Name: "workspace-base", + Value: "/woodpecker", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_WORKSPACE_PATH", - Name: "workspace-path", - Value: "src", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_WORKSPACE_PATH"}, + Name: "workspace-path", + Value: "src", }, // // netrc parameters // - cli.StringFlag{ - EnvVar: "WOODPECKER_NETRC_USERNAME", - Name: "netrc-username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_NETRC_USERNAME"}, + Name: "netrc-username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_NETRC_PASSWORD", - Name: "netrc-password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_NETRC_PASSWORD"}, + Name: "netrc-password", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_NETRC_MACHINE", - Name: "netrc-machine", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_NETRC_MACHINE"}, + Name: "netrc-machine", }, // // metadata parameters // - cli.StringFlag{ - EnvVar: "WOODPECKER_SYSTEM_ARCH", - Name: "system-arch", - Value: "linux/amd64", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SYSTEM_ARCH"}, + Name: "system-arch", + Value: "linux/amd64", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_SYSTEM_NAME", - Name: "system-name", - Value: "pipec", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SYSTEM_NAME"}, + Name: "system-name", + Value: "pipec", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_SYSTEM_LINK", - Name: "system-link", - Value: "https://github.com/cncd/pipec", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SYSTEM_LINK"}, + Name: "system-link", + Value: "https://github.com/cncd/pipec", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_REPO_NAME", - Name: "repo-name", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_REPO_NAME"}, + Name: "repo-name", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_REPO_LINK", - Name: "repo-link", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_REPO_LINK"}, + Name: "repo-link", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_REPO_REMOTE", - Name: "repo-remote-url", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_REPO_REMOTE"}, + Name: "repo-remote-url", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_REPO_PRIVATE", - Name: "repo-private", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_REPO_PRIVATE"}, + Name: "repo-private", }, - cli.IntFlag{ - EnvVar: "WOODPECKER_BUILD_NUMBER", - Name: "build-number", + &cli.IntFlag{ + EnvVars: []string{"WOODPECKER_BUILD_NUMBER"}, + Name: "build-number", }, - cli.IntFlag{ - EnvVar: "WOODPECKER_PARENT_BUILD_NUMBER", - Name: "parent-build-number", + &cli.IntFlag{ + EnvVars: []string{"WOODPECKER_PARENT_BUILD_NUMBER"}, + Name: "parent-build-number", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_BUILD_CREATED", - Name: "build-created", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_BUILD_CREATED"}, + Name: "build-created", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_BUILD_STARTED", - Name: "build-started", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_BUILD_STARTED"}, + Name: "build-started", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_BUILD_FINISHED", - Name: "build-finished", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_BUILD_FINISHED"}, + Name: "build-finished", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_BUILD_STATUS", - Name: "build-status", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_BUILD_STATUS"}, + Name: "build-status", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_BUILD_EVENT", - Name: "build-event", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_BUILD_EVENT"}, + Name: "build-event", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_BUILD_LINK", - Name: "build-link", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_BUILD_LINK"}, + Name: "build-link", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_BUILD_TARGET", - Name: "build-target", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_BUILD_TARGET"}, + Name: "build-target", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_SHA", - Name: "commit-sha", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_SHA"}, + Name: "commit-sha", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_REF", - Name: "commit-ref", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_REF"}, + Name: "commit-ref", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_REFSPEC", - Name: "commit-refspec", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_REFSPEC"}, + Name: "commit-refspec", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_BRANCH", - Name: "commit-branch", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_BRANCH"}, + Name: "commit-branch", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_MESSAGE", - Name: "commit-message", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_MESSAGE"}, + Name: "commit-message", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_AUTHOR_NAME", - Name: "commit-author-name", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_AUTHOR_NAME"}, + Name: "commit-author-name", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_AUTHOR_AVATAR", - Name: "commit-author-avatar", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_AUTHOR_AVATAR"}, + Name: "commit-author-avatar", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_COMMIT_AUTHOR_EMAIL", - Name: "commit-author-email", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_COMMIT_AUTHOR_EMAIL"}, + Name: "commit-author-email", }, - cli.IntFlag{ - EnvVar: "WOODPECKER_PREV_BUILD_NUMBER", - Name: "prev-build-number", + &cli.IntFlag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_NUMBER"}, + Name: "prev-build-number", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_PREV_BUILD_CREATED", - Name: "prev-build-created", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_CREATED"}, + Name: "prev-build-created", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_PREV_BUILD_STARTED", - Name: "prev-build-started", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_STARTED"}, + Name: "prev-build-started", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_PREV_BUILD_FINISHED", - Name: "prev-build-finished", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_FINISHED"}, + Name: "prev-build-finished", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_BUILD_STATUS", - Name: "prev-build-status", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_STATUS"}, + Name: "prev-build-status", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_BUILD_EVENT", - Name: "prev-build-event", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_EVENT"}, + Name: "prev-build-event", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_BUILD_LINK", - Name: "prev-build-link", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_BUILD_LINK"}, + Name: "prev-build-link", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_SHA", - Name: "prev-commit-sha", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_SHA"}, + Name: "prev-commit-sha", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_REF", - Name: "prev-commit-ref", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_REF"}, + Name: "prev-commit-ref", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_REFSPEC", - Name: "prev-commit-refspec", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_REFSPEC"}, + Name: "prev-commit-refspec", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_BRANCH", - Name: "prev-commit-branch", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_BRANCH"}, + Name: "prev-commit-branch", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_MESSAGE", - Name: "prev-commit-message", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_MESSAGE"}, + Name: "prev-commit-message", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_AUTHOR_NAME", - Name: "prev-commit-author-name", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_AUTHOR_NAME"}, + Name: "prev-commit-author-name", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_AUTHOR_AVATAR", - Name: "prev-commit-author-avatar", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_AUTHOR_AVATAR"}, + Name: "prev-commit-author-avatar", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PREV_COMMIT_AUTHOR_EMAIL", - Name: "prev-commit-author-email", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PREV_COMMIT_AUTHOR_EMAIL"}, + Name: "prev-commit-author-email", }, - cli.IntFlag{ - EnvVar: "WOODPECKER_JOB_NUMBER", - Name: "job-number", + &cli.IntFlag{ + EnvVars: []string{"WOODPECKER_JOB_NUMBER"}, + Name: "job-number", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_ENV", - Name: "env", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_ENV"}, + Name: "env", }, } diff --git a/cli/info/info.go b/cli/info/info.go index 1ded8d492..4952ad878 100644 --- a/cli/info/info.go +++ b/cli/info/info.go @@ -4,25 +4,21 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) // Command exports the info command. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "info", Usage: "show information about the current user", ArgsUsage: " ", Action: info, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplInfo, - Hidden: true, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplInfo, true), + ), } func info(c *cli.Context) error { diff --git a/cli/internal/util.go b/cli/internal/util.go index fe16902f0..c04bbec41 100644 --- a/cli/internal/util.go +++ b/cli/internal/util.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/jackspirou/syscerts" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "golang.org/x/net/proxy" "golang.org/x/oauth2" @@ -17,11 +17,11 @@ import ( // NewClient returns a new client from the CLI context. func NewClient(c *cli.Context) (woodpecker.Client, error) { var ( - skip = c.GlobalBool("skip-verify") - socks = c.GlobalString("socks-proxy") - socksoff = c.GlobalBool("socks-proxy-off") - token = c.GlobalString("token") - server = c.GlobalString("server") + skip = c.Bool("skip-verify") + socks = c.String("socks-proxy") + socksoff = c.Bool("socks-proxy-off") + token = c.String("token") + server = c.String("server") ) server = strings.TrimRight(server, "/") diff --git a/cli/lint/lint.go b/cli/lint/lint.go index ff4b418f2..c61805e46 100644 --- a/cli/lint/lint.go +++ b/cli/lint/lint.go @@ -6,18 +6,19 @@ import ( "path/filepath" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/pipeline/schema" ) // Command exports the info command. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "lint", Usage: "lint a pipeline configuration file", ArgsUsage: "[path/to/.woodpecker.yml]", Action: lint, - Flags: []cli.Flag{}, + Flags: common.GlobalFlags, } func lint(c *cli.Context) error { diff --git a/cli/log/log.go b/cli/log/log.go index 37a2c6190..5e9e58164 100644 --- a/cli/log/log.go +++ b/cli/log/log.go @@ -1,12 +1,17 @@ package log -import "github.com/urfave/cli" +import ( + "github.com/urfave/cli/v2" + + "github.com/woodpecker-ci/woodpecker/cli/common" +) // Command exports the build command set. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "log", Usage: "manage logs", - Subcommands: []cli.Command{ + Flags: common.GlobalFlags, + Subcommands: []*cli.Command{ logPurgeCmd, }, } diff --git a/cli/log/log_purge.go b/cli/log/log_purge.go index ab9c2594f..655ab44bf 100644 --- a/cli/log/log_purge.go +++ b/cli/log/log_purge.go @@ -4,16 +4,18 @@ import ( "fmt" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var logPurgeCmd = cli.Command{ +var logPurgeCmd = &cli.Command{ Name: "purge", Usage: "purge a log", ArgsUsage: " ", Action: logPurge, + Flags: common.GlobalFlags, } func logPurge(c *cli.Context) (err error) { diff --git a/cli/loglevel/loglevel.go b/cli/loglevel/loglevel.go index 1aee4262e..9e0330369 100644 --- a/cli/loglevel/loglevel.go +++ b/cli/loglevel/loglevel.go @@ -3,18 +3,20 @@ package loglevel import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) // Command exports the log-level command used to change the servers log-level. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "log-level", ArgsUsage: "[level]", Usage: "get the logging level of the server, or set it with [level]", Action: logLevel, + Flags: common.GlobalFlags, } func logLevel(c *cli.Context) error { diff --git a/cli/registry/registry.go b/cli/registry/registry.go index 60855a3ba..d7e636604 100644 --- a/cli/registry/registry.go +++ b/cli/registry/registry.go @@ -1,12 +1,17 @@ package registry -import "github.com/urfave/cli" +import ( + "github.com/urfave/cli/v2" + + "github.com/woodpecker-ci/woodpecker/cli/common" +) // Command exports the registry command set. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "registry", Usage: "manage registries", - Subcommands: []cli.Command{ + Flags: common.GlobalFlags, + Subcommands: []*cli.Command{ registryCreateCmd, registryDeleteCmd, registryUpdateCmd, diff --git a/cli/registry/registry_add.go b/cli/registry/registry_add.go index 4e20106b2..aabea3824 100644 --- a/cli/registry/registry_add.go +++ b/cli/registry/registry_add.go @@ -4,36 +4,37 @@ import ( "io/ioutil" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) -var registryCreateCmd = cli.Command{ +var registryCreateCmd = &cli.Command{ Name: "add", Usage: "adds a registry", ArgsUsage: "[repo/name]", Action: registryCreate, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "hostname", Usage: "registry hostname", Value: "docker.io", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "username", Usage: "registry username", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "password", Usage: "registry password", }, - }, + ), } func registryCreate(c *cli.Context) error { diff --git a/cli/registry/registry_info.go b/cli/registry/registry_info.go index e07a4e923..52ac35b54 100644 --- a/cli/registry/registry_info.go +++ b/cli/registry/registry_info.go @@ -4,33 +4,29 @@ import ( "html/template" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var registryInfoCmd = cli.Command{ +var registryInfoCmd = &cli.Command{ Name: "info", Usage: "display registry info", ArgsUsage: "[repo/name]", Action: registryInfo, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "hostname", Usage: "registry hostname", Value: "docker.io", }, - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplRegistryList, - Hidden: true, - }, - }, + common.FormatFlag(tmplRegistryList, true), + ), } func registryInfo(c *cli.Context) error { diff --git a/cli/registry/registry_list.go b/cli/registry/registry_list.go index f5cc79016..6b216f8c2 100644 --- a/cli/registry/registry_list.go +++ b/cli/registry/registry_list.go @@ -4,28 +4,24 @@ import ( "html/template" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var registryListCmd = cli.Command{ +var registryListCmd = &cli.Command{ Name: "ls", Usage: "list registries", ArgsUsage: "[repo/name]", Action: registryList, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplRegistryList, - Hidden: true, - }, - }, + common.FormatFlag(tmplRegistryList, true), + ), } func registryList(c *cli.Context) error { diff --git a/cli/registry/registry_rm.go b/cli/registry/registry_rm.go index 7e9f98fea..b8ab182ce 100644 --- a/cli/registry/registry_rm.go +++ b/cli/registry/registry_rm.go @@ -1,27 +1,28 @@ package registry import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var registryDeleteCmd = cli.Command{ +var registryDeleteCmd = &cli.Command{ Name: "rm", Usage: "remove a registry", ArgsUsage: "[repo/name]", Action: registryDelete, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "hostname", Usage: "registry hostname", Value: "docker.io", }, - }, + ), } func registryDelete(c *cli.Context) error { diff --git a/cli/registry/registry_set.go b/cli/registry/registry_set.go index 962bb965a..826dfec86 100644 --- a/cli/registry/registry_set.go +++ b/cli/registry/registry_set.go @@ -4,36 +4,37 @@ import ( "io/ioutil" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) -var registryUpdateCmd = cli.Command{ +var registryUpdateCmd = &cli.Command{ Name: "update", Usage: "update a registry", ArgsUsage: "[repo/name]", Action: registryUpdate, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "hostname", Usage: "registry hostname", Value: "docker.io", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "username", Usage: "registry username", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "password", Usage: "registry password", }, - }, + ), } func registryUpdate(c *cli.Context) error { diff --git a/cli/repo/repo.go b/cli/repo/repo.go index 123115bdf..c170ce663 100644 --- a/cli/repo/repo.go +++ b/cli/repo/repo.go @@ -1,12 +1,17 @@ package repo -import "github.com/urfave/cli" +import ( + "github.com/urfave/cli/v2" + + "github.com/woodpecker-ci/woodpecker/cli/common" +) // Command exports the repository command. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "repo", Usage: "manage repositories", - Subcommands: []cli.Command{ + Flags: common.GlobalFlags, + Subcommands: []*cli.Command{ repoListCmd, repoInfoCmd, repoAddCmd, diff --git a/cli/repo/repo_add.go b/cli/repo/repo_add.go index a2e0fcfe4..3423ab2b0 100644 --- a/cli/repo/repo_add.go +++ b/cli/repo/repo_add.go @@ -3,16 +3,18 @@ package repo import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoAddCmd = cli.Command{ +var repoAddCmd = &cli.Command{ Name: "add", Usage: "add a repository", ArgsUsage: "", Action: repoAdd, + Flags: common.GlobalFlags, } func repoAdd(c *cli.Context) error { diff --git a/cli/repo/repo_chown.go b/cli/repo/repo_chown.go index 0845f1d57..cfbf17c01 100644 --- a/cli/repo/repo_chown.go +++ b/cli/repo/repo_chown.go @@ -3,16 +3,18 @@ package repo import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoChownCmd = cli.Command{ +var repoChownCmd = &cli.Command{ Name: "chown", Usage: "assume ownership of a repository", ArgsUsage: "", Action: repoChown, + Flags: common.GlobalFlags, } func repoChown(c *cli.Context) error { diff --git a/cli/repo/repo_info.go b/cli/repo/repo_info.go index 4dc7632e6..ee4d66179 100644 --- a/cli/repo/repo_info.go +++ b/cli/repo/repo_info.go @@ -4,23 +4,20 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoInfoCmd = cli.Command{ +var repoInfoCmd = &cli.Command{ Name: "info", Usage: "show repository details", ArgsUsage: "", Action: repoInfo, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplRepoInfo, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplRepoInfo), + ), } func repoInfo(c *cli.Context) error { diff --git a/cli/repo/repo_list.go b/cli/repo/repo_list.go index 6d2f7b207..7335e1ed4 100644 --- a/cli/repo/repo_list.go +++ b/cli/repo/repo_list.go @@ -4,27 +4,24 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoListCmd = cli.Command{ +var repoListCmd = &cli.Command{ Name: "ls", Usage: "list all repos", ArgsUsage: " ", Action: repoList, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplRepoList, - }, - cli.StringFlag{ + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplRepoList), + &cli.StringFlag{ Name: "org", Usage: "filter by organization", }, - }, + ), } func repoList(c *cli.Context) error { diff --git a/cli/repo/repo_repair.go b/cli/repo/repo_repair.go index 25bc16961..647503667 100644 --- a/cli/repo/repo_repair.go +++ b/cli/repo/repo_repair.go @@ -1,16 +1,18 @@ package repo import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoRepairCmd = cli.Command{ +var repoRepairCmd = &cli.Command{ Name: "repair", Usage: "repair repository webhooks", ArgsUsage: "", Action: repoRepair, + Flags: common.GlobalFlags, } func repoRepair(c *cli.Context) error { diff --git a/cli/repo/repo_rm.go b/cli/repo/repo_rm.go index e434e21e4..07b17525d 100644 --- a/cli/repo/repo_rm.go +++ b/cli/repo/repo_rm.go @@ -3,16 +3,18 @@ package repo import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoRemoveCmd = cli.Command{ +var repoRemoveCmd = &cli.Command{ Name: "rm", Usage: "remove a repository", ArgsUsage: "", Action: repoRemove, + Flags: common.GlobalFlags, } func repoRemove(c *cli.Context) error { diff --git a/cli/repo/repo_sync.go b/cli/repo/repo_sync.go index f152c2b71..bbf373b56 100644 --- a/cli/repo/repo_sync.go +++ b/cli/repo/repo_sync.go @@ -4,23 +4,20 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var repoSyncCmd = cli.Command{ +var repoSyncCmd = &cli.Command{ Name: "sync", Usage: "synchronize the repository list", ArgsUsage: " ", Action: repoSync, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplRepoList, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplRepoList), + ), } func repoSync(c *cli.Context) error { diff --git a/cli/repo/repo_update.go b/cli/repo/repo_update.go index 852575cef..d771826d7 100644 --- a/cli/repo/repo_update.go +++ b/cli/repo/repo_update.go @@ -4,47 +4,48 @@ import ( "fmt" "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) -var repoUpdateCmd = cli.Command{ +var repoUpdateCmd = &cli.Command{ Name: "update", Usage: "update a repository", ArgsUsage: "", Action: repoUpdate, - Flags: []cli.Flag{ - cli.BoolFlag{ + Flags: append(common.GlobalFlags, + &cli.BoolFlag{ Name: "trusted", Usage: "repository is trusted", }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "gated", Usage: "repository is gated", }, - cli.DurationFlag{ + &cli.DurationFlag{ Name: "timeout", Usage: "repository timeout", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "visibility", Usage: "repository visibility", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "config", Usage: "repository configuration path (e.g. .woodpecker.yml)", }, - cli.IntFlag{ + &cli.IntFlag{ Name: "build-counter", Usage: "repository starting build number", }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "unsafe", Usage: "validate updating the build-counter is unsafe", }, - }, + ), } func repoUpdate(c *cli.Context) error { diff --git a/cli/secret/secret.go b/cli/secret/secret.go index fc1ee2353..3a8801f59 100644 --- a/cli/secret/secret.go +++ b/cli/secret/secret.go @@ -1,12 +1,17 @@ package secret -import "github.com/urfave/cli" +import ( + "github.com/urfave/cli/v2" + + "github.com/woodpecker-ci/woodpecker/cli/common" +) // Command exports the secret command. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "secret", Usage: "manage secrets", - Subcommands: []cli.Command{ + Flags: common.GlobalFlags, + Subcommands: []*cli.Command{ secretCreateCmd, secretDeleteCmd, secretUpdateCmd, diff --git a/cli/secret/secret_add.go b/cli/secret/secret_add.go index 73945a7d0..bed42d63e 100644 --- a/cli/secret/secret_add.go +++ b/cli/secret/secret_add.go @@ -4,39 +4,40 @@ import ( "io/ioutil" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) -var secretCreateCmd = cli.Command{ +var secretCreateCmd = &cli.Command{ Name: "add", Usage: "adds a secret", ArgsUsage: "[repo/name]", Action: secretCreate, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "name", Usage: "secret name", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "value", Usage: "secret value", }, - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: "event", Usage: "secret limited to these events", }, - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: "image", Usage: "secret limited to these images", }, - }, + ), } func secretCreate(c *cli.Context) error { diff --git a/cli/secret/secret_info.go b/cli/secret/secret_info.go index 23145141e..2e8a7a678 100644 --- a/cli/secret/secret_info.go +++ b/cli/secret/secret_info.go @@ -4,32 +4,28 @@ import ( "html/template" "os" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var secretInfoCmd = cli.Command{ +var secretInfoCmd = &cli.Command{ Name: "info", Usage: "display secret info", ArgsUsage: "[repo/name]", Action: secretInfo, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "name", Usage: "secret name", }, - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplSecretList, - Hidden: true, - }, - }, + common.FormatFlag(tmplSecretList, true), + ), } func secretInfo(c *cli.Context) error { diff --git a/cli/secret/secret_list.go b/cli/secret/secret_list.go index e2f526c48..b5a087742 100644 --- a/cli/secret/secret_list.go +++ b/cli/secret/secret_list.go @@ -5,28 +5,24 @@ import ( "os" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var secretListCmd = cli.Command{ +var secretListCmd = &cli.Command{ Name: "ls", Usage: "list secrets", ArgsUsage: "[repo/name]", Action: secretList, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplSecretList, - Hidden: true, - }, - }, + common.FormatFlag(tmplSecretList, true), + ), } func secretList(c *cli.Context) error { diff --git a/cli/secret/secret_rm.go b/cli/secret/secret_rm.go index a4c92389e..8441fef32 100644 --- a/cli/secret/secret_rm.go +++ b/cli/secret/secret_rm.go @@ -1,26 +1,27 @@ package secret import ( - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var secretDeleteCmd = cli.Command{ +var secretDeleteCmd = &cli.Command{ Name: "rm", Usage: "remove a secret", ArgsUsage: "[repo/name]", Action: secretDelete, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "name", Usage: "secret name", }, - }, + ), } func secretDelete(c *cli.Context) error { diff --git a/cli/secret/secret_set.go b/cli/secret/secret_set.go index 29ea9d48f..5ea3f030a 100644 --- a/cli/secret/secret_set.go +++ b/cli/secret/secret_set.go @@ -4,39 +4,40 @@ import ( "io/ioutil" "strings" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) -var secretUpdateCmd = cli.Command{ +var secretUpdateCmd = &cli.Command{ Name: "update", Usage: "update a secret", ArgsUsage: "[repo/name]", Action: secretUpdate, - Flags: []cli.Flag{ - cli.StringFlag{ + Flags: append(common.GlobalFlags, + &cli.StringFlag{ Name: "repository", Usage: "repository name (e.g. octocat/hello-world)", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "name", Usage: "secret name", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "value", Usage: "secret value", }, - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: "event", Usage: "secret limited to these events", }, - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: "image", Usage: "secret limited to these images", }, - }, + ), } func secretUpdate(c *cli.Context) error { diff --git a/cli/user/user.go b/cli/user/user.go index 03a4672a1..d578d0bd6 100644 --- a/cli/user/user.go +++ b/cli/user/user.go @@ -1,12 +1,17 @@ package user -import "github.com/urfave/cli" +import ( + "github.com/urfave/cli/v2" + + "github.com/woodpecker-ci/woodpecker/cli/common" +) // Command exports the user command set. -var Command = cli.Command{ +var Command = &cli.Command{ Name: "user", Usage: "manage users", - Subcommands: []cli.Command{ + Flags: common.GlobalFlags, + Subcommands: []*cli.Command{ userListCmd, userInfoCmd, userAddCmd, diff --git a/cli/user/user_add.go b/cli/user/user_add.go index 3978d5944..f5afce6a4 100644 --- a/cli/user/user_add.go +++ b/cli/user/user_add.go @@ -3,17 +3,19 @@ package user import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" "github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker" ) -var userAddCmd = cli.Command{ +var userAddCmd = &cli.Command{ Name: "add", Usage: "adds a user", ArgsUsage: "", Action: userAdd, + Flags: common.GlobalFlags, } func userAdd(c *cli.Context) error { diff --git a/cli/user/user_info.go b/cli/user/user_info.go index 55f1f5e8a..ce064fe7b 100644 --- a/cli/user/user_info.go +++ b/cli/user/user_info.go @@ -5,23 +5,20 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var userInfoCmd = cli.Command{ +var userInfoCmd = &cli.Command{ Name: "info", Usage: "show user details", ArgsUsage: "", Action: userInfo, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplUserInfo, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplUserInfo), + ), } func userInfo(c *cli.Context) error { diff --git a/cli/user/user_list.go b/cli/user/user_list.go index fb2432200..8783d37d8 100644 --- a/cli/user/user_list.go +++ b/cli/user/user_list.go @@ -4,23 +4,20 @@ import ( "os" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var userListCmd = cli.Command{ +var userListCmd = &cli.Command{ Name: "ls", Usage: "list all users", ArgsUsage: " ", Action: userList, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "format", - Usage: "format output", - Value: tmplUserList, - }, - }, + Flags: append(common.GlobalFlags, + common.FormatFlag(tmplUserList), + ), } func userList(c *cli.Context) error { diff --git a/cli/user/user_rm.go b/cli/user/user_rm.go index a2467abbd..c2c0f42a4 100644 --- a/cli/user/user_rm.go +++ b/cli/user/user_rm.go @@ -3,16 +3,18 @@ package user import ( "fmt" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/internal" ) -var userRemoveCmd = cli.Command{ +var userRemoveCmd = &cli.Command{ Name: "rm", Usage: "remove a user", ArgsUsage: "", Action: userRemove, + Flags: common.GlobalFlags, } func userRemove(c *cli.Context) error { diff --git a/cmd/agent/agent.go b/cmd/agent/agent.go index 094c7753b..66f9d3b6d 100644 --- a/cmd/agent/agent.go +++ b/cmd/agent/agent.go @@ -24,7 +24,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/tevino/abool" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "google.golang.org/grpc" grpccredentials "google.golang.org/grpc/credentials" "google.golang.org/grpc/keepalive" @@ -52,13 +52,13 @@ func loop(c *cli.Context) error { log.Logger = log.Output( zerolog.ConsoleWriter{ Out: os.Stderr, - NoColor: c.BoolT("nocolor"), + NoColor: c.Bool("nocolor"), }, ) } zerolog.SetGlobalLevel(zerolog.WarnLevel) - if c.BoolT("debug") { + if c.Bool("debug") { if c.IsSet("debug") { log.Warn().Msg("--debug is deprecated, use --log-level instead") } @@ -77,8 +77,12 @@ func loop(c *cli.Context) error { counter.Polling = c.Int("max-procs") counter.Running = 0 - if c.BoolT("healthcheck") { - go http.ListenAndServe(":3000", nil) + if c.Bool("healthcheck") { + go func() { + if err := http.ListenAndServe(":3000", nil); err != nil { + log.Error().Msgf("can not listen on port 3000: %v", err) + } + }() } // TODO pass version information to grpc server diff --git a/cmd/agent/flags.go b/cmd/agent/flags.go index d87d27952..c36d5599b 100644 --- a/cmd/agent/flags.go +++ b/cmd/agent/flags.go @@ -17,93 +17,97 @@ package main import ( "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var flags = []cli.Flag{ - cli.StringFlag{ - EnvVar: "WOODPECKER_SERVER", - Name: "server", - Usage: "server address", - Value: "localhost:9000", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SERVER"}, + Name: "server", + Usage: "server address", + Value: "localhost:9000", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_USERNAME", - Name: "username", - Usage: "auth username", - Value: "x-oauth-basic", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_USERNAME"}, + Name: "username", + Usage: "auth username", + Value: "x-oauth-basic", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_AGENT_SECRET", - Name: "password", - Usage: "server-agent shared password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_AGENT_SECRET"}, + Name: "password", + Usage: "server-agent shared password", }, - cli.BoolTFlag{ - EnvVar: "WOODPECKER_DEBUG", - Name: "debug", - Usage: "enable agent debug mode", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_DEBUG"}, + Name: "debug", + Usage: "enable agent debug mode", + Value: true, }, - cli.StringFlag{ - EnvVar: "WOODPECKER_LOG_LEVEL", - Name: "log-level", - Usage: "set logging level", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_LOG_LEVEL"}, + Name: "log-level", + Usage: "set logging level", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_DEBUG_PRETTY", - Name: "pretty", - Usage: "enable pretty-printed debug output", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_DEBUG_PRETTY"}, + Name: "pretty", + Usage: "enable pretty-printed debug output", }, - cli.BoolTFlag{ - EnvVar: "WOODPECKER_DEBUG_NOCOLOR", - Name: "nocolor", - Usage: "disable colored debug output", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_DEBUG_NOCOLOR"}, + Name: "nocolor", + Usage: "disable colored debug output", + Value: true, }, - cli.StringFlag{ - EnvVar: "WOODPECKER_HOSTNAME", - Name: "hostname", - Usage: "agent hostname", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_HOSTNAME"}, + Name: "hostname", + Usage: "agent hostname", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PLATFORM", - Name: "platform", - Usage: "restrict builds by platform conditions", - Value: "linux/amd64", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PLATFORM"}, + Name: "platform", + Usage: "restrict builds by platform conditions", + Value: "linux/amd64", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_FILTER", - Name: "filter", - Usage: "filter expression to restrict builds by label", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_FILTER"}, + Name: "filter", + Usage: "filter expression to restrict builds by label", }, - cli.IntFlag{ - EnvVar: "WOODPECKER_MAX_PROCS", - Name: "max-procs", - Usage: "agent parallel builds", - Value: 1, + &cli.IntFlag{ + EnvVars: []string{"WOODPECKER_MAX_PROCS"}, + Name: "max-procs", + Usage: "agent parallel builds", + Value: 1, }, - cli.BoolTFlag{ - EnvVar: "WOODPECKER_HEALTHCHECK", - Name: "healthcheck", - Usage: "enable healthcheck endpoint", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_HEALTHCHECK"}, + Name: "healthcheck", + Usage: "enable healthcheck endpoint", + Value: true, }, - cli.DurationFlag{ - EnvVar: "WOODPECKER_KEEPALIVE_TIME", - Name: "keepalive-time", - Usage: "after a duration of this time of no activity, the agent pings the server to check if the transport is still alive", + &cli.DurationFlag{ + EnvVars: []string{"WOODPECKER_KEEPALIVE_TIME"}, + Name: "keepalive-time", + Usage: "after a duration of this time of no activity, the agent pings the server to check if the transport is still alive", }, - cli.DurationFlag{ - EnvVar: "WOODPECKER_KEEPALIVE_TIMEOUT", - Name: "keepalive-timeout", - Usage: "after pinging for a keepalive check, the agent waits for a duration of this time before closing the connection if no activity", - Value: time.Second * 20, + &cli.DurationFlag{ + EnvVars: []string{"WOODPECKER_KEEPALIVE_TIMEOUT"}, + Name: "keepalive-timeout", + Usage: "after pinging for a keepalive check, the agent waits for a duration of this time before closing the connection if no activity", + Value: time.Second * 20, }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GRPC_SECURE", - Name: "secure-grpc", - Usage: "should the connection to WOODPECKER_SERVER be made using a secure transport", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GRPC_SECURE"}, + Name: "secure-grpc", + Usage: "should the connection to WOODPECKER_SERVER be made using a secure transport", }, - cli.BoolTFlag{ - EnvVar: "WOODPECKER_GRPC_VERIFY", - Name: "skip-insecure-grpc", - Usage: "should the grpc server certificate be verified, only valid when WOODPECKER_GRPC_SECURE is true", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GRPC_VERIFY"}, + Name: "skip-insecure-grpc", + Usage: "should the grpc server certificate be verified, only valid when WOODPECKER_GRPC_SECURE is true", + Value: true, }, } diff --git a/cmd/agent/health.go b/cmd/agent/health.go index eba638f7b..9c00bb4a4 100644 --- a/cmd/agent/health.go +++ b/cmd/agent/health.go @@ -19,7 +19,7 @@ import ( "fmt" "net/http" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/woodpecker-ci/woodpecker/agent" "github.com/woodpecker-ci/woodpecker/version" diff --git a/cmd/agent/main.go b/cmd/agent/main.go index 57c6c7832..c6fa71d07 100644 --- a/cmd/agent/main.go +++ b/cmd/agent/main.go @@ -19,7 +19,7 @@ import ( "os" _ "github.com/joho/godotenv/autoload" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/woodpecker-ci/woodpecker/version" ) @@ -30,7 +30,7 @@ func main() { app.Version = version.String() app.Usage = "woodpecker agent" app.Action = loop - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ { Name: "ping", Usage: "ping the agent", diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 640f7ff10..a2db51ff6 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -20,9 +20,10 @@ import ( _ "github.com/joho/godotenv/autoload" "github.com/rs/zerolog" zlog "github.com/rs/zerolog/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/woodpecker-ci/woodpecker/cli/build" + "github.com/woodpecker-ci/woodpecker/cli/common" "github.com/woodpecker-ci/woodpecker/cli/deploy" "github.com/woodpecker-ci/woodpecker/cli/exec" "github.com/woodpecker-ci/woodpecker/cli/info" @@ -42,40 +43,8 @@ func main() { app.Version = version.String() app.Usage = "command line utility" app.EnableBashCompletion = true - app.Flags = []cli.Flag{ - cli.StringFlag{ - EnvVar: "WOODPECKER_TOKEN", - // TODO: rename to `token` - Name: "t, token", - Usage: "server auth token", - }, - - cli.StringFlag{ - EnvVar: "WOODPECKER_SERVER", - // TODO: rename to `server` - Name: "s, server", - Usage: "server address", - }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_SKIP_VERIFY", - Name: "skip-verify", - Usage: "skip ssl verification", - Hidden: true, - }, - cli.StringFlag{ - EnvVar: "SOCKS_PROXY", - Name: "socks-proxy", - Usage: "socks proxy address", - Hidden: true, - }, - cli.BoolFlag{ - EnvVar: "SOCKS_PROXY_OFF", - Name: "socks-proxy-off", - Usage: "socks proxy ignored", - Hidden: true, - }, - } - app.Commands = []cli.Command{ + app.Flags = common.GlobalFlags + app.Commands = []*cli.Command{ build.Command, log.Command, deploy.Command, diff --git a/cmd/server/flags.go b/cmd/server/flags.go index f9bb83b1b..f9a36a3cf 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -17,497 +17,499 @@ package main import ( "time" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) var flags = []cli.Flag{ - cli.BoolFlag{ - EnvVar: "WOODPECKER_DEBUG", - Name: "debug", - Usage: "enable server debug mode", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_DEBUG"}, + Name: "debug", + Usage: "enable server debug mode", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_LOG_LEVEL", - Name: "log-level", - Usage: "set logging level", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_LOG_LEVEL"}, + Name: "log-level", + Usage: "set logging level", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_DEBUG_PRETTY", - Name: "pretty", - Usage: "enable pretty-printed debug output", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_DEBUG_PRETTY"}, + Name: "pretty", + Usage: "enable pretty-printed debug output", }, - cli.BoolTFlag{ - EnvVar: "WOODPECKER_DEBUG_NOCOLOR", - Name: "nocolor", - Usage: "disable colored debug output", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_DEBUG_NOCOLOR"}, + Name: "nocolor", + Usage: "disable colored debug output", + Value: true, }, - cli.StringFlag{ - EnvVar: "WOODPECKER_HOST", - Name: "server-host", - Usage: "server fully qualified url (://)", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_HOST"}, + Name: "server-host", + Usage: "server fully qualified url (://)", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_SERVER_ADDR", - Name: "server-addr", - Usage: "server address", - Value: ":8000", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SERVER_ADDR"}, + Name: "server-addr", + Usage: "server address", + Value: ":8000", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_SERVER_CERT", - Name: "server-cert", - Usage: "server ssl cert path", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SERVER_CERT"}, + Name: "server-cert", + Usage: "server ssl cert path", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_SERVER_KEY", - Name: "server-key", - Usage: "server ssl key path", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SERVER_KEY"}, + Name: "server-key", + Usage: "server ssl key path", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GRPC_ADDR", - Name: "grpc-addr", - Usage: "grpc address", - Value: ":9000", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GRPC_ADDR"}, + Name: "grpc-addr", + Usage: "grpc address", + Value: ":9000", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_LETS_ENCRYPT", - Name: "lets-encrypt", - Usage: "enable let's encrypt", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_LETS_ENCRYPT"}, + Name: "lets-encrypt", + Usage: "enable let's encrypt", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_QUIC", - Name: "quic", - Usage: "enable quic", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_QUIC"}, + Name: "quic", + Usage: "enable quic", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_WWW_PROXY", - Name: "www-proxy", - Usage: "serve the website by using a proxy (used for development)", - Hidden: true, + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_WWW_PROXY"}, + Name: "www-proxy", + Usage: "serve the website by using a proxy (used for development)", + Hidden: true, }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_ADMIN", - Name: "admin", - Usage: "list of admin users", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_ADMIN"}, + Name: "admin", + Usage: "list of admin users", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_ORGS", - Name: "orgs", - Usage: "list of approved organizations", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_ORGS"}, + Name: "orgs", + Usage: "list of approved organizations", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_REPO_OWNERS", - Name: "repo-owners", - Usage: "List of syncable repo owners", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_REPO_OWNERS"}, + Name: "repo-owners", + Usage: "List of syncable repo owners", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_OPEN", - Name: "open", - Usage: "enable open user registration", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_OPEN"}, + Name: "open", + Usage: "enable open user registration", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_DOCS", - Name: "docs", - Usage: "link to user documentation", - Value: "https://woodpecker-ci.org/", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_DOCS"}, + Name: "docs", + Usage: "link to user documentation", + Value: "https://woodpecker-ci.org/", }, - cli.DurationFlag{ - EnvVar: "WOODPECKER_SESSION_EXPIRES", - Name: "session-expires", - Usage: "session expiration time", - Value: time.Hour * 72, + &cli.DurationFlag{ + EnvVars: []string{"WOODPECKER_SESSION_EXPIRES"}, + Name: "session-expires", + Usage: "session expiration time", + Value: time.Hour * 72, }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_ESCALATE", - Name: "escalate", - Usage: "images to run in privileged mode", - Value: &cli.StringSlice{ + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_ESCALATE"}, + Name: "escalate", + Usage: "images to run in privileged mode", + Value: cli.NewStringSlice( "plugins/docker", "plugins/gcr", "plugins/ecr", - }, + ), }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_VOLUME", - Name: "volume", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_VOLUME"}, + Name: "volume", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_DOCKER_CONFIG", - Name: "docker-config", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_DOCKER_CONFIG"}, + Name: "docker-config", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_ENVIRONMENT", - Name: "environment", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_ENVIRONMENT"}, + Name: "environment", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_NETWORK", - Name: "network", + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_NETWORK"}, + Name: "network", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_AGENT_SECRET", - Name: "agent-secret", - Usage: "server-agent shared password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_AGENT_SECRET"}, + Name: "agent-secret", + Usage: "server-agent shared password", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_SECRET_ENDPOINT", - Name: "secret-service", - Usage: "secret plugin endpoint", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_SECRET_ENDPOINT"}, + Name: "secret-service", + Usage: "secret plugin endpoint", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_REGISTRY_ENDPOINT", - Name: "registry-service", - Usage: "registry plugin endpoint", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_REGISTRY_ENDPOINT"}, + Name: "registry-service", + Usage: "registry plugin endpoint", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GATEKEEPER_ENDPOINT", - Name: "gating-service", - Usage: "gated build endpoint", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GATEKEEPER_ENDPOINT"}, + Name: "gating-service", + Usage: "gated build endpoint", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_DATABASE_DRIVER", - Name: "driver", - Usage: "database driver", - Value: "sqlite3", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_DATABASE_DRIVER"}, + Name: "driver", + Usage: "database driver", + Value: "sqlite3", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_DATABASE_DATASOURCE", - Name: "datasource", - Usage: "database driver configuration string", - Value: "drone.sqlite", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_DATABASE_DATASOURCE"}, + Name: "datasource", + Usage: "database driver configuration string", + Value: "drone.sqlite", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_PROMETHEUS_AUTH_TOKEN", - Name: "prometheus-auth-token", - Usage: "token to secure prometheus metrics endpoint", - Value: "", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_PROMETHEUS_AUTH_TOKEN"}, + Name: "prometheus-auth-token", + Usage: "token to secure prometheus metrics endpoint", + Value: "", }, // // resource limit parameters // - cli.Int64Flag{ - EnvVar: "WOODPECKER_LIMIT_MEM_SWAP", - Name: "limit-mem-swap", - Usage: "maximum swappable memory allowed in bytes", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_LIMIT_MEM_SWAP"}, + Name: "limit-mem-swap", + Usage: "maximum swappable memory allowed in bytes", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_LIMIT_MEM", - Name: "limit-mem", - Usage: "maximum memory allowed in bytes", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_LIMIT_MEM"}, + Name: "limit-mem", + Usage: "maximum memory allowed in bytes", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_LIMIT_SHM_SIZE", - Name: "limit-shm-size", - Usage: "docker compose /dev/shm allowed in bytes", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_LIMIT_SHM_SIZE"}, + Name: "limit-shm-size", + Usage: "docker compose /dev/shm allowed in bytes", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_LIMIT_CPU_QUOTA", - Name: "limit-cpu-quota", - Usage: "impose a cpu quota", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_LIMIT_CPU_QUOTA"}, + Name: "limit-cpu-quota", + Usage: "impose a cpu quota", }, - cli.Int64Flag{ - EnvVar: "WOODPECKER_LIMIT_CPU_SHARES", - Name: "limit-cpu-shares", - Usage: "change the cpu shares", + &cli.Int64Flag{ + EnvVars: []string{"WOODPECKER_LIMIT_CPU_SHARES"}, + Name: "limit-cpu-shares", + Usage: "change the cpu shares", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_LIMIT_CPU_SET", - Name: "limit-cpu-set", - Usage: "set the cpus allowed to execute containers", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_LIMIT_CPU_SET"}, + Name: "limit-cpu-set", + Usage: "set the cpus allowed to execute containers", }, // // remote parameters // - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITHUB", - Name: "github", - Usage: "github driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITHUB"}, + Name: "github", + Usage: "github driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITHUB_URL", - Name: "github-server", - Usage: "github server address", - Value: "https://github.com", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_URL"}, + Name: "github-server", + Usage: "github server address", + Value: "https://github.com", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITHUB_CONTEXT", - Name: "github-context", - Usage: "github status context", - Value: "continuous-integration/woodpecker", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_CONTEXT"}, + Name: "github-context", + Usage: "github status context", + Value: "continuous-integration/woodpecker", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITHUB_CLIENT", - Name: "github-client", - Usage: "github oauth2 client id", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_CLIENT"}, + Name: "github-client", + Usage: "github oauth2 client id", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITHUB_SECRET", - Name: "github-secret", - Usage: "github oauth2 client secret", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_SECRET"}, + Name: "github-secret", + Usage: "github oauth2 client secret", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_GITHUB_SCOPE", - Name: "github-scope", - Usage: "github oauth scope", - Value: &cli.StringSlice{ + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_SCOPE"}, + Name: "github-scope", + Usage: "github oauth scope", + Value: cli.NewStringSlice( "repo", "repo:status", "user:email", "read:org", - }, + ), }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITHUB_GIT_USERNAME", - Name: "github-git-username", - Usage: "github machine user username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_GIT_USERNAME"}, + Name: "github-git-username", + Usage: "github machine user username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITHUB_GIT_PASSWORD", - Name: "github-git-password", - Usage: "github machine user password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_GIT_PASSWORD"}, + Name: "github-git-password", + Usage: "github machine user password", }, - cli.BoolTFlag{ - EnvVar: "WOODPECKER_GITHUB_MERGE_REF", - Name: "github-merge-ref", - Usage: "github pull requests use merge ref", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_MERGE_REF"}, + Name: "github-merge-ref", + Usage: "github pull requests use merge ref", + Value: true, }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITHUB_PRIVATE_MODE", - Name: "github-private-mode", - Usage: "github is running in private mode", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_PRIVATE_MODE"}, + Name: "github-private-mode", + Usage: "github is running in private mode", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITHUB_SKIP_VERIFY", - Name: "github-skip-verify", - Usage: "github skip ssl verification", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_SKIP_VERIFY"}, + Name: "github-skip-verify", + Usage: "github skip ssl verification", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GOGS", - Name: "gogs", - Usage: "gogs driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GOGS"}, + Name: "gogs", + Usage: "gogs driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GOGS_URL", - Name: "gogs-server", - Usage: "gogs server address", - Value: "https://github.com", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GOGS_URL"}, + Name: "gogs-server", + Usage: "gogs server address", + Value: "https://github.com", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GOGS_GIT_USERNAME", - Name: "gogs-git-username", - Usage: "gogs service account username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GOGS_GIT_USERNAME"}, + Name: "gogs-git-username", + Usage: "gogs service account username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GOGS_GIT_PASSWORD", - Name: "gogs-git-password", - Usage: "gogs service account password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GOGS_GIT_PASSWORD"}, + Name: "gogs-git-password", + Usage: "gogs service account password", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GOGS_PRIVATE_MODE", - Name: "gogs-private-mode", - Usage: "gogs private mode enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GOGS_PRIVATE_MODE"}, + Name: "gogs-private-mode", + Usage: "gogs private mode enabled", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GOGS_SKIP_VERIFY", - Name: "gogs-skip-verify", - Usage: "gogs skip ssl verification", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GOGS_SKIP_VERIFY"}, + Name: "gogs-skip-verify", + Usage: "gogs skip ssl verification", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITEA", - Name: "gitea", - Usage: "gitea driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITEA"}, + Name: "gitea", + Usage: "gitea driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITEA_URL", - Name: "gitea-server", - Usage: "gitea server address", - Value: "https://try.gitea.io", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITEA_URL"}, + Name: "gitea-server", + Usage: "gitea server address", + Value: "https://try.gitea.io", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITEA_CLIENT", - Name: "gitea-client", - Usage: "gitea oauth2 client id", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITEA_CLIENT"}, + Name: "gitea-client", + Usage: "gitea oauth2 client id", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITEA_SECRET", - Name: "gitea-secret", - Usage: "gitea oauth2 client secret", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITEA_SECRET"}, + Name: "gitea-secret", + Usage: "gitea oauth2 client secret", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITEA_CONTEXT", - Name: "gitea-context", - Usage: "gitea status context", - Value: "continuous-integration/woodpecker", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITEA_CONTEXT"}, + Name: "gitea-context", + Usage: "gitea status context", + Value: "continuous-integration/woodpecker", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITEA_GIT_USERNAME", - Name: "gitea-git-username", - Usage: "gitea service account username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITEA_GIT_USERNAME"}, + Name: "gitea-git-username", + Usage: "gitea service account username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITEA_GIT_PASSWORD", - Name: "gitea-git-password", - Usage: "gitea service account password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITEA_GIT_PASSWORD"}, + Name: "gitea-git-password", + Usage: "gitea service account password", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITEA_PRIVATE_MODE", - Name: "gitea-private-mode", - Usage: "gitea private mode enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITEA_PRIVATE_MODE"}, + Name: "gitea-private-mode", + Usage: "gitea private mode enabled", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITEA_SKIP_VERIFY", - Name: "gitea-skip-verify", - Usage: "gitea skip ssl verification", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITEA_SKIP_VERIFY"}, + Name: "gitea-skip-verify", + Usage: "gitea skip ssl verification", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_BITBUCKET", - Name: "bitbucket", - Usage: "bitbucket driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_BITBUCKET"}, + Name: "bitbucket", + Usage: "bitbucket driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_BITBUCKET_CLIENT", - Name: "bitbucket-client", - Usage: "bitbucket oauth2 client id", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_BITBUCKET_CLIENT"}, + Name: "bitbucket-client", + Usage: "bitbucket oauth2 client id", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_BITBUCKET_SECRET", - Name: "bitbucket-secret", - Usage: "bitbucket oauth2 client secret", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_BITBUCKET_SECRET"}, + Name: "bitbucket-secret", + Usage: "bitbucket oauth2 client secret", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITLAB", - Name: "gitlab", - Usage: "gitlab driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITLAB"}, + Name: "gitlab", + Usage: "gitlab driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITLAB_URL", - Name: "gitlab-server", - Usage: "gitlab server address", - Value: "https://gitlab.com", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_URL"}, + Name: "gitlab-server", + Usage: "gitlab server address", + Value: "https://gitlab.com", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITLAB_CLIENT", - Name: "gitlab-client", - Usage: "gitlab oauth2 client id", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_CLIENT"}, + Name: "gitlab-client", + Usage: "gitlab oauth2 client id", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITLAB_SECRET", - Name: "gitlab-secret", - Usage: "gitlab oauth2 client secret", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_SECRET"}, + Name: "gitlab-secret", + Usage: "gitlab oauth2 client secret", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITLAB_GIT_USERNAME", - Name: "gitlab-git-username", - Usage: "gitlab service account username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_GIT_USERNAME"}, + Name: "gitlab-git-username", + Usage: "gitlab service account username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_GITLAB_GIT_PASSWORD", - Name: "gitlab-git-password", - Usage: "gitlab service account password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_GIT_PASSWORD"}, + Name: "gitlab-git-password", + Usage: "gitlab service account password", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITLAB_SKIP_VERIFY", - Name: "gitlab-skip-verify", - Usage: "gitlab skip ssl verification", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_SKIP_VERIFY"}, + Name: "gitlab-skip-verify", + Usage: "gitlab skip ssl verification", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_GITLAB_PRIVATE_MODE", - Name: "gitlab-private-mode", - Usage: "gitlab is running in private mode", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITLAB_PRIVATE_MODE"}, + Name: "gitlab-private-mode", + Usage: "gitlab is running in private mode", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_STASH", - Name: "stash", - Usage: "stash driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_STASH"}, + Name: "stash", + Usage: "stash driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_STASH_URL", - Name: "stash-server", - Usage: "stash server address", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STASH_URL"}, + Name: "stash-server", + Usage: "stash server address", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_STASH_CONSUMER_KEY", - Name: "stash-consumer-key", - Usage: "stash oauth1 consumer key", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STASH_CONSUMER_KEY"}, + Name: "stash-consumer-key", + Usage: "stash oauth1 consumer key", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_STASH_CONSUMER_RSA", - Name: "stash-consumer-rsa", - Usage: "stash oauth1 private key file", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STASH_CONSUMER_RSA"}, + Name: "stash-consumer-rsa", + Usage: "stash oauth1 private key file", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_STASH_CONSUMER_RSA_STRING", - Name: "stash-consumer-rsa-string", - Usage: "stash oauth1 private key string", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STASH_CONSUMER_RSA_STRING"}, + Name: "stash-consumer-rsa-string", + Usage: "stash oauth1 private key string", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_STASH_GIT_USERNAME", - Name: "stash-git-username", - Usage: "stash service account username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STASH_GIT_USERNAME"}, + Name: "stash-git-username", + Usage: "stash service account username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_STASH_GIT_PASSWORD", - Name: "stash-git-password", - Usage: "stash service account password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_STASH_GIT_PASSWORD"}, + Name: "stash-git-password", + Usage: "stash service account password", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_STASH_SKIP_VERIFY", - Name: "stash-skip-verify", - Usage: "stash skip ssl verification", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_STASH_SKIP_VERIFY"}, + Name: "stash-skip-verify", + Usage: "stash skip ssl verification", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_CODING", - Name: "coding", - Usage: "coding driver is enabled", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_CODING"}, + Name: "coding", + Usage: "coding driver is enabled", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_CODING_URL", - Name: "coding-server", - Usage: "coding server address", - Value: "https://coding.net", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_CODING_URL"}, + Name: "coding-server", + Usage: "coding server address", + Value: "https://coding.net", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_CODING_CLIENT", - Name: "coding-client", - Usage: "coding oauth2 client id", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_CODING_CLIENT"}, + Name: "coding-client", + Usage: "coding oauth2 client id", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_CODING_SECRET", - Name: "coding-secret", - Usage: "coding oauth2 client secret", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_CODING_SECRET"}, + Name: "coding-secret", + Usage: "coding oauth2 client secret", }, - cli.StringSliceFlag{ - EnvVar: "WOODPECKER_CODING_SCOPE", - Name: "coding-scope", - Usage: "coding oauth scope", - Value: &cli.StringSlice{ + &cli.StringSliceFlag{ + EnvVars: []string{"WOODPECKER_CODING_SCOPE"}, + Name: "coding-scope", + Usage: "coding oauth scope", + Value: cli.NewStringSlice( "user", "project", "project:depot", - }, + ), }, - cli.StringFlag{ - EnvVar: "WOODPECKER_CODING_GIT_MACHINE", - Name: "coding-git-machine", - Usage: "coding machine name", - Value: "git.coding.net", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_CODING_GIT_MACHINE"}, + Name: "coding-git-machine", + Usage: "coding machine name", + Value: "git.coding.net", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_CODING_GIT_USERNAME", - Name: "coding-git-username", - Usage: "coding machine user username", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_CODING_GIT_USERNAME"}, + Name: "coding-git-username", + Usage: "coding machine user username", }, - cli.StringFlag{ - EnvVar: "WOODPECKER_CODING_GIT_PASSWORD", - Name: "coding-git-password", - Usage: "coding machine user password", + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_CODING_GIT_PASSWORD"}, + Name: "coding-git-password", + Usage: "coding machine user password", }, - cli.BoolFlag{ - EnvVar: "WOODPECKER_CODING_SKIP_VERIFY", - Name: "coding-skip-verify", - Usage: "coding skip ssl verification", + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_CODING_SKIP_VERIFY"}, + Name: "coding-skip-verify", + Usage: "coding skip ssl verification", }, - cli.DurationFlag{ - EnvVar: "WOODPECKER_KEEPALIVE_MIN_TIME", - Name: "keepalive-min-time", - Usage: "server-side enforcement policy on the minimum amount of time a client should wait before sending a keepalive ping.", + &cli.DurationFlag{ + EnvVars: []string{"WOODPECKER_KEEPALIVE_MIN_TIME"}, + Name: "keepalive-min-time", + Usage: "server-side enforcement policy on the minimum amount of time a client should wait before sending a keepalive ping.", }, } diff --git a/cmd/server/main.go b/cmd/server/main.go index fc92e8aea..53871eeda 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -20,7 +20,7 @@ import ( "github.com/joho/godotenv" _ "github.com/joho/godotenv/autoload" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/woodpecker-ci/woodpecker/version" ) diff --git a/cmd/server/server.go b/cmd/server/server.go index dd97a1ded..c4dc55c07 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -29,7 +29,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "golang.org/x/crypto/acme/autocert" "golang.org/x/sync/errgroup" "google.golang.org/grpc" @@ -55,7 +55,7 @@ func loop(c *cli.Context) error { log.Logger = log.Output( zerolog.ConsoleWriter{ Out: os.Stderr, - NoColor: c.BoolT("nocolor"), + NoColor: c.Bool("nocolor"), }, ) } diff --git a/cmd/server/setup.go b/cmd/server/setup.go index 40b3773f4..79fc5481b 100644 --- a/cmd/server/setup.go +++ b/cmd/server/setup.go @@ -22,7 +22,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/rs/zerolog/log" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "golang.org/x/sync/errgroup" "github.com/woodpecker-ci/woodpecker/server" @@ -180,7 +180,7 @@ func setupGithub(c *cli.Context) (remote.Remote, error) { Password: c.String("github-git-password"), PrivateMode: c.Bool("github-private-mode"), SkipVerify: c.Bool("github-skip-verify"), - MergeRef: c.BoolT("github-merge-ref"), + MergeRef: c.Bool("github-merge-ref"), } log.Trace().Msgf("Remote (github) opts: %#v", opts) return github.New(opts) diff --git a/go.mod b/go.mod index 60144a3f4..6956f98da 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/bmatcuk/doublestar/v4 v4.0.2 github.com/bradrydzewski/togo v0.0.0-20180401185031-50a0e4726e74 // indirect github.com/containerd/containerd v1.5.5 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/docker/cli v0.0.0-20200303215952-eb310fca4956 github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v20.10.8+incompatible @@ -46,7 +47,7 @@ require ( github.com/stretchr/testify v1.7.0 github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 github.com/ugorji/go v1.2.6 // indirect - github.com/urfave/cli v1.22.4 + github.com/urfave/cli/v2 v2.3.0 github.com/woodpecker-ci/expr v0.0.0-20210628233344-164b8b3d0915 github.com/woodpecker-ci/togo v0.0.0-20180401185031-50a0e4726e74 github.com/xanzy/go-gitlab v0.51.1 diff --git a/go.sum b/go.sum index bcb1306ef..1fda1d5c0 100644 --- a/go.sum +++ b/go.sum @@ -213,8 +213,9 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 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.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= @@ -619,14 +620,14 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II= github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI= -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/russross/meddler v1.0.1 h1:JLR7Z4M4iGm1nr7DIURBq18UW8cTrm+qArUFgOhELo8= github.com/russross/meddler v1.0.1/go.mod h1:GzGDChbFHuzxlFwt8gnJMRRNyFSQDSudmy2kHh7GYnQ= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -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.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -686,9 +687,10 @@ github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxW github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -1061,6 +1063,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/server/router/middleware/config.go b/server/router/middleware/config.go index 4888050c9..839affe51 100644 --- a/server/router/middleware/config.go +++ b/server/router/middleware/config.go @@ -16,7 +16,7 @@ package middleware import ( "github.com/gin-gonic/gin" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/woodpecker-ci/woodpecker/server/model" ) diff --git a/server/router/middleware/store.go b/server/router/middleware/store.go index e46f8aef7..54c9f6c78 100644 --- a/server/router/middleware/store.go +++ b/server/router/middleware/store.go @@ -16,7 +16,7 @@ package middleware import ( "github.com/gin-gonic/gin" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" "github.com/woodpecker-ci/woodpecker/server/store" ) 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/go.mod b/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod deleted file mode 100644 index 1e2553475..000000000 --- a/vendor/github.com/shurcooL/sanitized_anchor_name/go.mod +++ /dev/null @@ -1 +0,0 @@ -module github.com/shurcooL/sanitized_anchor_name 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 index 9c2506032..7a7e2d9ef 100644 --- a/vendor/github.com/urfave/cli/.gitignore +++ b/vendor/github.com/urfave/cli/.gitignore @@ -1,4 +1,3 @@ *.coverprofile node_modules/ -vendor -.idea \ No newline at end of file +vendor \ No newline at end of file diff --git a/vendor/github.com/urfave/cli/.travis.yml b/vendor/github.com/urfave/cli/.travis.yml new file mode 100644 index 000000000..d36c22436 --- /dev/null +++ b/vendor/github.com/urfave/cli/.travis.yml @@ -0,0 +1,35 @@ +language: go +sudo: false +dist: bionic +osx_image: xcode10 +go: + - 1.11.x + - 1.12.x + - 1.13.x + +os: + - linux + - osx + +env: + GO111MODULE=on + GOPROXY=https://proxy.golang.org + +cache: + directories: + - node_modules + +before_script: + - go get github.com/urfave/gfmrun/cmd/gfmrun + - go get golang.org/x/tools/cmd/goimports + - npm install markdown-toc + - go mod tidy + +script: + - go run build.go vet + - go run build.go test + - go run build.go gfmrun docs/v1/manual.md + - go run build.go toc docs/v1/manual.md + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/urfave/cli/app.go b/vendor/github.com/urfave/cli/app.go index ddb7685d6..95d203810 100644 --- a/vendor/github.com/urfave/cli/app.go +++ b/vendor/github.com/urfave/cli/app.go @@ -121,6 +121,7 @@ func NewApp() *App { HelpName: filepath.Base(os.Args[0]), Usage: "A new cli application", UsageText: "", + Version: "0.0.0", BashComplete: DefaultAppComplete, Action: helpCommand.Action, Compiled: compileTime(), @@ -158,10 +159,6 @@ func (a *App) Setup() { } } - if a.Version == "" { - a.HideVersion = true - } - if !a.HideVersion { a.appendFlag(VersionFlag) } @@ -207,7 +204,7 @@ func (a *App) Run(arguments []string) (err error) { return err } - err = parseIter(set, a, arguments[1:], shellComplete) + err = parseIter(set, a, arguments[1:]) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, nil) if nerr != nil { @@ -330,7 +327,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { return err } - err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) + err = parseIter(set, a, ctx.Args().Tail()) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, ctx) diff --git a/vendor/github.com/urfave/cli/command.go b/vendor/github.com/urfave/cli/command.go index 24e9e5c57..e7cb97a6a 100644 --- a/vendor/github.com/urfave/cli/command.go +++ b/vendor/github.com/urfave/cli/command.go @@ -114,7 +114,7 @@ func (c Command) Run(ctx *Context) (err error) { c.UseShortOptionHandling = true } - set, err := c.parseFlags(ctx.Args().Tail(), ctx.shellComplete) + set, err := c.parseFlags(ctx.Args().Tail()) context := NewContext(ctx.App, set, ctx) context.Command = c @@ -179,7 +179,7 @@ func (c Command) Run(ctx *Context) (err error) { return err } -func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { +func (c *Command) parseFlags(args Args) (*flag.FlagSet, error) { if c.SkipFlagParsing { set, err := c.newFlagSet() if err != nil { @@ -198,7 +198,7 @@ func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, erro return nil, err } - err = parseIter(set, c, args, shellComplete) + err = parseIter(set, c, args) if err != nil { return nil, err } diff --git a/vendor/github.com/urfave/cli/context.go b/vendor/github.com/urfave/cli/context.go index 957f39e0f..ecfc03282 100644 --- a/vendor/github.com/urfave/cli/context.go +++ b/vendor/github.com/urfave/cli/context.go @@ -87,14 +87,6 @@ func (c *Context) IsSet(name string) bool { 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 } diff --git a/vendor/github.com/urfave/cli/flag_int64_slice.go b/vendor/github.com/urfave/cli/flag_int64_slice.go index 2602408cf..ed2e983b6 100644 --- a/vendor/github.com/urfave/cli/flag_int64_slice.go +++ b/vendor/github.com/urfave/cli/flag_int64_slice.go @@ -22,12 +22,7 @@ func (f *Int64Slice) Set(value string) error { // 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, ",") + return fmt.Sprintf("%#v", *f) } // Value returns the slice of ints set by this flag @@ -115,7 +110,6 @@ func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { } set.Var(f.Value, name, f.Usage) }) - return nil } @@ -137,61 +131,11 @@ func (c *Context) GlobalInt64Slice(name string) []int64 { func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { f := set.Lookup(name) if f != nil { - value, ok := f.Value.(*Int64Slice) - if !ok { + parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil) + if err != nil { 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 { - return append(slice[:i], slice[i+1:]...) - } - } - 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 index a423d1ecb..c38d010fd 100644 --- a/vendor/github.com/urfave/cli/flag_int_slice.go +++ b/vendor/github.com/urfave/cli/flag_int_slice.go @@ -22,12 +22,7 @@ func (f *IntSlice) Set(value string) error { // 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, ",") + return fmt.Sprintf("%#v", *f) } // Value returns the slice of ints set by this flag @@ -137,60 +132,11 @@ func (c *Context) GlobalIntSlice(name string) []int { func lookupIntSlice(name string, set *flag.FlagSet) []int { f := set.Lookup(name) if f != nil { - value, ok := f.Value.(*IntSlice) - if !ok { + parsed, err := (f.Value.(*IntSlice)).Value(), error(nil) + if err != nil { 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 parsed } return nil } - -func removeFromIntSlice(slice []int, val int) []int { - for i, v := range slice { - if v == val { - return append(slice[:i], slice[i+1:]...) - } - } - 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_slice.go b/vendor/github.com/urfave/cli/flag_string_slice.go index c6cb44254..e865b2ff0 100644 --- a/vendor/github.com/urfave/cli/flag_string_slice.go +++ b/vendor/github.com/urfave/cli/flag_string_slice.go @@ -17,7 +17,7 @@ func (f *StringSlice) Set(value string) error { // String returns a readable representation of this value (for usage defaults) func (f *StringSlice) String() string { - return strings.Join(*f, ",") + return fmt.Sprintf("%s", *f) } // Value returns the slice of strings set by this flag @@ -128,55 +128,11 @@ func (c *Context) GlobalStringSlice(name string) []string { func lookupStringSlice(name string, set *flag.FlagSet) []string { f := set.Lookup(name) if f != nil { - value, ok := f.Value.(*StringSlice) - if !ok { + parsed, err := (f.Value.(*StringSlice)).Value(), error(nil) + if err != nil { 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 parsed } return nil } - -func removeFromStringSlice(slice []string, val string) []string { - for i, v := range slice { - if v == val { - return append(slice[:i], slice[i+1:]...) - } - } - 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/parse.go b/vendor/github.com/urfave/cli/parse.go index 7df17296a..660f538b0 100644 --- a/vendor/github.com/urfave/cli/parse.go +++ b/vendor/github.com/urfave/cli/parse.go @@ -11,18 +11,13 @@ type iterativeParser interface { } // To enable short-option handling (e.g., "-it" vs "-i -t") we have to -// iteratively catch parsing errors. This way we achieve LR parsing without +// iteratively catch parsing errors. This way we achieve LR parsing without // transforming any arguments. Otherwise, there is no way we can discriminate // combined short options from common arguments that should be left untouched. -// Pass `shellComplete` to continue parsing options on failure during shell -// completion when, the user-supplied options may be incomplete. -func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error { +func parseIter(set *flag.FlagSet, ip iterativeParser, args []string) error { for { err := set.Parse(args) if !ip.useShortOptionHandling() || err == nil { - if shellComplete { - return nil - } return err } diff --git a/vendor/github.com/urfave/cli/v2/.flake8 b/vendor/github.com/urfave/cli/v2/.flake8 new file mode 100644 index 000000000..6deafc261 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/vendor/github.com/urfave/cli/v2/.gitignore b/vendor/github.com/urfave/cli/v2/.gitignore new file mode 100644 index 000000000..2d5e149b4 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/.gitignore @@ -0,0 +1,7 @@ +*.coverprofile +*.orig +node_modules/ +vendor +.idea +internal/*/built-example +coverage.txt diff --git a/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..41ba294f6 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +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. + +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 +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + diff --git a/vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE b/vendor/github.com/urfave/cli/v2/LICENSE similarity index 95% rename from vendor/github.com/shurcooL/sanitized_anchor_name/LICENSE rename to vendor/github.com/urfave/cli/v2/LICENSE index c35c17af9..42a597e29 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) 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 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..408668bc3 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/README.md @@ -0,0 +1,70 @@ +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. Don't know what version you're on? You're probably using the version from the `master` branch, which is currently `v2`. + +- `v2` - [./docs/v2/manual.md](./docs/v2/manual.md) +- `v1` - [./docs/v1/manual.md](./docs/v1/manual.md) + +Guides for migrating to newer versions: + +- `v1-to-v2` - [./docs/migrate-v1-to-v2.md](./docs/migrate-v1-to-v2.md) + +## Installation + +Using this package requires a working Go environment. [See the install instructions for Go](http://golang.org/doc/install.html). + +Go Modules are required when using this package. [See the go blog guide on using Go Modules](https://blog.golang.org/using-go-modules). + +### Using `v2` releases + +``` +$ GO111MODULE=on go get github.com/urfave/cli/v2 +``` + +```go +... +import ( + "github.com/urfave/cli/v2" // imports as package "cli" +) +... +``` + +### Using `v1` releases + +``` +$ GO111MODULE=on go get github.com/urfave/cli +``` + +```go +... +import ( + "github.com/urfave/cli" +) +... +``` + +### 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. This project uses Github Actions for +builds. To see our currently supported go versions and platforms, look at the [./.github/workflows/cli.yml](https://github.com/urfave/cli/blob/master/.github/workflows/cli.yml). diff --git a/vendor/github.com/urfave/cli/v2/app.go b/vendor/github.com/urfave/cli/v2/app.go new file mode 100644 index 000000000..f801fce91 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/app.go @@ -0,0 +1,540 @@ +package cli + +import ( + "context" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "time" +) + +var ( + changeLogURL = "https://github.com/urfave/cli/blob/master/docs/CHANGELOG.md" + appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", 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. "+ + fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ + fmt.Sprintf("See %s", appActionDeprecationURL), 2) +) + +// App is the main structure of a cli application. It is recommended that +// an app be created with the cli.NewApp() function +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 + // 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 + // categories contains the categorized commands and is populated on app startup + categories CommandCategories + // 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 + + didSetup bool +} + +// Tries to find out when this binary was compiled. +// Returns the current time if it fails to find it. +func compileTime() time.Time { + info, err := os.Stat(os.Args[0]) + if err != nil { + return time.Now() + } + return info.ModTime() +} + +// NewApp creates a new cli Application with some reasonable defaults for Name, +// Usage, Version and Action. +func NewApp() *App { + return &App{ + Name: filepath.Base(os.Args[0]), + HelpName: filepath.Base(os.Args[0]), + Usage: "A new cli application", + UsageText: "", + BashComplete: DefaultAppComplete, + Action: helpCommand.Action, + Compiled: compileTime(), + Reader: os.Stdin, + Writer: os.Stdout, + ErrWriter: os.Stderr, + } +} + +// 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) Setup() { + if a.didSetup { + return + } + + a.didSetup = true + + if a.Name == "" { + a.Name = filepath.Base(os.Args[0]) + } + + if a.HelpName == "" { + a.HelpName = filepath.Base(os.Args[0]) + } + + 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 newCommands []*Command + + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCommands = append(newCommands, c) + } + a.Commands = newCommands + + if a.Command(helpCommand.Name) == nil && !a.HideHelp { + if !a.HideHelpCommand { + a.appendCommand(helpCommand) + } + + if HelpFlag != nil { + a.appendFlag(HelpFlag) + } + } + + if !a.HideVersion { + a.appendFlag(VersionFlag) + } + + a.categories = newCommandCategories() + for _, command := range a.Commands { + a.categories.AddCommand(command.Category, command) + } + sort.Sort(a.categories.(*commandCategories)) + + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) + } +} + +func (a *App) newFlagSet() (*flag.FlagSet, error) { + return flagSet(a.Name, a.Flags) +} + +func (a *App) useShortOptionHandling() bool { + return a.UseShortOptionHandling +} + +// 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 + // completion could be attempted after a flag, but before its value was put + // on the command line. this causes the flagset to interpret the completion + // flag name as the value of the flag before it which is undesirable + // note that we can only do this because the shell autocomplete function + // always appends the completion flag at the end of the command + shellComplete, arguments := checkShellCompleteFlag(a, arguments) + + set, err := a.newFlagSet() + if err != nil { + return err + } + + err = parseIter(set, a, arguments[1:], shellComplete) + nerr := normalizeFlags(a.Flags, set) + context := NewContext(a, set, &Context{Context: ctx}) + if nerr != nil { + _, _ = fmt.Fprintln(a.Writer, nerr) + _ = ShowAppHelp(context) + return nerr + } + context.shellComplete = shellComplete + + if checkCompletions(context) { + return nil + } + + if err != nil { + if a.OnUsageError != nil { + err := a.OnUsageError(context, err, false) + a.handleExitCoder(context, err) + return err + } + _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) + _ = ShowAppHelp(context) + 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 err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if a.Before != nil { + beforeErr := a.Before(context) + if beforeErr != nil { + a.handleExitCoder(context, beforeErr) + err = beforeErr + return err + } + } + + args := context.Args() + if args.Present() { + name := args.First() + c := a.Command(name) + if c != nil { + return c.Run(context) + } + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + // Run default Action + err = a.Action(context) + + a.handleExitCoder(context, err) + return err +} + +// 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 +// code in the cli.ExitCoder +func (a *App) RunAndExitOnError() { + if err := a.Run(os.Args); err != nil { + _, _ = fmt.Fprintln(a.ErrWriter, err) + OsExiter(1) + } +} + +// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to +// generate command-specific flags +func (a *App) RunAsSubcommand(ctx *Context) (err error) { + // Setup also handles HideHelp and HideHelpCommand + a.Setup() + + var newCmds []*Command + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCmds = append(newCmds, c) + } + a.Commands = newCmds + + set, err := a.newFlagSet() + if err != nil { + return err + } + + err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) + nerr := normalizeFlags(a.Flags, set) + context := NewContext(a, set, ctx) + + if nerr != nil { + _, _ = fmt.Fprintln(a.Writer, nerr) + _, _ = fmt.Fprintln(a.Writer) + if len(a.Commands) > 0 { + _ = ShowSubcommandHelp(context) + } else { + _ = ShowCommandHelp(ctx, context.Args().First()) + } + return nerr + } + + if checkCompletions(context) { + return nil + } + + if err != nil { + if a.OnUsageError != nil { + err = a.OnUsageError(context, err, true) + a.handleExitCoder(context, err) + return err + } + _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) + _ = ShowSubcommandHelp(context) + return err + } + + if len(a.Commands) > 0 { + if checkSubcommandHelp(context) { + return nil + } + } else { + if checkCommandHelp(ctx, context.Args().First()) { + return nil + } + } + + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + _ = ShowSubcommandHelp(context) + return cerr + } + + if a.After != nil { + defer func() { + afterErr := a.After(context) + if afterErr != nil { + a.handleExitCoder(context, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if a.Before != nil { + beforeErr := a.Before(context) + if beforeErr != nil { + a.handleExitCoder(context, beforeErr) + err = beforeErr + return err + } + } + + args := context.Args() + if args.Present() { + name := args.First() + c := a.Command(name) + if c != nil { + return c.Run(context) + } + } + + // Run default Action + err = a.Action(context) + + a.handleExitCoder(context, err) + return err +} + +// Command returns the named command on App. Returns nil if the command does not exist +func (a *App) Command(name string) *Command { + for _, c := range a.Commands { + if c.HasName(name) { + return c + } + } + + return nil +} + +// VisibleCategories returns a slice of categories and commands that are +// Hidden=false +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 { + ret = append(ret, visible) + } + } + return ret +} + +// VisibleCommands returns a slice of the Commands with Hidden=false +func (a *App) VisibleCommands() []*Command { + var ret []*Command + for _, command := range a.Commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} + +// VisibleFlags returns a slice of the Flags with Hidden=false +func (a *App) VisibleFlags() []Flag { + return visibleFlags(a.Flags) +} + +func (a *App) appendFlag(fl Flag) { + if !hasFlag(a.Flags, fl) { + a.Flags = append(a.Flags, fl) + } +} + +func (a *App) appendCommand(c *Command) { + if !hasCommand(a.Commands, c) { + a.Commands = append(a.Commands, c) + } +} + +func (a *App) handleExitCoder(context *Context, err error) { + if a.ExitErrHandler != nil { + a.ExitErrHandler(context, err) + } else { + HandleExitCoder(err) + } +} + +// Author represents someone who has contributed to a cli project. +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + +// String makes Author comply to the Stringer interface, to allow an easy print in the templating process +func (a *Author) String() string { + e := "" + if a.Email != "" { + e = " <" + a.Email + ">" + } + + return fmt.Sprintf("%v%v", a.Name, e) +} + +// 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) { + switch a := action.(type) { + case ActionFunc: + return a(context) + case func(*Context) error: + return a(context) + case func(*Context): // deprecated function signature + a(context) + return nil + } + + return errInvalidActionType +} 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..867e3908c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/category.go @@ -0,0 +1,79 @@ +package cli + +// 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 copy of the category slice + 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 +} diff --git a/vendor/github.com/urfave/cli/v2/cli.go b/vendor/github.com/urfave/cli/v2/cli.go new file mode 100644 index 000000000..62a5bc22d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/cli.go @@ -0,0 +1,23 @@ +// 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) +// } +package cli + +//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.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..dda2f49a0 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/command.go @@ -0,0 +1,300 @@ +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 + // 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) + + 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 + } + + context.Command = c + err = c.Action(context) + + if err != nil { + context.App.handleExitCoder(context, 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.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.Writer = ctx.App.Writer + app.ErrWriter = ctx.App.ErrWriter + app.ExitErrHandler = ctx.App.ExitErrHandler + app.UseShortOptionHandling = ctx.App.UseShortOptionHandling + + 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) +} + +// 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..74ed51912 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/context.go @@ -0,0 +1,273 @@ +package cli + +import ( + "context" + "errors" + "flag" + "fmt" + "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 (c *Context) NumFlags() int { + return c.flagSet.NFlag() +} + +// Set sets a context flag to a value. +func (c *Context) Set(name, value string) error { + return c.flagSet.Set(name, value) +} + +// IsSet determines if the flag was actually set +func (c *Context) IsSet(name string) bool { + if fs := lookupFlagSet(name, c); fs != nil { + if fs := lookupFlagSet(name, c); fs != nil { + isSet := false + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + isSet = true + } + }) + if isSet { + return true + } + } + + f := lookupFlag(name, c) + if f == nil { + return false + } + + return f.IsSet() + } + + return false +} + +// LocalFlagNames returns a slice of flag names used in this context. +func (c *Context) LocalFlagNames() []string { + var names []string + c.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 (c *Context) FlagNames() []string { + var names []string + for _, ctx := range c.Lineage() { + ctx.flagSet.Visit(makeFlagNameVisitor(&names)) + } + return names +} + +// Lineage returns *this* context and all of its ancestor contexts in order from +// child to parent +func (c *Context) Lineage() []*Context { + var lineage []*Context + + for cur := c; cur != nil; cur = cur.parentContext { + lineage = append(lineage, cur) + } + + return lineage +} + +// Value returns the value of the flag corresponding to `name` +func (c *Context) Value(name string) interface{} { + return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +} + +// Args returns the command line arguments associated with the context. +func (c *Context) Args() Args { + ret := args(c.flagSet.Args()) + return &ret +} + +// NArg returns the number of the command line arguments. +func (c *Context) NArg() int { + return c.Args().Len() +} + +func lookupFlag(name string, ctx *Context) Flag { + for _, c := range ctx.Lineage() { + if c.Command == nil { + continue + } + + for _, f := range c.Command.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + if ctx.App != nil { + for _, f := range ctx.App.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + return nil +} + +func lookupFlagSet(name string, ctx *Context) *flag.FlagSet { + for _, c := range ctx.Lineage() { + if f := c.flagSet.Lookup(name); f != nil { + return c.flagSet + } + } + + return 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 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) + } + } +} + +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 f.Names() { + if len(key) > 1 { + flagName = key + } + + if context.IsSet(strings.TrimSpace(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/v2/docs.go b/vendor/github.com/urfave/cli/v2/docs.go new file mode 100644 index 000000000..dc16fc82d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/docs.go @@ -0,0 +1,148 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "sort" + "strings" + "text/template" + + "github.com/cpuguy83/go-md2man/v2/md2man" +) + +// ToMarkdown creates a markdown string for the `*App` +// 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 { + return "", err + } + return w.String(), 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) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + man := md2man.Render(w.Bytes()) + return string(man), nil +} + +type cliTemplate struct { + App *App + Commands []string + GlobalArgs []string + SynopsisArgs []string +} + +func (a *App) writeDocTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(MarkdownDocTemplate) + if err != nil { + return err + } + return t.ExecuteTemplate(w, name, &cliTemplate{ + App: a, + Commands: prepareCommands(a.Commands, 0), + GlobalArgs: prepareArgsWithValues(a.VisibleFlags()), + SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()), + }) +} + +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", + strings.Repeat("#", level+2), + strings.Join(command.Names(), ", "), + usage, + ) + + flags := prepareArgsWithValues(command.Flags) + if len(flags) > 0 { + prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n")) + } + + coms = append(coms, prepared) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + coms = append( + coms, + prepareCommands(command.Subcommands, level+1)..., + ) + } + } + + return coms +} + +func prepareArgsWithValues(flags []Flag) []string { + return prepareFlags(flags, ", ", "**", "**", `""`, true) +} + +func prepareArgsSynopsis(flags []Flag) []string { + return prepareFlags(flags, "|", "[", "]", "[value]", false) +} + +func prepareFlags( + flags []Flag, + sep, opener, closer, value string, + addDetails bool, +) []string { + args := []string{} + for _, f := range flags { + flag, ok := f.(DocGenerationFlag) + if !ok { + continue + } + modifiedArg := opener + + for _, s := range flag.Names() { + trimmed := strings.TrimSpace(s) + if len(modifiedArg) > len(opener) { + modifiedArg += sep + } + if len(trimmed) > 1 { + modifiedArg += fmt.Sprintf("--%s", trimmed) + } else { + modifiedArg += fmt.Sprintf("-%s", trimmed) + } + } + modifiedArg += closer + if flag.TakesValue() { + modifiedArg += fmt.Sprintf("=%s", value) + } + + if addDetails { + modifiedArg += flagDetails(flag) + } + + args = append(args, modifiedArg+"\n") + + } + sort.Strings(args) + return args +} + +// flagDetails returns a string containing the flags metadata +func flagDetails(flag DocGenerationFlag) string { + description := flag.GetUsage() + value := flag.GetValue() + if value != "" { + description += " (default: " + value + ")" + } + return ": " + description +} 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..751ef9b16 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/errors.go @@ -0,0 +1,141 @@ +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 +} + +// 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/v2/fish.go b/vendor/github.com/urfave/cli/v2/fish.go new file mode 100644 index 000000000..588e070ea --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/fish.go @@ -0,0 +1,196 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "strings" + "text/template" +) + +// ToFishCompletion creates a fish completion string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToFishCompletion() (string, error) { + var w bytes.Buffer + if err := a.writeFishCompletionTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +type fishCompletionTemplate struct { + App *App + Completions []string + AllCommands []string +} + +func (a *App) writeFishCompletionTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(FishCompletionTemplate) + if err != nil { + return err + } + allCommands := []string{} + + // Add global flags + completions := a.prepareFishFlags(a.VisibleFlags(), allCommands) + + // Add help flag + if !a.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, allCommands)..., + ) + } + + // Add version flag + if !a.HideVersion { + completions = append( + completions, + a.prepareFishFlags([]Flag{VersionFlag}, allCommands)..., + ) + } + + // Add commands and their flags + completions = append( + completions, + a.prepareFishCommands(a.VisibleCommands(), &allCommands, []string{})..., + ) + + return t.ExecuteTemplate(w, name, &fishCompletionTemplate{ + App: a, + Completions: completions, + AllCommands: allCommands, + }) +} + +func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, previousCommands []string) []string { + completions := []string{} + for _, command := range commands { + if command.Hidden { + continue + } + + var completion strings.Builder + completion.WriteString(fmt.Sprintf( + "complete -r -c %s -n '%s' -a '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + strings.Join(command.Names(), " "), + )) + + if command.Usage != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(command.Usage))) + } + + if !command.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, command.Names())..., + ) + } + + *allCommands = append(*allCommands, command.Names()...) + completions = append(completions, completion.String()) + completions = append( + completions, + a.prepareFishFlags(command.Flags, command.Names())..., + ) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + completions = append( + completions, + a.prepareFishCommands( + command.Subcommands, allCommands, command.Names(), + )..., + ) + } + } + + return completions +} + +func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string { + completions := []string{} + for _, f := range flags { + flag, ok := f.(DocGenerationFlag) + if !ok { + continue + } + + completion := &strings.Builder{} + completion.WriteString(fmt.Sprintf( + "complete -c %s -n '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + )) + + fishAddFileFlag(f, completion) + + for idx, opt := range flag.Names() { + if idx == 0 { + completion.WriteString(fmt.Sprintf( + " -l %s", strings.TrimSpace(opt), + )) + } else { + completion.WriteString(fmt.Sprintf( + " -s %s", strings.TrimSpace(opt), + )) + + } + } + + if flag.TakesValue() { + completion.WriteString(" -r") + } + + if flag.GetUsage() != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(flag.GetUsage()))) + } + + completions = append(completions, completion.String()) + } + + return completions +} + +func fishAddFileFlag(flag Flag, completion *strings.Builder) { + switch f := flag.(type) { + case *GenericFlag: + if f.TakesFile { + return + } + case *StringFlag: + if f.TakesFile { + return + } + case *StringSliceFlag: + if f.TakesFile { + return + } + case *PathFlag: + if f.TakesFile { + return + } + } + completion.WriteString(" -f") +} + +func (a *App) fishSubcommandHelper(allCommands []string) string { + fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", a.Name) + if len(allCommands) > 0 { + fishHelper = fmt.Sprintf( + "__fish_seen_subcommand_from %s", + strings.Join(allCommands, " "), + ) + } + return fishHelper + +} + +func escapeSingleQuotes(input string) string { + return strings.Replace(input, `'`, `\'`, -1) +} 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..ad97c2d05 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag.go @@ -0,0 +1,388 @@ +package cli + +import ( + "flag" + "fmt" + "io/ioutil" + "reflect" + "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 +} + +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 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(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 envVars != nil && 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 flagStringSliceField(f Flag, name string) []string { + fv := flagValue(f) + field := fv.FieldByName(name) + + if field.IsValid() { + return field.Interface().([]string) + } + + return []string{} +} + +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 formatDefault(format string) string { + return " (default: " + format + ")" +} + +func stringifyFlag(f Flag) string { + fv := flagValue(f) + + switch f := f.(type) { + case *IntSliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyIntSliceFlag(f)) + case *Int64SliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyInt64SliceFlag(f)) + case *Float64SliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyFloat64SliceFlag(f)) + case *StringSliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyStringSliceFlag(f)) + } + + placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) + + needsPlaceholder := false + defaultValueString := "" + val := fv.FieldByName("Value") + if val.IsValid() { + needsPlaceholder = val.Kind() != reflect.Bool + defaultValueString = fmt.Sprintf(formatDefault("%v"), val.Interface()) + + if val.Kind() == reflect.String && val.String() != "" { + defaultValueString = fmt.Sprintf(formatDefault("%q"), val.String()) + } + } + + helpText := fv.FieldByName("DefaultText") + if helpText.IsValid() && helpText.String() != "" { + needsPlaceholder = val.Kind() != reflect.Bool + defaultValueString = fmt.Sprintf(formatDefault("%s"), helpText.String()) + } + + if defaultValueString == formatDefault("") { + defaultValueString = "" + } + + if needsPlaceholder && placeholder == "" { + placeholder = defaultPlaceholder + } + + usageWithDefault := strings.TrimSpace(usage + defaultValueString) + + return withEnvHint(flagStringSliceField(f, "EnvVars"), + fmt.Sprintf("%s\t%s", prefixedNames(f.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)) + return fmt.Sprintf("%s\t%s", prefixedNames(names, placeholder), usageWithDefault) +} + +func hasFlag(flags []Flag, fl Flag) bool { + for _, existing := range flags { + if fl == existing { + return true + } + } + + return false +} + +func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool) { + for _, envVar := range envVars { + envVar = strings.TrimSpace(envVar) + if val, ok := syscall.Getenv(envVar); ok { + return val, true + } + } + for _, fileVar := range strings.Split(filePath, ",") { + if data, err := ioutil.ReadFile(fileVar); err == nil { + return string(data), true + } + } + return "", false +} 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..bc9ea35d0 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_bool.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value bool + DefaultText string + Destination *bool + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *BoolFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *BoolFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 "" +} + +// Apply populates the flag given the flag set and environment +func (f *BoolFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valBool, err := strconv.ParseBool(val) + + if err != nil { + return fmt.Errorf("could not parse %q as bool value for flag %s: %s", val, 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 +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (c *Context) Bool(name string) bool { + if fs := lookupFlagSet(name, c); 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..22a2e6720 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_duration.go @@ -0,0 +1,105 @@ +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 + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value time.Duration + DefaultText string + Destination *time.Duration + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *DurationFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *DurationFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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() +} + +// Apply populates the flag given the flag set and environment +func (f *DurationFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valDuration, err := time.ParseDuration(val) + + if err != nil { + return fmt.Errorf("could not parse %q as duration value for flag %s: %s", val, 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 +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (c *Context) Duration(name string) time.Duration { + if fs := lookupFlagSet(name, c); 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..91c778c87 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value float64 + DefaultText string + Destination *float64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64Flag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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) +} + +// Apply populates the flag given the flag set and environment +func (f *Float64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valFloat, err := strconv.ParseFloat(val, 10) + + if err != nil { + return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", val, 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 +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (c *Context) Float64(name string) float64 { + if fs := lookupFlagSet(name, c); 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..706ee6cd4 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go @@ -0,0 +1,163 @@ +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...)} +} + +// 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 + } + + tmp, err := strconv.ParseFloat(value, 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 { + return fmt.Sprintf("%#v", f.slice) +} + +// 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 +} + +// Float64SliceFlag is a flag with type *Float64Slice +type Float64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *Float64Slice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64SliceFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +} + +// 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 "" +} + +// Apply populates the flag given the flag set and environment +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + f.Value = &Float64Slice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as float64 slice value for flag %s: %s", f.Value, f.Name, err) + } + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &Float64Slice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Float64Slice looks up the value of a local Float64SliceFlag, returns +// nil if not found +func (c *Context) Float64Slice(name string) []float64 { + if fs := lookupFlagSet(name, c); 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 := 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..b0c8ff44d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_generic.go @@ -0,0 +1,108 @@ +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 + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value Generic + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *GenericFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *GenericFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f GenericFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err) + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + 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{} { + if fs := lookupFlagSet(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/v2/flag_int.go b/vendor/github.com/urfave/cli/v2/flag_int.go new file mode 100644 index 000000000..ac39d4a9e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value int + DefaultText string + Destination *int + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *IntFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, 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 +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (c *Context) Int(name string) int { + if fs := lookupFlagSet(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/v2/flag_int64.go b/vendor/github.com/urfave/cli/v2/flag_int64.go new file mode 100644 index 000000000..e09991269 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value int64 + DefaultText string + Destination *int64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64Flag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *Int64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, 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 +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (c *Context) Int64(name string) int64 { + if fs := lookupFlagSet(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/v2/flag_int64_slice.go b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go new file mode 100644 index 000000000..6c7fd9376 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go @@ -0,0 +1,159 @@ +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...)} +} + +// 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 + } + + tmp, err := strconv.ParseInt(value, 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 { + return fmt.Sprintf("%#v", i.slice) +} + +// 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 +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *Int64Slice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64SliceFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &Int64Slice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + 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) +} + +func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { + f := set.Lookup(name) + if f != nil { + if slice, ok := 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..4e0afc021 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int_slice.go @@ -0,0 +1,173 @@ +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...)} +} + +// 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 + } + + tmp, err := strconv.ParseInt(value, 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 { + return fmt.Sprintf("%#v", i.slice) +} + +// 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 +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *IntSlice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntSliceFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &IntSlice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + 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 { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupIntSlice(name, c.flagSet) + } + return nil +} + +func lookupIntSlice(name string, set *flag.FlagSet) []int { + f := set.Lookup(name) + if f != nil { + if slice, ok := 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..8070dc4b0 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_path.go @@ -0,0 +1,95 @@ +package cli + +import "flag" + +type PathFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value string + DefaultText string + Destination *string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *PathFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *PathFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +} + +// 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 +} + +// Apply populates the flag given the flag set and environment +func (f *PathFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + 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 +} + +// Path looks up the value of a local PathFlag, returns +// "" if not found +func (c *Context) Path(name string) string { + if fs := lookupFlagSet(name, c); 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..400bb532e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string.go @@ -0,0 +1,95 @@ +package cli + +import "flag" + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value string + DefaultText string + Destination *string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *StringFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + 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 +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (c *Context) String(name string) string { + if fs := lookupFlagSet(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/v2/flag_string_slice.go b/vendor/github.com/urfave/cli/v2/flag_string_slice.go new file mode 100644 index 000000000..35497032c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string_slice.go @@ -0,0 +1,180 @@ +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...)} +} + +// 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 + } + + s.slice = append(s.slice, value) + + 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 +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value *StringSlice + DefaultText string + HasBeenSet bool + Destination *StringSlice +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringSliceFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { + + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]string, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + + } + + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if f.Value == nil { + f.Value = &StringSlice{} + } + destination := f.Value + if f.Destination != nil { + destination = f.Destination + } + + for _, s := range strings.Split(val, ",") { + if err := destination.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, 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. + destination.hasBeenSet = false + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &StringSlice{} + } + + if f.Destination != nil { + set.Var(f.Destination, name, f.Usage) + continue + } + + 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 { + if fs := lookupFlagSet(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 { + if slice, ok := 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..0382a6b9d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_timestamp.go @@ -0,0 +1,154 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// Timestamp wrap to satisfy golang's flag interface. +type Timestamp struct { + timestamp *time.Time + hasBeenSet bool + layout string +} + +// 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 +} + +// Parses the string value to timestamp +func (t *Timestamp) Set(value string) error { + 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 +} + +// TimestampFlag is a flag with type time +type TimestampFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Layout string + Value *Timestamp + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *TimestampFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *TimestampFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +} + +// 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 { + return f.Value.timestamp.String() + } + return "" +} + +// 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) + + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err) + } + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(f.Value, name, f.Usage) + } + return nil +} + +// Timestamp gets the timestamp from a flag name +func (c *Context) Timestamp(name string) *time.Time { + if fs := lookupFlagSet(name, c); 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..2e5e76b0e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value uint + DefaultText string + Destination *uint + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *UintFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *UintFlag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +func (f *UintFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint value for flag %s: %s", val, 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) +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (c *Context) Uint(name string) uint { + if fs := lookupFlagSet(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/v2/flag_uint64.go b/vendor/github.com/urfave/cli/v2/flag_uint64.go new file mode 100644 index 000000000..8fc3289d8 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint64.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value uint64 + DefaultText string + Destination *uint64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Uint64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Uint64Flag) String() string { + return FlagStringer(f) +} + +// 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 +} + +// 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 +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", val, 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) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (c *Context) Uint64(name string) uint64 { + if fs := lookupFlagSet(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/v2/funcs.go b/vendor/github.com/urfave/cli/v2/funcs.go new file mode 100644 index 000000000..474c48faf --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/funcs.go @@ -0,0 +1,44 @@ +package cli + +// 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 +// the context is ready if a non-nil error is returned, no subcommands are run +type BeforeFunc 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 AfterFunc func(*Context) error + +// ActionFunc is the action to execute when no subcommands are specified +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 +// 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 + +// 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) + +// FlagStringFunc is used by the help generation to display a flag, which is +// expected to be a single line. +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 []string, placeholder string) string + +// FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help +// with the environment variable details. +type FlagEnvHintFunc func(envVars []string, str string) string + +// FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help +// with the file path details. +type FlagFileHintFunc func(filePath, str string) string diff --git a/vendor/github.com/urfave/cli/v2/go.mod b/vendor/github.com/urfave/cli/v2/go.mod new file mode 100644 index 000000000..113966432 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/go.mod @@ -0,0 +1,9 @@ +module github.com/urfave/cli/v2 + +go 1.11 + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d + gopkg.in/yaml.v2 v2.2.3 +) diff --git a/vendor/github.com/urfave/cli/v2/go.sum b/vendor/github.com/urfave/cli/v2/go.sum new file mode 100644 index 000000000..663ad7276 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/go.sum @@ -0,0 +1,14 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +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/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= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/urfave/cli/v2/help.go b/vendor/github.com/urfave/cli/v2/help.go new file mode 100644 index 000000000..0a421ee99 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/help.go @@ -0,0 +1,386 @@ +package cli + +import ( + "fmt" + "io" + "os" + "strings" + "text/tabwriter" + "text/template" + "unicode/utf8" +) + +var helpCommand = &Command{ + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", + Action: func(c *Context) error { + args := c.Args() + if args.Present() { + return ShowCommandHelp(c, args.First()) + } + + _ = ShowAppHelp(c) + return nil + }, +} + +var helpSubcommand = &Command{ + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", + Action: func(c *Context) error { + args := c.Args() + if args.Present() { + return ShowCommandHelp(c, args.First()) + } + + return ShowSubcommandHelp(c) + }, +} + +// Prints help for the App or Command +type helpPrinter func(w io.Writer, templ string, data interface{}) + +// Prints help for the App or Command with custom template function. +type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{}) + +// 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 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. +var HelpPrinterCustom helpPrinterCustom = printHelpCustom + +// VersionPrinter prints the version for the App +var VersionPrinter = printVersion + +// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code. +func ShowAppHelpAndExit(c *Context, exitCode int) { + _ = ShowAppHelp(c) + os.Exit(exitCode) +} + +// ShowAppHelp is an action that displays the help. +func ShowAppHelp(c *Context) error { + tpl := c.App.CustomAppHelpTemplate + if tpl == "" { + tpl = AppHelpTemplate + } + + if c.App.ExtraInfo == nil { + HelpPrinter(c.App.Writer, tpl, c.App) + return nil + } + + customAppData := func() map[string]interface{} { + return map[string]interface{}{ + "ExtraInfo": c.App.ExtraInfo, + } + } + HelpPrinterCustom(c.App.Writer, tpl, c.App, customAppData()) + + return nil +} + +// DefaultAppComplete prints the list of subcommands as the default app completion method +func DefaultAppComplete(c *Context) { + DefaultCompleteWithFlags(nil)(c) +} + +func printCommandSuggestions(commands []*Command, writer io.Writer) { + for _, command := range commands { + if command.Hidden { + continue + } + if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + for _, name := range command.Names() { + _, _ = fmt.Fprintf(writer, "%s:%s\n", name, command.Usage) + } + } else { + for _, name := range command.Names() { + _, _ = fmt.Fprintf(writer, "%s\n", name) + } + } + } +} + +func cliArgContains(flagName string) bool { + for _, name := range strings.Split(flagName, ",") { + name = strings.TrimSpace(name) + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 + } + flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + for _, a := range os.Args { + if a == flag { + return true + } + } + } + return false +} + +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 { + continue + } + for _, name := range flag.Names() { + name = strings.TrimSpace(name) + // this will get total count utf8 letters in flag name + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 // resuse this count to generate single - or -- in flag completion + } + // if flag name has more than one utf8 letter and last argument in cli has -- prefix then + // skip flag completion for short flags example -v or -x + if strings.HasPrefix(lastArg, "--") && count == 1 { + continue + } + // match if last argument matches this flag and it is not repeated + if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(name) { + flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + _, _ = fmt.Fprintln(writer, flagCompletion) + } + } + } +} + +func DefaultCompleteWithFlags(cmd *Command) func(c *Context) { + return func(c *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) + } + return + } + } + if cmd != nil { + printCommandSuggestions(cmd.Subcommands, c.App.Writer) + } else { + printCommandSuggestions(c.App.Commands, c.App.Writer) + } + } +} + +// ShowCommandHelpAndExit - exits with code after showing help +func ShowCommandHelpAndExit(c *Context, command string, code int) { + _ = ShowCommandHelp(c, command) + os.Exit(code) +} + +// ShowCommandHelp prints help for the given command +func ShowCommandHelp(ctx *Context, command string) error { + // show the subcommand help for a command with subcommands + if command == "" { + HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) + return nil + } + + for _, c := range ctx.App.Commands { + if c.HasName(command) { + templ := c.CustomHelpTemplate + if templ == "" { + templ = CommandHelpTemplate + } + + HelpPrinter(ctx.App.Writer, templ, c) + + return nil + } + } + + if ctx.App.CommandNotFound == nil { + return Exit(fmt.Sprintf("No help topic for '%v'", command), 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 { + if c == nil { + return nil + } + + if c.Command != nil { + return ShowCommandHelp(c, c.Command.Name) + } + + return ShowCommandHelp(c, "") +} + +// ShowVersion prints the version number of the App +func ShowVersion(c *Context) { + VersionPrinter(c) +} + +func printVersion(c *Context) { + _, _ = fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) +} + +// ShowCompletions prints the lists of commands within a given context +func ShowCompletions(c *Context) { + a := c.App + if a != nil && a.BashComplete != nil { + a.BashComplete(c) + } +} + +// ShowCommandCompletions prints the custom completions for a given command +func ShowCommandCompletions(ctx *Context, command string) { + c := ctx.App.Command(command) + if c != nil { + if c.BashComplete != nil { + c.BashComplete(ctx) + } else { + DefaultCompleteWithFlags(c)(ctx) + } + } + +} + +// printHelpCustom is the default implementation of HelpPrinterCustom. +// +// 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{}) { + funcMap := template.FuncMap{ + "join": strings.Join, + "indent": indent, + "nindent": nindent, + "trim": strings.TrimSpace, + } + 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 + // we can do to recover. + if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" { + _, _ = fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err) + } + return + } + _ = w.Flush() +} + +func printHelp(out io.Writer, templ string, data interface{}) { + HelpPrinterCustom(out, templ, data, nil) +} + +func checkVersion(c *Context) bool { + found := false + for _, name := range VersionFlag.Names() { + if c.Bool(name) { + found = true + } + } + return found +} + +func checkHelp(c *Context) bool { + found := false + for _, name := range HelpFlag.Names() { + if c.Bool(name) { + found = true + } + } + return found +} + +func checkCommandHelp(c *Context, name string) bool { + if c.Bool("h") || c.Bool("help") { + _ = ShowCommandHelp(c, name) + return true + } + + return false +} + +func checkSubcommandHelp(c *Context) bool { + if c.Bool("h") || c.Bool("help") { + _ = ShowSubcommandHelp(c) + return true + } + + return false +} + +func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { + if !a.EnableBashCompletion { + return false, arguments + } + + pos := len(arguments) - 1 + lastArg := arguments[pos] + + if lastArg != "--generate-bash-completion" { + return false, arguments + } + + return true, arguments[:pos] +} + +func checkCompletions(c *Context) bool { + if !c.shellComplete { + return false + } + + if args := c.Args(); args.Present() { + name := args.First() + if cmd := c.App.Command(name); cmd != nil { + // let the command handle the completion + return false + } + } + + ShowCompletions(c) + return true +} + +func checkCommandCompletions(c *Context, name string) bool { + if !c.shellComplete { + return false + } + + 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) +} diff --git a/vendor/github.com/urfave/cli/v2/parse.go b/vendor/github.com/urfave/cli/v2/parse.go new file mode 100644 index 000000000..7df17296a --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/parse.go @@ -0,0 +1,94 @@ +package cli + +import ( + "flag" + "strings" +) + +type iterativeParser interface { + newFlagSet() (*flag.FlagSet, error) + useShortOptionHandling() bool +} + +// To enable short-option handling (e.g., "-it" vs "-i -t") we have to +// iteratively catch parsing errors. This way we achieve LR parsing without +// transforming any arguments. Otherwise, there is no way we can discriminate +// combined short options from common arguments that should be left untouched. +// Pass `shellComplete` to continue parsing options on failure during shell +// completion when, the user-supplied options may be incomplete. +func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error { + for { + err := set.Parse(args) + if !ip.useShortOptionHandling() || err == nil { + if shellComplete { + return nil + } + return err + } + + errStr := err.Error() + trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") + if errStr == trimmed { + return err + } + + // regenerate the initial args with the split short opts + argsWereSplit := false + for i, arg := range args { + // skip args that are not part of the error message + if name := strings.TrimLeft(arg, "-"); name != trimmed { + continue + } + + // if we can't split, the error was accurate + shortOpts := splitShortOptions(set, arg) + if len(shortOpts) == 1 { + return err + } + + // swap current argument with the split version + args = append(args[:i], append(shortOpts, args[i+1:]...)...) + argsWereSplit = true + break + } + + // This should be an impossible to reach code path, but in case the arg + // splitting failed to happen, this will prevent infinite loops + if !argsWereSplit { + return err + } + + // Since custom parsing failed, replace the flag set before retrying + newSet, err := ip.newFlagSet() + if err != nil { + return err + } + *set = *newSet + } +} + +func splitShortOptions(set *flag.FlagSet, arg string) []string { + shortFlagsExist := func(s string) bool { + for _, c := range s[1:] { + if f := set.Lookup(string(c)); f == nil { + return false + } + } + return true + } + + if !isSplittable(arg) || !shortFlagsExist(arg) { + return []string{arg} + } + + separated := make([]string, 0, len(arg)-1) + for _, flagChar := range arg[1:] { + separated = append(separated, "-"+string(flagChar)) + } + + return separated +} + +func isSplittable(flagArg string) bool { + return strings.HasPrefix(flagArg, "-") && !strings.HasPrefix(flagArg, "--") && len(flagArg) > 2 +} diff --git a/vendor/github.com/urfave/cli/v2/sort.go b/vendor/github.com/urfave/cli/v2/sort.go new file mode 100644 index 000000000..23d1c2f77 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/sort.go @@ -0,0 +1,29 @@ +package cli + +import "unicode" + +// lexicographicLess compares strings alphabetically considering case. +func lexicographicLess(i, j string) bool { + iRunes := []rune(i) + jRunes := []rune(j) + + lenShared := len(iRunes) + if lenShared > len(jRunes) { + lenShared = len(jRunes) + } + + for index := 0; index < lenShared; index++ { + ir := iRunes[index] + jr := jRunes[index] + + if lir, ljr := unicode.ToLower(ir), unicode.ToLower(jr); lir != ljr { + return lir < ljr + } + + if ir != jr { + return ir < jr + } + } + + return i < j +} diff --git a/vendor/github.com/urfave/cli/v2/template.go b/vendor/github.com/urfave/cli/v2/template.go new file mode 100644 index 000000000..31c03f81c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/template.go @@ -0,0 +1,120 @@ +package cli + +// 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 AppHelpTemplate = `NAME: + {{.Name}}{{if .Usage}} - {{.Usage}}{{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}} + +VERSION: + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description | nindent 3 | trim}}{{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}} + +GLOBAL OPTIONS: + {{range $index, $option := .VisibleFlags}}{{if $index}} + {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} + +COPYRIGHT: + {{.Copyright}}{{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}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + +CATEGORY: + {{.Category}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description | nindent 3 | trim}}{{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 SubcommandHelpTemplate = `NAME: + {{.HelpName}} - {{.Usage}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description | nindent 3 | trim}}{{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}} +` + +var MarkdownDocTemplate = `% {{ .App.Name }} 8 + +# NAME + +{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} + +# SYNOPSIS + +{{ .App.Name }} +{{ if .SynopsisArgs }} +` + "```" + ` +{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` +{{ end }}{{ if .App.UsageText }} +# DESCRIPTION + +{{ .App.UsageText }} +{{ end }} +**Usage**: + +` + "```" + ` +{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +` + "```" + ` +{{ if .GlobalArgs }} +# GLOBAL OPTIONS +{{ range $v := .GlobalArgs }} +{{ $v }}{{ end }} +{{ end }}{{ if .Commands }} +# COMMANDS +{{ range $v := .Commands }} +{{ $v }}{{ end }}{{ end }}` + +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 }}` diff --git a/vendor/modules.txt b/vendor/modules.txt index eeeb213b1..358b63c19 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -27,7 +27,8 @@ github.com/cespare/xxhash/v2 github.com/containerd/containerd/errdefs github.com/containerd/containerd/log github.com/containerd/containerd/platforms -# github.com/cpuguy83/go-md2man/v2 v2.0.0 +# github.com/cpuguy83/go-md2man/v2 v2.0.1 +## explicit github.com/cpuguy83/go-md2man/v2/md2man # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew @@ -221,13 +222,11 @@ github.com/rs/zerolog/cmd/lint github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log -# github.com/russross/blackfriday/v2 v2.0.1 +# github.com/russross/blackfriday/v2 v2.1.0 github.com/russross/blackfriday/v2 # github.com/russross/meddler v1.0.1 ## explicit github.com/russross/meddler -# github.com/shurcooL/sanitized_anchor_name v1.0.0 -github.com/shurcooL/sanitized_anchor_name # github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus # github.com/stretchr/objx v0.3.0 @@ -244,9 +243,11 @@ github.com/tevino/abool ## explicit # github.com/ugorji/go/codec v1.2.6 github.com/ugorji/go/codec -# github.com/urfave/cli v1.22.4 -## explicit +# github.com/urfave/cli v1.22.2 github.com/urfave/cli +# github.com/urfave/cli/v2 v2.3.0 +## explicit +github.com/urfave/cli/v2 # github.com/woodpecker-ci/expr v0.0.0-20210628233344-164b8b3d0915 ## explicit github.com/woodpecker-ci/expr