diff --git a/cmd_run.go b/cmd_run.go index 88a814af8..d1a7efb06 100644 --- a/cmd_run.go +++ b/cmd_run.go @@ -15,18 +15,20 @@ import ( type runOptions struct { // pull - PullOpts pullOptions - NoPull bool + PullOpts pullOptions + NoPull bool + ReposToFetch []string // db DBOpts dbOptions // run - ShowClosed bool `mapstructure:"show-closed"` - ShowOrphans bool - EpicLabel string - Destination string - DebugGraph bool + ShowClosed bool `mapstructure:"show-closed"` + ShowOrphans bool + AdditionalPulls []string + EpicLabel string + Destination string + DebugGraph bool Targets []string //Preview bool @@ -44,6 +46,7 @@ func runSetupFlags(flags *pflag.FlagSet, opts *runOptions) { flags.BoolVarP(&opts.ShowOrphans, "show-orphans", "", false, "show issues not linked to an epic") flags.StringVarP(&opts.EpicLabel, "epic-label", "", "epic", "label used for epics (empty means issues with dependencies but without dependants)") flags.StringVarP(&opts.Destination, "destination", "", "-", "destination ('-' for stdout)") + flags.StringSliceVarP(&opts.AdditionalPulls, "additional-pull", "", []string{}, "additional pull that won't necessarily be displayed on the graph") //flags.BoolVarP(&opts.Preview, "preview", "p", false, "preview result") viper.BindPFlags(flags) } @@ -63,7 +66,7 @@ func newRunCommand() *cobra.Command { return err } opts.PullOpts.DBOpts = opts.DBOpts - opts.PullOpts.Targets = args + opts.PullOpts.Targets = append(args, opts.AdditionalPulls...) opts.Targets = args return run(opts) }, @@ -91,14 +94,13 @@ func run(opts *runOptions) error { return errors.Wrap(err, "failed to prepare issues") } - issues.processEpicLinks() if !opts.ShowClosed { issues.HideClosed() } - if !opts.ShowOrphans && issues.HasNonOrphans() { - issues.HideOrphans() + issues.filterByTargets(opts.Targets) + if opts.ShowOrphans { + logger().Warn("--show-orphans is deprecated and will be removed") } - issues.processEpicLinks() out, err := graphviz(issues, opts) diff --git a/graphviz.go b/graphviz.go index 7f552a5c5..bf4ea14af 100644 --- a/graphviz.go +++ b/graphviz.go @@ -6,10 +6,17 @@ import ( "sort" "github.com/awalterschulze/gographviz" + "go.uber.org/zap" ) func graphviz(issues Issues, opts *runOptions) (string, error) { var ( + stats = map[string]int{ + "nodes": 0, + "edges": 0, + "hidden": 0, + "subgraphs": 0, + } invisStyle = map[string]string{"style": "invis", "label": escape("")} weightMap = map[int]bool{} weights = []int{} @@ -19,6 +26,7 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { } for _, issue := range issues { if issue.Hidden { + stats["hidden"]++ continue } weightMap[issue.Weight()] = true @@ -83,11 +91,13 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { } panicIfErr(issue.AddNodeToGraph(g, parent)) + stats["nodes"]++ } // issue relationships for _, issue := range issues { panicIfErr(issue.AddEdgesToGraph(g)) + stats["edges"]++ } // orphans cluster and placeholder @@ -97,18 +107,21 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { "cluster_orphans_without_links", map[string]string{"label": escape("orphans without links"), "style": "dashed"}, )) + stats["subgraphs"]++ panicIfErr(g.AddSubGraph( "cluster_orphans_without_links", "cluster_orphans_without_links_0", invisStyle, )) + stats["subgraphs"]++ for i := 0; i < orphansCols; i++ { panicIfErr(g.AddNode( fmt.Sprintf("cluster_orphans_without_links_%d", i), fmt.Sprintf("placeholder_orphans_without_links_%d", i), invisStyle, )) + stats["nodes"]++ } panicIfErr(g.AddEdge( @@ -117,6 +130,7 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { true, invisStyle, )) + stats["edges"]++ for i := 1; i < orphansCols; i++ { panicIfErr(g.AddSubGraph( @@ -124,29 +138,38 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { fmt.Sprintf("cluster_orphans_without_links_%d", i), invisStyle, )) + stats["subgraphs"]++ panicIfErr(g.AddEdge( fmt.Sprintf("placeholder_orphans_without_links_%d", i-1), fmt.Sprintf("placeholder_orphans_without_links_%d", i), true, invisStyle, )) + stats["edges"]++ } } if hasOrphansWithLinks { panicIfErr(g.AddSubGraph("G", "cluster_orphans_with_links", map[string]string{"label": escape("orphans with links"), "style": "dashed"})) + stats["subgraphs"]++ + panicIfErr(g.AddNode("cluster_orphans_with_links", "placeholder_orphans_with_links", invisStyle)) + stats["nodes"]++ + panicIfErr(g.AddEdge( "placeholder_orphans_with_links", fmt.Sprintf("placeholder_%d", weights[0]), true, invisStyle, )) + stats["edges"]++ } // set weights clusters and placeholders for _, weight := range weights { clusterName := fmt.Sprintf("anon%d", weight) panicIfErr(g.AddSubGraph("G", clusterName, map[string]string{"rank": "same"})) + stats["subgraphs"]++ + //clusterName := fmt.Sprintf("cluster_w%d", weight) //panicIfErr(g.AddSubGraph("G", clusterName, map[string]string{"label": fmt.Sprintf("w%d", weight)})) panicIfErr(g.AddNode( @@ -157,6 +180,7 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { "label": fmt.Sprintf(`"weight=%d"`, weight), }, )) + stats["nodes"]++ } for i := 0; i < len(weights)-1; i++ { panicIfErr(g.AddEdge( @@ -165,7 +189,9 @@ func graphviz(issues Issues, opts *runOptions) (string, error) { true, invisStyle, )) + stats["edges"]++ } + logger().Debug("graph stats", zap.Any("stats", stats)) return g.String(), nil } diff --git a/issue.go b/issue.go index 75c18367a..d18acc98a 100644 --- a/issue.go +++ b/issue.go @@ -242,7 +242,7 @@ func (i Issue) NodeTitle() string { for _, err := range i.Errors { errors = append(errors, err.Error()) } - errorsText = fmt.Sprintf(`
%s |