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

parse and validate some input parameters as filesystem-paths #669

Merged
merged 17 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 29 additions & 29 deletions cmds/ocm/commands/ocmcmds/common/inputs/options/standard.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and Open Component Model contributors.
//
// SPDX-License-Identifier: Apache-2.0

package options

import (
Expand All @@ -14,41 +10,45 @@ var (
MediaTypeOption = options.MediatypeOption
)

var PathOption = flagsets.NewStringOptionType("inputPath", "path field for input")

// string options
var (
CompressOption = flagsets.NewBoolOptionType("inputCompress", "compress option for input")
ExcludeOption = flagsets.NewStringArrayOptionType("inputExcludes", "excludes (path) for inputs")
VersionOption = flagsets.NewStringOptionType("inputVersion", "version info for inputs")
TextOption = flagsets.NewStringOptionType("inputText", "utf8 text")
HelmRepositoryOption = flagsets.NewStringOptionType("inputHelmRepository", "helm repository base URL")
)
var (
VariantsOption = flagsets.NewStringArrayOptionType("inputVariants", "(platform) variants for inputs")
PlatformsOption = flagsets.NewStringArrayOptionType("inputPlatforms", "input filter for image platforms ([os]/[architecture])")
)

// path options
var (
IncludeOption = flagsets.NewStringArrayOptionType("inputIncludes", "includes (path) for inputs")
PreserveDirOption = flagsets.NewBoolOptionType("inputPreserveDir", "preserve directory in archive for inputs")
PathOption = flagsets.NewPathOptionType("inputPath", "path field for input")
)
var (
IncludeOption = flagsets.NewPathArrayOptionType("inputIncludes", "includes (path) for inputs")
ExcludeOption = flagsets.NewPathArrayOptionType("inputExcludes", "excludes (path) for inputs")
LibrariesOption = flagsets.NewPathArrayOptionType("inputLibraries", "library path for inputs")
)

// boolean options
var (
CompressOption = flagsets.NewBoolOptionType("inputCompress", "compress option for input")
PreserveDirOption = flagsets.NewBoolOptionType("inputPreserveDir", "preserve directory in archive for inputs")
FollowSymlinksOption = flagsets.NewBoolOptionType("inputFollowSymlinks", "follow symbolic links during archive creation for inputs")
VariantsOption = flagsets.NewStringArrayOptionType("inputVariants", "(platform) variants for inputs")
)

var LibrariesOption = flagsets.NewStringArrayOptionType("inputLibraries", "library path for inputs")

var VersionOption = flagsets.NewStringOptionType("inputVersion", "version info for inputs")

var ValuesOption = flagsets.NewValueMapYAMLOptionType("inputValues", "YAML based generic values for inputs")

var DataOption = flagsets.NewBytesOptionType("inputData", "data (string, !!string or !<base64>")

var TextOption = flagsets.NewStringOptionType("inputText", "utf8 text")

var YAMLOption = flagsets.NewYAMLOptionType("inputYaml", "YAML formatted text")

var JSONOption = flagsets.NewYAMLOptionType("inputJson", "JSON formatted text")

var FormattedJSONOption = flagsets.NewYAMLOptionType("inputFormattedJson", "JSON formatted text")

var HelmRepositoryOption = flagsets.NewStringOptionType("inputHelmRepository", "helm repository base URL")
// data options
var (
DataOption = flagsets.NewBytesOptionType("inputData", "data (string, !!string or !<base64>")
)

// yaml/json options
var (
PlatformsOption = flagsets.NewStringArrayOptionType("inputPlatforms", "input filter for image platforms ([os]/[architecture])")
YAMLOption = flagsets.NewYAMLOptionType("inputYaml", "YAML formatted text")
JSONOption = flagsets.NewYAMLOptionType("inputJson", "JSON formatted text")
FormattedJSONOption = flagsets.NewYAMLOptionType("inputFormattedJson", "JSON formatted text")
)
var (
ValuesOption = flagsets.NewValueMapYAMLOptionType("inputValues", "YAML based generic values for inputs")
)
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ require (
github.com/imdario/mergo v0.3.16
github.com/klauspost/compress v1.17.2
github.com/klauspost/pgzip v1.2.6
github.com/mandelsoft/filepath v0.0.0-20230412200429-36b1eb66bd27
github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3
hilmarf marked this conversation as resolved.
Show resolved Hide resolved
github.com/mandelsoft/logging v0.0.0-20230905123808-7042ee3aae45
github.com/mandelsoft/spiff v1.7.0-beta-5
github.com/mandelsoft/vfs v0.4.1
github.com/mandelsoft/vfs v0.4.3-0.20240223095430-def3828dd181
hilmarf marked this conversation as resolved.
Show resolved Hide resolved
github.com/marstr/guid v1.1.0
github.com/mitchellh/copystructure v1.2.0
github.com/mittwald/go-helm-client v0.12.3
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1826,14 +1826,14 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mandelsoft/filepath v0.0.0-20230412200429-36b1eb66bd27 h1:VivN6K8H4H0G4bUmeQH68fQIROL5c8S2iyvVe4teufc=
github.com/mandelsoft/filepath v0.0.0-20230412200429-36b1eb66bd27/go.mod h1:LxhqC7khDoRENwooP6f/vWvia9ivj6TqLYrR39zqkN0=
github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3 h1:oo9nIgnyiBgYPbcZslRT4y29siuL5EoNJ/t1tr0xEVQ=
github.com/mandelsoft/filepath v0.0.0-20240223090642-3e2777258aa3/go.mod h1:LxhqC7khDoRENwooP6f/vWvia9ivj6TqLYrR39zqkN0=
github.com/mandelsoft/logging v0.0.0-20230905123808-7042ee3aae45 h1:BGJBqw9q1Brn3XAYcj52hhonjV7aHUftVJ3SuJpXQ/M=
github.com/mandelsoft/logging v0.0.0-20230905123808-7042ee3aae45/go.mod h1:J/kRqdfAOQmMPfJeAcV2pfX1QLV9/NlAQdAJzpnaU+g=
github.com/mandelsoft/spiff v1.7.0-beta-5 h1:3kC10nTviDQhL8diSxp7i4IC2iSiDg6KPbH1CAq7Lfw=
github.com/mandelsoft/spiff v1.7.0-beta-5/go.mod h1:TwEeOPuRZxlzQBCLEyVTlHmBSruSGGNdiQ2fovVJ8ao=
github.com/mandelsoft/vfs v0.4.1 h1:HvCC5wySpPIl7K3GFOU5MOftiaXbBlOSa7v+MEzln2g=
github.com/mandelsoft/vfs v0.4.1/go.mod h1:k83vb5I4cqRGJh3TUUVbf2oTF8FrYhvixQ+FwIAgP1Y=
github.com/mandelsoft/vfs v0.4.3-0.20240223095430-def3828dd181 h1:A3F9ihgRtezfoCSoOMtmTU2yOip3aYBTESa6X8hQ+Ek=
github.com/mandelsoft/vfs v0.4.3-0.20240223095430-def3828dd181/go.mod h1:zmbhx2ueQc96buqNXg2S88McBMm2mNFNeyGSpSebrHw=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
Expand Down
58 changes: 58 additions & 0 deletions pkg/cobrautils/flag/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package flag

import (
"strings"

"github.com/mandelsoft/filepath/pkg/filepath"
"github.com/spf13/pflag"
)

type pathValue string

func newPathValue(val string, p *string) *pathValue {
*p = pathConv(val)
return (*pathValue)(p)
}

func (s *pathValue) Set(val string) error {
*s = pathValue(pathConv(val))
return nil
}

func (s *pathValue) Type() string { return "filepath" }

func (s *pathValue) String() string { return string(*s) }

func pathConv(sval string) string {
vol, paths, rooted := filepath.SplitPath(sval)
if rooted {
return vol + "/" + strings.Join(paths, "/")
}
return vol + strings.Join(paths, "/")
}

// PathVar defines a filepath flag with specified name, default value, and usage string.
// The argument p points to a string variable in which to store the value of the flag.
func PathVar(f *pflag.FlagSet, p *string, name string, value string, usage string) {
f.VarP(newPathValue(value, p), name, "", usage)
}

// PathVarP is like PathVar, but accepts a shorthand letter that can be used after a single dash.
func PathVarP(f *pflag.FlagSet, p *string, name, shorthand string, value string, usage string) {
f.VarP(newPathValue(value, p), name, shorthand, usage)
}

// Path defines a filepath flag with specified name, default value, and usage string.
// The return value is the address of a string variable that stores the value of the flag.
func Path(f *pflag.FlagSet, name string, value string, usage string) *string {
p := new(string)
PathVarP(f, p, name, "", value, usage)
return p
}

// PathP is like Path, but accepts a shorthand letter that can be used after a single dash.
func PathP(f *pflag.FlagSet, name, shorthand string, value string, usage string) *string {
hilmarf marked this conversation as resolved.
Show resolved Hide resolved
p := new(string)
PathVarP(f, p, name, shorthand, value, usage)
return p
}
108 changes: 108 additions & 0 deletions pkg/cobrautils/flag/path_array.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package flag

import (
"path/filepath"
"strings"

"github.com/spf13/pflag"
)

type pathArrayValue struct {
value *[]string
changed bool
}

func newPathArrayValue(val []string, p *[]string) *pathArrayValue {
ssv := new(pathArrayValue)
ssv.value = p
*ssv.value = pathArrayConv(val)
return ssv
}

func (s *pathArrayValue) Set(val string) error {
if !s.changed {
*s.value = pathStringListConv(val)
s.changed = true
} else {
*s.value = append(*s.value, pathConv(val))
}
return nil
}

func (s *pathArrayValue) Append(val string) error {
*s.value = append(*s.value, pathConv(val))
return nil
}

func (s *pathArrayValue) Replace(val []string) error {
out := make([]string, len(val))
for i, d := range val {
var err error
out[i] = pathConv(d)
if err != nil {
return err
}
}
*s.value = out
return nil
}

func (s *pathArrayValue) GetSlice() []string {
out := make([]string, len(*s.value))
for i, d := range *s.value {

Check failure on line 52 in pkg/cobrautils/flag/path_array.go

View workflow job for this annotation

GitHub Actions / Lint

S1001: should use copy(to, from) instead of a loop (gosimple)
out[i] = d
}
return out
}

func (s *pathArrayValue) Type() string {
return "stringArray"
}

func (s *pathArrayValue) String() string {
str := new(string)
*str = strings.Join(*s.value, string(filepath.ListSeparator))
return *str
}

// Converts every string into correct filepath format. See pathConv for more details.
func pathArrayConv(sval []string) []string {
for i, val := range sval {
sval[i] = pathConv(val)
}
return sval
}

// pathStringListConv converts a string containing multiple filepaths seperated by filepath.ListSeparator into a list

Check failure on line 76 in pkg/cobrautils/flag/path_array.go

View workflow job for this annotation

GitHub Actions / Lint

`seperated` is a misspelling of `separated` (misspell)
// of filepaths.
func pathStringListConv(sval string) []string {
values := filepath.SplitList(sval)
values = pathArrayConv(values)
return values
}

// PathArrayVar defines a filepath flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the values of the multiple flags.
func PathArrayVar(f *pflag.FlagSet, p *[]string, name string, value []string, usage string) {
f.VarP(newPathArrayValue(value, p), name, "", usage)
}

// PathArrayVarP is like PathArrayVar, but accepts a shorthand letter that can be used after a single dash.
func PathArrayVarP(f *pflag.FlagSet, p *[]string, name, shorthand string, value []string, usage string) {
f.VarP(newPathArrayValue(value, p), name, shorthand, usage)
}

// PathArray defines a filepath flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
func PathArray(f *pflag.FlagSet, name string, value []string, usage string) *[]string {
p := []string{}
PathArrayVarP(f, &p, name, "", value, usage)
return &p
}

// PathArrayP is like PathArray, but accepts a shorthand letter that can be used after a single dash.
func PathArrayP(f *pflag.FlagSet, name, shorthand string, value []string, usage string) *[]string {
hilmarf marked this conversation as resolved.
Show resolved Hide resolved
p := []string{}
PathArrayVarP(f, &p, name, shorthand, value, usage)
return &p
}
34 changes: 34 additions & 0 deletions pkg/cobrautils/flag/path_array_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build !windows
// +build !windows

package flag_test

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/pflag"

. "github.com/open-component-model/ocm/pkg/cobrautils/flag"
)

var _ = Describe("path flags", func() {
var flags *pflag.FlagSet

BeforeEach(func() {
flags = pflag.NewFlagSet("test", pflag.ContinueOnError)
})

It("parse windows path", func() {
var val []string
PathArrayVarPF(flags, &val, "path", "p", nil, "help message")
flags.Parse([]string{"-p", `/foo/bar:other/path`})
Expect(val).To(Equal([]string{"/foo/bar", "other/path"}))
})

It("parse default path", func() {
var val []string
PathArrayVarPF(flags, &val, "path", "p", []string{`/foo/bar`, `other/path`}, "help message")
Expect(val).To(Equal([]string{"/foo/bar", "other/path"}))
})

})
34 changes: 34 additions & 0 deletions pkg/cobrautils/flag/path_array_win_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build windows
// +build windows

package flag_test

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/pflag"

. "github.com/open-component-model/ocm/pkg/cobrautils/flag"
)

