Convert CLI to urfave v2

Followed the Migration Guide at https://cli.urfave.org/migrate-v1-to-v2/
The major changes not pointed out in the migration guide are:
- context.Args() no longer produces a []slice, so context.Args().Slice()
  in substitued
- All cli.Global***** are deprecated (the migration guide is somewhat
  unclear on this)

Signed-off-by: Derek Nola <derek.nola@suse.com>

Vendor in urfave cli/v2

Signed-off-by: Derek Nola <derek.nola@suse.com>

Fix NewStringSlice calls

Signed-off-by: Derek Nola <derek.nola@suse.com>
This commit is contained in:
Derek Nola 2024-02-12 10:51:13 -08:00
parent d4d228926c
commit 132485adb0
No known key found for this signature in database
GPG Key ID: 5E741CE7ED12510E
149 changed files with 11041 additions and 4693 deletions

View File

@ -34,14 +34,14 @@ import (
"github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var densityCommand = cli.Command{ var densityCommand = &cli.Command{
Name: "density", Name: "density",
Usage: "Stress tests density of containers running on a system", Usage: "Stress tests density of containers running on a system",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.IntFlag{ &cli.IntFlag{
Name: "count", Name: "count",
Usage: "Number of containers to run", Usage: "Number of containers to run",
Value: 10, Value: 10,
@ -58,14 +58,14 @@ var densityCommand = cli.Command{
} }
config := config{ config := config{
Address: cliContext.GlobalString("address"), Address: cliContext.String("address"),
Duration: cliContext.GlobalDuration("duration"), Duration: cliContext.Duration("duration"),
Concurrency: cliContext.GlobalInt("concurrent"), Concurrency: cliContext.Int("concurrent"),
Exec: cliContext.GlobalBool("exec"), Exec: cliContext.Bool("exec"),
Image: cliContext.GlobalString("image"), Image: cliContext.String("image"),
JSON: cliContext.GlobalBool("json"), JSON: cliContext.Bool("json"),
Metrics: cliContext.GlobalString("metrics"), Metrics: cliContext.String("metrics"),
Snapshotter: cliContext.GlobalString("snapshotter"), Snapshotter: cliContext.String("snapshotter"),
} }
client, err := config.newClient() client, err := config.newClient()
if err != nil { if err != nil {

View File

@ -34,7 +34,7 @@ import (
"github.com/containerd/containerd/v2/plugins" "github.com/containerd/containerd/v2/plugins"
"github.com/containerd/log" "github.com/containerd/log"
metrics "github.com/docker/go-metrics" metrics "github.com/docker/go-metrics"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var ( var (
@ -63,8 +63,9 @@ func init() {
panic(err) panic(err)
} }
cli.HelpFlag = cli.BoolFlag{ cli.HelpFlag = &cli.BoolFlag{
Name: "help, h", Name: "help",
Aliases: []string{"h"},
Usage: "Show help", Usage: "Show help",
} }
} }
@ -129,85 +130,91 @@ func main() {
app.Name = "containerd-stress" app.Name = "containerd-stress"
app.Description = "stress test a containerd daemon" app.Description = "stress test a containerd daemon"
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "debug", Name: "debug",
Usage: "Set debug output in the logs", Usage: "Set debug output in the logs",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "address,a", Name: "address",
Aliases: []string{"a"},
Value: "/run/containerd/containerd.sock", Value: "/run/containerd/containerd.sock",
Usage: "Path to the containerd socket", Usage: "Path to the containerd socket",
}, },
cli.IntFlag{ &cli.IntFlag{
Name: "concurrent,c", Name: "concurrent",
Aliases: []string{"c"},
Value: 1, Value: 1,
Usage: "Set the concurrency of the stress test", Usage: "Set the concurrency of the stress test",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "cri", Name: "cri",
Usage: "Utilize CRI to create pods for the stress test. This requires a runtime that matches CRI runtime handler. Example: --runtime runc", Usage: "Utilize CRI to create pods for the stress test. This requires a runtime that matches CRI runtime handler. Example: --runtime runc",
}, },
cli.DurationFlag{ &cli.DurationFlag{
Name: "duration,d", Name: "duration",
Aliases: []string{"d"},
Value: 1 * time.Minute, Value: 1 * time.Minute,
Usage: "Set the duration of the stress test", Usage: "Set the duration of the stress test",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "exec", Name: "exec",
Usage: "Add execs to the stress tests (non-CRI only)", Usage: "Add execs to the stress tests (non-CRI only)",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "image,i", Name: "image",
Aliases: []string{"i"},
Value: "docker.io/library/alpine:latest", Value: "docker.io/library/alpine:latest",
Usage: "Image to be utilized for testing", Usage: "Image to be utilized for testing",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "json,j", Name: "json",
Aliases: []string{"j"},
Usage: "Output results in json format", Usage: "Output results in json format",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "metrics,m", Name: "metrics",
Aliases: []string{"m"},
Usage: "Address to serve the metrics API", Usage: "Address to serve the metrics API",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "runtime", Name: "runtime",
Usage: "Set the runtime to stress test", Usage: "Set the runtime to stress test",
Value: plugins.RuntimeRuncV2, Value: plugins.RuntimeRuncV2,
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "snapshotter", Name: "snapshotter",
Usage: "Set the snapshotter to use", Usage: "Set the snapshotter to use",
Value: "overlayfs", Value: "overlayfs",
}, },
} }
app.Before = func(context *cli.Context) error { app.Before = func(context *cli.Context) error {
if context.GlobalBool("json") { if context.Bool("json") {
if err := log.SetLevel("warn"); err != nil { if err := log.SetLevel("warn"); err != nil {
return err return err
} }
} }
if context.GlobalBool("debug") { if context.Bool("debug") {
if err := log.SetLevel("debug"); err != nil { if err := log.SetLevel("debug"); err != nil {
return err return err
} }
} }
return nil return nil
} }
app.Commands = []cli.Command{ app.Commands = []*cli.Command{
densityCommand, densityCommand,
} }
app.Action = func(context *cli.Context) error { app.Action = func(context *cli.Context) error {
config := config{ config := config{
Address: context.GlobalString("address"), Address: context.String("address"),
Duration: context.GlobalDuration("duration"), Duration: context.Duration("duration"),
Concurrency: context.GlobalInt("concurrent"), Concurrency: context.Int("concurrent"),
CRI: context.GlobalBool("cri"), CRI: context.Bool("cri"),
Exec: context.GlobalBool("exec"), Exec: context.Bool("exec"),
Image: context.GlobalString("image"), Image: context.String("image"),
JSON: context.GlobalBool("json"), JSON: context.Bool("json"),
Metrics: context.GlobalString("metrics"), Metrics: context.String("metrics"),
Runtime: context.GlobalString("runtime"), Runtime: context.String("runtime"),
Snapshotter: context.GlobalString("snapshotter"), Snapshotter: context.String("snapshotter"),
} }
if config.Metrics != "" { if config.Metrics != "" {
return serve(config) return serve(config)

View File

@ -29,7 +29,7 @@ import (
"github.com/containerd/plugin/registry" "github.com/containerd/plugin/registry"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pelletier/go-toml/v2" "github.com/pelletier/go-toml/v2"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func outputConfig(ctx gocontext.Context, config *srvconfig.Config) error { func outputConfig(ctx gocontext.Context, config *srvconfig.Config) error {
@ -78,10 +78,10 @@ func defaultConfig() *srvconfig.Config {
return platformAgnosticDefaultConfig() return platformAgnosticDefaultConfig()
} }
var configCommand = cli.Command{ var configCommand = &cli.Command{
Name: "config", Name: "config",
Usage: "Information on the containerd config", Usage: "Information on the containerd config",
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
{ {
Name: "default", Name: "default",
Usage: "See the output of the default config", Usage: "See the output of the default config",
@ -95,7 +95,7 @@ var configCommand = cli.Command{
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
config := defaultConfig() config := defaultConfig()
ctx := gocontext.Background() ctx := gocontext.Background()
if err := srvconfig.LoadConfig(ctx, context.GlobalString("config"), config); err != nil && !os.IsNotExist(err) { if err := srvconfig.LoadConfig(ctx, context.String("config"), config); err != nil && !os.IsNotExist(err) {
return err return err
} }
@ -108,7 +108,7 @@ var configCommand = cli.Command{
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
config := defaultConfig() config := defaultConfig()
ctx := gocontext.Background() ctx := gocontext.Background()
if err := srvconfig.LoadConfig(ctx, context.GlobalString("config"), config); err != nil && !os.IsNotExist(err) { if err := srvconfig.LoadConfig(ctx, context.String("config"), config); err != nil && !os.IsNotExist(err) {
return err return err
} }

View File

@ -36,7 +36,7 @@ import (
"github.com/containerd/containerd/v2/version" "github.com/containerd/containerd/v2/version"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
) )
@ -57,12 +57,14 @@ func init() {
cli.VersionPrinter = func(c *cli.Context) { cli.VersionPrinter = func(c *cli.Context) {
fmt.Println(c.App.Name, version.Package, c.App.Version, version.Revision) fmt.Println(c.App.Name, version.Package, c.App.Version, version.Revision)
} }
cli.VersionFlag = cli.BoolFlag{ cli.VersionFlag = &cli.BoolFlag{
Name: "version, v", Name: "version",
Aliases: []string{"v"},
Usage: "Print the version", Usage: "Print the version",
} }
cli.HelpFlag = cli.BoolFlag{ cli.HelpFlag = &cli.BoolFlag{
Name: "help, h", Name: "help",
Aliases: []string{"h"},
Usage: "Show help", Usage: "Show help",
} }
} }
@ -85,30 +87,33 @@ at the default file location. The *containerd config* command can be used to
generate the default configuration for containerd. The output of that command generate the default configuration for containerd. The output of that command
can be used and modified as necessary as a custom configuration.` can be used and modified as necessary as a custom configuration.`
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "config,c", Name: "config",
Aliases: []string{"c"},
Usage: "Path to the configuration file", Usage: "Path to the configuration file",
Value: filepath.Join(defaults.DefaultConfigDir, "config.toml"), Value: filepath.Join(defaults.DefaultConfigDir, "config.toml"),
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "log-level,l", Name: "log-level",
Aliases: []string{"l"},
Usage: "Set the logging level [trace, debug, info, warn, error, fatal, panic]", Usage: "Set the logging level [trace, debug, info, warn, error, fatal, panic]",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "address,a", Name: "address",
Aliases: []string{"a"},
Usage: "Address for containerd's GRPC server", Usage: "Address for containerd's GRPC server",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "root", Name: "root",
Usage: "containerd root directory", Usage: "containerd root directory",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "state", Name: "state",
Usage: "containerd state directory", Usage: "containerd state directory",
}, },
} }
app.Flags = append(app.Flags, serviceFlags()...) app.Flags = append(app.Flags, serviceFlags()...)
app.Commands = []cli.Command{ app.Commands = []*cli.Command{
configCommand, configCommand,
publishCommand, publishCommand,
ociHook, ociHook,
@ -126,9 +131,9 @@ can be used and modified as necessary as a custom configuration.`
// Only try to load the config if it either exists, or the user explicitly // Only try to load the config if it either exists, or the user explicitly
// told us to load this path. // told us to load this path.
configPath := context.GlobalString("config") configPath := context.String("config")
_, err := os.Stat(configPath) _, err := os.Stat(configPath)
if !os.IsNotExist(err) || context.GlobalIsSet("config") { if !os.IsNotExist(err) || context.IsSet("config") {
if err := srvconfig.LoadConfig(ctx, configPath, config); err != nil { if err := srvconfig.LoadConfig(ctx, configPath, config); err != nil {
return err return err
} }
@ -336,7 +341,7 @@ func applyFlags(context *cli.Context, config *srvconfig.Config) error {
d: &config.GRPC.Address, d: &config.GRPC.Address,
}, },
} { } {
if s := context.GlobalString(v.name); s != "" { if s := context.String(v.name); s != "" {
*v.d = s *v.d = s
if v.name == "root" || v.name == "state" { if v.name == "root" || v.name == "state" {
absPath, err := filepath.Abs(s) absPath, err := filepath.Abs(s)
@ -354,7 +359,7 @@ func applyFlags(context *cli.Context, config *srvconfig.Config) error {
} }
func setLogLevel(context *cli.Context, config *srvconfig.Config) error { func setLogLevel(context *cli.Context, config *srvconfig.Config) error {
l := context.GlobalString("log-level") l := context.String("log-level")
if l == "" { if l == "" {
l = config.Debug.Level l = config.Debug.Level
} }

View File

@ -27,10 +27,10 @@ import (
"github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/pkg/oci"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var ociHook = cli.Command{ var ociHook = &cli.Command{
Name: "oci-hook", Name: "oci-hook",
Usage: "Provides a base for OCI runtime hooks to allow arguments to be injected.", Usage: "Provides a base for OCI runtime hooks to allow arguments to be injected.",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
@ -45,7 +45,7 @@ var ociHook = cli.Command{
} }
var ( var (
ctx = newTemplateContext(state, spec) ctx = newTemplateContext(state, spec)
args = []string(context.Args()) args = context.Args().Slice()
env = os.Environ() env = os.Environ()
) )
if err := newList(&args).render(ctx); err != nil { if err := newList(&args).render(ctx); err != nil {

View File

@ -30,21 +30,21 @@ import (
"github.com/containerd/containerd/v2/protobuf/proto" "github.com/containerd/containerd/v2/protobuf/proto"
"github.com/containerd/containerd/v2/protobuf/types" "github.com/containerd/containerd/v2/protobuf/types"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/backoff" "google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
) )
var publishCommand = cli.Command{ var publishCommand = &cli.Command{
Name: "publish", Name: "publish",
Usage: "Binary to publish events to containerd", Usage: "Binary to publish events to containerd",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "namespace", Name: "namespace",
Usage: "Namespace to publish to", Usage: "Namespace to publish to",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "topic", Name: "topic",
Usage: "Topic of the event", Usage: "Topic of the event",
}, },
@ -59,7 +59,7 @@ var publishCommand = cli.Command{
if err != nil { if err != nil {
return err return err
} }
client, err := connectEvents(context.GlobalString("address")) client, err := connectEvents(context.String("address"))
if err != nil { if err != nil {
return err return err
} }

View File

@ -20,7 +20,7 @@ package command
import ( import (
"github.com/containerd/containerd/v2/cmd/containerd/server" "github.com/containerd/containerd/v2/cmd/containerd/server"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// serviceFlags returns an array of flags for configuring containerd to run // serviceFlags returns an array of flags for configuring containerd to run

View File

@ -27,7 +27,7 @@ import (
"github.com/containerd/containerd/v2/cmd/containerd/server" "github.com/containerd/containerd/v2/cmd/containerd/server"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug" "golang.org/x/sys/windows/svc/debug"
@ -53,25 +53,25 @@ const defaultServiceName = "containerd"
// as a Windows service under control of SCM. // as a Windows service under control of SCM.
func serviceFlags() []cli.Flag { func serviceFlags() []cli.Flag {
return []cli.Flag{ return []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "service-name", Name: "service-name",
Usage: "Set the Windows service name", Usage: "Set the Windows service name",
Value: defaultServiceName, Value: defaultServiceName,
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "register-service", Name: "register-service",
Usage: "Register the service and exit", Usage: "Register the service and exit",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "unregister-service", Name: "unregister-service",
Usage: "Unregister the service and exit", Usage: "Unregister the service and exit",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "run-service", Name: "run-service",
Usage: "", Usage: "",
Hidden: true, Hidden: true,
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "log-file", Name: "log-file",
Usage: "Path to the containerd log file", Usage: "Path to the containerd log file",
}, },
@ -80,7 +80,7 @@ func serviceFlags() []cli.Flag {
// applyPlatformFlags applies platform-specific flags. // applyPlatformFlags applies platform-specific flags.
func applyPlatformFlags(context *cli.Context) { func applyPlatformFlags(context *cli.Context) {
serviceNameFlag = context.GlobalString("service-name") serviceNameFlag = context.String("service-name")
if serviceNameFlag == "" { if serviceNameFlag == "" {
serviceNameFlag = defaultServiceName serviceNameFlag = defaultServiceName
} }
@ -101,9 +101,9 @@ func applyPlatformFlags(context *cli.Context) {
d: &runServiceFlag, d: &runServiceFlag,
}, },
} { } {
*v.d = context.GlobalBool(v.name) *v.d = context.Bool(v.name)
} }
logFileFlag = context.GlobalString("log-file") logFileFlag = context.String("log-file")
} }
type handler struct { type handler struct {

View File

@ -21,7 +21,7 @@ import (
"io" "io"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"github.com/containerd/containerd/v2/cmd/ctr/commands/containers" "github.com/containerd/containerd/v2/cmd/ctr/commands/containers"
@ -46,7 +46,7 @@ import (
"github.com/containerd/containerd/v2/version" "github.com/containerd/containerd/v2/version"
) )
var extraCmds = []cli.Command{} var extraCmds = []*cli.Command{}
func init() { func init() {
// Discard grpc logs so that they don't mess with our stdio // Discard grpc logs so that they don't mess with our stdio
@ -55,12 +55,14 @@ func init() {
cli.VersionPrinter = func(c *cli.Context) { cli.VersionPrinter = func(c *cli.Context) {
fmt.Println(c.App.Name, version.Package, c.App.Version) fmt.Println(c.App.Name, version.Package, c.App.Version)
} }
cli.VersionFlag = cli.BoolFlag{ cli.VersionFlag = &cli.BoolFlag{
Name: "version, v", Name: "version",
Aliases: []string{"v"},
Usage: "Print the version", Usage: "Print the version",
} }
cli.HelpFlag = cli.BoolFlag{ cli.HelpFlag = &cli.BoolFlag{
Name: "help, h", Name: "help",
Aliases: []string{"h"},
Usage: "Show help", Usage: "Show help",
} }
} }
@ -86,32 +88,34 @@ containerd CLI
` `
app.EnableBashCompletion = true app.EnableBashCompletion = true
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "debug", Name: "debug",
Usage: "Enable debug output in logs", Usage: "Enable debug output in logs",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "address, a", Name: "address",
Aliases: []string{"a"},
Usage: "Address for containerd's GRPC server", Usage: "Address for containerd's GRPC server",
Value: defaults.DefaultAddress, Value: defaults.DefaultAddress,
EnvVar: "CONTAINERD_ADDRESS", EnvVars: []string{"CONTAINERD_ADDRESS"},
}, },
cli.DurationFlag{ &cli.DurationFlag{
Name: "timeout", Name: "timeout",
Usage: "Total timeout for ctr commands", Usage: "Total timeout for ctr commands",
}, },
cli.DurationFlag{ &cli.DurationFlag{
Name: "connect-timeout", Name: "connect-timeout",
Usage: "Timeout for connecting to containerd", Usage: "Timeout for connecting to containerd",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "namespace, n", Name: "namespace",
Aliases: []string{"n"},
Usage: "Namespace to use with commands", Usage: "Namespace to use with commands",
Value: namespaces.Default, Value: namespaces.Default,
EnvVar: namespaces.NamespaceEnvVar, EnvVars: []string{namespaces.NamespaceEnvVar},
}, },
} }
app.Commands = append([]cli.Command{ app.Commands = append([]*cli.Command{
plugins.Command, plugins.Command,
versionCmd.Command, versionCmd.Command,
containers.Command, containers.Command,
@ -131,7 +135,7 @@ containerd CLI
deprecations.Command, deprecations.Command,
}, extraCmds...) }, extraCmds...)
app.Before = func(context *cli.Context) error { app.Before = func(context *cli.Context) error {
if context.GlobalBool("debug") { if context.Bool("debug") {
return log.SetLevel("debug") return log.SetLevel("debug")
} }
return nil return nil

View File

@ -23,7 +23,7 @@ import (
"github.com/containerd/containerd/v2/pkg/epoch" "github.com/containerd/containerd/v2/pkg/epoch"
"github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// AppContext returns the context for a command. Should only be called once per // AppContext returns the context for a command. Should only be called once per
@ -34,8 +34,8 @@ import (
func AppContext(context *cli.Context) (gocontext.Context, gocontext.CancelFunc) { func AppContext(context *cli.Context) (gocontext.Context, gocontext.CancelFunc) {
var ( var (
ctx = gocontext.Background() ctx = gocontext.Background()
timeout = context.GlobalDuration("timeout") timeout = context.Duration("timeout")
namespace = context.GlobalString("namespace") namespace = context.String("namespace")
cancel gocontext.CancelFunc cancel gocontext.CancelFunc
) )
ctx = namespaces.WithNamespace(ctx, namespace) ctx = namespaces.WithNamespace(ctx, namespace)
@ -55,9 +55,9 @@ func AppContext(context *cli.Context) (gocontext.Context, gocontext.CancelFunc)
// NewClient returns a new containerd client // NewClient returns a new containerd client
func NewClient(context *cli.Context, opts ...containerd.Opt) (*containerd.Client, gocontext.Context, gocontext.CancelFunc, error) { func NewClient(context *cli.Context, opts ...containerd.Opt) (*containerd.Client, gocontext.Context, gocontext.CancelFunc, error) {
timeoutOpt := containerd.WithTimeout(context.GlobalDuration("connect-timeout")) timeoutOpt := containerd.WithTimeout(context.Duration("connect-timeout"))
opts = append(opts, timeoutOpt) opts = append(opts, timeoutOpt)
client, err := containerd.New(context.GlobalString("address"), opts...) client, err := containerd.New(context.String("address"), opts...)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }

View File

@ -26,71 +26,73 @@ import (
"github.com/containerd/containerd/v2/defaults" "github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/atomicfile" "github.com/containerd/containerd/v2/pkg/atomicfile"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var ( var (
// SnapshotterFlags are cli flags specifying snapshotter names // SnapshotterFlags are cli flags specifying snapshotter names
SnapshotterFlags = []cli.Flag{ SnapshotterFlags = []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "snapshotter", Name: "snapshotter",
Usage: "Snapshotter name. Empty value stands for the default value.", Usage: "Snapshotter name. Empty value stands for the default value.",
EnvVar: "CONTAINERD_SNAPSHOTTER", EnvVars: []string{"CONTAINERD_SNAPSHOTTER"},
}, },
} }
// SnapshotterLabels are cli flags specifying labels which will be added to the new snapshot for container. // SnapshotterLabels are cli flags specifying labels which will be added to the new snapshot for container.
SnapshotterLabels = cli.StringSliceFlag{ SnapshotterLabels = &cli.StringSliceFlag{
Name: "snapshotter-label", Name: "snapshotter-label",
Usage: "Labels added to the new snapshot for this container.", Usage: "Labels added to the new snapshot for this container.",
} }
// LabelFlag is a cli flag specifying labels // LabelFlag is a cli flag specifying labels
LabelFlag = cli.StringSliceFlag{ LabelFlag = &cli.StringSliceFlag{
Name: "label", Name: "label",
Usage: "Labels to attach to the image", Usage: "Labels to attach to the image",
} }
// RegistryFlags are cli flags specifying registry options // RegistryFlags are cli flags specifying registry options
RegistryFlags = []cli.Flag{ RegistryFlags = []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-verify,k", Name: "skip-verify",
Aliases: []string{"k"},
Usage: "Skip SSL certificate validation", Usage: "Skip SSL certificate validation",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "plain-http", Name: "plain-http",
Usage: "Allow connections using plain HTTP", Usage: "Allow connections using plain HTTP",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "user,u", Name: "user",
Aliases: []string{"u"},
Usage: "User[:password] Registry user and password", Usage: "User[:password] Registry user and password",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "refresh", Name: "refresh",
Usage: "Refresh token for authorization server", Usage: "Refresh token for authorization server",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "hosts-dir", Name: "hosts-dir",
// compatible with "/etc/docker/certs.d" // compatible with "/etc/docker/certs.d"
Usage: "Custom hosts configuration directory", Usage: "Custom hosts configuration directory",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "tlscacert", Name: "tlscacert",
Usage: "Path to TLS root CA", Usage: "Path to TLS root CA",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "tlscert", Name: "tlscert",
Usage: "Path to TLS client certificate", Usage: "Path to TLS client certificate",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "tlskey", Name: "tlskey",
Usage: "Path to TLS client key", Usage: "Path to TLS client key",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "http-dump", Name: "http-dump",
Usage: "Dump all HTTP request/responses when interacting with container registry", Usage: "Dump all HTTP request/responses when interacting with container registry",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "http-trace", Name: "http-trace",
Usage: "Enable HTTP tracing for registry interactions", Usage: "Enable HTTP tracing for registry interactions",
}, },
@ -98,12 +100,12 @@ var (
// RuntimeFlags are cli flags specifying runtime // RuntimeFlags are cli flags specifying runtime
RuntimeFlags = []cli.Flag{ RuntimeFlags = []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "runtime", Name: "runtime",
Usage: "Runtime name or absolute path to runtime binary", Usage: "Runtime name or absolute path to runtime binary",
Value: defaults.DefaultRuntime, Value: defaults.DefaultRuntime,
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "runtime-config-path", Name: "runtime-config-path",
Usage: "Optional runtime config path", Usage: "Optional runtime config path",
}, },
@ -111,116 +113,119 @@ var (
// ContainerFlags are cli flags specifying container options // ContainerFlags are cli flags specifying container options
ContainerFlags = []cli.Flag{ ContainerFlags = []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "config,c", Name: "config",
Aliases: []string{"c"},
Usage: "Path to the runtime-specific spec config file", Usage: "Path to the runtime-specific spec config file",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "cwd", Name: "cwd",
Usage: "Specify the working directory of the process", Usage: "Specify the working directory of the process",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "env", Name: "env",
Usage: "Specify additional container environment variables (e.g. FOO=bar)", Usage: "Specify additional container environment variables (e.g. FOO=bar)",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "env-file", Name: "env-file",
Usage: "Specify additional container environment variables in a file(e.g. FOO=bar, one per line)", Usage: "Specify additional container environment variables in a file(e.g. FOO=bar, one per line)",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "label", Name: "label",
Usage: "Specify additional labels (e.g. foo=bar)", Usage: "Specify additional labels (e.g. foo=bar)",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "annotation", Name: "annotation",
Usage: "Specify additional OCI annotations (e.g. foo=bar)", Usage: "Specify additional OCI annotations (e.g. foo=bar)",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "mount", Name: "mount",
Usage: "Specify additional container mount (e.g. type=bind,src=/tmp,dst=/host,options=rbind:ro)", Usage: "Specify additional container mount (e.g. type=bind,src=/tmp,dst=/host,options=rbind:ro)",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "net-host", Name: "net-host",
Usage: "Enable host networking for the container", Usage: "Enable host networking for the container",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "privileged", Name: "privileged",
Usage: "Run privileged container", Usage: "Run privileged container",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "read-only", Name: "read-only",
Usage: "Set the containers filesystem as readonly", Usage: "Set the containers filesystem as readonly",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "sandbox", Name: "sandbox",
Usage: "Create the container in the given sandbox", Usage: "Create the container in the given sandbox",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "tty,t", Name: "tty",
Aliases: []string{"t"},
Usage: "Allocate a TTY for the container", Usage: "Allocate a TTY for the container",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "with-ns", Name: "with-ns",
Usage: "Specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')", Usage: "Specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "pid-file", Name: "pid-file",
Usage: "File path to write the task's pid", Usage: "File path to write the task's pid",
}, },
cli.IntSliceFlag{ &cli.IntSliceFlag{
Name: "gpus", Name: "gpus",
Usage: "Add gpus to the container", Usage: "Add gpus to the container",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "allow-new-privs", Name: "allow-new-privs",
Usage: "Turn off OCI spec's NoNewPrivileges feature flag", Usage: "Turn off OCI spec's NoNewPrivileges feature flag",
}, },
cli.Uint64Flag{ &cli.Uint64Flag{
Name: "memory-limit", Name: "memory-limit",
Usage: "Memory limit (in bytes) for the container", Usage: "Memory limit (in bytes) for the container",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "cap-add", Name: "cap-add",
Usage: "Add Linux capabilities (Set capabilities with 'CAP_' prefix)", Usage: "Add Linux capabilities (Set capabilities with 'CAP_' prefix)",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "cap-drop", Name: "cap-drop",
Usage: "Drop Linux capabilities (Set capabilities with 'CAP_' prefix)", Usage: "Drop Linux capabilities (Set capabilities with 'CAP_' prefix)",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "seccomp", Name: "seccomp",
Usage: "Enable the default seccomp profile", Usage: "Enable the default seccomp profile",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "seccomp-profile", Name: "seccomp-profile",
Usage: "File path to custom seccomp profile. seccomp must be set to true, before using seccomp-profile", Usage: "File path to custom seccomp profile. seccomp must be set to true, before using seccomp-profile",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "apparmor-default-profile", Name: "apparmor-default-profile",
Usage: "Enable AppArmor with the default profile with the specified name, e.g. \"cri-containerd.apparmor.d\"", Usage: "Enable AppArmor with the default profile with the specified name, e.g. \"cri-containerd.apparmor.d\"",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "apparmor-profile", Name: "apparmor-profile",
Usage: "Enable AppArmor with an existing custom profile", Usage: "Enable AppArmor with an existing custom profile",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "blockio-config-file", Name: "blockio-config-file",
Usage: "File path to blockio class definitions. By default class definitions are not loaded.", Usage: "File path to blockio class definitions. By default class definitions are not loaded.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "blockio-class", Name: "blockio-class",
Usage: "Name of the blockio class to associate the container with", Usage: "Name of the blockio class to associate the container with",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "rdt-class", Name: "rdt-class",
Usage: "Name of the RDT class to associate the container with. Specifies a Class of Service (CLOS) for cache and memory bandwidth management.", Usage: "Name of the RDT class to associate the container with. Specifies a Class of Service (CLOS) for cache and memory bandwidth management.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "hostname", Name: "hostname",
Usage: "Set the container's host name", Usage: "Set the container's host name",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "user,u", Name: "user",
Aliases: []string{"u"},
Usage: "Username or user id, group optional (format: <name|uid>[:<group|gid>])", Usage: "Username or user id, group optional (format: <name|uid>[:<group|gid>])",
}, },
} }

View File

@ -23,37 +23,37 @@ import (
"github.com/containerd/containerd/v2/core/runtime/v2/runc/options" "github.com/containerd/containerd/v2/core/runtime/v2/runc/options"
runtimeoptions "github.com/containerd/containerd/v2/pkg/runtimeoptions/v1" runtimeoptions "github.com/containerd/containerd/v2/pkg/runtimeoptions/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func init() { func init() {
RuntimeFlags = append(RuntimeFlags, cli.StringFlag{ RuntimeFlags = append(RuntimeFlags, &cli.StringFlag{
Name: "runc-binary", Name: "runc-binary",
Usage: "Specify runc-compatible binary", Usage: "Specify runc-compatible binary",
}, cli.StringFlag{ }, &cli.StringFlag{
Name: "runc-root", Name: "runc-root",
Usage: "Specify runc-compatible root", Usage: "Specify runc-compatible root",
}, cli.BoolFlag{ }, &cli.BoolFlag{
Name: "runc-systemd-cgroup", Name: "runc-systemd-cgroup",
Usage: "Start runc with systemd cgroup manager", Usage: "Start runc with systemd cgroup manager",
}) })
ContainerFlags = append(ContainerFlags, cli.BoolFlag{ ContainerFlags = append(ContainerFlags, &cli.BoolFlag{
Name: "rootfs", Name: "rootfs",
Usage: "Use custom rootfs that is not managed by containerd snapshotter", Usage: "Use custom rootfs that is not managed by containerd snapshotter",
}, cli.BoolFlag{ }, &cli.BoolFlag{
Name: "no-pivot", Name: "no-pivot",
Usage: "Disable use of pivot-root (linux only)", Usage: "Disable use of pivot-root (linux only)",
}, cli.Int64Flag{ }, &cli.Int64Flag{
Name: "cpu-quota", Name: "cpu-quota",
Usage: "Limit CPU CFS quota", Usage: "Limit CPU CFS quota",
Value: -1, Value: -1,
}, cli.Uint64Flag{ }, &cli.Uint64Flag{
Name: "cpu-period", Name: "cpu-period",
Usage: "Limit CPU CFS period", Usage: "Limit CPU CFS period",
}, cli.StringFlag{ }, &cli.StringFlag{
Name: "rootfs-propagation", Name: "rootfs-propagation",
Usage: "Set the propagation of the container rootfs", Usage: "Set the propagation of the container rootfs",
}, cli.StringSliceFlag{ }, &cli.StringSliceFlag{
Name: "device", Name: "device",
Usage: "File path to a device to add to the container; or a path to a directory tree of devices to add to the container", Usage: "File path to a device to add to the container; or a path to a directory tree of devices to add to the container",
}) })

View File

@ -17,23 +17,21 @@
package commands package commands
import ( import (
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func init() { func init() {
ContainerFlags = append(ContainerFlags, ContainerFlags = append(ContainerFlags,
cli.Uint64Flag{ &cli.Uint64Flag{
Name: "cpu-count", Name: "cpu-count",
Usage: "Number of CPUs available to the container", Usage: "Number of CPUs available to the container",
}, }, &cli.Uint64Flag{
cli.Uint64Flag{
Name: "cpu-shares", Name: "cpu-shares",
Usage: "The relative number of CPU shares given to the container relative to other workloads. Between 0 and 10,000.", Usage: "The relative number of CPU shares given to the container relative to other workloads. Between 0 and 10,000.",
}, }, &cli.Uint64Flag{
cli.Uint64Flag{
Name: "cpu-max", Name: "cpu-max",
Usage: "The number of processor cycles threads in a container can use per 10,000 cycles. Set to a percentage times 100. Between 1 and 10,000", Usage: "The number of processor cycles threads in a container can use per 10,000 cycles. Set to a percentage times 100. Between 1 and 10,000",
}, cli.StringSliceFlag{ }, &cli.StringSliceFlag{
Name: "device", Name: "device",
Usage: "Identifier of a device to add to the container (e.g. class://5B45201D-F2F2-4F3B-85BB-30FF1F953599)", Usage: "Identifier of a device to add to the container (e.g. class://5B45201D-F2F2-4F3B-85BB-30FF1F953599)",
}) })

View File

@ -23,23 +23,23 @@ import (
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var checkpointCommand = cli.Command{ var checkpointCommand = &cli.Command{
Name: "checkpoint", Name: "checkpoint",
Usage: "Checkpoint a container", Usage: "Checkpoint a container",
ArgsUsage: "CONTAINER REF", ArgsUsage: "CONTAINER REF",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "rw", Name: "rw",
Usage: "Include the rw layer in the checkpoint", Usage: "Include the rw layer in the checkpoint",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "image", Name: "image",
Usage: "Include the image in the checkpoint", Usage: "Include the image in the checkpoint",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "task", Name: "task",
Usage: "Checkpoint container task", Usage: "Checkpoint container task",
}, },

View File

@ -31,15 +31,15 @@ import (
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is the cli command for managing containers // Command is the cli command for managing containers
var Command = cli.Command{ var Command = &cli.Command{
Name: "containers", Name: "containers",
Usage: "Manage containers", Usage: "Manage containers",
Aliases: []string{"c", "container"}, Aliases: []string{"c", "container"},
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
createCommand, createCommand,
deleteCommand, deleteCommand,
infoCommand, infoCommand,
@ -50,11 +50,10 @@ var Command = cli.Command{
}, },
} }
var createCommand = cli.Command{ var createCommand = &cli.Command{
Name: "create", Name: "create",
Usage: "Create container", Usage: "Create container",
ArgsUsage: "[flags] Image|RootFS CONTAINER [COMMAND] [ARG...]", ArgsUsage: "[flags] Image|RootFS CONTAINER [COMMAND] [ARG...]",
SkipArgReorder: true,
Flags: append(commands.RuntimeFlags, append(append(commands.SnapshotterFlags, []cli.Flag{commands.SnapshotterLabels}...), commands.ContainerFlags...)...), Flags: append(commands.RuntimeFlags, append(append(commands.SnapshotterFlags, []cli.Flag{commands.SnapshotterLabels}...), commands.ContainerFlags...)...),
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
@ -91,20 +90,21 @@ var createCommand = cli.Command{
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "List containers", Usage: "List containers",
ArgsUsage: "[flags] [<filter>, ...]", ArgsUsage: "[flags] [<filter>, ...]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the container id", Usage: "Print only the container id",
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
filters = context.Args() filters = context.Args().Slice()
quiet = context.Bool("quiet") quiet = context.Bool("quiet")
) )
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
@ -145,13 +145,13 @@ var listCommand = cli.Command{
}, },
} }
var deleteCommand = cli.Command{ var deleteCommand = &cli.Command{
Name: "delete", Name: "delete",
Usage: "Delete one or more existing containers", Usage: "Delete one or more existing containers",
ArgsUsage: "[flags] CONTAINER [CONTAINER, ...]", ArgsUsage: "[flags] CONTAINER [CONTAINER, ...]",
Aliases: []string{"del", "remove", "rm"}, Aliases: []string{"del", "remove", "rm"},
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "keep-snapshot", Name: "keep-snapshot",
Usage: "Do not clean up snapshot with container", Usage: "Do not clean up snapshot with container",
}, },
@ -171,7 +171,7 @@ var deleteCommand = cli.Command{
if context.NArg() == 0 { if context.NArg() == 0 {
return fmt.Errorf("must specify at least one container to delete: %w", errdefs.ErrInvalidArgument) return fmt.Errorf("must specify at least one container to delete: %w", errdefs.ErrInvalidArgument)
} }
for _, arg := range context.Args() { for _, arg := range context.Args().Slice() {
if err := deleteContainer(ctx, client, arg, deleteOpts...); err != nil { if err := deleteContainer(ctx, client, arg, deleteOpts...); err != nil {
if exitErr == nil { if exitErr == nil {
exitErr = err exitErr = err
@ -206,7 +206,7 @@ func deleteContainer(ctx context.Context, client *containerd.Client, id string,
} }
var setLabelsCommand = cli.Command{ var setLabelsCommand = &cli.Command{
Name: "label", Name: "label",
Usage: "Set and clear labels for a container", Usage: "Set and clear labels for a container",
ArgsUsage: "[flags] CONTAINER [<key>=<value>, ...]", ArgsUsage: "[flags] CONTAINER [<key>=<value>, ...]",
@ -244,12 +244,12 @@ var setLabelsCommand = cli.Command{
}, },
} }
var infoCommand = cli.Command{ var infoCommand = &cli.Command{
Name: "info", Name: "info",
Usage: "Get info about a container", Usage: "Get info about a container",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "spec", Name: "spec",
Usage: "Only display the spec", Usage: "Only display the spec",
}, },

View File

@ -26,19 +26,19 @@ import (
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var restoreCommand = cli.Command{ var restoreCommand = &cli.Command{
Name: "restore", Name: "restore",
Usage: "Restore a container from checkpoint", Usage: "Restore a container from checkpoint",
ArgsUsage: "CONTAINER REF", ArgsUsage: "CONTAINER REF",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "rw", Name: "rw",
Usage: "Restore the rw layer from the checkpoint", Usage: "Restore the rw layer from the checkpoint",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "live", Name: "live",
Usage: "Restore the runtime and memory data from the checkpoint", Usage: "Restore the runtime and memory data from the checkpoint",
}, },
@ -136,7 +136,7 @@ var restoreCommand = cli.Command{
return err return err
} }
if code != 0 { if code != 0 {
return cli.NewExitError("", int(code)) return cli.Exit("", int(code))
} }
return nil return nil
}, },

View File

@ -35,12 +35,12 @@ import (
units "github.com/docker/go-units" units "github.com/docker/go-units"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var ( var (
// Command is the cli command for managing content // Command is the cli command for managing content
Command = cli.Command{ Command = &cli.Command{
Name: "content", Name: "content",
Usage: "Manage content", Usage: "Manage content",
Subcommands: cli.Commands{ Subcommands: cli.Commands{
@ -59,7 +59,7 @@ var (
}, },
} }
getCommand = cli.Command{ getCommand = &cli.Command{
Name: "get", Name: "get",
Usage: "Get the data for an object", Usage: "Get the data for an object",
ArgsUsage: "[<digest>, ...]", ArgsUsage: "[<digest>, ...]",
@ -88,17 +88,17 @@ var (
}, },
} }
ingestCommand = cli.Command{ ingestCommand = &cli.Command{
Name: "ingest", Name: "ingest",
Usage: "Accept content into the store", Usage: "Accept content into the store",
ArgsUsage: "[flags] <key>", ArgsUsage: "[flags] <key>",
Description: "ingest objects into the local content store", Description: "ingest objects into the local content store",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.Int64Flag{ &cli.Int64Flag{
Name: "expected-size", Name: "expected-size",
Usage: "Validate against provided size", Usage: "Validate against provided size",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "expected-digest", Name: "expected-digest",
Usage: "Verify content against expected digest", Usage: "Verify content against expected digest",
}, },
@ -130,18 +130,19 @@ var (
}, },
} }
activeIngestCommand = cli.Command{ activeIngestCommand = &cli.Command{
Name: "active", Name: "active",
Usage: "Display active transfers", Usage: "Display active transfers",
ArgsUsage: "[flags] [<regexp>]", ArgsUsage: "[flags] [<regexp>]",
Description: "display the ongoing transfers", Description: "display the ongoing transfers",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.DurationFlag{ &cli.DurationFlag{
Name: "timeout, t", Name: "timeout",
Aliases: []string{"t"},
Usage: "Total timeout for fetch", Usage: "Total timeout for fetch",
EnvVar: "CONTAINERD_FETCH_TIMEOUT", EnvVars: []string{"CONTAINERD_FETCH_TIMEOUT"},
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "root", Name: "root",
Usage: "Path to content store root", Usage: "Path to content store root",
Value: "/tmp/content", // TODO(stevvooe): for now, just use the PWD/.content Value: "/tmp/content", // TODO(stevvooe): for now, just use the PWD/.content
@ -172,22 +173,23 @@ var (
}, },
} }
listCommand = cli.Command{ listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "List all blobs in the store", Usage: "List all blobs in the store",
ArgsUsage: "[flags]", ArgsUsage: "[flags]",
Description: "list blobs in the content store", Description: "list blobs in the content store",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the blob digest", Usage: "Print only the blob digest",
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
quiet = context.Bool("quiet") quiet = context.Bool("quiet")
args = []string(context.Args()) args = context.Args().Slice()
) )
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
if err != nil { if err != nil {
@ -232,7 +234,7 @@ var (
}, },
} }
setLabelsCommand = cli.Command{ setLabelsCommand = &cli.Command{
Name: "label", Name: "label",
Usage: "Add labels to content", Usage: "Add labels to content",
ArgsUsage: "<digest> [<label>=<value> ...]", ArgsUsage: "<digest> [<label>=<value> ...]",
@ -286,20 +288,20 @@ var (
}, },
} }
editCommand = cli.Command{ editCommand = &cli.Command{
Name: "edit", Name: "edit",
Usage: "Edit a blob and return a new digest", Usage: "Edit a blob and return a new digest",
ArgsUsage: "[flags] <digest>", ArgsUsage: "[flags] <digest>",
Description: "edit a blob and return a new digest", Description: "edit a blob and return a new digest",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "validate", Name: "validate",
Usage: "Validate the result against a format (json, mediatype, etc.)", Usage: "Validate the result against a format (json, mediatype, etc.)",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "editor", Name: "editor",
Usage: "Select editor (vim, emacs, etc.)", Usage: "Select editor (vim, emacs, etc.)",
EnvVar: "EDITOR", EnvVars: []string{"EDITOR"},
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
@ -355,7 +357,7 @@ var (
}, },
} }
deleteCommand = cli.Command{ deleteCommand = &cli.Command{
Name: "delete", Name: "delete",
Aliases: []string{"del", "remove", "rm"}, Aliases: []string{"del", "remove", "rm"},
Usage: "Permanently delete one or more blobs", Usage: "Permanently delete one or more blobs",
@ -364,7 +366,7 @@ var (
blobs are printed to stdout.`, blobs are printed to stdout.`,
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
args = []string(context.Args()) args = context.Args().Slice()
exitError error exitError error
) )
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
@ -404,7 +406,7 @@ var (
// TODO(stevvooe): Create "multi-fetch" mode that just takes a remote // TODO(stevvooe): Create "multi-fetch" mode that just takes a remote
// then receives object/hint lines on stdin, returning content as // then receives object/hint lines on stdin, returning content as
// needed. // needed.
fetchObjectCommand = cli.Command{ fetchObjectCommand = &cli.Command{
Name: "fetch-object", Name: "fetch-object",
Usage: "Retrieve objects from a remote", Usage: "Retrieve objects from a remote",
ArgsUsage: "[flags] <remote> <object> [<hint>, ...]", ArgsUsage: "[flags] <remote> <object> [<hint>, ...]",
@ -446,13 +448,13 @@ var (
}, },
} }
fetchBlobCommand = cli.Command{ fetchBlobCommand = &cli.Command{
Name: "fetch-blob", Name: "fetch-blob",
Usage: "Retrieve blobs from a remote", Usage: "Retrieve blobs from a remote",
ArgsUsage: "[flags] <remote> [<digest>, ...]", ArgsUsage: "[flags] <remote> [<digest>, ...]",
Description: `Fetch blobs by digests from a remote.`, Description: `Fetch blobs by digests from a remote.`,
Flags: append(commands.RegistryFlags, []cli.Flag{ Flags: append(commands.RegistryFlags, []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "media-type", Name: "media-type",
Usage: "Specify target mediatype for request header", Usage: "Specify target mediatype for request header",
}, },
@ -506,7 +508,7 @@ var (
}, },
} }
pushObjectCommand = cli.Command{ pushObjectCommand = &cli.Command{
Name: "push-object", Name: "push-object",
Usage: "Push an object to a remote", Usage: "Push an object to a remote",
ArgsUsage: "[flags] <remote> <object> <type>", ArgsUsage: "[flags] <remote> <object> <type>",

View File

@ -37,10 +37,10 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var fetchCommand = cli.Command{ var fetchCommand = &cli.Command{
Name: "fetch", Name: "fetch",
Usage: "Fetch all content for an image into containerd", Usage: "Fetch all content for an image into containerd",
ArgsUsage: "[flags] <remote> <object>", ArgsUsage: "[flags] <remote> <object>",
@ -59,24 +59,24 @@ content and snapshots ready for a direct use via the 'ctr run'.
Most of this is experimental and there are few leaps to make this work.`, Most of this is experimental and there are few leaps to make this work.`,
Flags: append(commands.RegistryFlags, commands.LabelFlag, Flags: append(commands.RegistryFlags, commands.LabelFlag,
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "platform", Name: "platform",
Usage: "Pull content from a specific platform", Usage: "Pull content from a specific platform",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-platforms", Name: "all-platforms",
Usage: "Pull content from all platforms", Usage: "Pull content from all platforms",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-metadata", Name: "all-metadata",
Usage: "(Deprecated: use skip-metadata) Pull metadata for all platforms", Usage: "(Deprecated: use skip-metadata) Pull metadata for all platforms",
Hidden: true, Hidden: true,
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-metadata", Name: "skip-metadata",
Usage: "Skips metadata for unused platforms (Image may be unable to be pushed without metadata)", Usage: "Skips metadata for unused platforms (Image may be unable to be pushed without metadata)",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "metadata-only", Name: "metadata-only",
Usage: "Pull all metadata including manifests and configs", Usage: "Pull all metadata including manifests and configs",
}, },
@ -131,7 +131,7 @@ func NewFetchConfig(ctx context.Context, clicontext *cli.Context) (*FetchConfig,
Labels: clicontext.StringSlice("label"), Labels: clicontext.StringSlice("label"),
TraceHTTP: clicontext.Bool("http-trace"), TraceHTTP: clicontext.Bool("http-trace"),
} }
if !clicontext.GlobalBool("debug") { if !clicontext.Bool("debug") {
config.ProgressOutput = os.Stdout config.ProgressOutput = os.Stdout
} }
if !clicontext.Bool("all-platforms") { if !clicontext.Bool("all-platforms") {

View File

@ -25,7 +25,7 @@ import (
"github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/leases" "github.com/containerd/containerd/v2/core/leases"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const ( const (
@ -34,17 +34,17 @@ const (
) )
var pruneFlags = []cli.Flag{ var pruneFlags = []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "async", Name: "async",
Usage: "Allow garbage collection to cleanup asynchronously", Usage: "Allow garbage collection to cleanup asynchronously",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "dry", Name: "dry",
Usage: "Just show updates without applying (enables debug logging)", Usage: "Just show updates without applying (enables debug logging)",
}, },
} }
var pruneCommand = cli.Command{ var pruneCommand = &cli.Command{
Name: "prune", Name: "prune",
Usage: "Prunes content from the content store", Usage: "Prunes content from the content store",
Subcommands: cli.Commands{ Subcommands: cli.Commands{
@ -52,7 +52,7 @@ var pruneCommand = cli.Command{
}, },
} }
var pruneReferencesCommand = cli.Command{ var pruneReferencesCommand = &cli.Command{
Name: "references", Name: "references",
Usage: "Prunes preference labels from the content store (layers only by default)", Usage: "Prunes preference labels from the content store (layers only by default)",
Flags: pruneFlags, Flags: pruneFlags,

View File

@ -22,7 +22,7 @@ import (
"text/tabwriter" "text/tabwriter"
"time" "time"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
api "github.com/containerd/containerd/v2/api/services/introspection/v1" api "github.com/containerd/containerd/v2/api/services/introspection/v1"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
@ -31,17 +31,17 @@ import (
) )
// Command is the parent for all commands under "deprecations" // Command is the parent for all commands under "deprecations"
var Command = cli.Command{ var Command = &cli.Command{
Name: "deprecations", Name: "deprecations",
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
listCommand, listCommand,
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Usage: "Print warnings for deprecations", Usage: "Print warnings for deprecations",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "format", Name: "format",
Usage: "output format to use (Examples: 'default', 'json')", Usage: "output format to use (Examples: 'default', 'json')",
}, },

View File

@ -24,14 +24,14 @@ import (
"github.com/containerd/containerd/v2/pkg/events" "github.com/containerd/containerd/v2/pkg/events"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
// Register grpc event types // Register grpc event types
_ "github.com/containerd/containerd/v2/api/events" _ "github.com/containerd/containerd/v2/api/events"
) )
// Command is the cli command for displaying containerd events // Command is the cli command for displaying containerd events
var Command = cli.Command{ var Command = &cli.Command{
Name: "events", Name: "events",
Aliases: []string{"event"}, Aliases: []string{"event"},
Usage: "Display containerd events", Usage: "Display containerd events",
@ -42,7 +42,7 @@ var Command = cli.Command{
} }
defer cancel() defer cancel()
eventsClient := client.EventService() eventsClient := client.EventService()
eventsCh, errCh := eventsClient.Subscribe(ctx, context.Args()...) eventsCh, errCh := eventsClient.Subscribe(ctx, context.Args().Slice()...)
for { for {
var e *events.Envelope var e *events.Envelope
select { select {

View File

@ -24,10 +24,10 @@ import (
"github.com/containerd/containerd/v2/core/images/converter" "github.com/containerd/containerd/v2/core/images/converter"
"github.com/containerd/containerd/v2/core/images/converter/uncompress" "github.com/containerd/containerd/v2/core/images/converter/uncompress"
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var convertCommand = cli.Command{ var convertCommand = &cli.Command{
Name: "convert", Name: "convert",
Usage: "Convert an image", Usage: "Convert an image",
ArgsUsage: "[flags] <source_ref> <target_ref>", ArgsUsage: "[flags] <source_ref> <target_ref>",
@ -40,21 +40,21 @@ When '--all-platforms' is given all images in a manifest list must be available.
`, `,
Flags: []cli.Flag{ Flags: []cli.Flag{
// generic flags // generic flags
cli.BoolFlag{ &cli.BoolFlag{
Name: "uncompress", Name: "uncompress",
Usage: "Convert tar.gz layers to uncompressed tar layers", Usage: "Convert tar.gz layers to uncompressed tar layers",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "oci", Name: "oci",
Usage: "Convert Docker media types to OCI media types", Usage: "Convert Docker media types to OCI media types",
}, },
// platform flags // platform flags
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "platform", Name: "platform",
Usage: "Pull content from a specific platform", Usage: "Pull content from a specific platform",
Value: &cli.StringSlice{}, Value: cli.NewStringSlice(),
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-platforms", Name: "all-platforms",
Usage: "Exports content from all platforms", Usage: "Exports content from all platforms",
}, },

View File

@ -22,7 +22,7 @@ import (
"io" "io"
"os" "os"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/core/images/archive" "github.com/containerd/containerd/v2/core/images/archive"
@ -32,7 +32,7 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
) )
var exportCommand = cli.Command{ var exportCommand = &cli.Command{
Name: "export", Name: "export",
Usage: "Export images", Usage: "Export images",
ArgsUsage: "[flags] <out> <image> ...", ArgsUsage: "[flags] <out> <image> ...",
@ -44,24 +44,24 @@ Use '--platform' to define the output platform.
When '--all-platforms' is given all images in a manifest list must be available. When '--all-platforms' is given all images in a manifest list must be available.
`, `,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-manifest-json", Name: "skip-manifest-json",
Usage: "Do not add Docker compatible manifest.json to archive", Usage: "Do not add Docker compatible manifest.json to archive",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-non-distributable", Name: "skip-non-distributable",
Usage: "Do not add non-distributable blobs such as Windows layers to archive", Usage: "Do not add non-distributable blobs such as Windows layers to archive",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "platform", Name: "platform",
Usage: "Pull content from a specific platform", Usage: "Pull content from a specific platform",
Value: &cli.StringSlice{}, Value: cli.NewStringSlice(),
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-platforms", Name: "all-platforms",
Usage: "Exports content from all platforms", Usage: "Exports content from all platforms",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "local", Name: "local",
Usage: "Run export locally rather than through transfer API", Usage: "Run export locally rather than through transfer API",
}, },

View File

@ -30,11 +30,11 @@ import (
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is the cli command for managing images // Command is the cli command for managing images
var Command = cli.Command{ var Command = &cli.Command{
Name: "images", Name: "images",
Aliases: []string{"image", "i"}, Aliases: []string{"image", "i"},
Usage: "Manage images", Usage: "Manage images",
@ -57,21 +57,22 @@ var Command = cli.Command{
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "List images known to containerd", Usage: "List images known to containerd",
ArgsUsage: "[flags] [<filter>, ...]", ArgsUsage: "[flags] [<filter>, ...]",
Description: "list images registered with containerd", Description: "list images registered with containerd",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the image refs", Usage: "Print only the image refs",
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
filters = context.Args() filters = context.Args().Slice()
quiet = context.Bool("quiet") quiet = context.Bool("quiet")
) )
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
@ -141,14 +142,15 @@ var listCommand = cli.Command{
}, },
} }
var setLabelsCommand = cli.Command{ var setLabelsCommand = &cli.Command{
Name: "label", Name: "label",
Usage: "Set and clear labels for an image", Usage: "Set and clear labels for an image",
ArgsUsage: "[flags] <name> [<key>=<value>, ...]", ArgsUsage: "[flags] <name> [<key>=<value>, ...]",
Description: "set and clear labels for an image", Description: "set and clear labels for an image",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "replace-all, r", Name: "replace-all",
Aliases: []string{"r"},
Usage: "Replace all labels", Usage: "Replace all labels",
}, },
}, },
@ -200,14 +202,15 @@ var setLabelsCommand = cli.Command{
}, },
} }
var checkCommand = cli.Command{ var checkCommand = &cli.Command{
Name: "check", Name: "check",
Usage: "Check existing images to ensure all content is available locally", Usage: "Check existing images to ensure all content is available locally",
ArgsUsage: "[flags] [<filter>, ...]", ArgsUsage: "[flags] [<filter>, ...]",
Description: "check existing images to ensure all content is available locally", Description: "check existing images to ensure all content is available locally",
Flags: append([]cli.Flag{ Flags: append([]cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the ready image refs (fully downloaded and unpacked)", Usage: "Print only the ready image refs (fully downloaded and unpacked)",
}, },
}, commands.SnapshotterFlags...), }, commands.SnapshotterFlags...),
@ -224,7 +227,7 @@ var checkCommand = cli.Command{
var contentStore = client.ContentStore() var contentStore = client.ContentStore()
args := []string(context.Args()) args := context.Args().Slice()
imageList, err := client.ListImages(ctx, args...) imageList, err := client.ListImages(ctx, args...)
if err != nil { if err != nil {
return fmt.Errorf("failed listing images: %w", err) return fmt.Errorf("failed listing images: %w", err)
@ -313,14 +316,14 @@ var checkCommand = cli.Command{
}, },
} }
var removeCommand = cli.Command{ var removeCommand = &cli.Command{
Name: "delete", Name: "delete",
Aliases: []string{"del", "remove", "rm"}, Aliases: []string{"del", "remove", "rm"},
Usage: "Remove one or more images by reference", Usage: "Remove one or more images by reference",
ArgsUsage: "[flags] <ref> [<ref>, ...]", ArgsUsage: "[flags] <ref> [<ref>, ...]",
Description: "remove one or more images by reference", Description: "remove one or more images by reference",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "sync", Name: "sync",
Usage: "Synchronously remove image and all associated resources", Usage: "Synchronously remove image and all associated resources",
}, },
@ -335,7 +338,7 @@ var removeCommand = cli.Command{
exitErr error exitErr error
imageStore = client.ImageService() imageStore = client.ImageService()
) )
for i, target := range context.Args() { for i, target := range context.Args().Slice() {
var opts []images.DeleteOpt var opts []images.DeleteOpt
if context.Bool("sync") && i == context.NArg()-1 { if context.Bool("sync") && i == context.NArg()-1 {
opts = append(opts, images.SynchronousDelete()) opts = append(opts, images.SynchronousDelete())
@ -359,11 +362,11 @@ var removeCommand = cli.Command{
}, },
} }
var pruneCommand = cli.Command{ var pruneCommand = &cli.Command{
Name: "prune", Name: "prune",
Usage: "Remove unused images", Usage: "Remove unused images",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "all", // TODO: add more filters Name: "all", // TODO: add more filters
Usage: "Remove all unused images, not just dangling ones (if all is not specified no images will be pruned)", Usage: "Remove all unused images, not just dangling ones (if all is not specified no images will be pruned)",
}, },

View File

@ -23,7 +23,7 @@ import (
"time" "time"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
@ -35,7 +35,7 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
) )
var importCommand = cli.Command{ var importCommand = &cli.Command{
Name: "import", Name: "import",
Usage: "Import images", Usage: "Import images",
ArgsUsage: "[flags] <in>", ArgsUsage: "[flags] <in>",
@ -57,44 +57,44 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb
"foo/bar:latest" and "foo/bar@sha256:deadbeef" images in the containerd store. "foo/bar:latest" and "foo/bar@sha256:deadbeef" images in the containerd store.
`, `,
Flags: append([]cli.Flag{ Flags: append([]cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "base-name", Name: "base-name",
Value: "", Value: "",
Usage: "Base image name for added images, when provided only images with this name prefix are imported", Usage: "Base image name for added images, when provided only images with this name prefix are imported",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "digests", Name: "digests",
Usage: "Whether to create digest images (default: false)", Usage: "Whether to create digest images (default: false)",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-digest-for-named", Name: "skip-digest-for-named",
Usage: "Skip applying --digests option to images named in the importing tar (use it in conjunction with --digests)", Usage: "Skip applying --digests option to images named in the importing tar (use it in conjunction with --digests)",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "index-name", Name: "index-name",
Usage: "Image name to keep index as, by default index is discarded", Usage: "Image name to keep index as, by default index is discarded",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-platforms", Name: "all-platforms",
Usage: "Imports content for all platforms, false by default", Usage: "Imports content for all platforms, false by default",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "platform", Name: "platform",
Usage: "Imports content for specific platform", Usage: "Imports content for specific platform",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "no-unpack", Name: "no-unpack",
Usage: "Skip unpacking the images, cannot be used with --discard-unpacked-layers, false by default", Usage: "Skip unpacking the images, cannot be used with --discard-unpacked-layers, false by default",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "local", Name: "local",
Usage: "Run import locally rather than through transfer API", Usage: "Run import locally rather than through transfer API",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "compress-blobs", Name: "compress-blobs",
Usage: "Compress uncompressed blobs when creating manifest (Docker format only)", Usage: "Compress uncompressed blobs when creating manifest (Docker format only)",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "discard-unpacked-layers", Name: "discard-unpacked-layers",
Usage: "Allow the garbage collector to clean layers up from the content store after unpacking, cannot be used with --no-unpack, false by default", Usage: "Allow the garbage collector to clean layers up from the content store after unpacking, cannot be used with --no-unpack, false by default",
}, },

View File

@ -21,17 +21,17 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/pkg/display" "github.com/containerd/containerd/v2/pkg/display"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var inspectCommand = cli.Command{ var inspectCommand = &cli.Command{
Name: "inspect", Name: "inspect",
Aliases: []string{"i"}, Aliases: []string{"i"},
Usage: "inspect an image", Usage: "inspect an image",
ArgsUsage: "<image> [flags]", ArgsUsage: "<image> [flags]",
Description: `Inspect an image`, Description: `Inspect an image`,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "content", Name: "content",
Usage: "Show JSON content", Usage: "Show JSON content",
}, },

View File

@ -28,10 +28,10 @@ import (
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/identity"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var mountCommand = cli.Command{ var mountCommand = &cli.Command{
Name: "mount", Name: "mount",
Usage: "Mount an image to a target path", Usage: "Mount an image to a target path",
ArgsUsage: "[flags] <ref> <target>", ArgsUsage: "[flags] <ref> <target>",
@ -40,11 +40,11 @@ var mountCommand = cli.Command{
When you are done, use the unmount command. When you are done, use the unmount command.
`, `,
Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...), Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...),
cli.BoolFlag{ &cli.BoolFlag{
Name: "rw", Name: "rw",
Usage: "Enable write support on the mount", Usage: "Enable write support on the mount",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "platform", Name: "platform",
Usage: "Mount the image for the specified platform", Usage: "Mount the image for the specified platform",
Value: platforms.DefaultString(), Value: platforms.DefaultString(),

View File

@ -36,10 +36,10 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var pullCommand = cli.Command{ var pullCommand = &cli.Command{
Name: "pull", Name: "pull",
Usage: "Pull an image from a remote", Usage: "Pull an image from a remote",
ArgsUsage: "[flags] <ref>", ArgsUsage: "[flags] <ref>",
@ -53,33 +53,33 @@ command. As part of this process, we do the following:
3. Register metadata for the image. 3. Register metadata for the image.
`, `,
Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...), Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...),
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "platform", Name: "platform",
Usage: "Pull content from a specific platform", Usage: "Pull content from a specific platform",
Value: &cli.StringSlice{}, Value: cli.NewStringSlice(),
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-platforms", Name: "all-platforms",
Usage: "Pull content and metadata from all platforms", Usage: "Pull content and metadata from all platforms",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all-metadata", Name: "all-metadata",
Usage: "(Deprecated: use skip-metadata) Pull metadata for all platforms", Usage: "(Deprecated: use skip-metadata) Pull metadata for all platforms",
Hidden: true, Hidden: true,
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-metadata", Name: "skip-metadata",
Usage: "Skips metadata for unused platforms (Image may be unable to be pushed without metadata)", Usage: "Skips metadata for unused platforms (Image may be unable to be pushed without metadata)",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "print-chainid", Name: "print-chainid",
Usage: "Print the resulting image's chain ID", Usage: "Print the resulting image's chain ID",
}, },
cli.IntFlag{ &cli.IntFlag{
Name: "max-concurrent-downloads", Name: "max-concurrent-downloads",
Usage: "Set the max concurrent downloads for each pull", Usage: "Set the max concurrent downloads for each pull",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "local", Name: "local",
Usage: "Fetch content from local client rather than using transfer service", Usage: "Fetch content from local client rather than using transfer service",
}, },

View File

@ -40,11 +40,11 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
var pushCommand = cli.Command{ var pushCommand = &cli.Command{
Name: "push", Name: "push",
Usage: "Push an image to a remote", Usage: "Push an image to a remote",
ArgsUsage: "[flags] <remote> [<local>]", ArgsUsage: "[flags] <remote> [<local>]",
@ -57,24 +57,24 @@ var pushCommand = cli.Command{
creating the associated configuration, and creating the manifest creating the associated configuration, and creating the manifest
which references those resources. which references those resources.
`, `,
Flags: append(commands.RegistryFlags, cli.StringFlag{ Flags: append(commands.RegistryFlags, &cli.StringFlag{
Name: "manifest", Name: "manifest",
Usage: "Digest of manifest", Usage: "Digest of manifest",
}, cli.StringFlag{ }, &cli.StringFlag{
Name: "manifest-type", Name: "manifest-type",
Usage: "Media type of manifest digest", Usage: "Media type of manifest digest",
Value: ocispec.MediaTypeImageManifest, Value: ocispec.MediaTypeImageManifest,
}, cli.StringSliceFlag{ }, &cli.StringSliceFlag{
Name: "platform", Name: "platform",
Usage: "Push content from a specific platform", Usage: "Push content from a specific platform",
Value: &cli.StringSlice{}, Value: cli.NewStringSlice(),
}, cli.IntFlag{ }, &cli.IntFlag{
Name: "max-concurrent-uploaded-layers", Name: "max-concurrent-uploaded-layers",
Usage: "Set the max concurrent uploaded layers for each push", Usage: "Set the max concurrent uploaded layers for each push",
}, cli.BoolFlag{ }, &cli.BoolFlag{
Name: "local", Name: "local",
Usage: "Push content from local client rather than using transfer service", Usage: "Push content from local client rather than using transfer service",
}, cli.BoolFlag{ }, &cli.BoolFlag{
Name: "allow-non-distributable-blobs", Name: "allow-non-distributable-blobs",
Usage: "Allow pushing blobs that are marked as non-distributable", Usage: "Allow pushing blobs that are marked as non-distributable",
}), }),
@ -82,7 +82,7 @@ var pushCommand = cli.Command{
var ( var (
ref = context.Args().First() ref = context.Args().First()
local = context.Args().Get(1) local = context.Args().Get(1)
debug = context.GlobalBool("debug") debug = context.Bool("debug")
desc ocispec.Descriptor desc ocispec.Descriptor
) )
if ref == "" { if ref == "" {

View File

@ -19,7 +19,7 @@ package images
import ( import (
"fmt" "fmt"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/core/transfer/image" "github.com/containerd/containerd/v2/core/transfer/image"
@ -27,21 +27,21 @@ import (
"github.com/distribution/reference" "github.com/distribution/reference"
) )
var tagCommand = cli.Command{ var tagCommand = &cli.Command{
Name: "tag", Name: "tag",
Usage: "Tag an image", Usage: "Tag an image",
ArgsUsage: "[flags] <source_ref> <target_ref> [<target_ref>, ...]", ArgsUsage: "[flags] <source_ref> <target_ref> [<target_ref>, ...]",
Description: `Tag an image for use in containerd.`, Description: `Tag an image for use in containerd.`,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "force", Name: "force",
Usage: "Force target_ref to be created, regardless if it already exists", Usage: "Force target_ref to be created, regardless if it already exists",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "local", Name: "local",
Usage: "Run tag locally rather than through transfer API", Usage: "Run tag locally rather than through transfer API",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "skip-reference-check", Name: "skip-reference-check",
Usage: "Skip the strict check for reference names", Usage: "Skip the strict check for reference names",
}, },
@ -64,7 +64,7 @@ var tagCommand = cli.Command{
defer cancel() defer cancel()
if !context.Bool("local") { if !context.Bool("local") {
for _, targetRef := range context.Args()[1:] { for _, targetRef := range context.Args().Slice()[1:] {
if !context.Bool("skip-reference-check") { if !context.Bool("skip-reference-check") {
if _, err := reference.ParseAnyReference(targetRef); err != nil { if _, err := reference.ParseAnyReference(targetRef); err != nil {
return fmt.Errorf("error parsing reference: %q is not a valid repository/tag %v", targetRef, err) return fmt.Errorf("error parsing reference: %q is not a valid repository/tag %v", targetRef, err)
@ -91,7 +91,7 @@ var tagCommand = cli.Command{
return err return err
} }
// Support multiple references for one command run // Support multiple references for one command run
for _, targetRef := range context.Args()[1:] { for _, targetRef := range context.Args().Slice()[1:] {
if !context.Bool("skip-reference-check") { if !context.Bool("skip-reference-check") {
if _, err := reference.ParseAnyReference(targetRef); err != nil { if _, err := reference.ParseAnyReference(targetRef); err != nil {
return fmt.Errorf("error parsing reference: %q is not a valid repository/tag %v", targetRef, err) return fmt.Errorf("error parsing reference: %q is not a valid repository/tag %v", targetRef, err)

View File

@ -23,16 +23,16 @@ import (
"github.com/containerd/containerd/v2/core/leases" "github.com/containerd/containerd/v2/core/leases"
"github.com/containerd/containerd/v2/core/mount" "github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var unmountCommand = cli.Command{ var unmountCommand = &cli.Command{
Name: "unmount", Name: "unmount",
Usage: "Unmount the image from the target", Usage: "Unmount the image from the target",
ArgsUsage: "[flags] <target>", ArgsUsage: "[flags] <target>",
Description: "Unmount the image rootfs from the specified target.", Description: "Unmount the image rootfs from the specified target.",
Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...), Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...),
cli.BoolFlag{ &cli.BoolFlag{
Name: "rm", Name: "rm",
Usage: "Remove the snapshot after a successful unmount", Usage: "Remove the snapshot after a successful unmount",
}, },

View File

@ -27,10 +27,10 @@ import (
"github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/containerd/v2/pkg/progress"
"github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/identity"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var usageCommand = cli.Command{ var usageCommand = &cli.Command{
Name: "usage", Name: "usage",
Usage: "Display usage of snapshots for a given image ref", Usage: "Display usage of snapshots for a given image ref",
ArgsUsage: "[flags] <ref>", ArgsUsage: "[flags] <ref>",

View File

@ -20,7 +20,7 @@ import (
api "github.com/containerd/containerd/v2/api/services/introspection/v1" api "github.com/containerd/containerd/v2/api/services/introspection/v1"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
ptypes "github.com/containerd/containerd/v2/protobuf/types" ptypes "github.com/containerd/containerd/v2/protobuf/types"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
type Info struct { type Info struct {
@ -28,7 +28,7 @@ type Info struct {
} }
// Command is a cli command to output the containerd server info // Command is a cli command to output the containerd server info
var Command = cli.Command{ var Command = &cli.Command{
Name: "info", Name: "info",
Usage: "Print the server info", Usage: "Print the server info",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {

View File

@ -19,25 +19,27 @@ package install
import ( import (
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command to install binary packages // Command to install binary packages
var Command = cli.Command{ var Command = &cli.Command{
Name: "install", Name: "install",
Usage: "Install a new package", Usage: "Install a new package",
ArgsUsage: "<ref>", ArgsUsage: "<ref>",
Description: "install a new package", Description: "install a new package",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "libs,l", Name: "libs",
Aliases: []string{"l"},
Usage: "Install libs from the image", Usage: "Install libs from the image",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "replace,r", Name: "replace",
Aliases: []string{"r"},
Usage: "Replace any binaries or libs in the opt directory", Usage: "Replace any binaries or libs in the opt directory",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "path", Name: "path",
Usage: "Set an optional install path other than the managed opt directory", Usage: "Set an optional install path other than the managed opt directory",
}, },

View File

@ -26,11 +26,11 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/core/leases" "github.com/containerd/containerd/v2/core/leases"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is the cli command for managing content // Command is the cli command for managing content
var Command = cli.Command{ var Command = &cli.Command{
Name: "leases", Name: "leases",
Usage: "Manage leases", Usage: "Manage leases",
Subcommands: cli.Commands{ Subcommands: cli.Commands{
@ -40,7 +40,7 @@ var Command = cli.Command{
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
@ -48,14 +48,15 @@ var listCommand = cli.Command{
ArgsUsage: "[flags] <filter>", ArgsUsage: "[flags] <filter>",
Description: "list active leases by containerd", Description: "list active leases by containerd",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the blob digest", Usage: "Print only the blob digest",
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
filters = context.Args() filters = context.Args().Slice()
quiet = context.Bool("quiet") quiet = context.Bool("quiet")
) )
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
@ -99,24 +100,25 @@ var listCommand = cli.Command{
}, },
} }
var createCommand = cli.Command{ var createCommand = &cli.Command{
Name: "create", Name: "create",
Usage: "Create lease", Usage: "Create lease",
ArgsUsage: "[flags] <label>=<value> ...", ArgsUsage: "[flags] <label>=<value> ...",
Description: "create a new lease", Description: "create a new lease",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "id", Name: "id",
Usage: "Set the id for the lease, will be generated by default", Usage: "Set the id for the lease, will be generated by default",
}, },
cli.DurationFlag{ &cli.DurationFlag{
Name: "expires, x", Name: "expires",
Aliases: []string{"x"},
Usage: "Expiration of lease (0 value will not expire)", Usage: "Expiration of lease (0 value will not expire)",
Value: 24 * time.Hour, Value: 24 * time.Hour,
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var labelstr = context.Args() var labelstr = context.Args().Slice()
client, ctx, cancel, err := commands.NewClient(context) client, ctx, cancel, err := commands.NewClient(context)
if err != nil { if err != nil {
return err return err
@ -152,20 +154,20 @@ var createCommand = cli.Command{
}, },
} }
var deleteCommand = cli.Command{ var deleteCommand = &cli.Command{
Name: "delete", Name: "delete",
Aliases: []string{"del", "remove", "rm"}, Aliases: []string{"del", "remove", "rm"},
Usage: "Delete a lease", Usage: "Delete a lease",
ArgsUsage: "[flags] <lease id> ...", ArgsUsage: "[flags] <lease id> ...",
Description: "delete a lease", Description: "delete a lease",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "sync", Name: "sync",
Usage: "Synchronously remove leases and all unreferenced resources", Usage: "Synchronously remove leases and all unreferenced resources",
}, },
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var lids = context.Args() var lids = context.Args().Slice()
if len(lids) == 0 { if len(lids) == 0 {
return cli.ShowSubcommandHelp(context) return cli.ShowSubcommandHelp(context)
} }

View File

@ -27,11 +27,11 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is the cli command for managing namespaces // Command is the cli command for managing namespaces
var Command = cli.Command{ var Command = &cli.Command{
Name: "namespaces", Name: "namespaces",
Aliases: []string{"namespace", "ns"}, Aliases: []string{"namespace", "ns"},
Usage: "Manage namespaces", Usage: "Manage namespaces",
@ -43,7 +43,7 @@ var Command = cli.Command{
}, },
} }
var createCommand = cli.Command{ var createCommand = &cli.Command{
Name: "create", Name: "create",
Aliases: []string{"c"}, Aliases: []string{"c"},
Usage: "Create a new namespace", Usage: "Create a new namespace",
@ -64,7 +64,7 @@ var createCommand = cli.Command{
}, },
} }
var setLabelsCommand = cli.Command{ var setLabelsCommand = &cli.Command{
Name: "label", Name: "label",
Usage: "Set and clear labels for a namespace", Usage: "Set and clear labels for a namespace",
ArgsUsage: "<name> [<key>=<value>, ...]", ArgsUsage: "<name> [<key>=<value>, ...]",
@ -89,15 +89,16 @@ var setLabelsCommand = cli.Command{
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "List namespaces", Usage: "List namespaces",
ArgsUsage: "[flags]", ArgsUsage: "[flags]",
Description: "list namespaces", Description: "list namespaces",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the namespace name", Usage: "Print only the namespace name",
}, },
}, },
@ -141,15 +142,16 @@ var listCommand = cli.Command{
}, },
} }
var removeCommand = cli.Command{ var removeCommand = &cli.Command{
Name: "remove", Name: "remove",
Aliases: []string{"rm"}, Aliases: []string{"rm"},
Usage: "Remove one or more namespaces", Usage: "Remove one or more namespaces",
ArgsUsage: "<name> [<name>, ...]", ArgsUsage: "<name> [<name>, ...]",
Description: "remove one or more namespaces. for now, the namespace must be empty", Description: "remove one or more namespaces. for now, the namespace must be empty",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "cgroup,c", Name: "cgroup",
Aliases: []string{"c"},
Usage: "Delete the namespace's cgroup", Usage: "Delete the namespace's cgroup",
}, },
}, },
@ -163,7 +165,7 @@ var removeCommand = cli.Command{
opts := deleteOpts(context) opts := deleteOpts(context)
namespaces := client.NamespaceService() namespaces := client.NamespaceService()
for _, target := range context.Args() { for _, target := range context.Args().Slice() {
if err := namespaces.Delete(ctx, target, opts...); err != nil { if err := namespaces.Delete(ctx, target, opts...); err != nil {
if !errdefs.IsNotFound(err) { if !errdefs.IsNotFound(err) {
if exitErr == nil { if exitErr == nil {

View File

@ -19,7 +19,7 @@ package namespaces
import ( import (
"github.com/containerd/containerd/v2/core/runtime/opts" "github.com/containerd/containerd/v2/core/runtime/opts"
"github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func deleteOpts(context *cli.Context) []namespaces.DeleteOpts { func deleteOpts(context *cli.Context) []namespaces.DeleteOpts {

View File

@ -20,7 +20,7 @@ package namespaces
import ( import (
"github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func deleteOpts(context *cli.Context) []namespaces.DeleteOpts { func deleteOpts(context *cli.Context) []namespaces.DeleteOpts {

View File

@ -19,7 +19,7 @@ package oci
import ( import (
"fmt" "fmt"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/core/containers"
@ -28,19 +28,19 @@ import (
) )
// Command is the parent for all OCI related tools under 'oci' // Command is the parent for all OCI related tools under 'oci'
var Command = cli.Command{ var Command = &cli.Command{
Name: "oci", Name: "oci",
Usage: "OCI tools", Usage: "OCI tools",
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
defaultSpecCommand, defaultSpecCommand,
}, },
} }
var defaultSpecCommand = cli.Command{ var defaultSpecCommand = &cli.Command{
Name: "spec", Name: "spec",
Usage: "See the output of the default OCI spec", Usage: "See the output of the default OCI spec",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "platform", Name: "platform",
Usage: "Platform of the spec to print (Examples: 'linux/arm64', 'windows/amd64')", Usage: "Platform of the spec to print (Examples: 'linux/arm64', 'windows/amd64')",
}, },

View File

@ -29,32 +29,34 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
pluginutils "github.com/containerd/plugin" pluginutils "github.com/containerd/plugin"
v1 "github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
) )
// Command is a cli command that outputs plugin information // Command is a cli command that outputs plugin information
var Command = cli.Command{ var Command = &cli.Command{
Name: "plugins", Name: "plugins",
Aliases: []string{"plugin"}, Aliases: []string{"plugin"},
Usage: "Provides information about containerd plugins", Usage: "Provides information about containerd plugins",
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
listCommand, listCommand,
inspectRuntimeCommand, inspectRuntimeCommand,
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "Lists containerd plugins", Usage: "Lists containerd plugins",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet,q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the plugin ids", Usage: "Print only the plugin ids",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "detailed,d", Name: "detailed",
Aliases: []string{"d"},
Usage: "Print detailed information about each plugin", Usage: "Print detailed information about each plugin",
}, },
}, },
@ -69,7 +71,7 @@ var listCommand = cli.Command{
} }
defer cancel() defer cancel()
ps := client.IntrospectionService() ps := client.IntrospectionService()
response, err := ps.Plugins(ctx, context.Args()) response, err := ps.Plugins(ctx, context.Args().Slice())
if err != nil { if err != nil {
return err return err
} }
@ -165,7 +167,7 @@ func prettyPlatforms(pspb []*types.Platform) string {
return strings.Join(ps, ",") return strings.Join(ps, ",")
} }
var inspectRuntimeCommand = cli.Command{ var inspectRuntimeCommand = &cli.Command{
Name: "inspect-runtime", Name: "inspect-runtime",
Usage: "Display runtime info", Usage: "Display runtime info",
ArgsUsage: "[flags]", ArgsUsage: "[flags]",

View File

@ -24,7 +24,7 @@ import (
"time" "time"
"github.com/containerd/containerd/v2/defaults" "github.com/containerd/containerd/v2/defaults"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
type pprofDialer struct { type pprofDialer struct {
@ -33,17 +33,18 @@ type pprofDialer struct {
} }
// Command is the cli command for providing golang pprof outputs for containerd // Command is the cli command for providing golang pprof outputs for containerd
var Command = cli.Command{ var Command = &cli.Command{
Name: "pprof", Name: "pprof",
Usage: "Provide golang pprof outputs for containerd", Usage: "Provide golang pprof outputs for containerd",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "debug-socket, d", Name: "debug-socket",
Aliases: []string{"d"},
Usage: "Socket path for containerd's debug server", Usage: "Socket path for containerd's debug server",
Value: defaults.DefaultDebugAddress, Value: defaults.DefaultDebugAddress,
}, },
}, },
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
pprofBlockCommand, pprofBlockCommand,
pprofGoroutinesCommand, pprofGoroutinesCommand,
pprofHeapCommand, pprofHeapCommand,
@ -53,11 +54,11 @@ var Command = cli.Command{
}, },
} }
var pprofGoroutinesCommand = cli.Command{ var pprofGoroutinesCommand = &cli.Command{
Name: "goroutines", Name: "goroutines",
Usage: "Dump goroutine stack dump", Usage: "Dump goroutine stack dump",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.UintFlag{ &cli.UintFlag{
Name: "debug", Name: "debug",
Usage: "Debug pprof args", Usage: "Debug pprof args",
Value: 2, Value: 2,
@ -77,11 +78,11 @@ var pprofGoroutinesCommand = cli.Command{
}, },
} }
var pprofHeapCommand = cli.Command{ var pprofHeapCommand = &cli.Command{
Name: "heap", Name: "heap",
Usage: "Dump heap profile", Usage: "Dump heap profile",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.UintFlag{ &cli.UintFlag{
Name: "debug", Name: "debug",
Usage: "Debug pprof args", Usage: "Debug pprof args",
Value: 0, Value: 0,
@ -101,16 +102,17 @@ var pprofHeapCommand = cli.Command{
}, },
} }
var pprofProfileCommand = cli.Command{ var pprofProfileCommand = &cli.Command{
Name: "profile", Name: "profile",
Usage: "CPU profile", Usage: "CPU profile",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.DurationFlag{ &cli.DurationFlag{
Name: "seconds,s", Name: "seconds",
Aliases: []string{"s"},
Usage: "Duration for collection (seconds)", Usage: "Duration for collection (seconds)",
Value: 30 * time.Second, Value: 30 * time.Second,
}, },
cli.UintFlag{ &cli.UintFlag{
Name: "debug", Name: "debug",
Usage: "Debug pprof args", Usage: "Debug pprof args",
Value: 0, Value: 0,
@ -131,16 +133,17 @@ var pprofProfileCommand = cli.Command{
}, },
} }
var pprofTraceCommand = cli.Command{ var pprofTraceCommand = &cli.Command{
Name: "trace", Name: "trace",
Usage: "Collect execution trace", Usage: "Collect execution trace",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.DurationFlag{ &cli.DurationFlag{
Name: "seconds,s", Name: "seconds",
Aliases: []string{"s"},
Usage: "Trace time (seconds)", Usage: "Trace time (seconds)",
Value: 5 * time.Second, Value: 5 * time.Second,
}, },
cli.UintFlag{ &cli.UintFlag{
Name: "debug", Name: "debug",
Usage: "Debug pprof args", Usage: "Debug pprof args",
Value: 0, Value: 0,
@ -162,11 +165,11 @@ var pprofTraceCommand = cli.Command{
}, },
} }
var pprofBlockCommand = cli.Command{ var pprofBlockCommand = &cli.Command{
Name: "block", Name: "block",
Usage: "Goroutine blocking profile", Usage: "Goroutine blocking profile",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.UintFlag{ &cli.UintFlag{
Name: "debug", Name: "debug",
Usage: "Debug pprof args", Usage: "Debug pprof args",
Value: 0, Value: 0,
@ -186,11 +189,11 @@ var pprofBlockCommand = cli.Command{
}, },
} }
var pprofThreadcreateCommand = cli.Command{ var pprofThreadcreateCommand = &cli.Command{
Name: "threadcreate", Name: "threadcreate",
Usage: "Goroutine thread creating profile", Usage: "Goroutine thread creating profile",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.UintFlag{ &cli.UintFlag{
Name: "debug", Name: "debug",
Usage: "Debug pprof args", Usage: "Debug pprof args",
Value: 0, Value: 0,
@ -211,7 +214,7 @@ var pprofThreadcreateCommand = cli.Command{
} }
func getPProfClient(context *cli.Context) *http.Client { func getPProfClient(context *cli.Context) *http.Client {
dialer := getPProfDialer(context.GlobalString("debug-socket")) dialer := getPProfDialer(context.String("debug-socket"))
tr := &http.Transport{ tr := &http.Transport{
Dial: dialer.pprofDial, Dial: dialer.pprofDial,

View File

@ -36,7 +36,7 @@ import (
"github.com/containerd/containerd/v2/core/remotes/docker/config" "github.com/containerd/containerd/v2/core/remotes/docker/config"
"github.com/containerd/containerd/v2/core/transfer/registry" "github.com/containerd/containerd/v2/core/transfer/registry"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// PushTracker returns a new InMemoryTracker which tracks the ref status // PushTracker returns a new InMemoryTracker which tracks the ref status

View File

@ -26,7 +26,7 @@ import (
"github.com/containerd/console" "github.com/containerd/console"
gocni "github.com/containerd/go-cni" gocni "github.com/containerd/go-cni"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
@ -89,41 +89,41 @@ func parseMountFlag(m string) (specs.Mount, error) {
} }
// Command runs a container // Command runs a container
var Command = cli.Command{ var Command = &cli.Command{
Name: "run", Name: "run",
Usage: "Run a container", Usage: "Run a container",
ArgsUsage: "[flags] Image|RootFS ID [COMMAND] [ARG...]", ArgsUsage: "[flags] Image|RootFS ID [COMMAND] [ARG...]",
SkipArgReorder: true,
Flags: append([]cli.Flag{ Flags: append([]cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "rm", Name: "rm",
Usage: "Remove the container after running, cannot be used with --detach", Usage: "Remove the container after running, cannot be used with --detach",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "null-io", Name: "null-io",
Usage: "Send all IO to /dev/null", Usage: "Send all IO to /dev/null",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "log-uri", Name: "log-uri",
Usage: "Log uri", Usage: "Log uri",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "detach,d", Name: "detach",
Aliases: []string{"d"},
Usage: "Detach from the task after it has started execution, cannot be used with --rm", Usage: "Detach from the task after it has started execution, cannot be used with --rm",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "fifo-dir", Name: "fifo-dir",
Usage: "Directory used for storing IO FIFOs", Usage: "Directory used for storing IO FIFOs",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "cgroup", Name: "cgroup",
Usage: "Cgroup path (To disable use of cgroup, set to \"\" explicitly)", Usage: "Cgroup path (To disable use of cgroup, set to \"\" explicitly)",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "platform", Name: "platform",
Usage: "Run image for specific platform", Usage: "Run image for specific platform",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "cni", Name: "cni",
Usage: "Enable cni networking for the container", Usage: "Enable cni networking for the container",
}, },
@ -259,7 +259,7 @@ var Command = cli.Command{
return err return err
} }
if code != 0 { if code != 0 {
return cli.NewExitError("", int(code)) return cli.Exit("", int(code))
} }
return nil return nil
}, },

View File

@ -39,43 +39,43 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/intel/goresctrl/pkg/blockio" "github.com/intel/goresctrl/pkg/blockio"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"tags.cncf.io/container-device-interface/pkg/cdi" "tags.cncf.io/container-device-interface/pkg/cdi"
"tags.cncf.io/container-device-interface/pkg/parser" "tags.cncf.io/container-device-interface/pkg/parser"
) )
var platformRunFlags = []cli.Flag{ var platformRunFlags = []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "uidmap", Name: "uidmap",
Usage: "Run inside a user namespace with the specified UID mapping range; specified with the format `container-uid:host-uid:length`", Usage: "Run inside a user namespace with the specified UID mapping range; specified with the format `container-uid:host-uid:length`",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "gidmap", Name: "gidmap",
Usage: "Run inside a user namespace with the specified GID mapping range; specified with the format `container-gid:host-gid:length`", Usage: "Run inside a user namespace with the specified GID mapping range; specified with the format `container-gid:host-gid:length`",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "remap-labels", Name: "remap-labels",
Usage: "Provide the user namespace ID remapping to the snapshotter via label options; requires snapshotter support", Usage: "Provide the user namespace ID remapping to the snapshotter via label options; requires snapshotter support",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "privileged-without-host-devices", Name: "privileged-without-host-devices",
Usage: "Don't pass all host devices to privileged container", Usage: "Don't pass all host devices to privileged container",
}, },
cli.Float64Flag{ &cli.Float64Flag{
Name: "cpus", Name: "cpus",
Usage: "Set the CFS cpu quota", Usage: "Set the CFS cpu quota",
Value: 0.0, Value: 0.0,
}, },
cli.IntFlag{ &cli.IntFlag{
Name: "cpu-shares", Name: "cpu-shares",
Usage: "Set the cpu shares", Usage: "Set the cpu shares",
Value: 1024, Value: 1024,
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "cpuset-cpus", Name: "cpuset-cpus",
Usage: "Set the CPUs the container will run in (e.g., 1-2,4)", Usage: "Set the CPUs the container will run in (e.g., 1-2,4)",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "cpuset-mems", Name: "cpuset-mems",
Usage: "Set the memory nodes the container will run in (e.g., 1-2,4)", Usage: "Set the memory nodes the container will run in (e.g., 1-2,4)",
}, },
@ -110,7 +110,7 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
var ( var (
ref = context.Args().First() ref = context.Args().First()
// for container's id is Args[1] // for container's id is Args[1]
args = context.Args()[2:] args = context.Args().Slice()[2:]
) )
opts = append(opts, oci.WithDefaultSpec(), oci.WithDefaultUnixDevices) opts = append(opts, oci.WithDefaultSpec(), oci.WithDefaultUnixDevices)
if ef := context.String("env-file"); ef != "" { if ef := context.String("env-file"); ef != "" {

View File

@ -30,11 +30,11 @@ import (
"github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/log" "github.com/containerd/log"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var platformRunFlags = []cli.Flag{ var platformRunFlags = []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "isolated", Name: "isolated",
Usage: "Run the container with vm isolation", Usage: "Run the container with vm isolation",
}, },
@ -62,7 +62,7 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
} else { } else {
var ( var (
ref = context.Args().First() ref = context.Args().First()
args = context.Args()[2:] args = context.Args().Slice()[2:]
) )
id = context.Args().Get(1) id = context.Args().Get(1)
@ -176,7 +176,7 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
var runtimeOpts interface{} var runtimeOpts interface{}
if runtime == "io.containerd.runhcs.v1" { if runtime == "io.containerd.runhcs.v1" {
runtimeOpts = &options.Options{ runtimeOpts = &options.Options{
Debug: context.GlobalBool("debug"), Debug: context.Bool("debug"),
} }
} }
cOpts = append(cOpts, containerd.WithRuntime(runtime, runtimeOpts)) cOpts = append(cOpts, containerd.WithRuntime(runtime, runtimeOpts))

View File

@ -27,11 +27,11 @@ import (
"github.com/containerd/containerd/v2/defaults" "github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is a set of subcommands to manage runtimes with sandbox support // Command is a set of subcommands to manage runtimes with sandbox support
var Command = cli.Command{ var Command = &cli.Command{
Name: "sandboxes", Name: "sandboxes",
Aliases: []string{"sandbox", "sb", "s"}, Aliases: []string{"sandbox", "sb", "s"},
Usage: "Manage sandboxes", Usage: "Manage sandboxes",
@ -42,13 +42,13 @@ var Command = cli.Command{
}, },
} }
var runCommand = cli.Command{ var runCommand = &cli.Command{
Name: "run", Name: "run",
Aliases: []string{"create", "c", "r"}, Aliases: []string{"create", "c", "r"},
Usage: "Run a new sandbox", Usage: "Run a new sandbox",
ArgsUsage: "[flags] <pod-config.json> <sandbox-id>", ArgsUsage: "[flags] <pod-config.json> <sandbox-id>",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "runtime", Name: "runtime",
Usage: "Runtime name", Usage: "Runtime name",
Value: defaults.DefaultRuntime, Value: defaults.DefaultRuntime,
@ -97,12 +97,12 @@ var runCommand = cli.Command{
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "List sandboxes", Usage: "List sandboxes",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "filters", Name: "filters",
Usage: "The list of filters to apply when querying sandboxes from the store", Usage: "The list of filters to apply when querying sandboxes from the store",
}, },
@ -143,14 +143,15 @@ var listCommand = cli.Command{
}, },
} }
var removeCommand = cli.Command{ var removeCommand = &cli.Command{
Name: "remove", Name: "remove",
Aliases: []string{"rm"}, Aliases: []string{"rm"},
ArgsUsage: "<id> [<id>, ...]", ArgsUsage: "<id> [<id>, ...]",
Usage: "Remove sandboxes", Usage: "Remove sandboxes",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "force, f", Name: "force",
Aliases: []string{"f"},
Usage: "Ignore shutdown errors when removing sandbox", Usage: "Ignore shutdown errors when removing sandbox",
}, },
}, },
@ -163,7 +164,7 @@ var removeCommand = cli.Command{
force := context.Bool("force") force := context.Bool("force")
for _, id := range context.Args() { for _, id := range context.Args().Slice() {
sandbox, err := client.LoadSandbox(ctx, id) sandbox, err := client.LoadSandbox(ctx, id)
if err != nil { if err != nil {
log.G(ctx).WithError(err).Errorf("failed to load sandbox %s", id) log.G(ctx).WithError(err).Errorf("failed to load sandbox %s", id)

View File

@ -37,39 +37,40 @@ import (
"github.com/containerd/ttrpc" "github.com/containerd/ttrpc"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var fifoFlags = []cli.Flag{ var fifoFlags = []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "stdin", Name: "stdin",
Usage: "Specify the path to the stdin fifo", Usage: "Specify the path to the stdin fifo",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "stdout", Name: "stdout",
Usage: "Specify the path to the stdout fifo", Usage: "Specify the path to the stdout fifo",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "stderr", Name: "stderr",
Usage: "Specify the path to the stderr fifo", Usage: "Specify the path to the stderr fifo",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "tty,t", Name: "tty",
Aliases: []string{"t"},
Usage: "Enable tty support", Usage: "Enable tty support",
}, },
} }
// Command is the cli command for interacting with a task // Command is the cli command for interacting with a task
var Command = cli.Command{ var Command = &cli.Command{
Name: "shim", Name: "shim",
Usage: "Interact with a shim directly", Usage: "Interact with a shim directly",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "id", Name: "id",
Usage: "Container id", Usage: "Container id",
}, },
}, },
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
deleteCommand, deleteCommand,
execCommand, execCommand,
startCommand, startCommand,
@ -77,7 +78,7 @@ var Command = cli.Command{
}, },
} }
var startCommand = cli.Command{ var startCommand = &cli.Command{
Name: "start", Name: "start",
Usage: "Start a container with a task", Usage: "Start a container with a task",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
@ -92,7 +93,7 @@ var startCommand = cli.Command{
}, },
} }
var deleteCommand = cli.Command{ var deleteCommand = &cli.Command{
Name: "delete", Name: "delete",
Usage: "Delete a container with a task", Usage: "Delete a container with a task",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
@ -111,7 +112,7 @@ var deleteCommand = cli.Command{
}, },
} }
var stateCommand = cli.Command{ var stateCommand = &cli.Command{
Name: "state", Name: "state",
Usage: "Get the state of all the processes of the task", Usage: "Get the state of all the processes of the task",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
@ -120,7 +121,7 @@ var stateCommand = cli.Command{
return err return err
} }
r, err := service.State(gocontext.Background(), &task.StateRequest{ r, err := service.State(gocontext.Background(), &task.StateRequest{
ID: context.GlobalString("id"), ID: context.String("id"),
}) })
if err != nil { if err != nil {
return err return err
@ -130,24 +131,26 @@ var stateCommand = cli.Command{
}, },
} }
var execCommand = cli.Command{ var execCommand = &cli.Command{
Name: "exec", Name: "exec",
Usage: "Exec a new process in the task's container", Usage: "Exec a new process in the task's container",
Flags: append(fifoFlags, Flags: append(fifoFlags,
cli.BoolFlag{ &cli.BoolFlag{
Name: "attach,a", Name: "attach",
Aliases: []string{"a"},
Usage: "Stay attached to the container and open the fifos", Usage: "Stay attached to the container and open the fifos",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "env,e", Name: "env",
Aliases: []string{"e"},
Usage: "Add environment vars", Usage: "Add environment vars",
Value: &cli.StringSlice{}, Value: cli.NewStringSlice(),
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "cwd", Name: "cwd",
Usage: "Current working directory", Usage: "Current working directory",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "spec", Name: "spec",
Usage: "Runtime spec", Usage: "Runtime spec",
}, },
@ -230,18 +233,18 @@ var execCommand = cli.Command{
} }
func getTaskService(context *cli.Context) (task.TaskService, error) { func getTaskService(context *cli.Context) (task.TaskService, error) {
id := context.GlobalString("id") id := context.String("id")
if id == "" { if id == "" {
return nil, fmt.Errorf("container id must be specified") return nil, fmt.Errorf("container id must be specified")
} }
ns := context.GlobalString("namespace") ns := context.String("namespace")
// /containerd-shim/ns/id/shim.sock is the old way to generate shim socket, // /containerd-shim/ns/id/shim.sock is the old way to generate shim socket,
// compatible it // compatible it
s1 := filepath.Join(string(filepath.Separator), "containerd-shim", ns, id, "shim.sock") s1 := filepath.Join(string(filepath.Separator), "containerd-shim", ns, id, "shim.sock")
// this should not error, ctr always get a default ns // this should not error, ctr always get a default ns
ctx := namespaces.WithNamespace(gocontext.Background(), ns) ctx := namespaces.WithNamespace(gocontext.Background(), ns)
s2, _ := shim.SocketAddress(ctx, context.GlobalString("address"), id) s2, _ := shim.SocketAddress(ctx, context.String("address"), id)
s2 = strings.TrimPrefix(s2, "unix://") s2 = strings.TrimPrefix(s2, "unix://")
for _, socket := range []string{s2, "\x00" + s1} { for _, socket := range []string{s2, "\x00" + s1} {

View File

@ -38,11 +38,11 @@ import (
"github.com/containerd/log" "github.com/containerd/log"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is the cli command for managing snapshots // Command is the cli command for managing snapshots
var Command = cli.Command{ var Command = &cli.Command{
Name: "snapshots", Name: "snapshots",
Aliases: []string{"snapshot"}, Aliases: []string{"snapshot"},
Usage: "Manage snapshots", Usage: "Manage snapshots",
@ -63,7 +63,7 @@ var Command = cli.Command{
}, },
} }
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Usage: "List snapshots", Usage: "List snapshots",
@ -74,7 +74,7 @@ var listCommand = cli.Command{
} }
defer cancel() defer cancel()
var ( var (
snapshotter = client.SnapshotService(context.GlobalString("snapshotter")) snapshotter = client.SnapshotService(context.String("snapshotter"))
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0) tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
) )
fmt.Fprintln(tw, "KEY\tPARENT\tKIND\t") fmt.Fprintln(tw, "KEY\tPARENT\tKIND\t")
@ -92,21 +92,21 @@ var listCommand = cli.Command{
}, },
} }
var diffCommand = cli.Command{ var diffCommand = &cli.Command{
Name: "diff", Name: "diff",
Usage: "Get the diff of two snapshots. the default second snapshot is the first snapshot's parent.", Usage: "Get the diff of two snapshots. the default second snapshot is the first snapshot's parent.",
ArgsUsage: "[flags] <idA> [<idB>]", ArgsUsage: "[flags] <idA> [<idB>]",
Flags: append([]cli.Flag{ Flags: append([]cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "media-type", Name: "media-type",
Usage: "Media type to use for creating diff", Usage: "Media type to use for creating diff",
Value: ocispec.MediaTypeImageLayerGzip, Value: ocispec.MediaTypeImageLayerGzip,
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "ref", Name: "ref",
Usage: "Content upload reference to use", Usage: "Content upload reference to use",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "keep", Name: "keep",
Usage: "Keep diff content. up to creator to delete it.", Usage: "Keep diff content. up to creator to delete it.",
}, },
@ -133,7 +133,7 @@ var diffCommand = cli.Command{
var desc ocispec.Descriptor var desc ocispec.Descriptor
labels := commands.LabelArgs(context.StringSlice("label")) labels := commands.LabelArgs(context.StringSlice("label"))
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
if context.Bool("keep") { if context.Bool("keep") {
labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339) labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339)
@ -194,12 +194,12 @@ func withMounts(ctx gocontext.Context, id string, sn snapshots.Snapshotter, f fu
return f(mounts) return f(mounts)
} }
var usageCommand = cli.Command{ var usageCommand = &cli.Command{
Name: "usage", Name: "usage",
Usage: "Usage snapshots", Usage: "Usage snapshots",
ArgsUsage: "[flags] [<key>, ...]", ArgsUsage: "[flags] [<key>, ...]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "b", Name: "b",
Usage: "Display size in bytes", Usage: "Display size in bytes",
}, },
@ -221,7 +221,7 @@ var usageCommand = cli.Command{
} }
defer cancel() defer cancel()
var ( var (
snapshotter = client.SnapshotService(context.GlobalString("snapshotter")) snapshotter = client.SnapshotService(context.String("snapshotter"))
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0) tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
) )
fmt.Fprintln(tw, "KEY\tSIZE\tINODES\t") fmt.Fprintln(tw, "KEY\tSIZE\tINODES\t")
@ -237,7 +237,7 @@ var usageCommand = cli.Command{
return err return err
} }
} else { } else {
for _, id := range context.Args() { for _, id := range context.Args().Slice() {
usage, err := snapshotter.Usage(ctx, id) usage, err := snapshotter.Usage(ctx, id)
if err != nil { if err != nil {
return err return err
@ -250,7 +250,7 @@ var usageCommand = cli.Command{
}, },
} }
var removeCommand = cli.Command{ var removeCommand = &cli.Command{
Name: "delete", Name: "delete",
Aliases: []string{"del", "remove", "rm"}, Aliases: []string{"del", "remove", "rm"},
ArgsUsage: "<key> [<key>, ...]", ArgsUsage: "<key> [<key>, ...]",
@ -261,8 +261,8 @@ var removeCommand = cli.Command{
return err return err
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
for _, key := range context.Args() { for _, key := range context.Args().Slice() {
err = snapshotter.Remove(ctx, key) err = snapshotter.Remove(ctx, key)
if err != nil { if err != nil {
return fmt.Errorf("failed to remove %q: %w", key, err) return fmt.Errorf("failed to remove %q: %w", key, err)
@ -273,16 +273,17 @@ var removeCommand = cli.Command{
}, },
} }
var prepareCommand = cli.Command{ var prepareCommand = &cli.Command{
Name: "prepare", Name: "prepare",
Usage: "Prepare a snapshot from a committed snapshot", Usage: "Prepare a snapshot from a committed snapshot",
ArgsUsage: "[flags] <key> [<parent>]", ArgsUsage: "[flags] <key> [<parent>]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "target, t", Name: "target",
Aliases: []string{"t"},
Usage: "Mount target path, will print mount, if provided", Usage: "Mount target path, will print mount, if provided",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "mounts", Name: "mounts",
Usage: "Print out snapshot mounts as JSON", Usage: "Print out snapshot mounts as JSON",
}, },
@ -302,7 +303,7 @@ var prepareCommand = cli.Command{
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
labels := map[string]string{ labels := map[string]string{
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339),
} }
@ -324,16 +325,17 @@ var prepareCommand = cli.Command{
}, },
} }
var viewCommand = cli.Command{ var viewCommand = &cli.Command{
Name: "view", Name: "view",
Usage: "Create a read-only snapshot from a committed snapshot", Usage: "Create a read-only snapshot from a committed snapshot",
ArgsUsage: "[flags] <key> [<parent>]", ArgsUsage: "[flags] <key> [<parent>]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "target, t", Name: "target",
Aliases: []string{"t"},
Usage: "Mount target path, will print mount, if provided", Usage: "Mount target path, will print mount, if provided",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "mounts", Name: "mounts",
Usage: "Print out snapshot mounts as JSON", Usage: "Print out snapshot mounts as JSON",
}, },
@ -353,7 +355,7 @@ var viewCommand = cli.Command{
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
mounts, err := snapshotter.View(ctx, key, parent) mounts, err := snapshotter.View(ctx, key, parent)
if err != nil { if err != nil {
return err return err
@ -371,7 +373,7 @@ var viewCommand = cli.Command{
}, },
} }
var mountCommand = cli.Command{ var mountCommand = &cli.Command{
Name: "mounts", Name: "mounts",
Aliases: []string{"m", "mount"}, Aliases: []string{"m", "mount"},
Usage: "Mount gets mount commands for the snapshots", Usage: "Mount gets mount commands for the snapshots",
@ -389,7 +391,7 @@ var mountCommand = cli.Command{
return err return err
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
mounts, err := snapshotter.Mounts(ctx, key) mounts, err := snapshotter.Mounts(ctx, key)
if err != nil { if err != nil {
return err return err
@ -401,7 +403,7 @@ var mountCommand = cli.Command{
}, },
} }
var commitCommand = cli.Command{ var commitCommand = &cli.Command{
Name: "commit", Name: "commit",
Usage: "Commit an active snapshot into the provided name", Usage: "Commit an active snapshot into the provided name",
ArgsUsage: "<key> <active>", ArgsUsage: "<key> <active>",
@ -418,7 +420,7 @@ var commitCommand = cli.Command{
return err return err
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
labels := map[string]string{ labels := map[string]string{
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339),
} }
@ -426,7 +428,7 @@ var commitCommand = cli.Command{
}, },
} }
var treeCommand = cli.Command{ var treeCommand = &cli.Command{
Name: "tree", Name: "tree",
Usage: "Display tree view of snapshot branches", Usage: "Display tree view of snapshot branches",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
@ -436,7 +438,7 @@ var treeCommand = cli.Command{
} }
defer cancel() defer cancel()
var ( var (
snapshotter = client.SnapshotService(context.GlobalString("snapshotter")) snapshotter = client.SnapshotService(context.String("snapshotter"))
tree = newSnapshotTree() tree = newSnapshotTree()
) )
@ -454,7 +456,7 @@ var treeCommand = cli.Command{
}, },
} }
var infoCommand = cli.Command{ var infoCommand = &cli.Command{
Name: "info", Name: "info",
Usage: "Get info about a snapshot", Usage: "Get info about a snapshot",
ArgsUsage: "<key>", ArgsUsage: "<key>",
@ -469,7 +471,7 @@ var infoCommand = cli.Command{
return err return err
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
info, err := snapshotter.Stat(ctx, key) info, err := snapshotter.Stat(ctx, key)
if err != nil { if err != nil {
return err return err
@ -481,7 +483,7 @@ var infoCommand = cli.Command{
}, },
} }
var setLabelCommand = cli.Command{ var setLabelCommand = &cli.Command{
Name: "label", Name: "label",
Usage: "Add labels to content", Usage: "Add labels to content",
ArgsUsage: "<name> [<label>=<value> ...]", ArgsUsage: "<name> [<label>=<value> ...]",
@ -494,7 +496,7 @@ var setLabelCommand = cli.Command{
} }
defer cancel() defer cancel()
snapshotter := client.SnapshotService(context.GlobalString("snapshotter")) snapshotter := client.SnapshotService(context.String("snapshotter"))
info := snapshots.Info{ info := snapshots.Info{
Name: key, Name: key,
@ -530,7 +532,7 @@ var setLabelCommand = cli.Command{
}, },
} }
var unpackCommand = cli.Command{ var unpackCommand = &cli.Command{
Name: "unpack", Name: "unpack",
Usage: "Unpack applies layers from a manifest to a snapshot", Usage: "Unpack applies layers from a manifest to a snapshot",
ArgsUsage: "[flags] <digest>", ArgsUsage: "[flags] <digest>",

View File

@ -21,10 +21,10 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var attachCommand = cli.Command{ var attachCommand = &cli.Command{
Name: "attach", Name: "attach",
Usage: "Attach to the IO of a running container", Usage: "Attach to the IO of a running container",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",
@ -79,7 +79,7 @@ var attachCommand = cli.Command{
return err return err
} }
if code != 0 { if code != 0 {
return cli.NewExitError("", int(code)) return cli.Exit("", int(code))
} }
return nil return nil
}, },

View File

@ -23,23 +23,23 @@ import (
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/core/runtime/v2/runc/options" "github.com/containerd/containerd/v2/core/runtime/v2/runc/options"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var checkpointCommand = cli.Command{ var checkpointCommand = &cli.Command{
Name: "checkpoint", Name: "checkpoint",
Usage: "Checkpoint a container", Usage: "Checkpoint a container",
ArgsUsage: "[flags] CONTAINER", ArgsUsage: "[flags] CONTAINER",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "exit", Name: "exit",
Usage: "Stop the container after the checkpoint", Usage: "Stop the container after the checkpoint",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "image-path", Name: "image-path",
Usage: "Path to criu image files", Usage: "Path to criu image files",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "work-path", Name: "work-path",
Usage: "Path to criu work files and logs", Usage: "Path to criu work files and logs",
}, },

View File

@ -23,20 +23,21 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var deleteCommand = cli.Command{ var deleteCommand = &cli.Command{
Name: "delete", Name: "delete",
Usage: "Delete one or more tasks", Usage: "Delete one or more tasks",
ArgsUsage: "CONTAINER [CONTAINER, ...]", ArgsUsage: "CONTAINER [CONTAINER, ...]",
Aliases: []string{"del", "remove", "rm"}, Aliases: []string{"del", "remove", "rm"},
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "force, f", Name: "force",
Aliases: []string{"f"},
Usage: "Force delete task process", Usage: "Force delete task process",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "exec-id", Name: "exec-id",
Usage: "Process ID to kill", Usage: "Process ID to kill",
}, },
@ -70,10 +71,10 @@ var deleteCommand = cli.Command{
return err return err
} }
if ec := status.ExitCode(); ec != 0 { if ec := status.ExitCode(); ec != 0 {
return cli.NewExitError("", int(ec)) return cli.Exit("", int(ec))
} }
} else { } else {
for _, target := range context.Args() { for _, target := range context.Args().Slice() {
task, err := loadTask(ctx, client, target) task, err := loadTask(ctx, client, target)
if err != nil { if err != nil {
if exitErr == nil { if exitErr == nil {

View File

@ -28,41 +28,42 @@ import (
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/pkg/oci"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var execCommand = cli.Command{ var execCommand = &cli.Command{
Name: "exec", Name: "exec",
Usage: "Execute additional processes in an existing container", Usage: "Execute additional processes in an existing container",
ArgsUsage: "[flags] CONTAINER CMD [ARG...]", ArgsUsage: "[flags] CONTAINER CMD [ARG...]",
SkipArgReorder: true,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "cwd", Name: "cwd",
Usage: "Working directory of the new process", Usage: "Working directory of the new process",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "tty,t", Name: "tty",
Aliases: []string{"t"},
Usage: "Allocate a TTY for the container", Usage: "Allocate a TTY for the container",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "detach,d", Name: "detach",
Aliases: []string{"d"},
Usage: "Detach from the task after it has started execution", Usage: "Detach from the task after it has started execution",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "exec-id", Name: "exec-id",
Required: true, Required: true,
Usage: "Exec specific id for the process", Usage: "Exec specific id for the process",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "fifo-dir", Name: "fifo-dir",
Usage: "Directory used for storing IO FIFOs", Usage: "Directory used for storing IO FIFOs",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "log-uri", Name: "log-uri",
Usage: "Log uri for custom shim logging", Usage: "Log uri for custom shim logging",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "user", Name: "user",
Usage: "User id or name", Usage: "User id or name",
}, },
@ -186,7 +187,7 @@ var execCommand = cli.Command{
return err return err
} }
if code != 0 { if code != 0 {
return cli.NewExitError("", int(code)) return cli.Exit("", int(code))
} }
return nil return nil
}, },

View File

@ -27,7 +27,7 @@ import (
"github.com/containerd/log" "github.com/containerd/log"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/moby/sys/signal" "github.com/moby/sys/signal"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const defaultSignal = "SIGTERM" const defaultSignal = "SIGTERM"
@ -61,22 +61,24 @@ func RemoveCniNetworkIfExist(ctx context.Context, container containerd.Container
return nil return nil
} }
var killCommand = cli.Command{ var killCommand = &cli.Command{
Name: "kill", Name: "kill",
Usage: "Signal a container (default: SIGTERM)", Usage: "Signal a container (default: SIGTERM)",
ArgsUsage: "[flags] CONTAINER", ArgsUsage: "[flags] CONTAINER",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "signal, s", Name: "signal",
Aliases: []string{"s"},
Value: "", Value: "",
Usage: "Signal to send to the container", Usage: "Signal to send to the container",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "exec-id", Name: "exec-id",
Usage: "Process ID to kill", Usage: "Process ID to kill",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "all, a", Name: "all",
Aliases: []string{"a"},
Usage: "Send signal to all processes inside the container", Usage: "Send signal to all processes inside the container",
}, },
}, },

View File

@ -23,17 +23,18 @@ import (
tasks "github.com/containerd/containerd/v2/api/services/tasks/v1" tasks "github.com/containerd/containerd/v2/api/services/tasks/v1"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var listCommand = cli.Command{ var listCommand = &cli.Command{
Name: "list", Name: "list",
Usage: "List tasks", Usage: "List tasks",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
ArgsUsage: "[flags]", ArgsUsage: "[flags]",
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "quiet, q", Name: "quiet",
Aliases: []string{"q"},
Usage: "Print only the task id", Usage: "Print only the task id",
}, },
}, },

View File

@ -28,7 +28,7 @@ import (
v2 "github.com/containerd/cgroups/v3/cgroup2/stats" v2 "github.com/containerd/cgroups/v3/cgroup2/stats"
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const ( const (
@ -37,13 +37,13 @@ const (
formatJSON = "json" formatJSON = "json"
) )
var metricsCommand = cli.Command{ var metricsCommand = &cli.Command{
Name: "metrics", Name: "metrics",
Usage: "Get a single data point of metrics for a task with the built-in Linux runtime", Usage: "Get a single data point of metrics for a task with the built-in Linux runtime",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",
Aliases: []string{"metric"}, Aliases: []string{"metric"},
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: formatFlag, Name: formatFlag,
Usage: `"table" or "json"`, Usage: `"table" or "json"`,
Value: formatTable, Value: formatTable,

View File

@ -18,10 +18,10 @@ package tasks
import ( import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var pauseCommand = cli.Command{ var pauseCommand = &cli.Command{
Name: "pause", Name: "pause",
Usage: "Pause an existing container", Usage: "Pause an existing container",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",

View File

@ -24,10 +24,10 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var psCommand = cli.Command{ var psCommand = &cli.Command{
Name: "ps", Name: "ps",
Usage: "List processes for container", Usage: "List processes for container",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",

View File

@ -18,10 +18,10 @@ package tasks
import ( import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var resumeCommand = cli.Command{ var resumeCommand = &cli.Command{
Name: "resume", Name: "resume",
Usage: "Resume a paused container", Usage: "Resume a paused container",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",

View File

@ -25,32 +25,33 @@ import (
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var startCommand = cli.Command{ var startCommand = &cli.Command{
Name: "start", Name: "start",
Usage: "Start a container that has been created", Usage: "Start a container that has been created",
ArgsUsage: "CONTAINER", ArgsUsage: "CONTAINER",
Flags: append(platformStartFlags, []cli.Flag{ Flags: append(platformStartFlags, []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "null-io", Name: "null-io",
Usage: "Send all IO to /dev/null", Usage: "Send all IO to /dev/null",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "log-uri", Name: "log-uri",
Usage: "Log uri", Usage: "Log uri",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "fifo-dir", Name: "fifo-dir",
Usage: "Directory used for storing IO FIFOs", Usage: "Directory used for storing IO FIFOs",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "pid-file", Name: "pid-file",
Usage: "File path to write the task's pid", Usage: "File path to write the task's pid",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "detach,d", Name: "detach",
Aliases: []string{"d"},
Usage: "Detach from the task after it has started execution", Usage: "Detach from the task after it has started execution",
}, },
}...), }...),
@ -137,7 +138,7 @@ var startCommand = cli.Command{
return err return err
} }
if code != 0 { if code != 0 {
return cli.NewExitError("", int(code)) return cli.Exit("", int(code))
} }
return nil return nil
}, },

View File

@ -19,7 +19,7 @@ package tasks
import ( import (
gocontext "context" gocontext "context"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
type resizer interface { type resizer interface {
@ -27,11 +27,11 @@ type resizer interface {
} }
// Command is the cli command for managing tasks // Command is the cli command for managing tasks
var Command = cli.Command{ var Command = &cli.Command{
Name: "tasks", Name: "tasks",
Usage: "Manage tasks", Usage: "Manage tasks",
Aliases: []string{"t", "task"}, Aliases: []string{"t", "task"},
Subcommands: []cli.Command{ Subcommands: []*cli.Command{
attachCommand, attachCommand,
checkpointCommand, checkpointCommand,
deleteCommand, deleteCommand,

View File

@ -29,12 +29,12 @@ import (
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
var platformStartFlags = []cli.Flag{ var platformStartFlags = []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "no-pivot", Name: "no-pivot",
Usage: "Disable use of pivot-root (linux only)", Usage: "Disable use of pivot-root (linux only)",
}, },

View File

@ -26,7 +26,7 @@ import (
containerd "github.com/containerd/containerd/v2/client" containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/cio"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var platformStartFlags = []cli.Flag{} var platformStartFlags = []cli.Flag{}

View File

@ -22,11 +22,11 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/cmd/ctr/commands"
"github.com/containerd/containerd/v2/version" "github.com/containerd/containerd/v2/version"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
// Command is a cli command to output the client and containerd server version // Command is a cli command to output the client and containerd server version
var Command = cli.Command{ var Command = &cli.Command{
Name: "version", Name: "version",
Usage: "Print the client and server versions", Usage: "Print the client and server versions",
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {

View File

@ -24,10 +24,10 @@ import (
"github.com/containerd/containerd/v2/cmd/ctr/app" "github.com/containerd/containerd/v2/cmd/ctr/app"
"github.com/containerd/containerd/v2/internal/hasher" "github.com/containerd/containerd/v2/internal/hasher"
"github.com/containerd/containerd/v2/pkg/seed" //nolint:staticcheck // Global math/rand seed is deprecated, but still used by external dependencies "github.com/containerd/containerd/v2/pkg/seed" //nolint:staticcheck // Global math/rand seed is deprecated, but still used by external dependencies
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var pluginCmds = []cli.Command{} var pluginCmds = []*cli.Command{}
func init() { func init() {
//nolint:staticcheck // Global math/rand seed is deprecated, but still used by external dependencies //nolint:staticcheck // Global math/rand seed is deprecated, but still used by external dependencies

View File

@ -25,7 +25,7 @@ import (
"github.com/containerd/containerd/v2/cmd/containerd/command" "github.com/containerd/containerd/v2/cmd/containerd/command"
"github.com/containerd/containerd/v2/cmd/ctr/app" "github.com/containerd/containerd/v2/cmd/ctr/app"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func main() { func main() {

3
go.mod
View File

@ -54,7 +54,7 @@ require (
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/tchap/go-patricia/v2 v2.3.1 github.com/tchap/go-patricia/v2 v2.3.1
github.com/urfave/cli v1.22.14 github.com/urfave/cli/v2 v2.27.1
github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netlink v1.2.1-beta.2
go.etcd.io/bbolt v1.3.8 go.etcd.io/bbolt v1.3.8
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0
@ -113,6 +113,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/vishvananda/netns v0.0.4 // indirect github.com/vishvananda/netns v0.0.4 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel/metric v1.23.1 // indirect go.opentelemetry.io/otel/metric v1.23.1 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect

7
go.sum
View File

@ -11,7 +11,6 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.12.0-rc.3 h1:5GNGrobGs/sN/0nFO21W9k4lFn+iXXZAE8fCZbmdRak= github.com/Microsoft/hcsshim v0.12.0-rc.3 h1:5GNGrobGs/sN/0nFO21W9k4lFn+iXXZAE8fCZbmdRak=
@ -329,8 +328,8 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG
github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
@ -343,6 +342,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=

View File

@ -1,10 +0,0 @@
*.coverprofile
coverage.txt
node_modules/
vendor
.idea
/.local/
/internal/
/site/
package.json
package-lock.json

View File

@ -1,51 +0,0 @@
cli
===
[![Run Tests](https://github.com/urfave/cli/actions/workflows/cli.yml/badge.svg?branch=v1-maint)](https://github.com/urfave/cli/actions/workflows/cli.yml)
[![Go Reference](https://pkg.go.dev/badge/github.com/urfave/cli/.svg)](https://pkg.go.dev/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/v1-maint/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 for `v1` is available [at the docs
site](https://cli.urfave.org/v1/getting-started/) or in-tree at
[./docs/v1/manual.md](./docs/v1/manual.md)
## Installation
Make sure you have a working Go environment. Go version 1.18+ is supported.
### Supported platforms
cli is tested against multiple versions of Go on Linux, and against the latest released
version of Go on OS X and Windows. For full details, see
[./.github/workflows/cli.yml](./.github/workflows/cli.yml).
### Build tags
You can use the following build tags:
#### `urfave_cli_no_docs`
When set, this removes `ToMarkdown` and `ToMan` methods, so your application
won't be able to call those. This reduces the resulting binary size by about
300-400 KB (measured using Go 1.18.1 on Linux/amd64), due to less dependencies.
### Using `v1` releases
```
$ go get github.com/urfave/cli
```
```go
...
import (
"github.com/urfave/cli"
)
...
```

531
vendor/github.com/urfave/cli/app.go generated vendored
View File

@ -1,531 +0,0 @@
package cli
import (
"flag"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"time"
)
var (
changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
// unused variable. commented for now. will remove in future if agreed upon by everyone
//runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
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
HideHelp bool
// Boolean to hide built-in version flag and the VERSION section of help
HideVersion bool
// Populate on app startup, only gettable through method Categories()
categories CommandCategories
// An action to execute when the bash-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
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
// *Note*: support for the deprecated `Action` signature will be removed in a future version
Action interface{}
// Execute this function if the proper command cannot be found
CommandNotFound CommandNotFoundFunc
// Execute this function if an 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
// Name of Author (Note: Use App.Authors, this is deprecated)
Author string
// Email of Author (Note: Use App.Authors, this is deprecated)
Email string
// Writer writer to write output to
Writer io.Writer
// ErrWriter writes error output
ErrWriter io.Writer
// Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to
// function as a default, so this is optional.
ExitErrHandler 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 arguements 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(),
Writer: os.Stdout,
}
}
// 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.Author != "" || a.Email != "" {
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
}
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
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
a.Commands = append(a.Commands, helpCommand)
if (HelpFlag != BoolFlag{}) {
a.appendFlag(HelpFlag)
}
}
if a.Version == "" {
a.HideVersion = true
}
if !a.HideVersion {
a.appendFlag(VersionFlag)
}
a.categories = CommandCategories{}
for _, command := range a.Commands {
a.categories = a.categories.AddCommand(command.Category, command)
}
sort.Sort(a.categories)
if a.Metadata == nil {
a.Metadata = make(map[string]interface{})
}
if a.Writer == nil {
a.Writer = os.Stdout
}
}
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) {
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, nil)
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 && !context.shellComplete {
defer func() {
if afterErr := a.After(context); afterErr != nil {
if err != nil {
err = NewMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}
if a.Before != nil && !context.shellComplete {
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 = HandleAction(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) {
// append help to commands
if len(a.Commands) > 0 {
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
a.Commands = append(a.Commands, helpCommand)
if (HelpFlag != BoolFlag{}) {
a.appendFlag(HelpFlag)
}
}
}
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 && !context.shellComplete {
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 && !context.shellComplete {
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 = HandleAction(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
}
// Categories returns a slice containing all the categories with the commands they contain
func (a *App) Categories() CommandCategories {
return a.categories
}
// VisibleCategories returns a slice of categories and commands that are
// Hidden=false
func (a *App) VisibleCategories() []*CommandCategory {
ret := []*CommandCategory{}
for _, category := range a.categories {
if visible := func() *CommandCategory {
for _, command := range category.Commands {
if !command.Hidden {
return category
}
}
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) hasFlag(flag Flag) bool {
for _, f := range a.Flags {
if flag == f {
return true
}
}
return false
}
func (a *App) errWriter() io.Writer {
// When the app ErrWriter is nil use the package level one.
if a.ErrWriter == nil {
return ErrWriter
}
return a.ErrWriter
}
func (a *App) appendFlag(flag Flag) {
if !a.hasFlag(flag) {
a.Flags = append(a.Flags, flag)
}
}
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
}

View File

@ -1,44 +0,0 @@
package cli
// CommandCategories is a slice of *CommandCategory.
type CommandCategories []*CommandCategory
// CommandCategory is a category containing commands.
type CommandCategory struct {
Name string
Commands Commands
}
func (c CommandCategories) Less(i, j int) bool {
return lexicographicLess(c[i].Name, c[j].Name)
}
func (c CommandCategories) Len() int {
return len(c)
}
func (c CommandCategories) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
// AddCommand adds a command to a category.
func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
for _, commandCategory := range c {
if commandCategory.Name == category {
commandCategory.Commands = append(commandCategory.Commands, command)
return c
}
}
return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
}
// VisibleCommands returns a slice of the Commands with Hidden=false
func (c *CommandCategory) VisibleCommands() []Command {
ret := []Command{}
for _, command := range c.Commands {
if !command.Hidden {
ret = append(ret, command)
}
}
return ret
}

22
vendor/github.com/urfave/cli/cli.go generated vendored
View File

@ -1,22 +0,0 @@
// 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.NewApp().Run(os.Args)
// }
//
// Of course this application does not do much, so let's make this an actual application:
// func main() {
// app := cli.NewApp()
// app.Name = "greet"
// app.Usage = "say a greeting"
// app.Action = func(c *cli.Context) error {
// println("Greetings")
// return nil
// }
//
// app.Run(os.Args)
// }
package cli
//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go

View File

@ -1,386 +0,0 @@
package cli
import (
"flag"
"fmt"
"sort"
"strings"
)
// Command is a subcommand for a cli.App.
type Command struct {
// The name of the command
Name string
// short name of the command. Typically one character (deprecated, use `Aliases`)
ShortName string
// A list of aliases for the command
Aliases []string
// A short description of the usage of this command
Usage string
// Custom text to show on USAGE section of help
UsageText string
// A longer explanation of how the command works
Description string
// A short description of the arguments of this command
ArgsUsage string
// The category the command is part of
Category string
// The function to call when checking for bash command completions
BashComplete BashCompleteFunc
// An action to execute before any sub-subcommands are run, but after the context is ready
// If a non-nil error is returned, no sub-subcommands are run
Before BeforeFunc
// An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics
After AfterFunc
// The function to call when this command is invoked
Action interface{}
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
// of deprecation period has passed, maybe?
// Execute this function if a usage error occurs.
OnUsageError OnUsageErrorFunc
// List of child commands
Subcommands Commands
// List of flags to parse
Flags []Flag
// Treat all flags as normal arguments if true
SkipFlagParsing bool
// Skip argument reordering which attempts to move flags before arguments,
// but only works if all flags appear after all arguments. This behavior was
// removed n version 2 since it only works under specific conditions so we
// backport here by exposing it as an option for compatibility.
SkipArgReorder bool
// Boolean to hide built-in help command
HideHelp bool
// Boolean to hide this command from help or completion
Hidden bool
// Boolean to enable short-option handling so user can combine several
// single-character bool arguments into one
// i.e. foobar -o -v -> foobar -ov
UseShortOptionHandling bool
// Full name of command for help, defaults to full command name, including parent commands.
HelpName string
commandNamePath []string
// CustomHelpTemplate the text template for the command help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomHelpTemplate string
}
type CommandsByName []Command
func (c CommandsByName) Len() int {
return len(c)
}
func (c CommandsByName) Less(i, j int) bool {
return lexicographicLess(c[i].Name, c[j].Name)
}
func (c CommandsByName) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
// FullName returns the full name of the command.
// For subcommands this ensures that parent commands are part of the command path
func (c Command) FullName() string {
if c.commandNamePath == nil {
return c.Name
}
return strings.Join(c.commandNamePath, " ")
}
// Commands is a slice of Command
type Commands []Command
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
func (c Command) Run(ctx *Context) (err error) {
if !c.SkipFlagParsing {
if len(c.Subcommands) > 0 {
return c.startApp(ctx)
}
}
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
// append help to flags
c.Flags = append(
c.Flags,
HelpFlag,
)
}
if ctx.App.UseShortOptionHandling {
c.UseShortOptionHandling = true
}
set, err := c.parseFlags(ctx.Args().Tail(), ctx.shellComplete)
context := NewContext(ctx.App, set, ctx)
context.Command = c
if checkCommandCompletions(context, c.Name) {
return nil
}
if err != nil {
if c.OnUsageError != nil {
err := c.OnUsageError(context, err, false)
context.App.handleExitCoder(context, err)
return err
}
_, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error())
_, _ = fmt.Fprintln(context.App.Writer)
_ = ShowCommandHelp(context, c.Name)
return err
}
if checkCommandHelp(context, c.Name) {
return nil
}
cerr := checkRequiredFlags(c.Flags, context)
if cerr != nil {
_ = ShowCommandHelp(context, c.Name)
return cerr
}
if c.After != nil {
defer func() {
afterErr := c.After(context)
if afterErr != nil {
context.App.handleExitCoder(context, err)
if err != nil {
err = NewMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}
if c.Before != nil {
err = c.Before(context)
if err != nil {
context.App.handleExitCoder(context, err)
return err
}
}
if c.Action == nil {
c.Action = helpSubcommand.Action
}
err = HandleAction(c.Action, context)
if err != nil {
context.App.handleExitCoder(context, err)
}
return err
}
func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) {
if c.SkipFlagParsing {
set, err := c.newFlagSet()
if err != nil {
return nil, err
}
return set, set.Parse(append([]string{"--"}, args...))
}
if !c.SkipArgReorder {
args = reorderArgs(c.Flags, args)
}
set, err := c.newFlagSet()
if err != nil {
return nil, err
}
err = parseIter(set, c, args, shellComplete)
if err != nil {
return nil, err
}
err = normalizeFlags(c.Flags, set)
if err != nil {
return nil, err
}
return set, nil
}
func (c *Command) newFlagSet() (*flag.FlagSet, error) {
return flagSet(c.Name, c.Flags)
}
func (c *Command) useShortOptionHandling() bool {
return c.UseShortOptionHandling
}
// reorderArgs moves all flags (via reorderedArgs) before the rest of
// the arguments (remainingArgs) as this is what flag expects.
func reorderArgs(commandFlags []Flag, args []string) []string {
var remainingArgs, reorderedArgs []string
nextIndexMayContainValue := false
for i, arg := range args {
// if we're expecting an option-value, check if this arg is a value, in
// which case it should be re-ordered next to its associated flag
if nextIndexMayContainValue && !argIsFlag(commandFlags, arg) {
nextIndexMayContainValue = false
reorderedArgs = append(reorderedArgs, arg)
} else if arg == "--" {
// don't reorder any args after the -- delimiter As described in the POSIX spec:
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02
// > Guideline 10:
// > The first -- argument that is not an option-argument should be accepted
// > as a delimiter indicating the end of options. Any following arguments
// > should be treated as operands, even if they begin with the '-' character.
// make sure the "--" delimiter itself is at the start
remainingArgs = append([]string{"--"}, remainingArgs...)
remainingArgs = append(remainingArgs, args[i+1:]...)
break
// checks if this is an arg that should be re-ordered
} else if argIsFlag(commandFlags, arg) {
// we have determined that this is a flag that we should re-order
reorderedArgs = append(reorderedArgs, arg)
// if this arg does not contain a "=", then the next index may contain the value for this flag
nextIndexMayContainValue = !strings.Contains(arg, "=")
// simply append any remaining args
} else {
remainingArgs = append(remainingArgs, arg)
}
}
return append(reorderedArgs, remainingArgs...)
}
// argIsFlag checks if an arg is one of our command flags
func argIsFlag(commandFlags []Flag, arg string) bool {
if arg == "-" || arg == "--" {
// `-` is never a flag
// `--` is an option-value when following a flag, and a delimiter indicating the end of options in other cases.
return false
}
// flags always start with a -
if !strings.HasPrefix(arg, "-") {
return false
}
// this line turns `--flag` into `flag`
if strings.HasPrefix(arg, "--") {
arg = strings.Replace(arg, "-", "", 2)
}
// this line turns `-flag` into `flag`
if strings.HasPrefix(arg, "-") {
arg = strings.Replace(arg, "-", "", 1)
}
// this line turns `flag=value` into `flag`
arg = strings.Split(arg, "=")[0]
// look through all the flags, to see if the `arg` is one of our flags
for _, flag := range commandFlags {
for _, key := range strings.Split(flag.GetName(), ",") {
key := strings.TrimSpace(key)
if key == arg {
return true
}
}
}
// return false if this arg was not one of our flags
return false
}
// Names returns the names including short names and aliases.
func (c Command) Names() []string {
names := []string{c.Name}
if c.ShortName != "" {
names = append(names, c.ShortName)
}
return append(names, c.Aliases...)
}
// HasName returns true if Command.Name or Command.ShortName matches given name
func (c Command) HasName(name string) bool {
for _, n := range c.Names() {
if n == name {
return true
}
}
return false
}
func (c Command) startApp(ctx *Context) error {
app := NewApp()
app.Metadata = ctx.App.Metadata
app.ExitErrHandler = ctx.App.ExitErrHandler
// set the name and usage
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
if c.HelpName == "" {
app.HelpName = c.HelpName
} else {
app.HelpName = app.Name
}
app.Usage = c.Usage
app.Description = c.Description
app.ArgsUsage = c.ArgsUsage
// set CommandNotFound
app.CommandNotFound = ctx.App.CommandNotFound
app.CustomAppHelpTemplate = c.CustomHelpTemplate
// set the flags and commands
app.Commands = c.Subcommands
app.Flags = c.Flags
app.HideHelp = c.HideHelp
app.Version = ctx.App.Version
app.HideVersion = ctx.App.HideVersion
app.Compiled = ctx.App.Compiled
app.Author = ctx.App.Author
app.Email = ctx.App.Email
app.Writer = ctx.App.Writer
app.ErrWriter = ctx.App.ErrWriter
app.UseShortOptionHandling = ctx.App.UseShortOptionHandling
app.categories = CommandCategories{}
for _, command := range c.Subcommands {
app.categories = app.categories.AddCommand(command.Category, command)
}
sort.Sort(app.categories)
// bash completion
app.EnableBashCompletion = ctx.App.EnableBashCompletion
if c.BashComplete != nil {
app.BashComplete = c.BashComplete
}
// set the actions
app.Before = c.Before
app.After = c.After
if c.Action != nil {
app.Action = c.Action
} else {
app.Action = helpSubcommand.Action
}
app.OnUsageError = c.OnUsageError
for index, cc := range app.Commands {
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
}
return app.RunAsSubcommand(ctx)
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func (c Command) VisibleFlags() []Flag {
return visibleFlags(c.Flags)
}

View File

@ -1,348 +0,0 @@
package cli
import (
"errors"
"flag"
"fmt"
"os"
"reflect"
"strings"
"syscall"
)
// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
App *App
Command Command
shellComplete bool
flagSet *flag.FlagSet
setFlags map[string]bool
parentContext *Context
}
// NewContext creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
c := &Context{App: app, flagSet: set, parentContext: parentCtx}
if parentCtx != nil {
c.shellComplete = parentCtx.shellComplete
}
return c
}
// NumFlags returns the number of flags set
func (c *Context) NumFlags() int {
return c.flagSet.NFlag()
}
// Set sets a context flag to a value.
func (c *Context) Set(name, value string) error {
c.setFlags = nil
return c.flagSet.Set(name, value)
}
// GlobalSet sets a context flag to a value on the global flagset
func (c *Context) GlobalSet(name, value string) error {
globalContext(c).setFlags = nil
return globalContext(c).flagSet.Set(name, value)
}
// IsSet determines if the flag was actually set
func (c *Context) IsSet(name string) bool {
if c.setFlags == nil {
c.setFlags = make(map[string]bool)
c.flagSet.Visit(func(f *flag.Flag) {
c.setFlags[f.Name] = true
})
c.flagSet.VisitAll(func(f *flag.Flag) {
if _, ok := c.setFlags[f.Name]; ok {
return
}
c.setFlags[f.Name] = false
})
// XXX hack to support IsSet for flags with EnvVar
//
// There isn't an easy way to do this with the current implementation since
// whether a flag was set via an environment variable is very difficult to
// determine here. Instead, we intend to introduce a backwards incompatible
// change in version 2 to add `IsSet` to the Flag interface to push the
// responsibility closer to where the information required to determine
// whether a flag is set by non-standard means such as environment
// variables is available.
//
// See https://github.com/urfave/cli/issues/294 for additional discussion
flags := c.Command.Flags
if c.Command.Name == "" { // cannot == Command{} since it contains slice types
if c.App != nil {
flags = c.App.Flags
}
}
for _, f := range flags {
eachName(f.GetName(), func(name string) {
if isSet, ok := c.setFlags[name]; isSet || !ok {
// Check if a flag is set
if isSet {
// If the flag is set, also set its other aliases
eachName(f.GetName(), func(name string) {
c.setFlags[name] = true
})
}
return
}
val := reflect.ValueOf(f)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
filePathValue := val.FieldByName("FilePath")
if filePathValue.IsValid() {
eachName(filePathValue.String(), func(filePath string) {
if _, err := os.Stat(filePath); err == nil {
c.setFlags[name] = true
return
}
})
}
envVarValue := val.FieldByName("EnvVar")
if envVarValue.IsValid() {
eachName(envVarValue.String(), func(envVar string) {
envVar = strings.TrimSpace(envVar)
if _, ok := syscall.Getenv(envVar); ok {
c.setFlags[name] = true
return
}
})
}
})
}
}
return c.setFlags[name]
}
// GlobalIsSet determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool {
ctx := c
if ctx.parentContext != nil {
ctx = ctx.parentContext
}
for ; ctx != nil; ctx = ctx.parentContext {
if ctx.IsSet(name) {
return true
}
}
return false
}
// FlagNames returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) {
for _, f := range c.Command.Flags {
name := strings.Split(f.GetName(), ",")[0]
if name == "help" {
continue
}
names = append(names, name)
}
return
}
// GlobalFlagNames returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) {
for _, f := range c.App.Flags {
name := strings.Split(f.GetName(), ",")[0]
if name == "help" || name == "version" {
continue
}
names = append(names, name)
}
return
}
// Parent returns the parent context, if any
func (c *Context) Parent() *Context {
return c.parentContext
}
// value returns the value of the flag coressponding to `name`
func (c *Context) value(name string) interface{} {
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
}
// Args contains apps console arguments
type Args []string
// Args returns the command line arguments associated with the context.
func (c *Context) Args() Args {
args := Args(c.flagSet.Args())
return args
}
// NArg returns the number of the command line arguments.
func (c *Context) NArg() int {
return len(c.Args())
}
// Get returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
if len(a) > n {
return a[n]
}
return ""
}
// First returns the first argument, or else a blank string
func (a Args) First() string {
return a.Get(0)
}
// Tail returns the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
if len(a) >= 2 {
return []string(a)[1:]
}
return []string{}
}
// Present checks if there are any arguments present
func (a Args) Present() bool {
return len(a) != 0
}
// Swap swaps arguments at the given indexes
func (a Args) Swap(from, to int) error {
if from >= len(a) || to >= len(a) {
return errors.New("index out of range")
}
a[from], a[to] = a[to], a[from]
return nil
}
func globalContext(ctx *Context) *Context {
if ctx == nil {
return nil
}
for {
if ctx.parentContext == nil {
return ctx
}
ctx = ctx.parentContext
}
}
func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
if ctx.parentContext != nil {
ctx = ctx.parentContext
}
for ; ctx != nil; ctx = ctx.parentContext {
if f := ctx.flagSet.Lookup(name); f != nil {
return ctx.flagSet
}
}
return nil
}
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
switch ff.Value.(type) {
case *StringSlice:
default:
_ = set.Set(name, ff.Value.String())
}
}
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
visited := make(map[string]bool)
set.Visit(func(f *flag.Flag) {
visited[f.Name] = true
})
for _, f := range flags {
parts := strings.Split(f.GetName(), ",")
if len(parts) == 1 {
continue
}
var ff *flag.Flag
for _, name := range parts {
name = strings.Trim(name, " ")
if visited[name] {
if ff != nil {
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
}
ff = set.Lookup(name)
}
}
if ff == nil {
continue
}
for _, name := range parts {
name = strings.Trim(name, " ")
if !visited[name] {
copyFlag(name, ff, set)
}
}
}
return nil
}
type requiredFlagsErr interface {
error
getMissingFlags() []string
}
type errRequiredFlags struct {
missingFlags []string
}
func (e *errRequiredFlags) Error() string {
numberOfMissingFlags := len(e.missingFlags)
if numberOfMissingFlags == 1 {
return fmt.Sprintf("Required flag %q not set", e.missingFlags[0])
}
joinedMissingFlags := strings.Join(e.missingFlags, ", ")
return fmt.Sprintf("Required flags %q not set", joinedMissingFlags)
}
func (e *errRequiredFlags) getMissingFlags() []string {
return e.missingFlags
}
func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr {
var missingFlags []string
for _, f := range flags {
if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() {
var flagPresent bool
var flagName string
for _, key := range strings.Split(f.GetName(), ",") {
key = strings.TrimSpace(key)
if len(key) > 1 {
flagName = key
}
if context.IsSet(key) {
flagPresent = true
}
}
if !flagPresent && flagName != "" {
missingFlags = append(missingFlags, flagName)
}
}
}
if len(missingFlags) != 0 {
return &errRequiredFlags{missingFlags: missingFlags}
}
return nil
}

View File

@ -1,115 +0,0 @@
package cli
import (
"fmt"
"io"
"os"
"strings"
)
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
var OsExiter = os.Exit
// ErrWriter is used to write errors to the user. This can be anything
// implementing the io.Writer interface and defaults to os.Stderr.
var ErrWriter io.Writer = os.Stderr
// MultiError is an error that wraps multiple errors.
type MultiError struct {
Errors []error
}
// NewMultiError creates a new MultiError. Pass in one or more errors.
func NewMultiError(err ...error) MultiError {
return MultiError{Errors: err}
}
// Error implements the error interface.
func (m MultiError) Error() string {
errs := make([]string, len(m.Errors))
for i, err := range m.Errors {
errs[i] = err.Error()
}
return strings.Join(errs, "\n")
}
type ErrorFormatter interface {
Format(s fmt.State, verb rune)
}
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
type ExitCoder interface {
error
ExitCode() int
}
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
type ExitError struct {
exitCode int
message interface{}
}
// NewExitError makes a new *ExitError
func NewExitError(message interface{}, exitCode int) *ExitError {
return &ExitError{
exitCode: exitCode,
message: message,
}
}
// Error returns the string message, fulfilling the interface required by
// `error`
func (ee *ExitError) Error() string {
return fmt.Sprintf("%v", ee.message)
}
// ExitCode returns the exit code, fulfilling the interface required by
// `ExitCoder`
func (ee *ExitError) ExitCode() int {
return ee.exitCode
}
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
// given exit code. If the given error is a MultiError, then this func is
// called on all members of the Errors slice and calls OsExiter with the last exit code.
func HandleExitCoder(err error) {
if err == nil {
return
}
if exitErr, ok := err.(ExitCoder); ok {
if err.Error() != "" {
if _, ok := exitErr.(ErrorFormatter); ok {
fmt.Fprintf(ErrWriter, "%+v\n", err)
} else {
fmt.Fprintln(ErrWriter, err)
}
}
OsExiter(exitErr.ExitCode())
return
}
if multiErr, ok := err.(MultiError); ok {
code := handleMultiError(multiErr)
OsExiter(code)
return
}
}
func handleMultiError(multiErr MultiError) int {
code := 1
for _, merr := range multiErr.Errors {
if multiErr2, ok := merr.(MultiError); ok {
code = handleMultiError(multiErr2)
} else {
fmt.Fprintln(ErrWriter, merr)
if exitErr, ok := merr.(ExitCoder); ok {
code = exitErr.ExitCode()
}
}
}
return code
}

348
vendor/github.com/urfave/cli/flag.go generated vendored
View File

@ -1,348 +0,0 @@
package cli
import (
"flag"
"fmt"
"io/ioutil"
"reflect"
"runtime"
"strconv"
"strings"
"syscall"
)
const defaultPlaceholder = "value"
// BashCompletionFlag enables bash-completion for all commands and subcommands
var BashCompletionFlag Flag = BoolFlag{
Name: "generate-bash-completion",
Hidden: true,
}
// VersionFlag prints the version for the application
var VersionFlag Flag = BoolFlag{
Name: "version, v",
Usage: "print the version",
}
// HelpFlag prints the help for all commands and subcommands
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
// unless HideHelp is set to true)
var HelpFlag Flag = BoolFlag{
Name: "help, h",
Usage: "show help",
}
// FlagStringer converts a flag definition to a string. This is used by help
// to display a flag.
var FlagStringer FlagStringFunc = stringifyFlag
// FlagNamePrefixer converts a full flag name and its placeholder into the help
// message flag prefix. This is used by the default FlagStringer.
var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames
// FlagEnvHinter annotates flag help message with the environment variable
// details. This is used by the default FlagStringer.
var FlagEnvHinter FlagEnvHintFunc = withEnvHint
// FlagFileHinter annotates flag help message with the environment variable
// details. This is used by the default FlagStringer.
var FlagFileHinter FlagFileHintFunc = withFileHint
// FlagsByName is a slice of Flag.
type FlagsByName []Flag
func (f FlagsByName) Len() int {
return len(f)
}
func (f FlagsByName) Less(i, j int) bool {
return lexicographicLess(f[i].GetName(), f[j].GetName())
}
func (f FlagsByName) Swap(i, j int) {
f[i], f[j] = f[j], f[i]
}
// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that
// this interface be implemented.
type Flag interface {
fmt.Stringer
// Apply Flag settings to the given flag set
Apply(*flag.FlagSet)
GetName() string
}
// RequiredFlag is an interface that allows us to mark flags as required
// it allows flags required flags to be backwards compatible with the Flag interface
type RequiredFlag interface {
Flag
IsRequired() bool
}
// DocGenerationFlag is an interface that allows documentation generation for the flag
type DocGenerationFlag interface {
Flag
// TakesValue returns true if the flag takes a value, otherwise false
TakesValue() bool
// GetUsage returns the usage string for the flag
GetUsage() string
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
GetValue() string
}
// errorableFlag is an interface that allows us to return errors during apply
// it allows flags defined in this library to return errors in a fashion backwards compatible
// TODO remove in v2 and modify the existing Flag interface to return errors
type errorableFlag interface {
Flag
ApplyWithError(*flag.FlagSet) error
}
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
set := flag.NewFlagSet(name, flag.ContinueOnError)
for _, f := range flags {
//TODO remove in v2 when errorableFlag is removed
if ef, ok := f.(errorableFlag); ok {
if err := ef.ApplyWithError(set); err != nil {
return nil, err
}
} else {
f.Apply(set)
}
}
set.SetOutput(ioutil.Discard)
return set, nil
}
func eachName(longName string, fn func(string)) {
parts := strings.Split(longName, ",")
for _, name := range parts {
name = strings.Trim(name, " ")
fn(name)
}
}
func visibleFlags(fl []Flag) []Flag {
var visible []Flag
for _, f := range fl {
field := flagValue(f).FieldByName("Hidden")
if !field.IsValid() || !field.Bool() {
visible = append(visible, f)
}
}
return visible
}
func prefixFor(name string) (prefix string) {
if len(name) == 1 {
prefix = "-"
} else {
prefix = "--"
}
return
}
// Returns the placeholder, if any, and the unquoted usage string.
func unquoteUsage(usage string) (string, string) {
for i := 0; i < len(usage); i++ {
if usage[i] == '`' {
for j := i + 1; j < len(usage); j++ {
if usage[j] == '`' {
name := usage[i+1 : j]
usage = usage[:i] + name + usage[j+1:]
return name, usage
}
}
break
}
}
return "", usage
}
func prefixedNames(fullName, placeholder string) string {
var prefixed string
parts := strings.Split(fullName, ",")
for i, name := range parts {
name = strings.Trim(name, " ")
prefixed += prefixFor(name) + name
if placeholder != "" {
prefixed += " " + placeholder
}
if i < len(parts)-1 {
prefixed += ", "
}
}
return prefixed
}
func withEnvHint(envVar, str string) string {
envText := ""
if envVar != "" {
prefix := "$"
suffix := ""
sep := ", $"
if runtime.GOOS == "windows" {
prefix = "%"
suffix = "%"
sep = "%, %"
}
envText = " [" + prefix + strings.Join(strings.Split(envVar, ","), sep) + suffix + "]"
}
return str + envText
}
func withFileHint(filePath, str string) string {
fileText := ""
if filePath != "" {
fileText = fmt.Sprintf(" [%s]", filePath)
}
return str + fileText
}
func flagValue(f Flag) reflect.Value {
fv := reflect.ValueOf(f)
for fv.Kind() == reflect.Ptr {
fv = reflect.Indirect(fv)
}
return fv
}
func stringifyFlag(f Flag) string {
fv := flagValue(f)
switch f.(type) {
case IntSliceFlag:
return FlagFileHinter(
fv.FieldByName("FilePath").String(),
FlagEnvHinter(
fv.FieldByName("EnvVar").String(),
stringifyIntSliceFlag(f.(IntSliceFlag)),
),
)
case Int64SliceFlag:
return FlagFileHinter(
fv.FieldByName("FilePath").String(),
FlagEnvHinter(
fv.FieldByName("EnvVar").String(),
stringifyInt64SliceFlag(f.(Int64SliceFlag)),
),
)
case StringSliceFlag:
return FlagFileHinter(
fv.FieldByName("FilePath").String(),
FlagEnvHinter(
fv.FieldByName("EnvVar").String(),
stringifyStringSliceFlag(f.(StringSliceFlag)),
),
)
}
placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
needsPlaceholder := false
defaultValueString := ""
if val := fv.FieldByName("Value"); val.IsValid() {
needsPlaceholder = true
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
if val.Kind() == reflect.String && val.String() != "" {
defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
}
}
if defaultValueString == " (default: )" {
defaultValueString = ""
}
if needsPlaceholder && placeholder == "" {
placeholder = defaultPlaceholder
}
usageWithDefault := strings.TrimSpace(usage + defaultValueString)
return FlagFileHinter(
fv.FieldByName("FilePath").String(),
FlagEnvHinter(
fv.FieldByName("EnvVar").String(),
FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder)+"\t"+usageWithDefault,
),
)
}
func stringifyIntSliceFlag(f IntSliceFlag) string {
var defaultVals []string
if f.Value != nil && len(f.Value.Value()) > 0 {
for _, i := range f.Value.Value() {
defaultVals = append(defaultVals, strconv.Itoa(i))
}
}
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
var defaultVals []string
if f.Value != nil && len(f.Value.Value()) > 0 {
for _, i := range f.Value.Value() {
defaultVals = append(defaultVals, strconv.FormatInt(i, 10))
}
}
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}
func stringifyStringSliceFlag(f StringSliceFlag) string {
var defaultVals []string
if f.Value != nil && len(f.Value.Value()) > 0 {
for _, s := range f.Value.Value() {
if len(s) > 0 {
defaultVals = append(defaultVals, strconv.Quote(s))
}
}
}
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}
func stringifySliceFlag(usage, name string, defaultVals []string) string {
placeholder, usage := unquoteUsage(usage)
if placeholder == "" {
placeholder = defaultPlaceholder
}
defaultVal := ""
if len(defaultVals) > 0 {
defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
}
usageWithDefault := strings.TrimSpace(usage + defaultVal)
return FlagNamePrefixer(name, placeholder) + "\t" + usageWithDefault
}
func flagFromFileEnv(filePath, envName string) (val string, ok bool) {
for _, envVar := range strings.Split(envName, ",") {
envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok {
return envVal, true
}
}
for _, fileVar := range strings.Split(filePath, ",") {
if fileVar != "" {
if data, err := ioutil.ReadFile(fileVar); err == nil {
return string(data), true
}
}
}
return "", false
}

View File

@ -1,109 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// BoolFlag is a flag with type bool
type BoolFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
// (for usage defaults)
func (f BoolFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f BoolFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f BoolFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f BoolFlag) TakesValue() bool {
return false
}
// GetUsage returns the usage string for the flag
func (f BoolFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f BoolFlag) GetValue() string {
return ""
}
// Bool looks up the value of a local BoolFlag, returns
// false if not found
func (c *Context) Bool(name string) bool {
return lookupBool(name, c.flagSet)
}
// GlobalBool looks up the value of a global BoolFlag, returns
// false if not found
func (c *Context) GlobalBool(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBool(name, fs)
}
return false
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f BoolFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
val := false
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
if envVal == "" {
val = false
} else {
envValBool, err := strconv.ParseBool(envVal)
if err != nil {
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
}
val = envValBool
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.BoolVar(f.Destination, name, val, f.Usage)
return
}
set.Bool(name, val, f.Usage)
})
return nil
}
func lookupBool(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return parsed
}
return false
}

