Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Add format type text #1397

Merged
merged 11 commits into from
Jun 18, 2024
16 changes: 8 additions & 8 deletions cmd/oras/internal/display/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ func NewPushHandler(out io.Writer, format option.Format, tty *os.File, verbose b
var statusHandler status.PushHandler
if tty != nil {
statusHandler = status.NewTTYPushHandler(tty)
} else if format.Type == "" {
} else if format.Type == option.FormatTypeText.Name {
statusHandler = status.NewTextPushHandler(out, verbose)
} else {
statusHandler = status.NewDiscardHandler()
}

var metadataHandler metadata.PushHandler
switch format.Type {
case "":
case option.FormatTypeText.Name:
metadataHandler = text.NewPushHandler(out)
case option.FormatTypeJSON.Name:
metadataHandler = json.NewPushHandler(out)
Expand All @@ -64,15 +64,15 @@ func NewAttachHandler(out io.Writer, format option.Format, tty *os.File, verbose
var statusHandler status.AttachHandler
if tty != nil {
statusHandler = status.NewTTYAttachHandler(tty)
} else if format.Type == "" {
} else if format.Type == option.FormatTypeText.Name {
statusHandler = status.NewTextAttachHandler(out, verbose)
} else {
statusHandler = status.NewDiscardHandler()
}

var metadataHandler metadata.AttachHandler
switch format.Type {
case "":
case option.FormatTypeText.Name:
metadataHandler = text.NewAttachHandler(out)
case option.FormatTypeJSON.Name:
metadataHandler = json.NewAttachHandler(out)
Expand All @@ -89,15 +89,15 @@ func NewPullHandler(out io.Writer, format option.Format, path string, tty *os.Fi
var statusHandler status.PullHandler
if tty != nil {
statusHandler = status.NewTTYPullHandler(tty)
} else if format.Type == "" {
} else if format.Type == option.FormatTypeText.Name {
statusHandler = status.NewTextPullHandler(out, verbose)
} else {
statusHandler = status.NewDiscardHandler()
}

var metadataHandler metadata.PullHandler
switch format.Type {
case "":
case option.FormatTypeText.Name:
metadataHandler = text.NewPullHandler(out)
case option.FormatTypeJSON.Name:
metadataHandler = json.NewPullHandler(out, path)
Expand All @@ -113,7 +113,7 @@ func NewPullHandler(out io.Writer, format option.Format, path string, tty *os.Fi
func NewDiscoverHandler(out io.Writer, format option.Format, path string, rawReference string, desc ocispec.Descriptor, verbose bool) (metadata.DiscoverHandler, error) {
var handler metadata.DiscoverHandler
switch format.Type {
case option.FormatTypeTree.Name, "":
qweeah marked this conversation as resolved.
Show resolved Hide resolved
case option.FormatTypeTree.Name:
handler = tree.NewDiscoverHandler(out, path, desc, verbose)
case option.FormatTypeTable.Name:
handler = table.NewDiscoverHandler(out, rawReference, desc, verbose)
Expand All @@ -133,7 +133,7 @@ func NewManifestFetchHandler(out io.Writer, format option.Format, outputDescript
var contentHandler content.ManifestFetchHandler

switch format.Type {
case "":
case option.FormatTypeText.Name:
// raw
if outputDescriptor {
metadataHandler = descriptor.NewManifestFetchHandler(out, pretty)
Expand Down
44 changes: 44 additions & 0 deletions cmd/oras/internal/display/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
Copyright The ORAS Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package display

import (
"os"
"testing"

"oras.land/oras/cmd/oras/internal/option"
)

func TestNewPushHandler(t *testing.T) {
_, _, err := NewPushHandler(os.Stdout, option.Format{Type: option.FormatTypeText.Name}, os.Stdout, false)
if err != nil {
t.Errorf("NewPushHandler() error = %v, want nil", err)
}
}

func TestNewAttachHandler(t *testing.T) {
_, _, err := NewAttachHandler(os.Stdout, option.Format{Type: option.FormatTypeText.Name}, os.Stdout, false)
if err != nil {
t.Errorf("NewAttachHandler() error = %v, want nil", err)
}
}

func TestNewPullHandler(t *testing.T) {
_, _, err := NewPullHandler(os.Stdout, option.Format{Type: option.FormatTypeText.Name}, "", os.Stdout, false)
if err != nil {
t.Errorf("NewPullHandler() error = %v, want nil", err)
}
}
31 changes: 23 additions & 8 deletions cmd/oras/internal/option/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,41 @@ var (
Name: "tree",
Usage: "Get referrers recursively and print in tree format",
}
FormatTypeText = &FormatType{
Name: "text",
Usage: "Print in text format",
qweeah marked this conversation as resolved.
Show resolved Hide resolved
}
)

// Format contains input and parsed options for formatted output flags.
type Format struct {
FormatFlag string
Type string
Template string
AllowedTypes []*FormatType
allowedTypes []*FormatType
defaultType *FormatType
}

// SetTypes sets the default format type and allowed format types.
func (f *Format) SetTypes(defaultType *FormatType, allowedTypes ...*FormatType) {
TerryHowe marked this conversation as resolved.
Show resolved Hide resolved
f.defaultType = defaultType
f.allowedTypes = append(allowedTypes, defaultType)
}

// ApplyFlag implements FlagProvider.ApplyFlag.
// ApplyFlags implements FlagProvider.ApplyFlag.
func (opts *Format) ApplyFlags(fs *pflag.FlagSet) {
buf := bytes.NewBufferString("[Experimental] Format output using a custom template:")
w := tabwriter.NewWriter(buf, 0, 0, 2, ' ', 0)
for _, t := range opts.AllowedTypes {
for _, t := range opts.allowedTypes {
_, _ = fmt.Fprintf(w, "\n'%s':\t%s", t.Name, t.Usage)
}
w.Flush()
_ = w.Flush()
defaultTypeName := FormatTypeText.Name
if opts.defaultType != nil {
defaultTypeName = opts.defaultType.Name
}
qweeah marked this conversation as resolved.
Show resolved Hide resolved
// apply flags
fs.StringVar(&opts.FormatFlag, "format", opts.FormatFlag, buf.String())
fs.StringVar(&opts.FormatFlag, "format", defaultTypeName, buf.String())
fs.StringVar(&opts.Template, "template", "", "[Experimental] Template string used to format output")
}

Expand All @@ -93,7 +108,7 @@ func (opts *Format) Parse(_ *cobra.Command) error {
return err
}

if opts.Type == "" {
if opts.Type == FormatTypeText.Name {
// flag not specified
return nil
}
Expand All @@ -106,7 +121,7 @@ func (opts *Format) Parse(_ *cobra.Command) error {
}

var optionalTypes []string
for _, t := range opts.AllowedTypes {
for _, t := range opts.allowedTypes {
if opts.Type == t.Name {
// type validation passed
return nil
Expand All @@ -129,7 +144,7 @@ func (opts *Format) parseFlag() error {
return nil
}

for _, t := range opts.AllowedTypes {
for _, t := range opts.allowedTypes {
if !t.HasParams {
continue
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/oras/root/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Example - Attach file to the manifest tagged 'v1' in an OCI image layout folder
opts.FlagDescription = "[Preview] attach to an arch-specific subject"
_ = cmd.MarkFlagRequired("artifact-type")
opts.EnableDistributionSpecFlag()
opts.AllowedTypes = []*option.FormatType{option.FormatTypeJSON, option.FormatTypeGoTemplate}
opts.SetTypes(option.FormatTypeText, option.FormatTypeJSON, option.FormatTypeGoTemplate)
option.ApplyFlags(&opts, cmd.Flags())
return oerrors.Command(cmd, &opts.Target)
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/oras/root/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ Example - Discover referrers of the manifest tagged 'v1' in an OCI image layout
cmd.Flags().StringVarP(&opts.artifactType, "artifact-type", "", "", "artifact type")
cmd.Flags().StringVarP(&opts.Format.FormatFlag, "output", "o", "tree", "[Deprecated] format in which to display referrers (table, json, or tree). tree format will also show indirect referrers")
opts.FormatFlag = option.FormatTypeTree.Name
opts.AllowedTypes = []*option.FormatType{
opts.SetTypes(
option.FormatTypeTree,
option.FormatTypeTable,
option.FormatTypeJSON.WithUsage("Get direct referrers and output in JSON format"),
option.FormatTypeGoTemplate.WithUsage("Print direct referrers using the given Go template"),
}
)
opts.EnableDistributionSpecFlag()
option.ApplyFlags(&opts, cmd.Flags())
return oerrors.Command(cmd, &opts.Target)
Expand Down
7 changes: 4 additions & 3 deletions cmd/oras/root/manifest/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Example - Fetch raw manifest from an OCI layout archive file 'layout.tar':
Args: oerrors.CheckArgs(argument.Exactly(1), "the manifest to fetch"),
PreRunE: func(cmd *cobra.Command, args []string) error {
switch {
case opts.outputPath == "-" && opts.FormatFlag != "":
case opts.outputPath == "-" && opts.FormatFlag != option.FormatTypeText.Name:
return fmt.Errorf("`--output -` cannot be used with `--format %s` at the same time", opts.Template)
case opts.outputPath == "-" && opts.OutputDescriptor:
return fmt.Errorf("`--descriptor` cannot be used with `--output -` at the same time")
Expand All @@ -98,10 +98,11 @@ Example - Fetch raw manifest from an OCI layout archive file 'layout.tar':

cmd.Flags().StringSliceVarP(&opts.mediaTypes, "media-type", "", nil, "accepted media types")
cmd.Flags().StringVarP(&opts.outputPath, "output", "o", "", "file `path` to write the fetched manifest to, use - for stdout")
opts.AllowedTypes = []*option.FormatType{
opts.SetTypes(
option.FormatTypeText,
option.FormatTypeJSON.WithUsage("Print in prettified JSON format"),
option.FormatTypeGoTemplate.WithUsage("Print using the given Go template"),
}
)
option.ApplyFlags(&opts, cmd.Flags())
return oerrors.Command(cmd, &opts.Target)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/oras/root/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Example - Pull artifact files from an OCI layout archive 'layout.tar':
cmd.Flags().StringVarP(&opts.Output, "output", "o", ".", "output directory")
cmd.Flags().StringVarP(&opts.ManifestConfigRef, "config", "", "", "output manifest config file")
cmd.Flags().IntVarP(&opts.concurrency, "concurrency", "", 3, "concurrency level")
opts.AllowedTypes = []*option.FormatType{option.FormatTypeJSON, option.FormatTypeGoTemplate}
opts.SetTypes(option.FormatTypeText, option.FormatTypeJSON, option.FormatTypeGoTemplate)
option.ApplyFlags(&opts, cmd.Flags())
return oerrors.Command(cmd, &opts.Target)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/oras/root/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Example - Push file "hi.txt" into an OCI image layout folder 'layout-dir' with t
cmd.Flags().StringVarP(&opts.manifestConfigRef, "config", "", "", "`path` of image config file")
cmd.Flags().StringVarP(&opts.artifactType, "artifact-type", "", "", "artifact type")
cmd.Flags().IntVarP(&opts.concurrency, "concurrency", "", 5, "concurrency level")
opts.AllowedTypes = []*option.FormatType{option.FormatTypeJSON, option.FormatTypeGoTemplate}
opts.SetTypes(option.FormatTypeText, option.FormatTypeJSON, option.FormatTypeGoTemplate)
option.ApplyFlags(&opts, cmd.Flags())
return oerrors.Command(cmd, &opts.Target)
}
Expand Down
Loading