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

Papercuts in context.go #354

Merged
merged 8 commits into from
Dec 18, 2021
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
54 changes: 54 additions & 0 deletions cli/internal/context/color_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package context

import (
"sync"

"github.com/fatih/color"
)

type colorFn = func(format string, a ...interface{}) string

func getTerminalPackageColors() []colorFn {
return []colorFn{color.CyanString, color.MagentaString, color.GreenString, color.YellowString, color.BlueString}
}

type ColorCache struct {
mu sync.Mutex
index int
TermColors []colorFn
Cache map[interface{}]colorFn
}

func NewColorCache() *ColorCache {
return &ColorCache{
TermColors: getTerminalPackageColors(),
index: 0,
Cache: make(map[interface{}]colorFn),
}
}

// PrefixColor returns a color function for a given package name
func (c *ColorCache) PrefixColor(name string) colorFn {
c.mu.Lock()
defer c.mu.Unlock()
colorFn, ok := c.Cache[name]
if ok {
return colorFn
}
c.index++
colorFn = c.TermColors[positiveMod(c.index, 5)] // 5 possible colors
c.Cache[name] = colorFn
return colorFn
}

// postitiveMod returns a modulo operator like JavaScripts
func positiveMod(x, d int) int {
x = x % d
if x >= 0 {
return x
}
if d < 0 {
return x - d
}
return x + d
}
76 changes: 24 additions & 52 deletions cli/internal/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"turbo/internal/util"

mapset "github.com/deckarep/golang-set"
"github.com/fatih/color"
"github.com/google/chrometracing"
"github.com/pyr-sh/dag"
gitignore "github.com/sabhiram/go-gitignore"
Expand All @@ -35,19 +34,6 @@ const (
Pnpm
)

type colorFn = func(format string, a ...interface{}) string

var (
childProcessIndex = 0
terminalPackageColors = [5]colorFn{color.CyanString, color.MagentaString, color.GreenString, color.YellowString, color.BlueString}
)

type ColorCache struct {
sync.Mutex
index int
Cache map[interface{}]colorFn
}