View File

@ -1,110 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// BoolTFlag is a flag with type bool that is true by default
type BoolTFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
// (for usage defaults)
func (f BoolTFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f BoolTFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f BoolTFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f BoolTFlag) TakesValue() bool {
return false
}
// GetUsage returns the usage string for the flag
func (f BoolTFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f BoolTFlag) GetValue() string {
return ""
}
// BoolT looks up the value of a local BoolTFlag, returns
// false if not found
func (c *Context) BoolT(name string) bool {
return lookupBoolT(name, c.flagSet)
}
// GlobalBoolT looks up the value of a global BoolTFlag, returns
// false if not found
func (c *Context) GlobalBoolT(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBoolT(name, fs)
}
return false
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f BoolTFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
val := true
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
if envVal == "" {
val = false
} else {
envValBool, err := strconv.ParseBool(envVal)
if err != nil {
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
}
val = envValBool
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.BoolVar(f.Destination, name, val, f.Usage)
return
}
set.Bool(name, val, f.Usage)
})
return nil
}
func lookupBoolT(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return parsed
}
return false
}

View File

@ -1,106 +0,0 @@
package cli
import (
"flag"
"fmt"
"time"
)
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
type DurationFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value time.Duration
Destination *time.Duration
}
// String returns a readable representation of this value
// (for usage defaults)
func (f DurationFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f DurationFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f DurationFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f DurationFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f DurationFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f DurationFlag) GetValue() string {
return f.Value.String()
}
// Duration looks up the value of a local DurationFlag, returns
// 0 if not found
func (c *Context) Duration(name string) time.Duration {
return lookupDuration(name, c.flagSet)
}
// GlobalDuration looks up the value of a global DurationFlag, returns
// 0 if not found
func (c *Context) GlobalDuration(name string) time.Duration {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupDuration(name, fs)
}
return 0
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f DurationFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
envValDuration, err := time.ParseDuration(envVal)
if err != nil {
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValDuration
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.DurationVar(f.Destination, name, f.Value, f.Usage)
return
}
set.Duration(name, f.Value, f.Usage)
})
return nil
}
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
f := set.Lookup(name)
if f != nil {
parsed, err := time.ParseDuration(f.Value.String())
if err != nil {
return 0
}
return parsed
}
return 0
}

