stamm/dep_radar

View on GitHub
deps/detect.go

Summary

Maintainability
A
35 mins
Test Coverage
package deps

import (
    "context"
    "errors"
    "strings"
    "sync"

    "github.com/stamm/dep_radar"
    "github.com/stamm/dep_radar/deps/dep"
    "github.com/stamm/dep_radar/deps/glide"
)

var (
    _ dep_radar.IDepDetector = &Detector{}
)

// Detector for deps
type Detector struct {
    Tools []dep_radar.IDepTool
}

// AddTool adds dep tool
func (d *Detector) AddTool(tool dep_radar.IDepTool) dep_radar.IDepDetector {
    d.Tools = append(d.Tools, tool)
    return d
}

// Deps returns deps for app
func (d *Detector) Deps(ctx context.Context, app dep_radar.IApp) (dep_radar.AppDeps, error) {
    var (
        errs []string
        wg   sync.WaitGroup
        mx   sync.Mutex
    )

    depResult := make(chan dep_radar.AppDeps, len(d.Tools))
    done := make(chan struct{}, 1)
    wg.Add(len(d.Tools))

    ctx, cancel := context.WithCancel(ctx)
    defer cancel()
    for _, tool := range d.Tools {
        go func(tool dep_radar.IDepTool) {
            defer wg.Done()
            deps, err := tool.Deps(ctx, app)
            if err == nil {
                depResult <- deps
                return
                // return deps, nil
            }
            mx.Lock()
            errs = append(errs, err.Error())
            mx.Unlock()
        }(tool)
    }

    go func() {
        wg.Wait()
        done <- struct{}{}
    }()

    select {
    case <-ctx.Done():
        return dep_radar.AppDeps{}, ctx.Err()
    // TODO: check that done will be called later that result
    case result := <-depResult:
        cancel()
        return result, nil
    case <-done:
    }

    if len(errs) > 0 {
        str := strings.Join(errs, "; ")
        return dep_radar.AppDeps{}, errors.New(str)
    }
    return dep_radar.AppDeps{}, errors.New("Bad")
}

// NewDetector returns empty detector
func NewDetector() *Detector {
    return &Detector{}
}

// DefaultDetector returns detector with all dependency systems
func DefaultDetector() *Detector {
    detector := &Detector{}
    detector.AddTool(dep.New())
    detector.AddTool(glide.New())
    return detector
}