diff --git a/cmds/ocm/commands/ocmcmds/components/hash/cmd.go b/cmds/ocm/commands/ocmcmds/components/hash/cmd.go index 43922b6ff0..b2ef1f9932 100644 --- a/cmds/ocm/commands/ocmcmds/components/hash/cmd.go +++ b/cmds/ocm/commands/ocmcmds/components/hash/cmd.go @@ -13,6 +13,7 @@ import ( "ocm.software/ocm/api/ocm" "ocm.software/ocm/api/ocm/compdesc" common "ocm.software/ocm/api/utils/misc" + "ocm.software/ocm/api/utils/out" "ocm.software/ocm/cmds/ocm/commands/common/options/closureoption" ocmcommon "ocm.software/ocm/cmds/ocm/commands/ocmcmds/common" "ocm.software/ocm/cmds/ocm/commands/ocmcmds/common/handlers/comphdlr" @@ -180,17 +181,26 @@ func (h *action) Close() error { func (h *action) Out() error { if len(h.norms) > 1 { - dir := h.mode.outfile - dir = strings.TrimSuffix(dir, ".ncd") - err := h.ctx.FileSystem().Mkdir(dir, 0o755) - if err != nil { - return fmt.Errorf("cannot create output dir %s", dir) - } - for k, n := range h.norms { - p := filepath.Join(dir, k.String()) - err := h.write(p+".ncd", n) + if h.mode.outfile == "" || h.mode.outfile == "-" { + for _, n := range h.norms { + err := h.write(h.mode.outfile, n) + if err != nil { + return err + } + } + } else { + dir := h.mode.outfile + dir = strings.TrimSuffix(dir, ".ncd") + err := h.ctx.FileSystem().Mkdir(dir, 0o755) if err != nil { - return err + return fmt.Errorf("cannot create output dir %s", dir) + } + for k, n := range h.norms { + p := filepath.Join(dir, k.String()) + err := h.write(p+".ncd", n) + if err != nil { + return err + } } } } else { @@ -202,12 +212,17 @@ func (h *action) Out() error { } func (h *action) write(p, n string) error { - dir := filepath.Dir(p) - err := h.ctx.FileSystem().MkdirAll(dir, 0o755) - if err != nil { - return fmt.Errorf("cannot create dir %s", dir) + if p == "" || p == "-" { + out.Outln(h.ctx, n) + return nil + } else { + dir := filepath.Dir(p) + err := h.ctx.FileSystem().MkdirAll(dir, 0o755) + if err != nil { + return fmt.Errorf("cannot create dir %s", dir) + } + return vfs.WriteFile(h.ctx.FileSystem(), p, []byte(n), 0o644) } - return vfs.WriteFile(h.ctx.FileSystem(), p, []byte(n), 0o644) } ///////// diff --git a/cmds/ocm/commands/ocmcmds/components/hash/cmd_test.go b/cmds/ocm/commands/ocmcmds/components/hash/cmd_test.go index 7783820f74..f79e2c1c05 100644 --- a/cmds/ocm/commands/ocmcmds/components/hash/cmd_test.go +++ b/cmds/ocm/commands/ocmcmds/components/hash/cmd_test.go @@ -2,6 +2,8 @@ package hash_test import ( "bytes" + "crypto/sha256" + "encoding/hex" "fmt" . "github.com/mandelsoft/goutils/testutils" @@ -50,6 +52,48 @@ test.de/x v1 37f7f500d87f4b0a8765649f7c047db382e272b73e042805131df57279991b `)) }) + It("normalize component archive v1", func() { + env.ComponentArchive(ARCH, accessio.FormatDirectory, COMP, VERSION, func() { + env.Provider(PROVIDER) + }) + + buf := bytes.NewBuffer(nil) + Expect(env.CatchOutput(buf).Execute("hash", "components", ARCH, "-O", "-", "-o", "norm")).To(Succeed()) + Expect(buf.String()).To(Equal(`[{"component":[{"componentReferences":[]},{"name":"test.de/x"},{"provider":"mandelsoft"},{"resources":[]},{"version":"v1"}]},{"meta":[{"schemaVersion":"v2"}]}] +`)) + }) + + It("normalize component archive v2", func() { + env.ComponentArchive(ARCH, accessio.FormatDirectory, COMP, VERSION, func() { + env.Provider(PROVIDER) + }) + + buf := bytes.NewBuffer(nil) + Expect(env.CatchOutput(buf).Execute("hash", "components", ARCH, "-N", "jsonNormalisation/v2", "-o", "norm")).To(Succeed()) + Expect(buf.String()).To(StringEqualTrimmedWithContext(`{"component":{"componentReferences":[],"name":"test.de/x","provider":{"name":"mandelsoft"},"resources":[],"sources":[],"version":"v1"}} +`)) + }) + + It("check hash", func() { + env.ComponentArchive(ARCH, accessio.FormatDirectory, COMP, VERSION, func() { + env.Provider(PROVIDER) + }) + + buf := bytes.NewBuffer(nil) + Expect(env.CatchOutput(buf).Execute("hash", "components", ARCH, "-o", "yaml")).To(Succeed()) + Expect(buf.String()).To(StringEqualTrimmedWithContext(` +--- +component: test.de/x +context: [] +hash: 37f7f500d87f4b0a8765649f7c047db382e272b73e042805131df57279991b2b +normalized: '[{"component":[{"componentReferences":[]},{"name":"test.de/x"},{"provider":"mandelsoft"},{"resources":[]},{"version":"v1"}]},{"meta":[{"schemaVersion":"v2"}]}]' +version: v1 +`)) + + h := sha256.Sum256([]byte(`[{"component":[{"componentReferences":[]},{"name":"test.de/x"},{"provider":"mandelsoft"},{"resources":[]},{"version":"v1"}]},{"meta":[{"schemaVersion":"v2"}]}]`)) + Expect(hex.EncodeToString(h[:])).To(Equal("37f7f500d87f4b0a8765649f7c047db382e272b73e042805131df57279991b2b")) + }) + It("hash component archive with resources", func() { env.ComponentArchive(ARCH, accessio.FormatDirectory, COMP, VERSION, func() { env.Provider(PROVIDER) diff --git a/cmds/ocm/commands/ocmcmds/components/hash/options.go b/cmds/ocm/commands/ocmcmds/components/hash/options.go index d3165c732b..99346e88a2 100644 --- a/cmds/ocm/commands/ocmcmds/components/hash/options.go +++ b/cmds/ocm/commands/ocmcmds/components/hash/options.go @@ -33,7 +33,7 @@ func (o *Option) AddFlags(fs *pflag.FlagSet) { fs.BoolVarP(&o.Actual, "actual", "", false, "use actual component descriptor") fs.BoolVarP(&o.Update, "update", "U", false, "update digests in component version") fs.BoolVarP(&o.Verify, "verify", "V", false, "verify digests found in component version") - fs.StringVarP(&o.outfile, "outfile", "O", "norm.ncd", "Output file for normalized component descriptor") + fs.StringVarP(&o.outfile, "outfile", "O", "-", "Output file for normalized component descriptor") } func (o *Option) Complete(cmd *Command) error {