commit d1d2328fcd779fe7e50fe6acb0032faff6fe3ffb Author: Thomas von Dein Date: Mon Dec 16 19:11:36 2024 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c9923b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +anydb +*.log +*.db diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5186d12 --- /dev/null +++ b/Makefile @@ -0,0 +1,101 @@ + +# Copyright © 2024 Thomas von Dein + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# +# no need to modify anything below +tool = anydb +version = $(shell egrep "= .v" cfg/config.go | cut -d'=' -f2 | cut -d'"' -f 2) +archs = android darwin freebsd linux netbsd openbsd windows +PREFIX = /usr/local +UID = root +GID = 0 +BRANCH = $(shell git branch --show-current) +COMMIT = $(shell git rev-parse --short=8 HEAD) +BUILD = $(shell date +%Y.%m.%d.%H%M%S) +VERSION := $(if $(filter $(BRANCH), development),$(version)-$(BRANCH)-$(COMMIT)-$(BUILD),$(version)) +HAVE_POD := $(shell pod2text -h 2>/dev/null) + +all: $(tool).1 cmd/$(tool).go buildlocal + +%.1: %.pod +ifdef HAVE_POD + pod2man -c "User Commands" -r 1 -s 1 $*.pod > $*.1 +endif + +cmd/%.go: %.pod +ifdef HAVE_POD + echo "package cmd" > cmd/$*.go + echo >> cmd/$*.go + echo "var manpage = \`" >> cmd/$*.go + pod2text $*.pod >> cmd/$*.go + echo "\`" >> cmd/$*.go + + echo "var usage = \`" >> cmd/$*.go + awk '/SYNOPS/{f=1;next} /DESCR/{f=0} f' $*.pod | sed 's/^ //' >> cmd/$*.go + echo "\`" >> cmd/$*.go +endif + +buildlocal: + go build -ldflags "-X 'github.com/tlinden/anydb/cfg.VERSION=$(VERSION)'" + +release: + ./mkrel.sh $(tool) $(version) + gh release create $(version) --generate-notes releases/* + +install: buildlocal + install -d -o $(UID) -g $(GID) $(PREFIX)/bin + install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1 + install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/ + install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/ + +clean: + rm -rf $(tool) releases coverage.out + +test: + go test -v ./... + bash t/test.sh + +singletest: + @echo "Call like this: ''make singletest TEST=TestPrepareColumns MOD=lib" + go test -run $(TEST) github.com/tlinden/anydb/$(MOD) + +cover-report: + go test ./... -cover -coverprofile=coverage.out + go tool cover -html=coverage.out + +show-versions: buildlocal + @echo "### anydb version:" + @./anydb --version + + @echo + @echo "### go module versions:" + @go list -m all + + @echo + @echo "### go version used for building:" + @grep -m 1 go go.mod + +goupdate: + go get -t -u=patch ./... + +lint: + golangci-lint run + +# keep til ireturn +lint-full: + golangci-lint run --enable-all --exclude-use-default --disable exhaustivestruct,exhaustruct,depguard,interfacer,deadcode,golint,structcheck,scopelint,varcheck,ifshort,maligned,nosnakecase,godot,funlen,gofumpt,cyclop,noctx,gochecknoglobals,paralleltest,forbidigo,gci,godox,goimports,ireturn,stylecheck,testpackage,mirror,nestif,revive,goerr113,gomnd + gocritic check -enableAll *.go diff --git a/anydb.1 b/anydb.1 new file mode 100644 index 0000000..f120d8e --- /dev/null +++ b/anydb.1 @@ -0,0 +1,143 @@ +.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ANYDB 1" +.TH ANYDB 1 "2024-12-16" "1" "User Commands" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "anydb" +.IX Header "anydb" +\&\s-1FIXME\s0 diff --git a/anydb.pod b/anydb.pod new file mode 100644 index 0000000..21de854 --- /dev/null +++ b/anydb.pod @@ -0,0 +1,5 @@ +=head1 anydb + +FIXME + +=cut diff --git a/app/db.go b/app/db.go new file mode 100644 index 0000000..946f3cd --- /dev/null +++ b/app/db.go @@ -0,0 +1,59 @@ +package app + +import ( + "os" + "path/filepath" + "time" + + "github.com/asdine/storm/v3" +) + +type DB struct { + Debug bool + DB *storm.DB +} + +type DbAttr struct { + Key string + Args []string + Tags []string + File string +} + +type DbEntry struct { + ID int `storm:"id,increment"` + Key string `storm:"unique"` + Value string `storm:"index"` // FIXME: turn info []byte or add blob? + Tags []string `storm:"index"` + CreatedAt time.Time `storm:"index"` +} + +func New(file string, debug bool) (*DB, error) { + if _, err := os.Stat(filepath.Dir(file)); os.IsNotExist(err) { + os.MkdirAll(filepath.Dir(file), 0700) + } + + db, err := storm.Open(file) + if err != nil { + return nil, err + } + // FIXME: defer db.Close() here leads to: Error: database not open + + return &DB{Debug: debug, DB: db}, nil +} + +func (db *DB) Close() error { + return db.DB.Close() +} + +func (db *DB) Set(attr *DbAttr) error { + entry := DbEntry{Key: attr.Key, Tags: attr.Tags} + + if len(attr.Args) > 0 { + entry.Value = attr.Args[0] + } + + // FIXME: check attr.File or STDIN + + return db.DB.Save(&entry) +} diff --git a/cfg/config.go b/cfg/config.go new file mode 100644 index 0000000..8070119 --- /dev/null +++ b/cfg/config.go @@ -0,0 +1,13 @@ +package cfg + +import "github.com/tlinden/anydb/app" + +var Version string = "v0.0.1" + +type Config struct { + Debug bool + Dbfile string + DB *app.DB + File string + Tags []string +} diff --git a/cmd/anydb.go b/cmd/anydb.go new file mode 100644 index 0000000..258bf6c --- /dev/null +++ b/cmd/anydb.go @@ -0,0 +1,9 @@ +package cmd + +var manpage = ` +anydb + FIXME + +` +var usage = ` +` diff --git a/cmd/maincommands.go b/cmd/maincommands.go new file mode 100644 index 0000000..0d7c99c --- /dev/null +++ b/cmd/maincommands.go @@ -0,0 +1,68 @@ +package cmd + +import ( + "errors" + + "github.com/spf13/cobra" + "github.com/tlinden/anydb/app" + "github.com/tlinden/anydb/cfg" +) + +func Set(conf *cfg.Config) *cobra.Command { + var ( + attr app.DbAttr + ) + + var cmd = &cobra.Command{ + Use: "set [ | -r ] [-t ]", + Short: "Insert key/value pair", + Long: `Insert key/value pair`, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errors.New("No key/value pair specified") + } + + // errors at this stage do not cause the usage to be shown + cmd.SilenceUsage = true + + if len(args) > 0 { + attr.Args = args + } + + if err := conf.DB.Set(&attr); err != nil { + return err + } + + return conf.DB.Close() + }, + } + + cmd.PersistentFlags().StringVarP(&attr.File, "file", "r", "", "Filename or - for STDIN") + cmd.PersistentFlags().StringArrayVarP(&attr.Tags, "tags", "t", nil, "tags, multiple allowed") + + return cmd +} + +func Get(conf *cfg.Config) *cobra.Command { + return nil +} + +func Del(conf *cfg.Config) *cobra.Command { + return nil +} + +func List(conf *cfg.Config) *cobra.Command { + return nil +} + +func Find(conf *cfg.Config) *cobra.Command { + return nil +} + +func Help(conf *cfg.Config) *cobra.Command { + return nil +} + +func Man(conf *cfg.Config) *cobra.Command { + return nil +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..e284047 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,86 @@ +package cmd + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + "github.com/tlinden/anydb/app" + "github.com/tlinden/anydb/cfg" +) + +func completion(cmd *cobra.Command, mode string) error { + switch mode { + case "bash": + return cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + return cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + return cmd.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) + default: + return errors.New("Invalid shell parameter! Valid ones: bash|zsh|fish|powershell") + } +} + +func Execute() { + var ( + conf cfg.Config + ShowVersion bool + ShowCompletion string + ) + + var rootCmd = &cobra.Command{ + Use: "anydb [options]", + Short: "anydb", + Long: `A personal key value store`, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + db, err := app.New(conf.Dbfile, conf.Debug) + if err != nil { + return err + } + + conf.DB = db + + return nil + }, + + RunE: func(cmd *cobra.Command, args []string) error { + if ShowVersion { + fmt.Println(cfg.Version) + return nil + } + + if len(ShowCompletion) > 0 { + return completion(cmd, ShowCompletion) + } + + if len(args) == 0 { + return errors.New("No command specified!") + } + + return nil + }, + } + + // options + rootCmd.PersistentFlags().BoolVarP(&ShowVersion, "version", "v", false, "Print program version") + rootCmd.PersistentFlags().BoolVarP(&conf.Debug, "debug", "d", false, "Enable debugging") + rootCmd.PersistentFlags().StringVarP(&conf.Dbfile, "dbfile", "f", filepath.Join(os.Getenv("HOME"), ".config", "anydb", "default.db"), "DB file to use") + + rootCmd.AddCommand(Set(&conf)) + // rootCmd.AddCommand(Set(&conf)) + // rootCmd.AddCommand(Del(&conf)) + // rootCmd.AddCommand(List(&conf)) + // rootCmd.AddCommand(Find(&conf)) + // rootCmd.AddCommand(Help(&conf)) + // rootCmd.AddCommand(Man(&conf)) + + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8279fb3 --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +module github.com/tlinden/anydb + +go 1.22.1 + +require ( + github.com/alecthomas/repr v0.4.0 // indirect + github.com/asdine/storm/v3 v3.2.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.etcd.io/bbolt v1.3.11 // indirect + golang.org/x/sys v0.28.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ef56660 --- /dev/null +++ b/go.sum @@ -0,0 +1,41 @@ +github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac= +github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..2bea875 --- /dev/null +++ b/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/tlinden/anydb/cmd" +) + +func main() { + cmd.Execute() +}