diff --git a/.gitignore b/.gitignore index 71f6a2d..1a431c2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,11 @@ # Test binary, built with `go test -c` *.test -# Dependency directories -vendor/ +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ # Go workspace file go.work @@ -20,6 +23,4 @@ go.work.sum # env file .env - -build/ -.task/ +cover.* diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index b47e994..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,14 +0,0 @@ -# Changelog - -## [0.0.1] - 2025-03-10 - -Initial Release! Hope you like it! - -### Added - -- nomino.Make -- nomino.Config -- nomino.Generator - + We needs more of these until I'm ready -- Lots of tests! - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9f61e2e..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2025, Dan Jones . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index e364bfc..0000000 --- a/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# nomino - A filename generator - -The purpose of nomino is to generate (probably random) filenames, for example, if you want to save an uploaded file to storage under a new name. - -It takes a lot of inspiration (although no actual code) from [Onym](https://github.com/Blaspsoft/onym). - -## TODO - -I'll fill this out more in depth later. - -For now, add it to a new project, and run `go doc codeberg.org/danjones000/nomino` diff --git a/Taskfile.yml b/Taskfile.yml deleted file mode 100644 index 025ff4b..0000000 --- a/Taskfile.yml +++ /dev/null @@ -1,86 +0,0 @@ -version: '3' - -tasks: - default: - cmds: - - task: fmt - - task: test - - task: build - - fmt: - desc: Format go code - sources: - - '**/*.go' - cmds: - - go fmt ./... - - go mod tidy - - gen: - desc: Generate files - sources: - - '**/*.go' - cmds: - - go generate ./... - - vet: - desc: Vet go code - sources: - - '**/*.go' - cmds: - - go vet ./... - - critic: - desc: Critique go code - sources: - - '**/*.go' - cmds: - - gocritic check ./... - - staticcheck: - desc: Static check go code - sources: - - '**/*.go' - cmds: - - staticcheck ./... - - vuln: - desc: Check for vulnerabilities - sources: - - '**/*.go' - cmds: - - govulncheck ./... - - lint: - desc: Do static analysis - deps: - - vet - - critic - - staticcheck - - vuln - - test: - desc: Run unit tests - deps: [fmt, vet] - sources: - - '**/*.go' - generates: - - build/cover.out - cmds: - - go test -race -cover -coverprofile build/cover.out ./... - - coverage-report: - desc: Build coverage report - deps: [test] - sources: - - build/cover.out - generates: - - build/cover.html - cmds: - - go tool cover -html=build/cover.out -o build/cover.html - - serve-report: - desc: Serve the coverage report - deps: [coverage-report] - cmds: - - ip addr list | grep inet - - php -S 0.0.0.0:3265 -t build diff --git a/config.go b/config.go deleted file mode 100644 index dc6af3d..0000000 --- a/config.go +++ /dev/null @@ -1,20 +0,0 @@ -package nomino - -type Config struct { - original string - prefix string - suffix string - extension string - generator Generator -} - -func NewConfig(options ...Option) Config { - conf := Config{ - extension: ".txt", - generator: uuidGen, - } - for _, opt := range options { - opt(&conf) - } - return conf -} diff --git a/config_test.go b/config_test.go deleted file mode 100644 index bb88b53..0000000 --- a/config_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package nomino - -import ( - "testing" - - "github.com/google/uuid" - "github.com/stretchr/testify/assert" -) - -func TestNewConf(t *testing.T) { - c := NewConfig() - assert.Equal(t, ".txt", c.extension) - st, _ := c.generator() - _, parseErr := uuid.Parse(st) - assert.NoError(t, parseErr) -} - -func TestNewConfWithOpts(t *testing.T) { - c := NewConfig(WithoutExtension(), WithPrefix("foobar")) - assert.Equal(t, "", c.extension) - assert.Equal(t, "foobar_", c.prefix) -} diff --git a/generators.go b/generators.go deleted file mode 100644 index fdbdabd..0000000 --- a/generators.go +++ /dev/null @@ -1,99 +0,0 @@ -package nomino - -import ( - "errors" - "time" - - "github.com/google/uuid" -) - -// Generator is a function that returns the "random" portion of the returned filename. -// Technically, it doesn't necessarily need to be random, and could be based on time, or a counter, -// for example. -type Generator func() (string, error) - -// WithGenerator sets the specified generator -func WithGenerator(g Generator) Option { - return func(c *Config) { - c.generator = g - } -} - -// ErrMissingGenerators is returned by a multi-generator if no generators are supplied. -var ErrMissingGenerators = errors.New("no generators supplied") - -func missingGen() (string, error) { - return "", ErrMissingGenerators -} - -// MultiGeneratorInOrder allows the use of multiple generators. Each new invokation will use the next generator in turn. -// If none are passed, the generator will always return ErrMissingGenerators. -func MultiGeneratorInOrder(gens ...Generator) Generator { - if len(gens) == 0 { - return missingGen - } - - if len(gens) == 1 { - return gens[0] - } - - var idx int - return func() (string, error) { - st, err := gens[idx]() - idx = (idx + 1) % len(gens) - return st, err - } -} - -func uuidGen() (string, error) { - u, err := uuid.NewRandom() - if err != nil { - return "", err - } - return u.String(), nil -} - -// UUID generates a UUIDv4. -func UUID() Generator { - return uuidGen -} - -// FileTimestamp is the default format for WithTimestamp and WithTime -const FileTimestamp string = "2006-01-02_03-05-06-0700" - -// Timestamp generates a a date and time for the current time. -// It is formatted accourding to FileTimestamp -func Timestamp() Generator { - return TimestampWithFormat(FileTimestamp) -} - -// TimestampWithFormat generates a date and time for the current time with the supplied format. -func TimestampWithFormat(f string) Generator { - return FormattedTime(time.Now(), FileTimestamp) -} - -// Time generates a date and time for the supplied time. -// It is formatted accourding to FileTimestamp -func Time(t time.Time) Generator { - return FormattedTime(t, FileTimestamp) -} - -// FormattedTime generates a date and time for the supplied time with the supplied format. -func FormattedTime(t time.Time, f string) Generator { - return func() (string, error) { - return t.Format(f), nil - } -} - -// FileTimestamp is the default format for WithTimestampUTC and WithTimeUTC -const FileTimestampNoTZ string = "2006-01-02_03-05-06" - -// TimestampUTC generates a date and time for the current time in UTC without a timezone in the format. -func TimestampUTC() Generator { - return TimeUTC(time.Now()) -} - -// TimeUTC generates a date and time for the supplied time in UTC without a timezone in the format. -func TimeUTC(t time.Time) Generator { - return FormattedTime(t.UTC(), FileTimestampNoTZ) -} diff --git a/generators_test.go b/generators_test.go deleted file mode 100644 index 7282656..0000000 --- a/generators_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package nomino - -import ( - "errors" - "testing" - "time" - - "github.com/google/uuid" - "github.com/stretchr/testify/assert" -) - -func TestWithGenerator(t *testing.T) { - g := func() (string, error) { return "abc", nil } - var c Config - WithGenerator(g)(&c) - st, err := c.generator() - assert.NoError(t, err) - assert.Equal(t, "abc", st) -} - -func TestMultiGeneratorInOrder(t *testing.T) { - st1 := "abc" - st2 := "def" - er1 := errors.New("oops") - g1 := func() (string, error) { return st1, nil } - g2 := func() (string, error) { return st2, nil } - g3 := func() (string, error) { return "", er1 } - g := MultiGeneratorInOrder(g1, g2, g3) - st, err := g() - assert.NoError(t, err) - assert.Equal(t, st1, st) - st, err = g() - assert.NoError(t, err) - assert.Equal(t, st2, st) - st, err = g() - assert.Zero(t, st) - assert.ErrorIs(t, err, er1) - st, err = g() - assert.NoError(t, err) - assert.Equal(t, st1, st) -} - -func TestMultiGeneratorInOrderOne(t *testing.T) { - st1 := "abc" - g1 := func() (string, error) { return st1, nil } - g := MultiGeneratorInOrder(g1) - - st, err := g() - assert.NoError(t, err) - assert.Equal(t, st1, st) - st, err = g() - assert.NoError(t, err) - assert.Equal(t, st1, st) -} - -func TestMultiGeneratorInOrderMissing(t *testing.T) { - g := MultiGeneratorInOrder() - st, err := g() - assert.Zero(t, st) - assert.ErrorIs(t, err, ErrMissingGenerators) - st, err = g() - assert.Zero(t, st) - assert.ErrorIs(t, err, ErrMissingGenerators) -} - -func TestUUID(t *testing.T) { - st, err := UUID()() - assert.NoError(t, err) - _, parseErr := uuid.Parse(st) - assert.NoError(t, parseErr) -} - -type badRead struct{} - -func (badRead) Read([]byte) (int, error) { - return 0, errors.New("sorry") -} - -func TestUUIDFail(t *testing.T) { - uuid.SetRand(badRead{}) - defer uuid.SetRand(nil) - - _, err := UUID()() - assert.Equal(t, errors.New("sorry"), err) -} - -func TestTimestamp(t *testing.T) { - n := time.Now() - st, err := Timestamp()() - assert.NoError(t, err) - assert.Equal(t, n.Format(FileTimestamp), st) -} - -func TestTime(t *testing.T) { - d := time.Date(1986, time.March, 28, 12, 0, 0, 0, time.UTC) - - st, err := Time(d)() - assert.NoError(t, err) - assert.Equal(t, d.Format(FileTimestamp), st) -} - -func TestTimestampUTC(t *testing.T) { - n := time.Now() - st, err := TimestampUTC()() - assert.NoError(t, err) - assert.Equal(t, n.UTC().Format(FileTimestampNoTZ), st) -} diff --git a/go.mod b/go.mod index de6af60..ff9df1b 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,3 @@ module codeberg.org/danjones000/nomino go 1.23.6 - -require ( - github.com/google/uuid v1.6.0 - github.com/stretchr/testify v1.10.0 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 14c872b..0000000 --- a/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/make.go b/make.go deleted file mode 100644 index 3cd537a..0000000 --- a/make.go +++ /dev/null @@ -1,15 +0,0 @@ -package nomino - -import "fmt" - -// Make generates a random filename. The behavior can be controlled by specifying Options -// In general, the final filename will be [prefix]_[generated_string]_[original_filename]_[suffix].[extension]. -// If the name generator returns an error (generally, it shouldn't), that will be returned instead. -func Make(conf Config) (string, error) { - name, err := conf.generator() - if err != nil { - return "", err - } - - return fmt.Sprintf("%s%s%s%s%s", conf.prefix, name, conf.original, conf.suffix, conf.original), nil -} diff --git a/make_test.go b/make_test.go deleted file mode 100644 index e9cc006..0000000 --- a/make_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package nomino - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMake(t *testing.T) { - conf := NewConfig(WithGenerator(func() (string, error) { return "abc", nil })) - st, err := Make(conf) - assert.NoError(t, err) - assert.Equal(t, "abc", st) -} - -func TestMakeErr(t *testing.T) { - retErr := errors.New("oops") - conf := NewConfig(WithGenerator(func() (string, error) { return "foobar", retErr })) - st, err := Make(conf) - assert.Zero(t, st) - assert.ErrorIs(t, err, retErr) -} diff --git a/options.go b/options.go deleted file mode 100644 index fa6c81c..0000000 --- a/options.go +++ /dev/null @@ -1,42 +0,0 @@ -package nomino - -import "strings" - -// Option sets configuration parameters for Config. -type Option func(c *Config) - -// WithOriginal sets the original filename. -// This will be included in the generated name after the generated string and before the suffix. -func WithOriginal(o string) Option { - return func(c *Config) { - c.original = "_" + o - } -} - -// WithPrefix sets a prefix for the generated name. -func WithPrefix(p string) Option { - return func(c *Config) { - c.prefix = p + "_" - } -} - -// WithSuffix sets a suffix for the generated name. It will be included in the base name before the suffix. -func WithSuffix(s string) Option { - return func(c *Config) { - c.suffix = "_" + s - } -} - -// WithoutExtension sets no extension for the generated filename. By default, it will be txt -func WithoutExtension() Option { - return func(c *Config) { - c.extension = "" - } -} - -// WithExtension sets the extension for the generated filename. -func WithExtension(ext string) Option { - return func(c *Config) { - c.extension = "." + strings.TrimPrefix(ext, ".") - } -} diff --git a/options_test.go b/options_test.go deleted file mode 100644 index 12a2bb5..0000000 --- a/options_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package nomino - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestWithOriginal(t *testing.T) { - var c Config - name := "foobar" - WithOriginal(name)(&c) - assert.Equal(t, "_"+name, c.original) -} - -func TestWithPrefix(t *testing.T) { - var c Config - pref := "draft" - WithPrefix(pref)(&c) - assert.Equal(t, pref+"_", c.prefix) -} - -func TestWithSuffix(t *testing.T) { - var c Config - suff := "out" - WithSuffix(suff)(&c) - assert.Equal(t, "_"+suff, c.suffix) -} - -func TestWithoutExtension(t *testing.T) { - c := Config{extension: ".foobar"} - WithoutExtension()(&c) - assert.Equal(t, "", c.extension) -} - -func TestWithExtension(t *testing.T) { - var c Config - ext := "yaml" - WithExtension(ext)(&c) - assert.Equal(t, "."+ext, c.extension) -}