Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: filters #663

Merged
merged 3 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/dvcore/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func Gen(h *cayley.Handle, args []string, opts GenOpts) error {

if !opts.NoGraph { // nolint:nestif
// load tasks
filters := dvstore.LoadTasksFilters{
filters := dvmodel.Filters{
Targets: targets,
WithClosed: opts.ShowClosed,
WithoutIsolated: opts.HideIsolated,
Expand Down
69 changes: 59 additions & 10 deletions pkg/dvcore/graphviz.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func GenGraphviz(h *cayley.Handle, args []string, opts GraphvizOpts) error {
return fmt.Errorf("parse targets: %w", err)
}

filters := dvstore.LoadTasksFilters{
filters := dvmodel.Filters{
Targets: targets,
WithClosed: opts.ShowClosed,
WithoutIsolated: opts.HideIsolated,
Expand All @@ -49,10 +49,10 @@ func GenGraphviz(h *cayley.Handle, args []string, opts GraphvizOpts) error {

roadmap := make(map[string]dvmodel.Task)
for _, t := range tasks {
if t.Kind != 1 {
continue
// TODO: handle more once implemented
if t.Kind == dvmodel.Task_Issue || t.Kind == dvmodel.Task_MergeRequest {
roadmap[fmtIRI(t.ID)] = t
}
roadmap[fmtIRI(t.ID)] = t
}

g := graphviz.New()
Expand Down Expand Up @@ -89,21 +89,70 @@ func GenGraphviz(h *cayley.Handle, args []string, opts GraphvizOpts) error {
}

for _, task := range roadmap {
for _, dependingID := range task.IsDependingOn {
depending, ok := roadmap[fmtIRI(dependingID)]
if !ok {
continue
}
name := depending.ID + task.ID
edge, err := graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(depending.ID)], nodes[fmtIRI(task.ID)])
if err != nil {
return fmt.Errorf("create depending edge: %w", err)
}
_ = edge
}
for _, dependentID := range task.IsBlocking {
dependent := roadmap[fmtIRI(dependentID)]
dependent, ok := roadmap[fmtIRI(dependentID)]
if !ok {
continue
}
name := task.ID + dependent.ID
edge, err := graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(task.ID)], nodes[fmtIRI(dependent.ID)])
if err != nil {
return fmt.Errorf("create dependent edge: %w", err)
}
_ = edge
}
for _, dependingID := range task.IsDependingOn {
depending := roadmap[fmtIRI(dependingID)]
name := depending.ID + task.ID
edge, err := graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(depending.ID)], nodes[fmtIRI(task.ID)])
for _, relatedID := range task.IsRelatedWith {
related, ok := roadmap[fmtIRI(relatedID)]
if !ok {
continue
}
name := task.ID + related.ID
edge, err := graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(task.ID)], nodes[fmtIRI(related.ID)])
if err != nil {
return fmt.Errorf("create depending edge: %w", err)
return fmt.Errorf("create related edge: %w", err)
}

name = related.ID + task.ID
edge, err = graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(related.ID)], nodes[fmtIRI(task.ID)])
if err != nil {
return fmt.Errorf("create related edge: %w", err)
}
_ = edge
}
// TODO: define best relationship for both following
for _, partID := range task.IsPartOf {
part, ok := roadmap[fmtIRI(partID)]
if !ok {
continue
}
name := task.ID + part.ID
edge, err := graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(task.ID)], nodes[fmtIRI(part.ID)])
if err != nil {
return fmt.Errorf("create dependent edge: %w", err)
}
_ = edge
}
for _, partID := range task.HasPart {
part, ok := roadmap[fmtIRI(partID)]
if !ok {
continue
}
name := part.ID + task.ID
edge, err := graph.CreateEdge(fmtIRI(name), nodes[fmtIRI(part.ID)], nodes[fmtIRI(task.ID)])
if err != nil {
return fmt.Errorf("create dependent edge: %w", err)
}
_ = edge
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/dvmodel/filters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dvmodel

import (
"moul.io/depviz/v3/pkg/multipmuri"
)

type Filters struct {
Targets []multipmuri.Entity
TheWorld bool
WithClosed bool
WithoutIsolated bool
WithoutPRs bool
WithoutExternalDeps bool
WithFetch bool
}
41 changes: 40 additions & 1 deletion pkg/dvmodel/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,48 @@ func (t *Task) AllDeps() []quad.IRI {
return allDeps
}

func FilterIsolatedTasks(in []Task, logger *zap.Logger) []Task {
func FilterIsolatedTasks(in []Task, logger *zap.Logger, filters Filters) []Task {
tasks := map[quad.IRI]Task{}
uniqueDeps := map[quad.IRI]*Task{}

for _, task := range in {
tasks[task.ID] = task
}

for _, task := range in {
for _, dep := range task.IsDependingOn {
if isFiltered(tasks[dep], filters) {
continue
}
uniqueDeps[task.ID] = nil
uniqueDeps[dep] = nil
}
for _, dep := range task.IsBlocking {
if isFiltered(tasks[dep], filters) {
continue
}
uniqueDeps[task.ID] = nil
uniqueDeps[dep] = nil
}
for _, dep := range task.IsRelatedWith {
if isFiltered(tasks[dep], filters) {
continue
}
uniqueDeps[task.ID] = nil
uniqueDeps[dep] = nil
}
for _, dep := range task.IsPartOf {
if isFiltered(tasks[dep], filters) {
continue
}
uniqueDeps[task.ID] = nil
uniqueDeps[dep] = nil
}
for _, dep := range task.HasPart {
if isFiltered(tasks[dep], filters) {
continue
}
uniqueDeps[task.ID] = nil
uniqueDeps[dep] = nil
}
}
Expand All @@ -63,6 +88,20 @@ func FilterIsolatedTasks(in []Task, logger *zap.Logger) []Task {
return out
}

func isFiltered(task Task, filters Filters) bool {
if filters.WithoutPRs && task.Kind == Task_MergeRequest {
return true
}
// TODO: catch external deps
//if filters.WithoutExternalDeps && task. {
// return true
//}
if !filters.WithClosed && task.State == Task_Closed {
return true
}
return false
}

func (t *Task) MarshalCSV() []string {
if t == nil {
return nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/dvserver/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func (s *service) Graph(ctx context.Context, in *Graph_Input) (*Graph_Output, er
return nil, fmt.Errorf("targets is required")
}

filters := dvstore.LoadTasksFilters{
filters := dvmodel.Filters{
WithClosed: in.WithClosed,
WithoutIsolated: in.WithoutIsolated,
WithoutPRs: in.WithoutPRs,
Expand Down
18 changes: 5 additions & 13 deletions pkg/dvstore/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,7 @@ func LastUpdatedIssueInRepo(ctx context.Context, h *cayley.Handle, entity multip
return since, nil
}

type LoadTasksFilters struct {
Targets []multipmuri.Entity
TheWorld bool
WithClosed bool
WithoutIsolated bool
WithoutPRs bool
WithoutExternalDeps bool
WithFetch bool
}

func LoadTasks(h *cayley.Handle, schema *schema.Config, filters LoadTasksFilters, logger *zap.Logger) (dvmodel.Tasks, error) {
func LoadTasks(h *cayley.Handle, schema *schema.Config, filters dvmodel.Filters, logger *zap.Logger) (dvmodel.Tasks, error) {
if (filters.Targets == nil || len(filters.Targets) == 0) && !filters.TheWorld {
return nil, fmt.Errorf("missing filter.targets")
}
Expand Down Expand Up @@ -101,6 +91,8 @@ func LoadTasks(h *cayley.Handle, schema *schema.Config, filters LoadTasksFilters
kinds = append(kinds, quad.Int(dvmodel.Task_MergeRequest))
}
p = p.Has(quad.IRI("schema:kind"), kinds...)

// TODO: fix this, seems to be break some rare times on MRs
if !filters.WithClosed {
p = p.Has(quad.IRI("schema:state"), quad.Int(dvmodel.Task_Open))
}
Expand All @@ -116,14 +108,14 @@ func LoadTasks(h *cayley.Handle, schema *schema.Config, filters LoadTasksFilters
}

tasks := dvmodel.Tasks{}
p = p.Limit(300) // nolint:gomnd
p = p.Limit(3000) // nolint:gomnd
err := schema.LoadPathTo(ctx, h, &tasks, p)
if err != nil {
return nil, fmt.Errorf("load tasks: %w", err)
}

if filters.WithoutIsolated {
tasks = dvmodel.FilterIsolatedTasks(tasks, logger)
tasks = dvmodel.FilterIsolatedTasks(tasks, logger, filters)
}

{ // remove duplicates
Expand Down
1 change: 1 addition & 0 deletions pkg/githubprovider/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func fromIssue(batch *dvmodel.Batch, input *github.Issue) error {
relationships, errs := pmbodyparser.RelParseString(entity, issue.Description)
if len(errs) > 0 {
for _, err := range errs {
batch.Tasks = append(batch.Tasks, &issue)
return fmt.Errorf("pmbodyparser error: %w", err)
}
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/multipmuri/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,9 @@ func gitHubRelDecodeString(hostname, owner, repo, input string, force bool) (Ent
return NewGitHubIssueOrPullRequest(hostname, owner, repo, u.Fragment), nil
}
if u.Path == "" && u.Fragment == "" {
return NewGitHubService(hostname), nil
//return NewGitHubService(hostname), nil
// TODO: replace by real handling of service once defined
return nil, fmt.Errorf("failed to parse %q", input)
}
if u.Path != "" && u.Fragment != "" { // user/repo#42
u.Path += "/issue-or-pull-request/" + u.Fragment
Expand Down