View File

@ -1,106 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// Float64Flag is a flag with type float64
type Float64Flag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value float64
Destination *float64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Float64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Float64Flag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f Float64Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Float64Flag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Float64Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Float64Flag) GetValue() string {
return fmt.Sprintf("%f", f.Value)
}
// Float64 looks up the value of a local Float64Flag, returns
// 0 if not found
func (c *Context) Float64(name string) float64 {
return lookupFloat64(name, c.flagSet)
}
// GlobalFloat64 looks up the value of a global Float64Flag, returns
// 0 if not found
func (c *Context) GlobalFloat64(name string) float64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupFloat64(name, fs)
}
return 0
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Float64Flag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
envValFloat, err := strconv.ParseFloat(envVal, 10)
if err != nil {
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValFloat
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.Float64Var(f.Destination, name, f.Value, f.Usage)
return
}
set.Float64(name, f.Value, f.Usage)
})
return nil
}
func lookupFloat64(name string, set *flag.FlagSet) float64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseFloat(f.Value.String(), 64)
if err != nil {
return 0
}
return parsed
}
return 0
}

View File

@ -1,110 +0,0 @@
package cli
import (
"flag"
"fmt"
)
// Generic is a generic parseable type identified by a specific flag
type Generic interface {
Set(value string) error
String() string
}
// GenericFlag is a flag with type Generic
type GenericFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
TakesFile bool
Value Generic
}
// String returns a readable representation of this value
// (for usage defaults)
func (f GenericFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f GenericFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f GenericFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f GenericFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f GenericFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f GenericFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
// Ignores parsing errors
func (f GenericFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
val := f.Value
if fileEnvVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
if err := val.Set(fileEnvVal); err != nil {
return fmt.Errorf("could not parse %s as value for flag %s: %s", fileEnvVal, f.Name, err)
}
}
eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage)
})
return nil
}
// Generic looks up the value of a local GenericFlag, returns
// nil if not found
func (c *Context) Generic(name string) interface{} {
return lookupGeneric(name, c.flagSet)
}
// GlobalGeneric looks up the value of a global GenericFlag, returns
// nil if not found
func (c *Context) GlobalGeneric(name string) interface{} {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupGeneric(name, fs)
}
return nil
}
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
f := set.Lookup(name)
if f != nil {
parsed, err := f.Value, error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}

