func GetProjectStates(ctx *tool.Context, checkDirty bool) (map[string]*ProjectState, error) { projects, err := LocalProjects(ctx, FastScan) if err != nil { return nil, err } states := make(map[string]*ProjectState, len(projects)) sem := make(chan error, len(projects)) for name, project := range projects { state := &ProjectState{ Project: project, } states[name] = state // ctx is not threadsafe, so we make a clone for each goroutine. go setProjectState(ctx.Clone(tool.ContextOpts{}), state, checkDirty, sem) } for _ = range projects { err := <-sem if err != nil { return nil, err } } return states, nil }