From 7318c3e1c29599210ee08c433d4540584f27f122 Mon Sep 17 00:00:00 2001 From: Paul Schwabauer Date: Wed, 19 Feb 2025 17:07:43 +0100 Subject: [PATCH] Improve option parsing --- .github/workflows/go.yml | 6 +-- Makefile | 45 ++++++++++++++++++ cmd/fakedoc/main.go | 99 ++++++++++++---------------------------- go.mod | 4 +- go.sum | 4 ++ pkg/fakedoc/version.go | 13 ++++++ 6 files changed, 97 insertions(+), 74 deletions(-) create mode 100644 Makefile create mode 100644 pkg/fakedoc/version.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6123ba7..3716391 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -21,6 +21,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Ensures all tags are fetched - name: Set up Go uses: actions/setup-go@v4 @@ -28,7 +30,7 @@ jobs: go-version: "stable" - name: Build - run: go build -v ./cmd/... + run: make - name: vet run: go vet ./... @@ -45,5 +47,3 @@ jobs: - name: Revive Action uses: morphy2k/revive-action@v2.5.1 - - name: Tests - run: go test -v ./... diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..37cc87b --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +# This file is Free Software under the Apache-2.0 License +# without warranty, see README.md and LICENSES/Apache-2.0.txt for details. +# +# SPDX-License-Identifier: Apache-2.0 +# +# SPDX-FileCopyrightText: 2025 German Federal Office for Information Security (BSI) +# Software-Engineering: 2025 Intevation GmbH + +.PHONY: all fakedoc createtemplate test + +all: fakedoc createtemplate test + +# See comment here (2024-11-15) +# https://github.com/gocsaf/csaf/blob/3093f717817b9369d390e56d1012eaedcfa19e32/Makefile#L40-L49 +GITDESC := $(shell git describe --tags --always) +GITDESCPATCH := $(shell echo '$(GITDESC)' | sed -E 's/v?[0-9]+\.[0-9]+\.([0-9]+)[-+]?.*/\1/') +SEMVERPATCH := $(shell echo $$(( $(GITDESCPATCH) + 1 ))) +# Hint: The second regexp in the next line only matches +# if there is a hyphen (`-`) followed by a number, +# by which we assume that git describe has added a string after the tag +SEMVER := $(shell echo '$(GITDESC)' | sed -E -e 's/^v//' -e 's/([0-9]+\.[0-9]+\.)([0-9]+)(-[1-9].*)/\1$(SEMVERPATCH)\3/' ) +testsemver: + @echo from \'$(GITDESC)\' transformed to \'$(SEMVER)\' + +LDFLAGS=-ldflags "-X github.com/gocsaf/fakedoc/pkg/fakedoc.SemVersion=$(SEMVER)" +GO_FLAGS=$(LDFLAGS) + +# Build for coverage profile generation +ifeq ($(BUILD_COVER), true) +GO_FLAGS += "-cover" +endif + + +fakedoc: build_pkg + cd cmd/fakedoc && go build $(GO_FLAGS) + +createtemplate: build_pkg + cd cmd/createtemplate && go build $(GO_FLAGS) + +build_pkg: + cd pkg && go build $(GO_FLAGS) ./... + +test: + go test ./... + diff --git a/cmd/fakedoc/main.go b/cmd/fakedoc/main.go index 38fe470..f193f4b 100644 --- a/cmd/fakedoc/main.go +++ b/cmd/fakedoc/main.go @@ -13,7 +13,6 @@ import ( "bytes" "encoding/json" "errors" - "flag" "fmt" "io" "log" @@ -24,47 +23,9 @@ import ( "strings" "text/template" - "github.com/gocsaf/fakedoc/pkg/fakedoc" -) - -const ( - seedDocumentation = ` -random number seed, format 'pcg:<1-16 hex digits>:<1-16 hex digits>'. -If omitted, the generator uses a random seed. -` - - outputDocumentation = ` -output filename. Setting this will also set the tracking ID in the -generated file so that it matches the filename. The filename must end -with '.json' -` - - numOutputDocumentation = ` -How many documents to generate . If greate than 1, the output filename -must be given. It is treated as a template for filenames in which {{$}} -will be replaced with the number of the file, starting with 0. -` - - formattedDocumentation = ` -Output JSON should be formatted. -` - - limitsDocumentation = ` -Guidance on the Size of CSAF Documents. -` + "github.com/jessevdk/go-flags" - sizeFactorDocumentation = ` -Factor by which to multiply the maxima given in the limits file. -` - - forceMaxSizeDocumentation = ` -Try to force size of arrays to their maxiumum as defined in the limits -file and modified by the size factor. -` - - requireDocumentation = ` -Specifies with a regular expression what fields to force as required. -` + "github.com/gocsaf/fakedoc/pkg/fakedoc" ) func check(err error) { @@ -73,46 +34,44 @@ func check(err error) { } } +type options struct { + Version bool `long:"version" description:"Display version of the binary"` + TemplateFile string `long:"template" short:"t" description:"Template file"` + LimitsFile string `long:"limit-file" short:"l" description:"Guidance on the Size of CSAF Documents."` + SizeFactor float64 `long:"size" default:"0.00001" description:"Factor by which to multiply the maxima given in the limits file."` + ForceMaxSize bool `long:"force-max-size" description:"Try to force size of arrays to their maxiumum as defined in the limits file and modified by the size factor."` + Seed string `long:"seed" description:"random number seed, format 'pcg:<1-16 hex digits>:<1-16 hex digits>'. If omitted, the generator uses a random seed."` + OutputFile string `long:"output-file" short:"o" description:"Output filename. Setting this will also set the tracking ID in the generated file so that it matches the filename. The filename must end with '.json'"` + NumOutputs int `long:"num-outputs" short:"n" description:"How many documents to generate . If greate than 1, the output filename must be given. It is treated as a template for filenames in which {{$}} will be replaced with the number of the file, starting with 0."` + Formatted bool `long:"format" short:"f" description:"Output JSON should be formatted."` + RequireRegex string `long:"require" description:"Specifies with a regular expression what fields to force as required."` +} + func main() { - var ( - templatefile string - limitsfile string - sizeFactor float64 - forceMaxSize bool - seed string - outputfile string - numOutputs int - formatted bool - requireRegex string - ) + var opts options + parser := flags.NewParser(&opts, flags.Default) + parser.Parse() + if opts.Version { + fmt.Println(fakedoc.SemVersion) + return + } - flag.StringVar(&templatefile, "template", "", "template file") - flag.StringVar(&limitsfile, "l", "", limitsDocumentation) - flag.Float64Var(&sizeFactor, "size", 0.00001, sizeFactorDocumentation) - flag.BoolVar(&forceMaxSize, "force-max-size", false, forceMaxSizeDocumentation) - flag.StringVar(&seed, "seed", "", seedDocumentation) - flag.StringVar(&outputfile, "o", "", outputDocumentation) - flag.IntVar(&numOutputs, "n", 1, numOutputDocumentation) - flag.BoolVar(&formatted, "f", false, formattedDocumentation) - flag.StringVar(&requireRegex, "require", "", requireDocumentation) - // Only used when compiled with 'profile' tag. pf := addProfileFlags() - flag.Parse() - if numOutputs > 1 && outputfile == "" { + if opts.NumOutputs > 1 && opts.OutputFile == "" { log.Fatal("Multiple outputs require an explicit output file template") } - rng, err := fakedoc.ParseSeed(seed) + rng, err := fakedoc.ParseSeed(opts.Seed) check(err) check(pf.profile(func() error { return generate( - templatefile, rng, - outputfile, limitsfile, - sizeFactor, forceMaxSize, - numOutputs, formatted, - requireRegex) + opts.TemplateFile, rng, + opts.OutputFile, opts.LimitsFile, + opts.SizeFactor, opts.ForceMaxSize, + opts.NumOutputs, opts.Formatted, + opts.RequireRegex) })) } diff --git a/go.mod b/go.mod index f8563e9..b21a5cd 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.23 require ( github.com/BurntSushi/toml v1.4.0 + github.com/go-loremipsum/loremipsum v1.1.3 + github.com/jessevdk/go-flags v1.6.1 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 ) -require github.com/go-loremipsum/loremipsum v1.1.3 +require golang.org/x/sys v0.21.0 // indirect diff --git a/go.sum b/go.sum index 34311fb..7494db4 100644 --- a/go.sum +++ b/go.sum @@ -4,11 +4,15 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-loremipsum/loremipsum v1.1.3 h1:ZRhA0ZmJ49lGe5HhWeMONr+iGftWDsHfrYBl5ktDXso= github.com/go-loremipsum/loremipsum v1.1.3/go.mod h1:OJQjXdvwlG9hsyhmMQoT4HOm4DG4l62CYywebw0XBoo= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/fakedoc/version.go b/pkg/fakedoc/version.go new file mode 100644 index 0000000..ae37577 --- /dev/null +++ b/pkg/fakedoc/version.go @@ -0,0 +1,13 @@ +// This file is Free Software under the Apache-2.0 License +// without warranty, see README.md and LICENSES/Apache-2.0.txt for details. +// +// SPDX-License-Identifier: Apache-2.0 +// +// SPDX-FileCopyrightText: 2024 German Federal Office for Information Security (BSI) +// Software-Engineering: 2024 Intevation GmbH + +package fakedoc + +// SemVersion the version in semver.org format, MUST be overwritten during +// the linking stage of the build process +var SemVersion = "0.0.0"