View File

@ -1,105 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// IntFlag is a flag with type int
type IntFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value int
Destination *int
}
// String returns a readable representation of this value
// (for usage defaults)
func (f IntFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f IntFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f IntFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f IntFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f IntFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f IntFlag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f IntFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
}
f.Value = int(envValInt)
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.IntVar(f.Destination, name, f.Value, f.Usage)
return
}
set.Int(name, f.Value, f.Usage)
})
return nil
}
// Int looks up the value of a local IntFlag, returns
// 0 if not found
func (c *Context) Int(name string) int {
return lookupInt(name, c.flagSet)
}
// GlobalInt looks up the value of a global IntFlag, returns
// 0 if not found
func (c *Context) GlobalInt(name string) int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt(name, fs)
}
return 0
}
func lookupInt(name string, set *flag.FlagSet) int {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return int(parsed)
}
return 0
}

View File

@ -1,106 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// Int64Flag is a flag with type int64
type Int64Flag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value int64
Destination *int64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Int64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Int64Flag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f Int64Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Int64Flag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Int64Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Int64Flag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Int64Flag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValInt
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.Int64Var(f.Destination, name, f.Value, f.Usage)
return
}
set.Int64(name, f.Value, f.Usage)
})
return nil
}
// Int64 looks up the value of a local Int64Flag, returns
// 0 if not found
func (c *Context) Int64(name string) int64 {
return lookupInt64(name, c.flagSet)
}
// GlobalInt64 looks up the value of a global Int64Flag, returns
// 0 if not found
func (c *Context) GlobalInt64(name string) int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64(name, fs)
}
return 0
}
func lookupInt64(name string, set *flag.FlagSet) int64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return parsed
}
return 0
}

