func (proj *Project) loadRepoDeps(download bool) error {
	seen := map[string]struct{}{}
	loadDeps := func(r *repo.Repo) ([]*repo.Repo, error) {
		var newRepos []*repo.Repo
		depMap := r.CommitDepMap()
		for _, depSlice := range depMap {
			for _, dep := range depSlice {
				if _, ok := seen[dep.Name]; !ok {
					seen[r.Name()] = struct{}{}
					depRepo := proj.repos[dep.Name]
					if depRepo == nil {
						var err error
						depRepo, err = proj.loadRepo(dep.Name, dep.Fields)
						if err != nil {
							if !util.IsNotExist(err) {
								return nil, err
							}
						}
						if err := proj.addRepo(depRepo, download); err != nil {
							return nil, err
						}
					}
					newRepos = append(newRepos, depRepo)
					if download {
						if _, err := depRepo.UpdateDesc(); err != nil {
							return nil, err
						}
					}
				}
			}
		}
		return newRepos, nil
	}
	curRepos := proj.repos.Sorted()
	for len(curRepos) > 0 {
		var nextRepos []*repo.Repo
		for _, r := range curRepos {
			depRepos, err := loadDeps(r)
			if err != nil {
				return err
			}
			nextRepos = append(nextRepos, depRepos...)
		}
		curRepos = nextRepos
	}
	return nil
}
Loads the `repository.yml` file for each depended-on repo.  This
package project
import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
	log "github.com/sirupsen/logrus"
	"mynewt.apache.org/newt/newt/compat"
	"mynewt.apache.org/newt/newt/config"
	"mynewt.apache.org/newt/newt/deprepo"
	"mynewt.apache.org/newt/newt/downloader"
	"mynewt.apache.org/newt/newt/install"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/newtutil"
	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/repo"
	"mynewt.apache.org/newt/newt/ycfg"
	"mynewt.apache.org/newt/util"
)
var globalProject *Project = nil
const PROJECT_FILE_NAME = "project.yml"
var ignoreSearchDirs []string = []string{
	"bin",
	"repos",
}
type Project struct {
	name string
	BasePath string
	packages interfaces.PackageList
	repos deprepo.RepoMap
	localRepo *repo.Repo
	rootRepoReqs deprepo.RequirementMap
	warnings []string
	unknownRepoVers map[string]struct{}
	yc ycfg.YCfg
}
func initProject(dir string, download bool) error {
	var err error
	globalProject, err = LoadProject(dir, download)
	if err != nil {
		return err
	}
	if err := globalProject.loadPackageList(); err != nil {
		return err
	}
	return nil
}
func initialize(download bool) error {
	if globalProject == nil {
		wd, err := os.Getwd()
		wd = filepath.ToSlash(wd)
		if err != nil {
			return util.NewNewtError(err.Error())
		}
		if err := initProject(wd, download); err != nil {
			return err
		}
	}
	return nil
}
func TryGetProject() (*Project, error) {
	if err := initialize(false); err != nil {
		return nil, err
	}
	return globalProject, nil
}
func TryGetOrDownloadProject() (*Project, error) {
	if err := initialize(true); err != nil {
		return nil, err
	}
	return globalProject, nil
}
func GetProject() *Project {
	if _, err := TryGetProject(); err != nil {
		panic(err.Error())
	}
	return globalProject
}
func ResetProject() {
	globalProject = nil
}
func ResetDeps(newList interfaces.PackageList) interfaces.PackageList {
	return nil
	if globalProject == nil {
		return nil
	}
	oldList := globalProject.packages
	globalProject.packages = newList
	if newList == nil {
		globalProject.loadPackageList()
	}
	return oldList
}
func NewProject(dir string, download bool) (*Project, error) {
	proj := &Project{}
	if err := proj.Init(dir, download); err != nil {
		return nil, err
	}
	return proj, nil
}
func (proj *Project) Path() string {
	return proj.BasePath
}
func (proj *Project) Name() string {
	return proj.name
}
func (proj *Project) Repos() map[string]*repo.Repo {
	return proj.repos
}
func (proj *Project) FindRepo(rname string) *repo.Repo {
	if rname == repo.REPO_NAME_LOCAL {
		return proj.LocalRepo()
	} else {
		r, _ := proj.repos[rname]
		return r
	}
}
func (proj *Project) FindRepoPath(rname string) string {
	r := proj.FindRepo(rname)
	if r == nil {
		return ""
	}
	return r.Path()
}
func (proj *Project) GetRepoVersion(
	rname string) (*newtutil.RepoVersion, error) {
	r := proj.repos[rname]
	if r == nil {
		return nil, nil
	}
	ver, err := r.InstalledVersion()
	if err != nil {
		return nil, err
	}
	if ver == nil {
		commit, err := r.CurrentHash()
		if err != nil {
			return nil, err
		}
		if proj.unknownRepoVers == nil {
			proj.unknownRepoVers = map[string]struct{}{}
		}
		if _, ok := proj.unknownRepoVers[rname]; !ok {
			proj.unknownRepoVers[rname] = struct{}{}
		}
		ver = &newtutil.RepoVersion{
			Commit: commit,
		}
	}
	return ver, nil
}
func (proj *Project) RepoIsInstalled(rname string) bool {
	ver, err := proj.GetRepoVersion(rname)
	return err == nil && ver != nil
}
func (proj *Project) RepoIsRoot(rname string) bool {
	_, ok := proj.rootRepoReqs[rname]
	return ok == true
}
func (proj *Project) LocalRepo() *repo.Repo {
	return proj.localRepo
}
func (proj *Project) Warnings() []string {
	return proj.warnings
}
func (proj *Project) SelectRepos(pred func(r *repo.Repo) bool) []*repo.Repo {
	all := proj.repos.Sorted()
	var filtered []*repo.Repo
	for _, r := range all {
		if pred(r) {
			filtered = append(filtered, r)
		}
	}
	return filtered
}
func (proj *Project) UpgradeIf(
	force bool, ask bool, predicate func(r *repo.Repo) bool) error {
	if err := proj.downloadRepositoryYmlFiles(); err != nil {
		return err
	}
	specifiedRepoList := proj.SelectRepos(predicate)
	inst, err := install.NewInstaller(proj.repos, proj.rootRepoReqs)
	if err != nil {
		return err
	}
	return inst.Upgrade(specifiedRepoList, force, ask)
}
func (proj *Project) InfoIf(predicate func(r *repo.Repo) bool,
	remote bool) error {
	if remote {
		if err := proj.downloadRepositoryYmlFiles(); err != nil {
			return err
		}
	}
	repoList := proj.SelectRepos(predicate)
	inst, _ := install.NewInstaller(proj.repos, proj.rootRepoReqs)
	if err := inst.Info(repoList, remote); err != nil {
		return err
	}
	return nil
}
func (proj *Project) loadRepo(name string, fields map[string]string) (
	*repo.Repo, error) {
	if fields["type"] == "" {
		return nil,
			util.FmtNewtError("Missing type for repository %s", name)
	}
	dl, err := downloader.LoadDownloader(name, fields)
	if err != nil {
		return nil, err
	}
	r, err := repo.NewRepo(name, dl)
	if err != nil {
		return nil, err
	}
	for _, ignDir := range ignoreSearchDirs {
		r.AddIgnoreDir(ignDir)
	}
	if err := r.Read(); err != nil {
		return r, err
	}
	log.Debugf("Loaded repository %s (type: %s, user: %s, repo: %s)", name,
		fields["type"], fields["user"], fields["repo"])
	return r, nil
}
func (proj *Project) checkNewtVer() error {
	compatSms, err := proj.yc.GetValStringMapString(
		"project.newt_compatibility", nil)
	util.OneTimeWarningError(err)
	if len(compatSms) == 0 {
		return nil
	}
	tbl, err := compat.ParseNcTable(compatSms)
	if err != nil {
		return util.FmtNewtError("Error reading project.yml: %s", err.Error())
	}
	code, msg := tbl.CheckNewtVer(newtutil.NewtVersion)
	msg = fmt.Sprintf("This version of newt (%s) is incompatible with "+
		"your project; %s", newtutil.NewtVersion.String(), msg)
	switch code {
	case compat.NEWT_COMPAT_GOOD:
		return nil
	case compat.NEWT_COMPAT_WARN:
		util.OneTimeWarning("%s", msg)
		return nil
	case compat.NEWT_COMPAT_ERROR:
		return util.NewNewtError(msg)
	default:
		return nil
	}
}