From a07ed70028b488ade8542d95941feff2a8058f04 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Sun, 23 Sep 2018 00:20:30 +0200 Subject: [PATCH] feat: use SQL for database --- cmd_db.go | 38 +++++++++++++------------------------- cmd_pull.go | 10 ++++++---- cmd_run.go | 9 ++++++--- go.mod | 15 +++++++++++++++ go.sum | 32 ++++++++++++++++++++++++++++++++ issue.go | 46 +++++++++++++++++++--------------------------- main.go | 27 +++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 59 deletions(-) diff --git a/cmd_db.go b/cmd_db.go index 7c91728e0..6d9d6b814 100644 --- a/cmd_db.go +++ b/cmd_db.go @@ -3,18 +3,17 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" - "os" + "github.com/jinzhu/gorm" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" - "go.uber.org/zap" ) type dbOptions struct { - Path string `mapstructure:"db-path"` + Path string `mapstructure:"dbpath"` + Verbose bool } func (opts dbOptions) String() string { @@ -23,7 +22,7 @@ func (opts dbOptions) String() string { } func dbSetupFlags(flags *pflag.FlagSet, opts *dbOptions) { - flags.StringVarP(&opts.Path, "db-path", "", "./depviz.db", "depviz database path") + viper.BindPFlags(flags) } @@ -51,10 +50,9 @@ func newDBDumpCommand() *cobra.Command { } func dbDump(opts *dbOptions) error { - logger().Debug("dbDump", zap.Stringer("opts", *opts)) - issues, err := dbLoad(opts) - if err != nil { - return err + var issues IssueSlice + if err := db.Find(&issues).Error; err != nil { + return errors.Wrap(err, "failed to load issues") } out, err := json.MarshalIndent(issues, "", " ") if err != nil { @@ -64,21 +62,11 @@ func dbDump(opts *dbOptions) error { return nil } -func dbExists(opts *dbOptions) bool { - logger().Debug("dbExists", zap.Stringer("opts", *opts)) - _, err := os.Stat(opts.Path) - return err == nil -} - -func dbLoad(opts *dbOptions) (Issues, error) { - logger().Debug("dbLoad", zap.Stringer("opts", *opts)) - var issues IssueSlice - content, err := ioutil.ReadFile(opts.Path) - if err != nil { - return nil, errors.Wrap(err, "failed to open db file") - } - if err := json.Unmarshal(content, &issues); err != nil { - return nil, errors.Wrap(err, "failed to parse db file") +func loadIssues(db *gorm.DB) (Issues, error) { + var issues []*Issue + if err := db.Find(&issues).Error; err != nil { + return nil, err } - return issues.ToMap(), nil + slice := IssueSlice(issues) + return slice.ToMap(), nil } diff --git a/cmd_pull.go b/cmd_pull.go index 33e6816d9..bcc14cd14 100644 --- a/cmd_pull.go +++ b/cmd_pull.go @@ -4,12 +4,10 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "log" "sync" "github.com/google/go-github/github" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" @@ -160,6 +158,10 @@ func pull(opts *pullOptions) error { allIssues = append(allIssues, issues...) } - issuesJson, _ := json.MarshalIndent(allIssues, "", " ") - return errors.Wrap(ioutil.WriteFile(opts.DBOpts.Path, issuesJson, 0644), "failed to write db") + for _, issue := range allIssues { + if err := db.Save(issue).Error; err != nil { + return err + } + } + return nil } diff --git a/cmd_run.go b/cmd_run.go index d1a7efb06..d7cb09da5 100644 --- a/cmd_run.go +++ b/cmd_run.go @@ -79,18 +79,18 @@ func newRunCommand() *cobra.Command { func run(opts *runOptions) error { logger().Debug("run", zap.Stringer("opts", *opts)) - if !opts.NoPull || !dbExists(&opts.DBOpts) { + if !opts.NoPull { if err := pull(&opts.PullOpts); err != nil { return err } } - issues, err := dbLoad(&opts.DBOpts) + issues, err := loadIssues(db) if err != nil { return errors.Wrap(err, "failed to load issues") } - if err = issues.prepare(); err != nil { + if err := issues.prepare(); err != nil { return errors.Wrap(err, "failed to prepare issues") } @@ -103,6 +103,9 @@ func run(opts *runOptions) error { } out, err := graphviz(issues, opts) + if err != nil { + return err + } var dest io.WriteCloser switch opts.Destination { diff --git a/go.mod b/go.mod index 26227cd7a..65fc17e8b 100644 --- a/go.mod +++ b/go.mod @@ -1,30 +1,45 @@ module moul.io/depviz require ( + cloud.google.com/go v0.28.0 // indirect + github.com/BurntSushi/toml v0.3.1 // indirect github.com/awalterschulze/gographviz v0.0.0-20180813113015-16ed621cdb51 + github.com/denisenkom/go-mssqldb v0.0.0-20180901172138-1eb28afdf9b6 // indirect + github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect github.com/fsnotify/fsnotify v1.4.7 // indirect github.com/gilliek/go-opml v1.0.0 + github.com/go-sql-driver/mysql v1.4.0 // indirect github.com/golang/protobuf v1.2.0 // indirect + github.com/google/go-cmp v0.2.0 // indirect github.com/google/go-github v17.0.0+incompatible github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jinzhu/gorm v1.9.1 + github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect + github.com/jinzhu/now v0.0.0-20180511015916-ed742868f2ae // indirect + github.com/lib/pq v1.0.0 // indirect github.com/magiconair/properties v1.8.0 // indirect + github.com/mattn/go-sqlite3 v1.9.0 github.com/mitchellh/mapstructure v1.0.0 // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/pkg/errors v0.8.0 + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/afero v1.1.1 // indirect github.com/spf13/cast v1.2.0 // indirect github.com/spf13/cobra v0.0.3 github.com/spf13/jwalterweatherman v0.0.0-20180814060501-14d3d4c51834 // indirect github.com/spf13/pflag v1.0.2 github.com/spf13/viper v1.1.0 + github.com/stretchr/testify v1.2.2 // indirect github.com/xanzy/go-gitlab v0.11.0 go.uber.org/atomic v1.3.2 // indirect go.uber.org/multierr v1.1.0 // indirect go.uber.org/zap v1.9.1 + golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b // indirect golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be + golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 // indirect golang.org/x/text v0.3.0 // indirect google.golang.org/appengine v1.1.0 // indirect diff --git a/go.sum b/go.sum index 6613cc49c..8a4ec56a4 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,25 @@ +cloud.google.com/go v0.28.0 h1:KZ/88LWSw8NxMkjdQyX7LQSGR9PkHr4PaVuNm8zgFq0= +cloud.google.com/go v0.28.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/awalterschulze/gographviz v0.0.0-20180813113015-16ed621cdb51 h1:XeDlTdy8+US+DB/2v+wIous/nbb0xT4pBm0D+oPXlMM= github.com/awalterschulze/gographviz v0.0.0-20180813113015-16ed621cdb51/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= +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/denisenkom/go-mssqldb v0.0.0-20180901172138-1eb28afdf9b6 h1:BZGp1dbKFjqlGmxEpwkDpCWNxVwEYnUPoncIzLiHlPo= +github.com/denisenkom/go-mssqldb v0.0.0-20180901172138-1eb28afdf9b6/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gilliek/go-opml v1.0.0 h1:X8xVjtySRXU/x6KvaiXkn7OV3a4DHqxY8Rpv6U/JvCY= github.com/gilliek/go-opml v1.0.0/go.mod h1:fOxmtlzyBvUjU6bjpdjyxCGlWz+pgtAHrHf/xRZl3lk= +github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= @@ -15,14 +28,26 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jinzhu/gorm v1.9.1 h1:lDSDtsCt5AGGSKTs8AHlSDbbgif4G4+CKJ8ETBDVHTA= +github.com/jinzhu/gorm v1.9.1/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= +github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a h1:eeaG9XMUvRBYXJi4pg1ZKM7nxc5AfXfojeLLW7O5J3k= +github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v0.0.0-20180511015916-ed742868f2ae h1:8bBMcboXYVuo0WYH+rPe5mB8obO89a993hdTZ3phTjc= +github.com/jinzhu/now v0.0.0-20180511015916-ed742868f2ae/go.mod h1:oHTiXerJ20+SfYcrdlBO7rzZRJWGwSTQ0iUY2jI6Gfc= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mitchellh/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KHeTRY+7I= github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/spf13/afero v1.1.1 h1:Lt3ihYMlE+lreX1GS4Qw4ZsNpYQLxIXKBTEOXm3nt6I= github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg= @@ -35,6 +60,8 @@ github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.1.0 h1:V7OZpY8i3C1x/pDmU0zNNlfVoDz112fSYvtWMjjS3f4= github.com/spf13/viper v1.1.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/xanzy/go-gitlab v0.11.0 h1:H9exAT9A+VQSkDnoJPxMhC4uJip8kQ8edlVC28gFuOI= github.com/xanzy/go-gitlab v0.11.0/go.mod h1:CRKHkvFWNU6C3AEfqLWjnCNnAs4nj8Zk95rX2S3X6Mw= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= @@ -43,16 +70,21 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b h1:2b9XGzhjiYsYPnKXoEfL7klWZQIt8IfyRCz62gCqqlQ= +golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 h1:T8D7l6WB3tLu+VpKvw06ieD/OhBi1XpJmG1U/FtttZg= golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +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.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/issue.go b/issue.go index b7b730923..697296d0f 100644 --- a/issue.go +++ b/issue.go @@ -28,20 +28,20 @@ const ( type Issue struct { // proxy - GitHub *github.Issue - GitLab *gitlab.Issue + GitHub *github.Issue `json:"-" gorm:"-"` + GitLab *gitlab.Issue `json:"-" gorm:"-"` // internal Provider Provider - DependsOn IssueSlice `json:"-"` - Blocks IssueSlice `json:"-"` - weightMultiplier int `json:"-"` - BaseWeight int `json:"-"` - IsOrphan bool `json:"-"` - Hidden bool `json:"-"` - Duplicates []string `json:"-"` - LinkedWithEpic bool `json:"-"` - Errors []error `json:"-"` + DependsOn IssueSlice `json:"-" gorm:"-"` + Blocks IssueSlice `json:"-" gorm:"-"` + weightMultiplier int `gorm:"-"` + BaseWeight int `json:"-" gorm:"-"` + IsOrphan bool `json:"-" gorm:"-"` + Hidden bool `json:"-" gorm:"-"` + Duplicates []string `json:"-" gorm:"-"` + LinkedWithEpic bool `json:"-" gorm:"-"` + Errors []error `json:"-" gorm:"-"` // mapping Number int @@ -49,19 +49,20 @@ type Issue struct { State string Body string RepoURL string - URL string - Labels []*IssueLabel - Assignees []*Profile + URL string `gorm:"primary_key"` + Labels []*IssueLabel `gorm:"many2many:issue_labels;"` + Assignees []*Profile `gorm:"many2many:issue_assignees;"` + IsPR bool } type IssueLabel struct { - Name string + Name string `gorm:"primary_key"` Color string } type Profile struct { Name string - Username string + Username string `gorm:"primary_key"` } func FromGitHubIssue(input *github.Issue) *Issue { @@ -77,6 +78,7 @@ func FromGitHubIssue(input *github.Issue) *Issue { Title: *input.Title, State: *input.State, Body: body, + IsPR: input.PullRequestLinks != nil, URL: strings.Replace(*input.HTMLURL, "/pull/", "/issues/", -1), RepoURL: strings.Join(parts[0:len(parts)-2], "/"), Labels: make([]*IssueLabel, 0), @@ -450,7 +452,7 @@ func (issues Issues) prepare() error { if len(issue.Duplicates) > 0 { issue.Hidden = true } - if issue.IsPR() { + if issue.IsPR { issue.Hidden = true } } @@ -458,16 +460,6 @@ func (issues Issues) prepare() error { return nil } -func (i Issue) IsPR() bool { - switch i.Provider { - case GitHubProvider: - return i.GitHub.PullRequestLinks != nil - case GitLabProvider: - return false // only fetching issues for now - } - panic("should not happen") -} - func (issues Issues) processEpicLinks() { for _, issue := range issues { issue.LinkedWithEpic = !issue.Hidden && (issue.IsEpic() || issue.BlocksAnEpic() || issue.DependsOnAnEpic()) diff --git a/main.go b/main.go index efe49326e..cb581187e 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,8 @@ import ( "os" "strings" + "github.com/jinzhu/gorm" + _ "github.com/mattn/go-sqlite3" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -24,6 +26,8 @@ func main() { var ( verbose bool cfgFile string + dbPath string + db *gorm.DB ) func newRootCommand() *cobra.Command { @@ -33,6 +37,8 @@ func newRootCommand() *cobra.Command { cmd.PersistentFlags().BoolP("help", "h", false, "print usage") cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode") cmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is ./.depviz.yml)") + cmd.PersistentFlags().StringVarP(&dbPath, "db-path", "", "$HOME/.depviz.db", "database path") + cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { // configure zap config := zap.NewDevelopmentConfig() @@ -61,6 +67,27 @@ func newRootCommand() *cobra.Command { return errors.Wrap(err, "cannot read config") } } + + // configure sql + dbPath = os.ExpandEnv(dbPath) + db, err = gorm.Open("sqlite3", dbPath) + if err != nil { + return err + } + db = db.Set("gorm:auto_preload", true) + db = db.Set("gorm:association_autoupdate", true) + db.BlockGlobalUpdate(true) + db.SingularTable(true) + db.LogMode(verbose) + if err := db.AutoMigrate( + Issue{}, + IssueLabel{}, + Profile{}, + ).Error; err != nil { + return err + } + fmt.Println(dbPath, db) + return nil } cmd.AddCommand(