View File

@ -1,199 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
"strings"
)
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter
type Int64Slice []int64
// Set parses the value into an integer and appends it to the list of values
func (f *Int64Slice) Set(value string) error {
tmp, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
*f = append(*f, tmp)
return nil
}
// String returns a readable representation of this value (for usage defaults)
func (f *Int64Slice) String() string {
slice := make([]string, len(*f))
for i, v := range *f {
slice[i] = strconv.FormatInt(v, 10)
}
return strings.Join(slice, ",")
}
// Value returns the slice of ints set by this flag
func (f *Int64Slice) Value() []int64 {
return *f
}
// Get returns the slice of ints set by this flag
func (f *Int64Slice) Get() interface{} {
return *f
}
// Int64SliceFlag is a flag with type *Int64Slice
type Int64SliceFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *Int64Slice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Int64SliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Int64SliceFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f Int64SliceFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Int64SliceFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Int64SliceFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Int64SliceFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
newVal := &Int64Slice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
}
}
if f.Value == nil {
f.Value = newVal
} else {
*f.Value = *newVal
}
}
eachName(f.Name, func(name string) {
if f.Value == nil {
f.Value = &Int64Slice{}
}
set.Var(f.Value, name, f.Usage)
})
return nil
}
// Int64Slice looks up the value of a local Int64SliceFlag, returns
// nil if not found
func (c *Context) Int64Slice(name string) []int64 {
return lookupInt64Slice(name, c.flagSet)
}
// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns
// nil if not found
func (c *Context) GlobalInt64Slice(name string) []int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64Slice(name, fs)
}
return nil
}
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
f := set.Lookup(name)
if f != nil {
value, ok := f.Value.(*Int64Slice)
if !ok {
return nil
}
// extract the slice from asserted value
parsed := value.Value()
// extract default value from the flag
var defaultVal []int64
for _, v := range strings.Split(f.DefValue, ",") {
if v != "" {
int64Value, err := strconv.ParseInt(v, 10, 64)
if err != nil {
panic(err)
}
defaultVal = append(defaultVal, int64Value)
}
}
// if the current value is not equal to the default value
// remove the default values from the flag
if !isInt64SliceEqual(parsed, defaultVal) {
for _, v := range defaultVal {
parsed = removeFromInt64Slice(parsed, v)
}
}
return parsed
}
return nil
}
func removeFromInt64Slice(slice []int64, val int64) []int64 {
for i, v := range slice {
if v == val {
ret := append([]int64{}, slice[:i]...)
ret = append(ret, slice[i+1:]...)
return ret
}
}
return slice
}
func isInt64SliceEqual(newValue, defaultValue []int64) bool {
// If one is nil, the other must also be nil.
if (newValue == nil) != (defaultValue == nil) {
return false
}
if len(newValue) != len(defaultValue) {
return false
}
for i, v := range newValue {
if v != defaultValue[i] {
return false
}
}
return true
}