var _ = Describe("path flags", func() {
var flags *pflag.FlagSet

BeforeEach(func() {
flags = pflag.NewFlagSet("test", pflag.ContinueOnError)
})

It("parse windows path", func() {
var val []string
PathArrayVarPF(flags, &val, "path", "p", nil, "help message")
flags.Parse([]string{"-p", `C:\foo\bar;E:\other\path`})
Expect(val).To(Equal([]string{"C:/foo/bar", "E:/other/path"}))
})

It("parse default path", func() {
var val []string
PathArrayVarPF(flags, &val, "path", "p", []string{`C:\foo\bar`, `E:\other\path`}, "help message")
Expect(val).To(Equal([]string{"C:/foo/bar", "E:/other/path"}))
})

})
34 changes: 34 additions & 0 deletions pkg/cobrautils/flag/path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build !windows
// +build !windows

package flag_test

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/pflag"

. "github.com/open-component-model/ocm/pkg/cobrautils/flag"
)

var _ = Describe("path flags", func() {
var flags *pflag.FlagSet

BeforeEach(func() {
flags = pflag.NewFlagSet("test", pflag.ContinueOnError)
})

It("parse linux path", func() {
var val string
PathVarP(flags, &val, "path", "p", "", "help message")
flags.Parse([]string{"-p", `/t/bugrepo/postgresql-14.0.5.tgz`})
Expect(val).To(Equal("/t/bugrepo/postgresql-14.0.5.tgz"))
})

It("parse default path", func() {
var val string
PathVarP(flags, &val, "path", "p", `/t/bugrepo/postgresql-14.0.5.tgz`, "help message")
Expect(val).To(Equal("/t/bugrepo/postgresql-14.0.5.tgz"))
})

})
Loading
Loading