Skip to content

Commit

Permalink
cmd/cp: Fix --from-oci-layout when using full reference
Browse files Browse the repository at this point in the history
Copying an image from an OCI layout with a value like
"foo/bar:latest" for "org.opencontainers.image.ref.name" was failing with:

```
$ oras cp --from-oci-layout ./myimage:foo/bar:latest localhost:5000/foo:latest
Error: invalid argument "./myimage:foo/bar:latest": failed to find path "./myimage:foo/bar:": stat /myimage:foo/bar: no such file or directory
```

According to [0], foo/bar:latest if a valid value for
"org.opencontainers.image.ref.name", so the command should work.

This commit fixes that by using strings.Index() instead of strings.LastIndex().

[0]: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc5/annotations.md

Signed-off-by: Mauricio Vásquez <mauriciov@microsoft.com>
  • Loading branch information
mauriciovasquezbernal committed Sep 20, 2024
1 parent 961e9f8 commit 2ebab51
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 10 deletions.
19 changes: 10 additions & 9 deletions cmd/oras/internal/option/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
"oras.land/oras-go/v2/registry/remote/auth"
"oras.land/oras-go/v2/registry/remote/errcode"
oerrors "oras.land/oras/cmd/oras/internal/errors"
"oras.land/oras/cmd/oras/internal/fileref"
)

const (
Expand Down Expand Up @@ -123,20 +122,22 @@ func (opts *Target) Parse(cmd *cobra.Command) error {
// parseOCILayoutReference parses the raw in format of <path>[:<tag>|@<digest>]
func (opts *Target) parseOCILayoutReference() error {
raw := opts.RawReference
var path string
path := raw
var ref string
if idx := strings.LastIndex(raw, "@"); idx != -1 {
// `digest` found
path = raw[:idx]
ref = raw[idx+1:]
} else {
// find `tag`
var err error
path, ref, err = fileref.Parse(raw, "")
if err != nil {
return errors.Join(err, errdef.ErrInvalidReference)
}
} else if idx := strings.Index(raw, ":"); idx != -1 {
// `tag` found
path = raw[:idx]
ref = raw[idx+1:]
}

if path == "" {
return fmt.Errorf("found empty file path in %q", raw)
}

opts.Path = path
opts.Reference = ref
return nil
Expand Down
3 changes: 2 additions & 1 deletion cmd/oras/internal/option/target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ func Test_parseOCILayoutReference(t *testing.T) {
}{
{"Empty input", "", "", "", true},
{"Empty path and tag", ":", "", "", true},
{"Empty path and digest", "@", "", "", false},
{"Empty path and digest", "@", "", "", true},
{"Empty digest", "path@", "path", "", false},
{"Empty tag", "path:", "path", "", false},
{"path and digest", "path@digest", "path", "digest", false},
{"path and tag", "path:tag", "path", "tag", false},
{"path with full reference", "path:repo:tag", "path", "repo:tag", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit 2ebab51

Please sign in to comment.