View File

@ -1,198 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
"strings"
)
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter
type IntSlice []int
// Set parses the value into an integer and appends it to the list of values
func (f *IntSlice) Set(value string) error {
tmp, err := strconv.Atoi(value)
if err != nil {
return err
}
*f = append(*f, tmp)
return nil
}
// String returns a readable representation of this value (for usage defaults)
func (f *IntSlice) String() string {
slice := make([]string, len(*f))
for i, v := range *f {
slice[i] = strconv.Itoa(v)
}
return strings.Join(slice, ",")
}
// Value returns the slice of ints set by this flag
func (f *IntSlice) Value() []int {
return *f
}
// Get returns the slice of ints set by this flag
func (f *IntSlice) Get() interface{} {
return *f
}
// IntSliceFlag is a flag with type *IntSlice
type IntSliceFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value *IntSlice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f IntSliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f IntSliceFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f IntSliceFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f IntSliceFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f IntSliceFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f IntSliceFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
newVal := &IntSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err)
}
}
if f.Value == nil {
f.Value = newVal
} else {
*f.Value = *newVal
}
}
eachName(f.Name, func(name string) {
if f.Value == nil {
f.Value = &IntSlice{}
}
set.Var(f.Value, name, f.Usage)
})
return nil
}
// IntSlice looks up the value of a local IntSliceFlag, returns
// nil if not found
func (c *Context) IntSlice(name string) []int {
return lookupIntSlice(name, c.flagSet)
}
// GlobalIntSlice looks up the value of a global IntSliceFlag, returns
// nil if not found
func (c *Context) GlobalIntSlice(name string) []int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupIntSlice(name, fs)
}
return nil
}
func lookupIntSlice(name string, set *flag.FlagSet) []int {
f := set.Lookup(name)
if f != nil {
value, ok := f.Value.(*IntSlice)
if !ok {
return nil
}
// extract the slice from asserted value
slice := value.Value()
// extract default value from the flag
var defaultVal []int
for _, v := range strings.Split(f.DefValue, ",") {
if v != "" {
intValue, err := strconv.Atoi(v)
if err != nil {
panic(err)
}
defaultVal = append(defaultVal, intValue)
}
}
// if the current value is not equal to the default value
// remove the default values from the flag
if !isIntSliceEqual(slice, defaultVal) {
for _, v := range defaultVal {
slice = removeFromIntSlice(slice, v)
}
}
return slice
}
return nil
}
func removeFromIntSlice(slice []int, val int) []int {
for i, v := range slice {
if v == val {
ret := append([]int{}, slice[:i]...)
ret = append(ret, slice[i+1:]...)
return ret
}
}
return slice
}
func isIntSliceEqual(newValue, defaultValue []int) bool {
// If one is nil, the other must also be nil.
if (newValue == nil) != (defaultValue == nil) {
return false
}
if len(newValue) != len(defaultValue) {
return false
}
for i, v := range newValue {
if v != defaultValue[i] {
return false
}
}
return true
}