// Context of the CLI
type Context struct {
Args []string
Expand Down Expand Up @@ -86,20 +72,6 @@ func New(opts ...Option) (*Context, error) {
return &m, nil
}

// PrefixColor returns a color function for a given package name
func PrefixColor(c *Context, name *string) colorFn {
c.ColorCache.Lock()
defer c.ColorCache.Unlock()
colorFn, ok := c.ColorCache.Cache[name]
if ok {
return colorFn
}
c.ColorCache.index++
colorFn = terminalPackageColors[util.PositiveMod(c.ColorCache.index, len(terminalPackageColors))]
c.ColorCache.Cache[name] = colorFn
return colorFn
}

// WithDir specifies the directory where turbo is initiated
func WithDir(d string) Option {
return func(m *Context) error {
Expand Down Expand Up @@ -141,10 +113,7 @@ func WithTracer(filename string) Option {
func WithGraph(rootpath string, config *config.Config) Option {
return func(c *Context) error {
c.PackageInfos = make(map[interface{}]*fs.PackageJSON)
c.ColorCache = &ColorCache{
Cache: make(map[interface{}]colorFn),
index: 0,
}
c.ColorCache = NewColorCache()
c.RootNode = ROOT_NODE_NAME
c.PendingTaskNodes = make(dag.Set)
// Need to ALWAYS have a root node, might as well do it now
Expand Down Expand Up @@ -219,18 +188,12 @@ func WithGraph(rootpath string, config *config.Config) Option {
// until all parsing is complete
// and populate the graph
parseJSONWaitGroup := new(errgroup.Group)
justJsons := make([]string, len(spaces))
for i, space := range spaces {
justJsons[i] = path.Join(space, "package.json")
}
ignore := []string{
"**/node_modules/**/*",
"**/bower_components/**/*",
"**/test/**/*",
"**/tests/**/*",
justJsons := make([]string, 0, len(spaces))
for _, space := range spaces {
justJsons = append(justJsons, path.Join(space, "package.json"))
}

f := globby.GlobFiles(rootpath, justJsons, ignore)
f := globby.GlobFiles(rootpath, justJsons, getWorkspaceIgnores())

for i, val := range f {
_, val := i, val // https://golang.org/doc/faq#closures_and_goroutines
Expand Down Expand Up @@ -337,9 +300,9 @@ func (c *Context) ResolveWorkspaceRootDeps() (*fs.PackageJSON, error) {
pkg.SubLockfile = make(fs.YarnLockfile)
c.ResolveDepGraph(&lockfileWg, pkg.UnresolvedExternalDeps, depSet, seen, pkg)
lockfileWg.Wait()
pkg.ExternalDeps = make([]string, depSet.Cardinality())
for i, v := range depSet.ToSlice() {
pkg.ExternalDeps[i] = v.(string)
pkg.ExternalDeps = make([]string, 0, depSet.Cardinality())
for v := range depSet.ToSlice() {
pkg.ExternalDeps = append(pkg.ExternalDeps, fmt.Sprintf("%v", v))
}
sort.Strings(pkg.ExternalDeps)
hashOfExternalDeps, err := fs.HashObject(pkg.ExternalDeps)
Expand Down Expand Up @@ -438,13 +401,13 @@ func (c *Context) populateTopologicGraphForPackageJson(pkg *fs.PackageJSON) erro
if internalDepsSet.Len() == 0 {
c.TopologicalGraph.Connect(dag.BasicEdge(pkg.Name, ROOT_NODE_NAME))
}
pkg.ExternalDeps = make([]string, externalDepSet.Cardinality())
for i, v := range externalDepSet.ToSlice() {
pkg.ExternalDeps[i] = v.(string)
pkg.ExternalDeps = make([]string, 0, externalDepSet.Cardinality())
for v := range externalDepSet.ToSlice() {
pkg.ExternalDeps = append(pkg.ExternalDeps, fmt.Sprintf("%v", v))
}
pkg.InternalDeps = make([]string, internalDepsSet.Len())
for i, v := range internalDepsSet.List() {
pkg.InternalDeps[i] = v.(string)
pkg.InternalDeps = make([]string, 0, internalDepsSet.Len())
for v := range internalDepsSet.List() {
pkg.ExternalDeps = append(pkg.InternalDeps, fmt.Sprintf("%v", v))
}
sort.Strings(pkg.InternalDeps)
sort.Strings(pkg.ExternalDeps)
Expand All @@ -464,7 +427,7 @@ func (c *Context) parsePackageJSON(buildFilePath string) error {
if fs.FileExists(buildFilePath) {
pkg, err := fs.ReadPackageJSON(buildFilePath)
if err != nil {
return fmt.Errorf("error parsing %v: %w", buildFilePath, err)
return fmt.Errorf("parsing %s: %w", buildFilePath, err)
}

// log.Printf("[TRACE] adding %+v to graph", pkg.Name)
Expand Down Expand Up @@ -517,3 +480,12 @@ func safeCompileIgnoreFile(filepath string) (*gitignore.GitIgnore, error) {
// no op
return gitignore.CompileIgnoreLines([]string{}...), nil
}

func getWorkspaceIgnores() []string {
return []string{
"**/node_modules/**/*",
"**/bower_components/**/*",
"**/test/**/*",
"**/tests/**/*",
}
}
4 changes: 2 additions & 2 deletions cli/internal/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ func (c *RunCommand) Run(args []string) int {
tracer := runState.Run(context.GetTaskId(pack.Name, task))

// Create a logger
pref := context.PrefixColor(ctx, &pack.Name)
actualPrefix := pref("%v:%v: ", pack.Name, task)
pref := ctx.ColorCache.PrefixColor(pack.Name)
actualPrefix := pref("%s:%s: ", pack.Name, task)
targetUi := &cli.PrefixedUi{
Ui: c.Ui,
OutputPrefix: actualPrefix,
Expand Down