From dbe605be7f50b0c0a9b03b67f6eb4cbea55680a6 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 27 Dec 2023 07:06:58 +0000 Subject: [PATCH 01/17] chore(ux): improve error output for unknown spec flag Signed-off-by: Billy Zha --- cmd/oras/internal/option/remote.go | 5 +- cmd/oras/internal/option/spec.go | 75 +++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/cmd/oras/internal/option/remote.go b/cmd/oras/internal/option/remote.go index 26c01fc90..5547569e5 100644 --- a/cmd/oras/internal/option/remote.go +++ b/cmd/oras/internal/option/remote.go @@ -116,10 +116,7 @@ func (opts *Remote) Parse() error { if err := opts.parseCustomHeaders(); err != nil { return err } - if err := opts.readPassword(); err != nil { - return err - } - return opts.DistributionSpec.Parse() + return opts.readPassword() } // readPassword tries to read password with optional cmd prompt. diff --git a/cmd/oras/internal/option/spec.go b/cmd/oras/internal/option/spec.go index 965eb929b..015c54b76 100644 --- a/cmd/oras/internal/option/spec.go +++ b/cmd/oras/internal/option/spec.go @@ -20,11 +20,14 @@ import ( "github.com/spf13/pflag" "oras.land/oras-go/v2" + oerrors "oras.land/oras/cmd/oras/internal/errors" ) const ( - ImageSpecV1_1 = "v1.1" - ImageSpecV1_0 = "v1.0" + ImageSpecV1_1 = "v1.1" + ImageSpecV1_0 = "v1.0" + ReferrersTagV1_1 = "v1.1-referrers-tag" + ReferrersAPIV1_1 = "v1.1-referrers-api" ) // ImageSpec option struct. @@ -33,22 +36,37 @@ type ImageSpec struct { PackVersion oras.PackManifestVersion } -// Parse parses flags into the option. -func (opts *ImageSpec) Parse() error { - switch opts.flag { - case ImageSpecV1_1: - opts.PackVersion = oras.PackManifestVersion1_1_RC4 +// Set validates and sets the flag value from a string argument. +func (i *ImageSpec) Set(value string) error { + i.flag = value + switch value { + case ImageSpecV1_1, "": + // default to v1.1 + i.PackVersion = oras.PackManifestVersion1_1_RC4 case ImageSpecV1_0: - opts.PackVersion = oras.PackManifestVersion1_0 + i.PackVersion = oras.PackManifestVersion1_0 default: - return fmt.Errorf("unknown image specification flag: %q", opts.flag) + return &oerrors.Error{ + Err: fmt.Errorf("unknown image specification flag: %s", value), + Recommendation: fmt.Sprintf("Available options: %s", i.Type()), + } } return nil } +// Type returns the type of the flag. +func (i *ImageSpec) Type() string { + return fmt.Sprintf("%s, %s", ImageSpecV1_1, ImageSpecV1_0) +} + +// String returns the string representation of the flag. +func (i *ImageSpec) String() string { + return i.flag +} + // ApplyFlags applies flags to a command flag set. func (opts *ImageSpec) ApplyFlags(fs *pflag.FlagSet) { - fs.StringVar(&opts.flag, "image-spec", ImageSpecV1_1, fmt.Sprintf("[Experimental] specify manifest type for building artifact. options: %s, %s", ImageSpecV1_1, ImageSpecV1_0)) + fs.Var(opts, "image-spec", "[Experimental] specify manifest type for building artifact") } // DistributionSpec option struct. @@ -58,28 +76,43 @@ type DistributionSpec struct { ReferrersAPI *bool // specFlag should be provided in form of`--