View File

@ -1,98 +0,0 @@
package cli
import "flag"
// StringFlag is a flag with type string
type StringFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
TakesFile bool
Value string
Destination *string
}
// String returns a readable representation of this value
// (for usage defaults)
func (f StringFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f StringFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f StringFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f StringFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f StringFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f StringFlag) GetValue() string {
return f.Value
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f StringFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
f.Value = envVal
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.StringVar(f.Destination, name, f.Value, f.Usage)
return
}
set.String(name, f.Value, f.Usage)
})
return nil
}
// String looks up the value of a local StringFlag, returns
// "" if not found
func (c *Context) String(name string) string {
return lookupString(name, c.flagSet)
}
// GlobalString looks up the value of a global StringFlag, returns
// "" if not found
func (c *Context) GlobalString(name string) string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupString(name, fs)
}
return ""
}
func lookupString(name string, set *flag.FlagSet) string {
f := set.Lookup(name)
if f != nil {
parsed, err := f.Value.String(), error(nil)
if err != nil {
return ""
}
return parsed
}
return ""
}

View File

@ -1,184 +0,0 @@
package cli
import (
"flag"
"fmt"
"strings"
)
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter
type StringSlice []string
// Set appends the string value to the list of values
func (f *StringSlice) Set(value string) error {
*f = append(*f, value)
return nil
}
// String returns a readable representation of this value (for usage defaults)
func (f *StringSlice) String() string {
return strings.Join(*f, ",")
}
// Value returns the slice of strings set by this flag
func (f *StringSlice) Value() []string {
return *f
}
// Get returns the slice of strings set by this flag
func (f *StringSlice) Get() interface{} {
return *f
}
// StringSliceFlag is a flag with type *StringSlice
type StringSliceFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
TakesFile bool
Value *StringSlice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f StringSliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f StringSliceFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f StringSliceFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f StringSliceFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f StringSliceFlag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f StringSliceFlag) GetValue() string {
if f.Value != nil {
return f.Value.String()
}
return ""
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
newVal := &StringSlice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
}
}
if f.Value == nil {
f.Value = newVal
} else {
*f.Value = *newVal
}
}
eachName(f.Name, func(name string) {
if f.Value == nil {
f.Value = &StringSlice{}
}
set.Var(f.Value, name, f.Usage)
})
return nil
}
// StringSlice looks up the value of a local StringSliceFlag, returns
// nil if not found
func (c *Context) StringSlice(name string) []string {
return lookupStringSlice(name, c.flagSet)
}
// GlobalStringSlice looks up the value of a global StringSliceFlag, returns
// nil if not found
func (c *Context) GlobalStringSlice(name string) []string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupStringSlice(name, fs)
}
return nil
}
func lookupStringSlice(name string, set *flag.FlagSet) []string {
f := set.Lookup(name)
if f != nil {
value, ok := f.Value.(*StringSlice)
if !ok {
return nil
}
// extract the slice from asserted value
slice := value.Value()
// extract default value from the flag
var defaultVal []string
for _, v := range strings.Split(f.DefValue, ",") {
defaultVal = append(defaultVal, v)
}
// if the current value is not equal to the default value
// remove the default values from the flag
if !isStringSliceEqual(slice, defaultVal) {
for _, v := range defaultVal {
slice = removeFromStringSlice(slice, v)
}
}
return slice
}
return nil
}
func removeFromStringSlice(slice []string, val string) []string {
for i, v := range slice {
if v == val {
ret := append([]string{}, slice[:i]...)
ret = append(ret, slice[i+1:]...)
return ret
}
}
return slice
}
func isStringSliceEqual(newValue, defaultValue []string) bool {
// If one is nil, the other must also be nil.
if (newValue == nil) != (defaultValue == nil) {
return false
}
if len(newValue) != len(defaultValue) {
return false
}
for i, v := range newValue {
if v != defaultValue[i] {
return false
}
}
return true
}

View File

@ -1,106 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// UintFlag is a flag with type uint
type UintFlag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value uint
Destination *uint
}
// String returns a readable representation of this value
// (for usage defaults)
func (f UintFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f UintFlag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f UintFlag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f UintFlag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f UintFlag) GetUsage() string {
return f.Usage
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f UintFlag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f UintFlag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
}
f.Value = uint(envValInt)
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.UintVar(f.Destination, name, f.Value, f.Usage)
return
}
set.Uint(name, f.Value, f.Usage)
})
return nil
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f UintFlag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Uint looks up the value of a local UintFlag, returns
// 0 if not found
func (c *Context) Uint(name string) uint {
return lookupUint(name, c.flagSet)
}
// GlobalUint looks up the value of a global UintFlag, returns
// 0 if not found
func (c *Context) GlobalUint(name string) uint {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint(name, fs)
}
return 0
}
func lookupUint(name string, set *flag.FlagSet) uint {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return uint(parsed)
}
return 0
}

View File

@ -1,106 +0,0 @@
package cli
import (
"flag"
"fmt"
"strconv"
)
// Uint64Flag is a flag with type uint64
type Uint64Flag struct {
Name string
Usage string
EnvVar string
FilePath string
Required bool
Hidden bool
Value uint64
Destination *uint64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Uint64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Uint64Flag) GetName() string {
return f.Name
}
// IsRequired returns whether or not the flag is required
func (f Uint64Flag) IsRequired() bool {
return f.Required
}
// TakesValue returns true of the flag takes a value, otherwise false
func (f Uint64Flag) TakesValue() bool {
return true
}
// GetUsage returns the usage string for the flag
func (f Uint64Flag) GetUsage() string {
return f.Usage
}
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f Uint64Flag) GetValue() string {
return fmt.Sprintf("%d", f.Value)
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Uint64Flag) Apply(set *flag.FlagSet) {
_ = f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
if envVal, ok := flagFromFileEnv(f.FilePath, f.EnvVar); ok {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValInt
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
return
}
set.Uint64(name, f.Value, f.Usage)
})
return nil
}
// Uint64 looks up the value of a local Uint64Flag, returns
// 0 if not found
func (c *Context) Uint64(name string) uint64 {
return lookupUint64(name, c.flagSet)
}
// GlobalUint64 looks up the value of a global Uint64Flag, returns
// 0 if not found
func (c *Context) GlobalUint64(name string) uint64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint64(name, fs)
}
return 0
}
func lookupUint64(name string, set *flag.FlagSet) uint64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return parsed
}
return 0
}

363
vendor/github.com/urfave/cli/help.go generated vendored
View File

@ -1,363 +0,0 @@
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 {
template := c.App.CustomAppHelpTemplate
if template == "" {
template = AppHelpTemplate
}
if c.App.ExtraInfo == nil {
HelpPrinter(c.App.Writer, template, c.App)
return nil
}
customAppData := func() map[string]interface{} {
return map[string]interface{}{
"ExtraInfo": c.App.ExtraInfo,
}
}
HelpPrinterCustom(c.App.Writer, template, 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 strings.Split(flag.GetName(), ",") {
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(flag.GetName()) {
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 NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
}
ctx.App.CommandNotFound(ctx, command)
return nil
}
// ShowSubcommandHelp prints help for the given subcommand
func ShowSubcommandHelp(c *Context) error {
return ShowCommandHelp(c, c.Command.Name)
}
// 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,
}
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
if VersionFlag.GetName() != "" {
eachName(VersionFlag.GetName(), func(name string) {
if c.GlobalBool(name) || c.Bool(name) {
found = true
}
})
}
return found
}
func checkHelp(c *Context) bool {
found := false
if HelpFlag.GetName() != "" {
eachName(HelpFlag.GetName(), func(name string) {
if c.GlobalBool(name) || 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 != "--"+BashCompletionFlag.GetName() {
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
}

View File

@ -1,121 +0,0 @@
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}}{{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}}{{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}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{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) {{ .App.Description }}
% {{ .App.Author }}
# 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 }}`

14
vendor/github.com/urfave/cli/v2/.gitignore generated vendored Normal file
View File

@ -0,0 +1,14 @@
*.coverprofile
*.exe
*.orig
.*envrc
.envrc
.idea
# goimports is installed here if not available
/.local/
/site/
coverage.txt
internal/*/built-example
vendor
/cmd/urfave-cli-genflags/urfave-cli-genflags
*.exe

4
vendor/github.com/urfave/cli/v2/.golangci.yaml generated vendored Normal file
View File

@ -0,0 +1,4 @@
# https://golangci-lint.run/usage/configuration/
linters:
enable:
- misspell

View File

@ -55,11 +55,12 @@ further defined and clarified by project maintainers.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting Dan Buch at dan@meatballhat.com. All complaints will be reported by contacting urfave-governance@googlegroups.com, a members-only group
reviewed and investigated and will result in a response that is deemed necessary that is world-postable. All complaints will be reviewed and investigated and
and appropriate to the circumstances. The project team is obligated to maintain will result in a response that is deemed necessary and appropriate to the
confidentiality with regard to the reporter of an incident. Further details of circumstances. The project team is obligated to maintain confidentiality with
specific enforcement policies may be posted separately. 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 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 faith may face temporary or permanent repercussions as determined by other

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2023 Jeremy Saenz & Contributors Copyright (c) 2022 urfave/cli maintainers
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

26
vendor/github.com/urfave/cli/v2/Makefile generated vendored Normal file
View File

@ -0,0 +1,26 @@
# NOTE: this Makefile is meant to provide a simplified entry point for humans to
# run all of the critical steps to verify one's changes are harmonious in
# nature. Keeping target bodies to one line each and abstaining from make magic
# are very important so that maintainers and contributors can focus their
# attention on files that are primarily Go.
GO_RUN_BUILD := go run internal/build/build.go
.PHONY: all
all: generate vet test check-binary-size gfmrun yamlfmt v2diff
# NOTE: this is a special catch-all rule to run any of the commands
# defined in internal/build/build.go with optional arguments passed
# via GFLAGS (global flags) and FLAGS (command-specific flags), e.g.:
#
# $ make test GFLAGS='--packages cli'
%:
$(GO_RUN_BUILD) $(GFLAGS) $* $(FLAGS)
.PHONY: docs
docs:
mkdocs build
.PHONY: serve-docs
serve-docs:
mkdocs serve

19
vendor/github.com/urfave/cli/v2/README.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# cli
[![Run Tests](https://github.com/urfave/cli/actions/workflows/cli.yml/badge.svg?branch=v2-maint)](https://github.com/urfave/cli/actions/workflows/cli.yml)
[![Go Reference](https://pkg.go.dev/badge/github.com/urfave/cli/v2.svg)](https://pkg.go.dev/github.com/urfave/cli/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/urfave/cli/v2)](https://goreportcard.com/report/github.com/urfave/cli/v2)
[![codecov](https://codecov.io/gh/urfave/cli/branch/v2-maint/graph/badge.svg?token=t9YGWLh05g)](https://app.codecov.io/gh/urfave/cli/tree/v2-maint)
cli is a simple, fast, and fun package for building command line apps in Go. The
goal is to enable developers to write fast and distributable command line
applications in an expressive way.
## Documentation
More documentation is available in [`./docs`](./docs) or the hosted
documentation site at <https://cli.urfave.org>.
## License
See [`LICENSE`](./LICENSE)

540
vendor/github.com/urfave/cli/v2/app.go generated vendored Normal file
View File

@ -0,0 +1,540 @@
package cli
import (
"context"
"flag"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
const suggestDidYouMeanTemplate = "Did you mean %q?"
var (
changeLogURL = "https://github.com/urfave/cli/blob/main/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)
ignoreFlagPrefix = "test." // this is to ignore test flags when adding flags from other packages
SuggestFlag SuggestFlagFunc = nil // initialized in suggestions.go unless built with urfave_cli_no_suggest
SuggestCommand SuggestCommandFunc = nil // initialized in suggestions.go unless built with urfave_cli_no_suggest
SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate
)
// 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
// Whether this command supports arguments
Args bool
// Description of the program argument format.
ArgsUsage string
// Version of the program
Version string
// Description of the program
Description string
// DefaultCommand is the (optional) name of a command
// to run if no command names are passed as CLI arguments.
DefaultCommand string
// List of commands to execute
Commands []*Command
// List of flags to parse
Flags []Flag
// Boolean to enable bash completion commands
EnableBashCompletion bool
// Boolean to hide built-in help command and help flag
HideHelp bool
// Boolean to hide built-in help command but keep help flag.
// Ignored if HideHelp is true.
HideHelpCommand bool
// Boolean to hide built-in version flag and the VERSION section of help
HideVersion bool
// categories contains the categorized commands and is populated on app startup
categories CommandCategories
// flagCategories contains the categorized flags and is populated on app startup
flagCategories FlagCategories
// An action to execute when the shell completion flag is set
BashComplete BashCompleteFunc
// An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run
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
// Execute this function when an invalid flag is accessed from the context
InvalidFlagAccessHandler InvalidFlagAccessFunc
// 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
// SliceFlagSeparator is used to customize the separator for SliceFlag, the default is ","
SliceFlagSeparator string
// DisableSliceFlagSeparator is used to disable SliceFlagSeparator, the default is false
DisableSliceFlagSeparator 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
// Enable suggestions for commands and flags
Suggest bool
// Allows global flags set by libraries which use flag.XXXVar(...) directly
// to be parsed through this library
AllowExtFlags bool
// Treat all flags as normal arguments if true
SkipFlagParsing bool
didSetup bool
separator separatorSpec
rootCommand *Command
}
type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string
type SuggestCommandFunc func(commands []*Command, provided string) string
// Tries to find out when this binary was compiled.
// Returns the current time if it fails to find it.
func compileTime() time.Time {
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]),
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 = a.Name
}
if a.Usage == "" {
a.Usage = "A new cli application"
}
if a.Version == "" {
a.HideVersion = true
}
if a.BashComplete == nil {
a.BashComplete = DefaultAppComplete
}
if a.Action == nil {
a.Action = helpCommand.Action
}
if a.Compiled == (time.Time{}) {
a.Compiled = compileTime()
}
if a.Reader == nil {
a.Reader = os.Stdin
}
if a.Writer == nil {
a.Writer = os.Stdout
}
if a.ErrWriter == nil {
a.ErrWriter = os.Stderr
}
if a.AllowExtFlags {
// add global flags added by other packages
flag.VisitAll(func(f *flag.Flag) {
// skip test flags
if !strings.HasPrefix(f.Name, ignoreFlagPrefix) {
a.Flags = append(a.Flags, &extFlag{f})
}
})
}
if len(a.SliceFlagSeparator) != 0 {
a.separator.customized = true
a.separator.sep = a.SliceFlagSeparator
}
if a.DisableSliceFlagSeparator {
a.separator.customized = true
a.separator.disabled = true
}
var newCommands []*Command
for _, c := range a.Commands {
cname := c.Name
if c.HelpName != "" {
cname = c.HelpName
}
c.separator = a.separator
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, cname)
c.flagCategories = newFlagCategoriesFromFlags(c.Flags)
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))
a.flagCategories = newFlagCategoriesFromFlags(a.Flags)
if a.Metadata == nil {
a.Metadata = make(map[string]interface{})
}
}
func (a *App) newRootCommand() *Command {
return &Command{
Name: a.Name,
Usage: a.Usage,
UsageText: a.UsageText,
Description: a.Description,
ArgsUsage: a.ArgsUsage,
BashComplete: a.BashComplete,
Before: a.Before,
After: a.After,
Action: a.Action,
OnUsageError: a.OnUsageError,
Subcommands: a.Commands,
Flags: a.Flags,
flagCategories: a.flagCategories,
HideHelp: a.HideHelp,
HideHelpCommand: a.HideHelpCommand,
UseShortOptionHandling: a.UseShortOptionHandling,
HelpName: a.HelpName,
CustomHelpTemplate: a.CustomAppHelpTemplate,
categories: a.categories,
SkipFlagParsing: a.SkipFlagParsing,
isRoot: true,
separator: a.separator,
}
}
func (a *App) newFlagSet() (*flag.FlagSet, error) {
return flagSet(a.Name, a.Flags, a.separator)
}
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)
cCtx := NewContext(a, nil, &Context{Context: ctx})
cCtx.shellComplete = shellComplete
a.rootCommand = a.newRootCommand()
cCtx.Command = a.rootCommand
if err := checkDuplicatedCmds(a.rootCommand); err != nil {
return err
}
return a.rootCommand.Run(cCtx, arguments...)
}
// RunAsSubcommand is for legacy/compatibility purposes only. New code should only
// use App.RunContext. This function is slated to be removed in v3.
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
a.Setup()
cCtx := NewContext(a, nil, ctx)
cCtx.shellComplete = ctx.shellComplete
a.rootCommand = a.newRootCommand()
cCtx.Command = a.rootCommand
return a.rootCommand.Run(cCtx, ctx.Args().Slice()...)
}
func (a *App) suggestFlagFromError(err error, command string) (string, error) {
flag, parseErr := flagFromError(err)
if parseErr != nil {
return "", err
}
flags := a.Flags
hideHelp := a.HideHelp
if command != "" {
cmd := a.Command(command)
if cmd == nil {
return "", err
}
flags = cmd.Flags
hideHelp = hideHelp || cmd.HideHelp
}
if SuggestFlag == nil {
return "", err
}
suggestion := SuggestFlag(flags, flag, hideHelp)
if len(suggestion) == 0 {
return "", err
}
return fmt.Sprintf(SuggestDidYouMeanTemplate+"\n\n", suggestion), nil
}
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
//
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
// to cli.App.Run. This will cause the application to exit with the given error
// code in the cli.ExitCoder
func (a *App) RunAndExitOnError() {
if err := a.Run(os.Args); err != nil {
_, _ = fmt.Fprintln(a.ErrWriter, err)
OsExiter(1)
}
}
// 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
}
// VisibleFlagCategories returns a slice containing all the categories with the flags they contain
func (a *App) VisibleFlagCategories() []VisibleFlagCategory {
if a.flagCategories == nil {
return []VisibleFlagCategory{}
}
return a.flagCategories.VisibleCategories()
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func (a *App) VisibleFlags() []Flag {
return visibleFlags(a.Flags)
}
func (a *App) 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(cCtx *Context, err error) {
if a.ExitErrHandler != nil {
a.ExitErrHandler(cCtx, err)
} else {
HandleExitCoder(err)
}
}
func (a *App) argsWithDefaultCommand(oldArgs Args) Args {
if a.DefaultCommand != "" {
rawArgs := append([]string{a.DefaultCommand}, oldArgs.Slice()...)
newArgs := args(rawArgs)
return &newArgs
}
return oldArgs
}
func runFlagActions(c *Context, fs []Flag) error {
for _, f := range fs {
isSet := false
for _, name := range f.Names() {
if c.IsSet(name) {
isSet = true
break
}
}
if isSet {
if af, ok := f.(ActionableFlag); ok {
if err := af.RunAction(c); err != nil {
return err
}
}
}
}
return nil
}
// 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{}, cCtx *Context) (err error) {
switch a := action.(type) {
case ActionFunc:
return a(cCtx)
case func(*Context) error:
return a(cCtx)
case func(*Context): // deprecated function signature
a(cCtx)
return nil
}
return errInvalidActionType
}
func checkStringSliceIncludes(want string, sSlice []string) bool {
found := false
for _, s := range sSlice {
if want == s {
found = true
break
}
}
return found
}

54
vendor/github.com/urfave/cli/v2/args.go generated vendored Normal file
View File

@ -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
}

Some files were not shown because too many files have changed in this diff Show More