mynewt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sterl...@apache.org
Subject [4/9] incubator-mynewt-newt git commit: update egg to pkg/package, clutch to pkg-list, and nest to repo. adjust git import paths to unify w newtmgr.
Date Thu, 11 Feb 2016 01:54:33 GMT
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/be14580e/newt/cli/pkglist.go
----------------------------------------------------------------------
diff --git a/newt/cli/pkglist.go b/newt/cli/pkglist.go
new file mode 100644
index 0000000..26bcacf
--- /dev/null
+++ b/newt/cli/pkglist.go
@@ -0,0 +1,1005 @@
+/*
+ Copyright 2015 Runtime Inc.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cli
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/spf13/viper"
+)
+
+type PkgList struct {
+	// Repository associated with the Pkgs
+	Repo *Repo
+
+	// List of packages for Repo
+	Pkgs map[string]*Pkg
+
+	PkgDescs map[string]*PkgDesc
+
+	Name string
+
+	LarvaFile string
+
+	RemoteUrl string
+
+	Branch string
+}
+
+// Allocate a new package manager structure, and initialize it.
+func NewPkgList(nest *Repo) (*PkgList, error) {
+	pkgList := &PkgList{
+		Repo: nest,
+	}
+	err := pkgList.Init()
+
+	return pkgList, err
+}
+
+func (pkgList *PkgList) LoadConfigs(t *Target, force bool) error {
+	for _, pkg := range pkgList.Pkgs {
+		if err := pkg.LoadConfig(t, force); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (pkgList *PkgList) CheckPkgDeps(pkg *Pkg,
+	deps map[string]*DependencyRequirement,
+	reqcap map[string]*DependencyRequirement,
+	caps map[string]*DependencyRequirement,
+	capPkgs map[string]string) error {
+
+	for _, depReq := range pkg.Deps {
+		// don't process this package if we've already processed it
+		if _, ok := deps[depReq.String()]; ok {
+			continue
+		}
+
+		pkgName := pkg.Name
+		StatusMessage(VERBOSITY_VERBOSE,
+			"Checking dependency %s for package %s\n", depReq.Name, pkgName)
+		pkg, ok := pkgList.Pkgs[depReq.Name]
+		if !ok {
+			return NewNewtError(
+				fmt.Sprintf("No package dependency %s found for %s",
+					depReq.Name, pkgName))
+		}
+
+		if ok := depReq.SatisfiesDependency(pkg); !ok {
+			return NewNewtError(fmt.Sprintf("Pkg %s doesn't satisfy dependency %s",
+				pkg.Name, depReq))
+		}
+
+		// We've checked this dependency requirement, all is gute!
+		deps[depReq.String()] = depReq
+	}
+
+	for _, reqCap := range pkg.ReqCapabilities {
+		reqcap[reqCap.String()] = reqCap
+	}
+
+	for _, cap := range pkg.Capabilities {
+		if caps[cap.String()] != nil && capPkgs[cap.String()] != pkg.FullName {
+			return NewNewtError(fmt.Sprintf("Multiple pkgs with capability %s",
+				cap.String()))
+		}
+		caps[cap.String()] = cap
+		if capPkgs != nil {
+			capPkgs[cap.String()] = pkg.FullName
+		}
+	}
+
+	// Now go through and recurse through the sub-package dependencies
+	for _, depReq := range pkg.Deps {
+		if _, ok := deps[depReq.String()]; ok {
+			continue
+		}
+
+		if err := pkgList.CheckPkgDeps(pkgList.Pkgs[depReq.Name], deps,
+			reqcap, caps, capPkgs); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (pkgList *PkgList) VerifyCaps(reqcaps map[string]*DependencyRequirement,
+	caps map[string]*DependencyRequirement) error {
+
+	for name, rcap := range reqcaps {
+		capability, ok := caps[name]
+		if !ok {
+			return NewNewtError(fmt.Sprintf("Required capability %s not found",
+				name))
+		}
+
+		if err := rcap.SatisfiesCapability(capability); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (pkgList *PkgList) CheckDeps() error {
+	// Go through all the packages and check that their dependencies are satisfied
+	for _, pkg := range pkgList.Pkgs {
+		deps := map[string]*DependencyRequirement{}
+		reqcap := map[string]*DependencyRequirement{}
+		caps := map[string]*DependencyRequirement{}
+
+		if err := pkgList.CheckPkgDeps(pkg, deps, reqcap, caps, nil); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// Load an individual package specified by pkgName into the package list for
+// this repository
+func (pkgList *PkgList) loadPkg(pkgDir string, pkgPrefix string,
+	pkgName string) error {
+	StatusMessage(VERBOSITY_VERBOSE, "Loading Pkg "+pkgDir+"...\n")
+
+	if pkgList.Pkgs == nil {
+		pkgList.Pkgs = make(map[string]*Pkg)
+	}
+
+	pkg, err := NewPkg(pkgList.Repo, pkgDir)
+	if err != nil {
+		return nil
+	}
+
+	pkgList.Pkgs[pkgPrefix+pkgName] = pkg
+
+	return nil
+}
+
+func (pkgList *PkgList) String() string {
+	str := ""
+	for pkgName, _ := range pkgList.Pkgs {
+		str += pkgName + " "
+	}
+	return str
+}
+
+// Recursively load a package.  Given the baseDir of the packages (e.g. pkg/ or
+// hw/bsp), and the base package name.
+func (pkgList *PkgList) loadPkgDir(baseDir string, pkgPrefix string,
+	pkgName string) error {
+	log.Printf("[DEBUG] Loading pkgs in %s, starting with pkg %s",
+		baseDir, pkgName)
+
+	// first recurse and load subpackages
+	list, err := ioutil.ReadDir(baseDir + "/" + pkgName)
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	for _, ent := range list {
+		if !ent.IsDir() {
+			continue
+		}
+
+		name := ent.Name()
+
+		if name == "src" || name == "include" || strings.HasPrefix(name, ".") ||
+			name == "bin" {
+			continue
+		} else {
+			if err := pkgList.loadPkgDir(baseDir, pkgPrefix,
+				pkgName+"/"+name); err != nil {
+				return err
+			}
+		}
+	}
+
+	if NodeNotExist(baseDir + "/" + pkgName + "/pkg.yml") {
+		return nil
+	}
+
+	return pkgList.loadPkg(baseDir+"/"+pkgName, pkgPrefix, pkgName)
+}
+
+// Load all the packages in the repository into the package structure
+func (pkgList *PkgList) loadPkgs() error {
+	nest := pkgList.Repo
+
+	// Multiple package directories to be searched
+	searchDirs := []string{
+		"compiler/",
+		"fs/",
+		"libs/",
+		"net/",
+		"hw/bsp/",
+		"hw/mcu/",
+		"hw/mcu/stm",
+		"hw/drivers/",
+		"hw/",
+		"project/",
+		"sys/",
+	}
+
+	for _, pkgDir := range searchDirs {
+		pkgBaseDir := nest.BasePath + "/" + pkgDir
+
+		if NodeNotExist(pkgBaseDir) {
+			continue
+		}
+
+		pkgDirList, err := ioutil.ReadDir(pkgBaseDir)
+		if err != nil {
+			return NewNewtError(err.Error())
+		}
+
+		for _, subPkgDir := range pkgDirList {
+			name := subPkgDir.Name()
+			if filepath.HasPrefix(name, ".") || filepath.HasPrefix(name, "..") {
+				continue
+			}
+
+			if !subPkgDir.IsDir() {
+				continue
+			}
+
+			if err = pkgList.loadPkgDir(pkgBaseDir, pkgDir, name); err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+// Initialize the package manager
+func (pkgList *PkgList) Init() error {
+	if err := pkgList.loadPkgs(); err != nil {
+		return err
+	}
+
+	pkgList.PkgDescs = map[string]*PkgDesc{}
+
+	return nil
+}
+
+// Resolve the package specified by pkgName into a package structure.
+func (pkgList *PkgList) ResolvePkgName(pkgName string) (*Pkg, error) {
+	pkg, ok := pkgList.Pkgs[pkgName]
+	if !ok {
+		return nil, NewNewtError(fmt.Sprintf("Invalid pkg '%s' specified "+
+			"(pkgs = %s)", pkgName, pkgList))
+	}
+	return pkg, nil
+}
+
+func (pkgList *PkgList) ResolvePkgDescName(pkgName string) (*PkgDesc, error) {
+	pkgDesc, ok := pkgList.PkgDescs[pkgName]
+	if !ok {
+		return nil, NewNewtError(fmt.Sprintf("Invalid pkg '%s' specified "+
+			"(pkgs = %s)", pkgName, pkgList))
+	}
+	return pkgDesc, nil
+}
+
+func (pkgList *PkgList) ResolvePkgDir(pkgDir string) (*Pkg, error) {
+	pkgDir = filepath.Clean(pkgDir)
+	for name, pkg := range pkgList.Pkgs {
+		if filepath.Clean(pkg.BasePath) == pkgDir {
+			return pkgList.Pkgs[name], nil
+		}
+	}
+	return nil, NewNewtError(fmt.Sprintf("Cannot resolve package dir %s in "+
+		"package manager", pkgDir))
+}
+
+// Clean the build for the package specified by pkgName.   if cleanAll is
+// specified, all architectures are cleaned.
+func (pkgList *PkgList) BuildClean(t *Target, pkgName string, cleanAll bool) error {
+	pkg, err := pkgList.ResolvePkgName(pkgName)
+	if err != nil {
+		return err
+	}
+
+	if err := pkg.LoadConfig(t, false); err != nil {
+		return err
+	}
+
+	tName := t.Name + "/"
+	if cleanAll {
+		tName = ""
+	}
+
+	if pkg.Clean {
+		return nil
+	}
+	pkg.Clean = true
+
+	for _, dep := range pkg.Deps {
+		if err := pkgList.BuildClean(t, dep.Name, cleanAll); err != nil {
+			return err
+		}
+	}
+
+	c, err := NewCompiler(t.GetCompiler(), t.Cdef, t.Name, []string{})
+	if err != nil {
+		return err
+	}
+
+	if NodeExist(pkg.BasePath + "/src/") {
+		if err := c.RecursiveClean(pkg.BasePath+"/src/", tName); err != nil {
+			return err
+		}
+
+		if err := os.RemoveAll(pkg.BasePath + "/bin/" + tName); err != nil {
+			return NewNewtError(err.Error())
+		}
+	}
+
+	pkg.Clean = true
+
+	return nil
+}
+
+func (pkgList *PkgList) GetPkgLib(t *Target, pkg *Pkg) string {
+	libDir := pkg.BasePath + "/bin/" + t.Name + "/" +
+		"lib" + filepath.Base(pkg.Name) + ".a"
+	return libDir
+}
+
+// @param incls                 Extra include paths that get specified during
+//                                  build; not modified by this function.
+// @param libs                  List of libraries that have been built so far;
+//                                  This function appends entries to this list.
+func (pkgList *PkgList) buildDeps(pkg *Pkg, t *Target, incls *[]string,
+	libs *[]string) error {
+
+	StatusMessage(VERBOSITY_VERBOSE,
+		"Building pkg dependencies for %s, target %s\n", pkg.Name, t.Name)
+
+	var err error
+
+	if pkg.Includes, err = pkg.GetIncludes(t); err != nil {
+		return err
+	}
+
+	if incls == nil {
+		incls = &[]string{}
+	}
+	if libs == nil {
+		libs = &[]string{}
+	}
+
+	for _, dep := range pkg.Deps {
+		if dep.Name == "" {
+			break
+		}
+
+		log.Printf("[DEBUG] Loading package dependency: %s", dep.Name)
+		// Get package structure
+		dpkg, err := pkgList.ResolvePkgName(dep.Name)
+		if err != nil {
+			return err
+		}
+
+		// Build the package
+		if err = pkgList.Build(t, dep.Name, *incls, libs); err != nil {
+			return err
+		}
+
+		// After build, get dependency package includes.  Build function
+		// generates all the package includes
+		pkg.Includes = append(pkg.Includes, dpkg.Includes...)
+		if lib := pkgList.GetPkgLib(t, dpkg); NodeExist(lib) {
+			*libs = append(*libs, lib)
+		}
+	}
+
+	// Add on dependency includes to package includes
+	log.Printf("[DEBUG] Pkg dependencies for %s built, incls = %s",
+		pkg.Name, pkg.Includes)
+
+	return nil
+}
+
+// Build the package specified by pkgName
+//
+// @param incls            Extra include paths that get specified during
+//                             build.  Note: passed by value.
+// @param lib              List of libraries that have been built so far;
+//                             This function appends entries to this list.
+func (pkgList *PkgList) Build(t *Target, pkgName string, incls []string,
+	libs *[]string) error {
+
+	// Look up package structure
+	pkg, err := pkgList.ResolvePkgName(pkgName)
+	if err != nil {
+		return err
+	}
+
+	if err := pkg.LoadConfig(t, false); err != nil {
+		return err
+	}
+
+	// already built the package, no need to rebuild.  This is to handle
+	// recursive calls to Build()
+	if pkg.Built {
+		return nil
+	}
+	pkg.Built = true
+
+	if err := pkgList.buildDeps(pkg, t, &incls, libs); err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_VERBOSE, "Building pkg %s for arch %s\n",
+		pkgName, t.Arch)
+
+	// NOTE: this assignment must happen after the call to buildDeps(), as
+	// buildDeps() fills in the package includes.
+	incls = append(incls, PkgIncludeDirs(pkg, t)...)
+	log.Printf("[DEBUG] Pkg includes for %s are %s", pkgName, incls)
+
+	srcDir := pkg.BasePath + "/src/"
+	if NodeNotExist(srcDir) {
+		// nothing to compile, return true!
+		return nil
+	}
+
+	// Build the package designated by pkgName
+	// Initialize a compiler
+	c, err := NewCompiler(t.GetCompiler(), t.Cdef, t.Name, incls)
+	if err != nil {
+		return err
+	}
+	// setup Cflags, Lflags and Aflags
+	c.Cflags = CreateCflags(pkgList, c, t, pkg.Cflags)
+	c.Lflags += " " + pkg.Lflags + " " + t.Lflags
+	c.Aflags += " " + pkg.Aflags + " " + t.Aflags
+
+	log.Printf("[DEBUG] compiling src pkgs in base pkg directory: %s", srcDir)
+
+	// For now, ignore test code.  Tests get built later if the test identity
+	// is in effect.
+	ignDirs := []string{"test"}
+
+	if err = BuildDir(srcDir, c, t, ignDirs); err != nil {
+		return err
+	}
+
+	// Now build the test code if requested.
+	if t.HasIdentity("test") {
+		testSrcDir := srcDir + "/test"
+		if err = BuildDir(testSrcDir, c, t, ignDirs); err != nil {
+			return err
+		}
+	}
+
+	// Archive everything into a static library, which can be linked with a
+	// main program
+	if err := os.Chdir(pkg.BasePath + "/"); err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	binDir := pkg.BasePath + "/bin/" + t.Name + "/"
+
+	if NodeNotExist(binDir) {
+		if err := os.MkdirAll(binDir, 0755); err != nil {
+			return NewNewtError(err.Error())
+		}
+	}
+
+	if err = c.CompileArchive(pkgList.GetPkgLib(t, pkg), []string{}); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// Check the include directories for the package, to make sure there are
+// no conflicts in include paths for source code
+func (pkgList *PkgList) checkIncludes(pkg *Pkg) error {
+	incls, err := filepath.Glob(pkg.BasePath + "/include/*")
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	// Append all the architecture specific directories
+	archDir := pkg.BasePath + "/include/" + pkg.Name + "/arch/"
+	dirs, err := ioutil.ReadDir(archDir)
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	for _, dir := range dirs {
+		if !dir.IsDir() {
+			return NewNewtError(fmt.Sprintf(
+				"Only directories are allowed in architecture dir: %s",
+				archDir+dir.Name()))
+		}
+
+		incls2, err := filepath.Glob(archDir + dir.Name() + "/*")
+		if err != nil {
+			return NewNewtError(err.Error())
+		}
+
+		incls = append(incls, incls2...)
+	}
+
+	for _, incl := range incls {
+		finfo, err := os.Stat(incl)
+		if err != nil {
+			return NewNewtError(err.Error())
+		}
+
+		bad := false
+		if !finfo.IsDir() {
+			bad = true
+		}
+
+		if filepath.Base(incl) != pkg.Name {
+			if pkg.IsBsp && filepath.Base(incl) != "bsp" {
+				bad = true
+			}
+		}
+
+		if bad {
+			return NewNewtError(fmt.Sprintf("File %s should not exist"+
+				"in include directory, only file allowed in include "+
+				"directory is a directory with the package name %s",
+				incl, pkg.Name))
+		}
+	}
+
+	return nil
+}
+
+// Clean the tests in the tests parameter, for the package identified by
+// pkgName.  If cleanAll is set to true, all architectures will be removed.
+func (pkgList *PkgList) TestClean(t *Target, pkgName string,
+	cleanAll bool) error {
+	pkg, err := pkgList.ResolvePkgName(pkgName)
+	if err != nil {
+		return err
+	}
+
+	if err := pkg.LoadConfig(t, false); err != nil {
+		return err
+	}
+
+	tName := t.Name + "/"
+	if cleanAll {
+		tName = ""
+	}
+
+	if err := os.RemoveAll(pkg.BasePath + "/src/test/bin/" + tName); err != nil {
+		return NewNewtError(err.Error())
+	}
+	if err := os.RemoveAll(pkg.BasePath + "/src/test/obj/" + tName); err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	return nil
+}
+
+// Compile tests specified by the tests parameter.  The tests are linked
+// to the package specified by the pkg parameter
+func (pkgList *PkgList) linkTests(t *Target, pkg *Pkg,
+	incls []string, libs *[]string) error {
+
+	c, err := NewCompiler(t.GetCompiler(), t.Cdef, t.Name, incls)
+	if err != nil {
+		return err
+	}
+
+	// Configure Lflags.  Since we are only linking, Cflags and Aflags are
+	// unnecessary.
+	c.Lflags += " " + pkg.Lflags + " " + t.Lflags
+
+	testBinDir := pkg.BasePath + "/src/test/bin/" + t.Name + "/"
+	binFile := testBinDir + pkg.TestBinName()
+	options := map[string]bool{}
+
+	// Determine if the test executable is already up to date.
+	linkRequired, err := c.depTracker.LinkRequired(binFile, options, *libs)
+	if err != nil {
+		return err
+	}
+
+	// Build the test executable if necessary.
+	if linkRequired {
+		if NodeNotExist(testBinDir) {
+			if err := os.MkdirAll(testBinDir, 0755); err != nil {
+				return NewNewtError(err.Error())
+			}
+		}
+
+		err = c.CompileBinary(binFile, options, *libs)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// Run all the tests in the tests parameter.  pkg is the package to check for
+// the tests.  exitOnFailure specifies whether to exit immediately when a
+// test fails, or continue executing all tests.
+func (pkgList *PkgList) runTests(t *Target, pkg *Pkg, exitOnFailure bool) error {
+	StatusMessage(VERBOSITY_DEFAULT, "Testing pkg %s for arch %s\n",
+		pkg.Name, t.Arch)
+
+	if err := os.Chdir(pkg.BasePath + "/src/test/bin/" + t.Name +
+		"/"); err != nil {
+		return err
+	}
+
+	o, err := ShellCommand("./" + pkg.TestBinName())
+	if err != nil {
+		StatusMessage(VERBOSITY_DEFAULT, "%s", string(o))
+
+		// Always terminate on test failure since only one test is being run.
+		return NewtErrorNoTrace(fmt.Sprintf("Test %s failed",
+			pkg.TestBinName()))
+	} else {
+		StatusMessage(VERBOSITY_VERBOSE, "%s", string(o))
+		StatusMessage(VERBOSITY_DEFAULT, "Test %s ok!\n", pkg.TestBinName())
+		return nil
+	}
+}
+
+// Check to ensure tests exist.  Go through the array of tests specified by
+// the tests parameter.  pkg is the package to check for these tests.
+func (pkgList *PkgList) testsExist(pkg *Pkg) error {
+	dirName := pkg.BasePath + "/src/test/"
+	if NodeNotExist(dirName) {
+		return NewNewtError("No test exists for package " + pkg.Name)
+	}
+
+	return nil
+}
+
+// Test the package identified by pkgName, by executing the tests specified.
+// exitOnFailure signifies whether to stop the test program when one of them
+// fails.
+func (pkgList *PkgList) Test(t *Target, pkgName string,
+	exitOnFailure bool) error {
+
+	// A few identities are implicitly exported when the test command is used:
+	// *    test:       ensures that the test code gets compiled.
+	// *    selftest:   indicates that there is no project
+	t.Identities["test"] = "test"
+	t.Identities["selftest"] = "selftest"
+
+	pkg, err := pkgList.ResolvePkgName(pkgName)
+	if err != nil {
+		return err
+	}
+
+	if err := pkg.LoadConfig(t, false); err != nil {
+		return err
+	}
+
+	// Make sure the test directories exist
+	if err := pkgList.testsExist(pkg); err != nil {
+		return err
+	}
+
+	// The pkg under test must be compiled with the PKG_TEST symbol defined so
+	// that the appropriate main function gets built.
+	pkg.Cflags += " -DPKG_TEST"
+
+	incls := []string{}
+	libs := []string{}
+
+	// If there is a BSP:
+	//     1. Calculate the include paths that it and its dependencies export.
+	//        This set of include paths is accessible during all subsequent
+	//        builds.
+	//     2. Build the BSP package.
+	if t.Bsp != "" {
+		incls, err = BspIncludePaths(pkgList, t)
+		if err != nil {
+			return err
+		}
+		_, err = buildBsp(t, pkgList, &incls, &libs, nil)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Build the package under test.
+	if err := pkgList.Build(t, pkgName, incls, &libs); err != nil {
+		return err
+	}
+	lib := pkgList.GetPkgLib(t, pkg)
+	if !NodeExist(lib) {
+		return NewNewtError("Pkg " + pkgName + " did not produce binary")
+	}
+	libs = append(libs, lib)
+
+	// Compile the package's test code.
+	if err := pkgList.linkTests(t, pkg, incls, &libs); err != nil {
+		return err
+	}
+
+	// Run the tests.
+	if err := pkgList.runTests(t, pkg, exitOnFailure); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (cl *PkgList) LoadFromPkgList(local *PkgList) error {
+	var err error
+	for _, pkg := range local.Pkgs {
+		if err := pkg.LoadConfig(nil, false); err != nil {
+			return err
+		}
+
+		log.Printf("[DEBUG] Pkg %s loaded, putting it into pkgList %s",
+			pkg.FullName, local.Name)
+
+		pkgDesc := &PkgDesc{}
+		pkgDesc.FullName = pkg.FullName
+		pkgDesc.Deps = pkg.Deps
+		pkgDesc.Caps = pkg.Capabilities
+		pkgDesc.ReqCaps = pkg.ReqCapabilities
+		pkgDesc.Version = pkg.Version
+		pkgDesc.Hash, err = pkg.GetHash()
+		if err != nil {
+			return err
+		}
+
+		cl.PkgDescs[pkgDesc.FullName] = pkgDesc
+	}
+
+	return nil
+}
+
+func (cl *PkgList) Serialize() (string, error) {
+	clStr := "name: " + cl.Name + "\n"
+	clStr = clStr + "url: " + cl.RemoteUrl + "\n"
+	clStr = clStr + "pkgs:\n"
+
+	buf := bytes.Buffer{}
+
+	indent := "    "
+	for _, pkgDesc := range cl.PkgDescs {
+		buf.WriteString(pkgDesc.Serialize(indent))
+	}
+
+	return clStr + buf.String(), nil
+}
+
+func (cl *PkgList) strSliceToDr(list []string) ([]*DependencyRequirement, error) {
+	drList := []*DependencyRequirement{}
+
+	for _, name := range list {
+		req, err := NewDependencyRequirementParseString(name)
+		if err != nil {
+			return nil, err
+		}
+		drList = append(drList, req)
+	}
+
+	if len(drList) == 0 {
+		return nil, nil
+	} else {
+		return drList, nil
+	}
+}
+
+func (cl *PkgList) fileToPkgList(cfg *viper.Viper) (map[string]*PkgDesc,
+	error) {
+	pkgMap := cfg.GetStringMap("pkgs")
+
+	pkgList := map[string]*PkgDesc{}
+
+	for name, _ := range pkgMap {
+		pkgDesc, err := NewPkgDesc(cl)
+		if err != nil {
+			return nil, err
+		}
+		pkgDesc.FullName = name
+
+		pkgDef := cfg.GetStringMap("pkgs." + name)
+		pkgDesc.Version, err = NewVersParseString(pkgDef["vers"].(string))
+		if err != nil {
+			return nil, err
+		}
+
+		pkgDesc.Deps, err = cl.strSliceToDr(
+			cfg.GetStringSlice("pkgs." + name + ".deps"))
+		if err != nil {
+			return nil, err
+		}
+
+		pkgDesc.Caps, err = cl.strSliceToDr(
+			cfg.GetStringSlice("pkgs." + name + ".caps"))
+		if err != nil {
+			return nil, err
+		}
+
+		pkgDesc.ReqCaps, err = cl.strSliceToDr(
+			cfg.GetStringSlice("pkgs." + name + ".req_caps"))
+		if err != nil {
+			return nil, err
+		}
+
+		pkgList[name] = pkgDesc
+	}
+
+	return pkgList, nil
+}
+
+// Create the manifest file name, it's the manifest dir + manifest name +
+// branch and a.yml extension
+func (pkgList *PkgList) GetPkgListFile(name string, branch string) string {
+	return name + "@" + branch
+}
+
+func (pkgList *PkgList) GetPkgListFullFile(name string, branch string) string {
+	return pkgList.Repo.PkgListPath + pkgList.GetPkgListFile(name, branch) + ".yml"
+}
+
+func (pkgList *PkgList) Load(name string) error {
+	cfg, err := ReadConfig(pkgList.Repo.PkgListPath, name)
+	if err != nil {
+		return err
+	}
+
+	pkgListName := name
+	branchName := "master"
+
+	parts := strings.Split(name, "@")
+	if len(parts) == 2 {
+		pkgListName = parts[0]
+		branchName = parts[1]
+	}
+
+	if cfg.GetString("name") != pkgListName {
+		return NewNewtError(
+			fmt.Sprintf("Wrong name %s in remote larva file (expected %s)",
+				cfg.GetString("name"), pkgListName))
+	}
+
+	pkgList.Name = cfg.GetString("name")
+	pkgList.Branch = branchName
+	pkgList.RemoteUrl = cfg.GetString("url")
+
+	pkgList.PkgDescs, err = pkgList.fileToPkgList(cfg)
+	if err != nil {
+		return err
+	}
+
+	pkgList.Repo.PkgLists[name] = pkgList
+
+	return nil
+}
+
+func (cl *PkgList) Install(name string, url string, branch string) error {
+	pkgListFile := cl.GetPkgListFullFile(name, branch)
+
+	// XXX: Should warn if file already exists, and require force option
+	os.Remove(pkgListFile)
+
+	// Download the manifest
+	dl, err := NewDownloader()
+	if err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_DEFAULT, "Downloading pkgList.yml from %s/"+
+		"%s...", url, branch)
+
+	if err := dl.DownloadFile(url, branch, "pkgList.yml",
+		pkgListFile); err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_DEFAULT, OK_STRING)
+
+	// Load the manifest, and ensure that it is in the correct format
+	StatusMessage(VERBOSITY_DEFAULT, "Verifying pkgList.yml format...\n")
+	if err := cl.Load(cl.GetPkgListFile(name, branch)); err != nil {
+		os.Remove(pkgListFile)
+		return err
+	}
+	StatusMessage(VERBOSITY_DEFAULT, OK_STRING)
+
+	return nil
+}
+
+func (pkgList *PkgList) InstallPkg(pkgName string, branch string,
+	downloaded []*RemoteRepo) ([]*RemoteRepo, error) {
+	log.Print("[VERBOSE] Looking for ", pkgName)
+	pkg, err := pkgList.ResolvePkgName(pkgName)
+	if err == nil {
+		log.Printf("[VERBOSE] ", pkgName, " installed already")
+		return downloaded, nil
+	}
+	nest := pkgList.Repo
+	for _, remoteRepo := range downloaded {
+		pkg, err = remoteRepo.ResolvePkgName(pkgName)
+		if err == nil {
+			log.Print("[VERBOSE] ", pkgName, " present in downloaded pkgList ",
+				remoteRepo.Name)
+
+			err = remoteRepo.fetchPkg(pkgName, nest.BasePath)
+			if err != nil {
+				return downloaded, err
+			}
+
+			// update local pkgList
+			err = pkgList.loadPkgDir(nest.BasePath, "", pkgName)
+			if err != nil {
+				return downloaded, err
+			}
+
+			deps, err := pkg.GetDependencies()
+			if err != nil {
+				return downloaded, err
+			}
+			for _, dep := range deps {
+				log.Print("[VERBOSE] ", pkgName, " checking dependency ",
+					dep.Name)
+				depBranch := dep.BranchName()
+				downloaded, err = pkgList.InstallPkg(dep.Name, depBranch,
+					downloaded)
+				if err != nil {
+					return downloaded, err
+				}
+			}
+			return downloaded, nil
+		}
+	}
+
+	// Not in downloaded pkgLists
+	pkgLists, err := nest.GetPkgLists()
+	if err != nil {
+		return downloaded, err
+	}
+	for _, remotePkgList := range pkgLists {
+		pkgDesc, err := remotePkgList.ResolvePkgDescName(pkgName)
+		if err == nil {
+			log.Print("[VERBOSE] ", pkgName, " present in remote pkgList ",
+				remotePkgList.Name, remotePkgList.Branch)
+			if branch == "" {
+				branch = remotePkgList.Branch
+			}
+			remoteRepo, err := NewRemoteRepo(remotePkgList, branch)
+			if err != nil {
+				return downloaded, err
+			}
+			downloaded = append(downloaded, remoteRepo)
+			return pkgList.InstallPkg(pkgDesc.FullName, branch, downloaded)
+		}
+	}
+
+	return downloaded, NewNewtError(fmt.Sprintf("No package %s found\n", pkgName))
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/be14580e/newt/cli/project.go
----------------------------------------------------------------------
diff --git a/newt/cli/project.go b/newt/cli/project.go
index e7aa0da..b7648ad 100644
--- a/newt/cli/project.go
+++ b/newt/cli/project.go
@@ -28,8 +28,8 @@ type Project struct {
 	// Base path of project
 	BasePath string
 
-	// Eggs
-	Eggs []string
+	// Pkgs
+	Pkgs []string
 
 	// Capabilities
 	Capabilities []string
@@ -44,24 +44,24 @@ type Project struct {
 	Lflags string
 
 	// The repository the project is located in
-	Nest *Nest
+	Repo *Repo
 
 	// The target associated with this project
 	Target *Target
 }
 
 // Load and initialize a project specified by name
-// nest & t are the nest and target to associate the project with
-func LoadProject(nest *Nest, t *Target, name string) (*Project, error) {
+// repo & t are the repo and target to associate the project with
+func LoadProject(repo *Repo, t *Target, name string) (*Project, error) {
 	p := &Project{
 		Name:   name,
-		Nest:   nest,
+		Repo:   repo,
 		Target: t,
 	}
 
 	StatusMessage(VERBOSITY_VERBOSE,
 		"Loading project %s for repo %s, target %s\n",
-		name, nest.BasePath, t.Name)
+		name, repo.BasePath, t.Name)
 
 	if err := p.Init(); err != nil {
 		return nil, err
@@ -71,8 +71,8 @@ func LoadProject(nest *Nest, t *Target, name string) (*Project, error) {
 }
 
 // Get the packages associated with the project
-func (p *Project) GetEggs() []string {
-	return p.Eggs
+func (p *Project) GetPkgs() []string {
+	return p.Pkgs
 }
 
 // Load project configuration
@@ -87,7 +87,7 @@ func (p *Project) loadConfig() error {
 
 	t := p.Target
 
-	p.Eggs = GetStringSliceIdentities(v, t.Identities, "project.eggs")
+	p.Pkgs = GetStringSliceIdentities(v, t.Identities, "project.pkgs")
 
 	idents := GetStringSliceIdentities(v, t.Identities, "project.identities")
 	for _, ident := range idents {
@@ -106,7 +106,7 @@ func (p *Project) loadConfig() error {
 // project, if cleanAll is true, then clean everything, not just the current
 // architecture
 func (p *Project) BuildClean(cleanAll bool) error {
-	clutch, err := NewClutch(p.Nest)
+	pkgList, err := NewPkgList(p.Repo)
 	if err != nil {
 		return err
 	}
@@ -114,8 +114,8 @@ func (p *Project) BuildClean(cleanAll bool) error {
 	// first, clean packages
 	StatusMessage(VERBOSITY_VERBOSE,
 		"Cleaning all the packages associated with project %s", p.Name)
-	for _, eggName := range p.GetEggs() {
-		err = clutch.BuildClean(p.Target, eggName, cleanAll)
+	for _, pkgName := range p.GetPkgs() {
+		err = pkgList.BuildClean(p.Target, pkgName, cleanAll)
 		if err != nil {
 			return err
 		}
@@ -123,7 +123,7 @@ func (p *Project) BuildClean(cleanAll bool) error {
 
 	// clean the BSP, if it exists
 	if p.Target.Bsp != "" {
-		if err := clutch.BuildClean(p.Target, p.Target.Bsp, cleanAll); err != nil {
+		if err := pkgList.BuildClean(p.Target, p.Target.Bsp, cleanAll); err != nil {
 			return err
 		}
 	}
@@ -146,11 +146,11 @@ func (p *Project) BuildClean(cleanAll bool) error {
 }
 
 // Collect all identities and capabilities that project has
-func (p *Project) collectAllDeps(clutch *Clutch, identities map[string]string,
+func (p *Project) collectAllDeps(pkgList *PkgList, identities map[string]string,
 	capabilities map[string]string) error {
 
-	eggList := p.GetEggs()
-	if eggList == nil {
+	pkgDepList := p.GetPkgs()
+	if pkgList == nil {
 		return nil
 	}
 
@@ -158,22 +158,22 @@ func (p *Project) collectAllDeps(clutch *Clutch, identities map[string]string,
 
 	t := p.Target
 
-	eggList = append(eggList, t.Dependencies...)
+	pkgDepList = append(pkgDepList, t.Dependencies...)
 	if t.Bsp != "" {
-		eggList = append(eggList, t.Bsp)
+		pkgDepList = append(pkgDepList, t.Bsp)
 	}
 
-	for _, eggName := range eggList {
-		if eggName == "" {
+	for _, pkgName := range pkgDepList {
+		if pkgName == "" {
 			continue
 		}
 
-		egg, err := clutch.ResolveEggName(eggName)
+		pkg, err := pkgList.ResolvePkgName(pkgName)
 		if err != nil {
 			return err
 		}
 
-		err = egg.collectDependencies(clutch, identities, capabilities)
+		err = pkg.collectDependencies(pkgList, identities, capabilities)
 		if err != nil {
 			return err
 		}
@@ -181,34 +181,34 @@ func (p *Project) collectAllDeps(clutch *Clutch, identities map[string]string,
 	return nil
 }
 
-func (p *Project) clearAllDeps(clutch *Clutch) {
-	eggList := p.GetEggs()
-	if eggList == nil {
+func (p *Project) clearAllDeps(pkgList *PkgList) {
+	pkgDepList := p.GetPkgs()
+	if pkgDepList == nil {
 		return
 	}
 
 	t := p.Target
 
-	eggList = append(eggList, t.Dependencies...)
+	pkgDepList = append(pkgDepList, t.Dependencies...)
 	if t.Bsp != "" {
-		eggList = append(eggList, t.Bsp)
+		pkgDepList = append(pkgDepList, t.Bsp)
 	}
 
-	for _, eggName := range eggList {
-		if eggName == "" {
+	for _, pkgName := range pkgDepList {
+		if pkgName == "" {
 			continue
 		}
-		egg, err := clutch.ResolveEggName(eggName)
+		pkg, err := pkgList.ResolvePkgName(pkgName)
 		if err != nil {
 			return
 		}
-		egg.clearDependencyMarker(clutch)
+		pkg.clearDependencyMarker(pkgList)
 	}
 }
 
 // Collect project identities and capabilities, and make target ready for
 // building.
-func (p *Project) collectDeps(clutch *Clutch) error {
+func (p *Project) collectDeps(pkgList *PkgList) error {
 
 	identCount := 0
 	capCount := 0
@@ -216,14 +216,14 @@ func (p *Project) collectDeps(clutch *Clutch) error {
 	t := p.Target
 
 	StatusMessage(VERBOSITY_VERBOSE,
-		"Collecting egg dependencies for project %s\n", p.Name)
+		"Collecting pkg dependencies for project %s\n", p.Name)
 
 	// Need to do this multiple times, until there are no new identities,
 	// capabilities which show up.
 	identities := t.Identities
 	capabilities := map[string]string{}
 	for {
-		err := p.collectAllDeps(clutch, identities, capabilities)
+		err := p.collectAllDeps(pkgList, identities, capabilities)
 		if err != nil {
 			return err
 		}
@@ -234,7 +234,7 @@ func (p *Project) collectDeps(clutch *Clutch) error {
 		if identCount == newIdentCount && capCount == newCapCount {
 			break
 		}
-		p.clearAllDeps(clutch)
+		p.clearAllDeps(pkgList)
 		identCount = newIdentCount
 		capCount = newCapCount
 	}
@@ -243,25 +243,25 @@ func (p *Project) collectDeps(clutch *Clutch) error {
 }
 
 // Build the packages that this project depends on
-// clutch is an initialized package manager, incls is an array of includes to
+// pkgList is an initialized package manager, incls is an array of includes to
 // append to (package includes get append as they are built)
 // libs is an array of archive files to append to (package libraries get
 // appended as they are built)
-func (p *Project) buildDeps(clutch *Clutch, incls *[]string,
+func (p *Project) buildDeps(pkgList *PkgList, incls *[]string,
 	libs *[]string) (map[string]string, error) {
-	eggList := p.GetEggs()
-	if eggList == nil {
+	pkgDepList := p.GetPkgs()
+	if pkgDepList == nil {
 		return nil, nil
 	}
 
 	StatusMessage(VERBOSITY_VERBOSE,
-		"Building egg dependencies for project %s\n", p.Name)
+		"Building pkg dependencies for project %s\n", p.Name)
 
 	t := p.Target
 
 	// Append project variables to target variables, so that all package builds
 	// inherit from them
-	eggList = append(eggList, t.Dependencies...)
+	pkgDepList = append(pkgDepList, t.Dependencies...)
 	t.Capabilities = append(t.Capabilities, p.Capabilities...)
 	t.Cflags += " " + p.Cflags
 	t.Lflags += " " + p.Lflags
@@ -270,7 +270,7 @@ func (p *Project) buildDeps(clutch *Clutch, incls *[]string,
 	deps := map[string]*DependencyRequirement{}
 	reqcaps := map[string]*DependencyRequirement{}
 	caps := map[string]*DependencyRequirement{}
-	capEggs := map[string]string{}
+	capPkgs := map[string]string{}
 
 	// inherit project capabilities, mark these capabilities as supported.
 	for _, cName := range t.Capabilities {
@@ -282,17 +282,17 @@ func (p *Project) buildDeps(clutch *Clutch, incls *[]string,
 		caps[dr.String()] = dr
 	}
 
-	for _, eggName := range eggList {
-		if eggName == "" {
+	for _, pkgName := range pkgDepList {
+		if pkgName == "" {
 			continue
 		}
 
-		egg, err := clutch.ResolveEggName(eggName)
+		pkg, err := pkgList.ResolvePkgName(pkgName)
 		if err != nil {
 			return nil, err
 		}
 
-		if err := clutch.CheckEggDeps(egg, deps, reqcaps, caps, capEggs); err != nil {
+		if err := pkgList.CheckPkgDeps(pkg, deps, reqcaps, caps, capPkgs); err != nil {
 			return nil, err
 		}
 	}
@@ -308,9 +308,9 @@ func (p *Project) buildDeps(clutch *Clutch, incls *[]string,
 	for dname, dep := range caps {
 		StatusMessage(VERBOSITY_VERBOSE,
 			"	%s - %s ", dname, dep.Name)
-		if capEggs[dname] != "" {
+		if capPkgs[dname] != "" {
 			StatusMessage(VERBOSITY_VERBOSE,
-				"- %s\n", capEggs[dname])
+				"- %s\n", capPkgs[dname])
 		} else {
 			StatusMessage(VERBOSITY_VERBOSE, "\n")
 		}
@@ -318,45 +318,45 @@ func (p *Project) buildDeps(clutch *Clutch, incls *[]string,
 
 	// After processing all the dependencies, verify that the package's
 	// capability requirements are satisfied as well
-	if err := clutch.VerifyCaps(reqcaps, caps); err != nil {
+	if err := pkgList.VerifyCaps(reqcaps, caps); err != nil {
 		return nil, err
 	}
 
 	// now go through and build everything
-	for _, eggName := range eggList {
-		if eggName == "" {
+	for _, pkgName := range pkgDepList {
+		if pkgName == "" {
 			continue
 		}
 
-		egg, err := clutch.ResolveEggName(eggName)
+		pkg, err := pkgList.ResolvePkgName(pkgName)
 		if err != nil {
 			return nil, err
 		}
 
-		if err = clutch.Build(p.Target, eggName, *incls, libs); err != nil {
+		if err = pkgList.Build(p.Target, pkgName, *incls, libs); err != nil {
 			return nil, err
 		}
 
 		// Don't fail if package did not produce a library file; some packages
 		// are header-only.
-		if lib := clutch.GetEggLib(p.Target, egg); NodeExist(lib) {
+		if lib := pkgList.GetPkgLib(p.Target, pkg); NodeExist(lib) {
 			*libs = append(*libs, lib)
 		}
 
-		*incls = append(*incls, egg.Includes...)
+		*incls = append(*incls, pkg.Includes...)
 	}
 
-	return capEggs, nil
+	return capPkgs, nil
 }
 
 // Build the BSP for this project.
 // The BSP is specified by the Target attached to the project.
-// clutch is an initialized egg mgr, containing all the packages
+// pkgList is an initialized pkg mgr, containing all the packages
 // incls and libs are pointers to an array of includes and libraries, when buildBsp()
 // builds the BSP, it appends the include directories for the BSP, and the archive file
 // to these variables.
-func (p *Project) buildBsp(clutch *Clutch, incls *[]string,
-	libs *[]string, capEggs map[string]string) (string, error) {
+func (p *Project) buildBsp(pkgList *PkgList, incls *[]string,
+	libs *[]string, capPkgs map[string]string) (string, error) {
 
 	StatusMessage(VERBOSITY_VERBOSE, "Building BSP %s for project %s\n",
 		p.Target.Bsp, p.Name)
@@ -365,18 +365,18 @@ func (p *Project) buildBsp(clutch *Clutch, incls *[]string,
 		return "", NewNewtError("Must specify a BSP to build project")
 	}
 
-	return buildBsp(p.Target, clutch, incls, libs, capEggs)
+	return buildBsp(p.Target, pkgList, incls, libs, capPkgs)
 }
 
 // Build the project
 func (p *Project) Build() error {
-	clutch, err := NewClutch(p.Nest)
+	pkgList, err := NewPkgList(p.Repo)
 	if err != nil {
 		return err
 	}
 
 	// Load the configuration for this target
-	if err := clutch.LoadConfigs(nil, false); err != nil {
+	if err := pkgList.LoadConfigs(nil, false); err != nil {
 		return err
 	}
 
@@ -385,7 +385,7 @@ func (p *Project) Build() error {
 	linkerScript := ""
 
 	// Collect target identities, libraries to include
-	err = p.collectDeps(clutch)
+	err = p.collectDeps(pkgList)
 	if err != nil {
 		return err
 	}
@@ -396,20 +396,20 @@ func (p *Project) Build() error {
 	//        builds.
 	//     2. Build the BSP package.
 	if p.Target.Bsp != "" {
-		incls, err = BspIncludePaths(clutch, p.Target)
+		incls, err = BspIncludePaths(pkgList, p.Target)
 		if err != nil {
 			return err
 		}
 	}
 
 	// Build the project dependencies.
-	capEggs, err := p.buildDeps(clutch, &incls, &libs)
+	capPkgs, err := p.buildDeps(pkgList, &incls, &libs)
 	if err != nil {
 		return err
 	}
 
 	if p.Target.Bsp != "" {
-		linkerScript, err = p.buildBsp(clutch, &incls, &libs, capEggs)
+		linkerScript, err = p.buildBsp(pkgList, &incls, &libs, capPkgs)
 		if err != nil {
 			return err
 		}
@@ -432,7 +432,7 @@ func (p *Project) Build() error {
 	c.LinkerScript = linkerScript
 
 	// Add target C flags
-	c.Cflags = CreateCflags(clutch, c, p.Target, p.Cflags)
+	c.Cflags = CreateCflags(pkgList, c, p.Target, p.Cflags)
 
 	os.Chdir(p.BasePath + "/src/")
 	if err = c.Compile("*.c"); err != nil {
@@ -467,7 +467,7 @@ func (p *Project) Build() error {
 
 // Initialize the project, and project definition
 func (p *Project) Init() error {
-	p.BasePath = p.Nest.BasePath + "/project/" + p.Name + "/"
+	p.BasePath = p.Repo.BasePath + "/project/" + p.Name + "/"
 	if NodeNotExist(p.BasePath) {
 		return NewNewtError("Project directory does not exist")
 	}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/be14580e/newt/cli/remotenest.go
----------------------------------------------------------------------
diff --git a/newt/cli/remotenest.go b/newt/cli/remotenest.go
deleted file mode 100644
index 7bd51d7..0000000
--- a/newt/cli/remotenest.go
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- Copyright 2015 Runtime Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-package cli
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-)
-
-type RemoteNest struct {
-	// Nestsitory associated with the Eggs
-	Nest *Nest
-
-	Clutch *Clutch
-
-	Name string
-
-	RemoteLoc string
-
-	LocalLoc string
-}
-
-// Allocate a new  structure, and initialize it.
-func NewRemoteNest(clutch *Clutch, branch string) (*RemoteNest, error) {
-	remoteNest := &RemoteNest{
-		Name : clutch.Name,
-		RemoteLoc: clutch.RemoteUrl,
-		LocalLoc: "",
-	}
-
-	err := remoteNest.Download(branch)
-	if err != nil {
-		return nil, err
-	}
-	return remoteNest, nil
-}
-
-// Download it
-func (remoteNest *RemoteNest) Download(branch string) error {
-	dl, err := NewDownloader()
-	if err != nil {
-		return err
-	}
-
-	StatusMessage(VERBOSITY_DEFAULT, "Downloading %s from %s/"+
-		"%s...", remoteNest.Name, remoteNest.RemoteLoc, branch)
-
-	dir, err := dl.GetRepo(remoteNest.RemoteLoc, branch)
-	if err != nil {
-		return err
-	}
-
-	StatusMessage(VERBOSITY_DEFAULT, OK_STRING)
-
-	remoteNest.LocalLoc = dir
-
-	nest, err := NewNestWithDir(dir)
-	if err != nil {
-		return err
-	}
-	remoteNest.Nest = nest
-
-	clutch, err := NewClutch(nest)
-	if err != nil {
-		return err
-	}
-
-	err = clutch.LoadConfigs(nil, false)
-	if err != nil {
-		return err
-	}
-	remoteNest.Clutch = clutch
-
-	return nil
-}
-
-func (remoteNest *RemoteNest) ResolveEggName(eggName string) (*Egg, error) {
-	if remoteNest.Clutch == nil {
-		return nil, NewNewtError(fmt.Sprintf("RemoteNest %s not downloaded yet!",
-					remoteNest.Name))
-	}
-	return remoteNest.Clutch.ResolveEggName(eggName)
-}
-
-func (remoteNest *RemoteNest) fetchEgg(eggName string, tgtBase string) error {
-	egg, err := remoteNest.ResolveEggName(eggName)
-	if err != nil {
-		return err
-	}
-
-	StatusMessage(VERBOSITY_DEFAULT, "Installing %s\n", egg.FullName)
-
-	srcDir := filepath.Join(remoteNest.LocalLoc, egg.FullName)
-	tgtDir := filepath.Join(tgtBase, egg.FullName)
-
-	err = CopyDir(srcDir, tgtDir)
-	return err
-}
-
-// Remove local copy
-func (remoteNest *RemoteNest) Remove() error {
-	if remoteNest.LocalLoc != "" {
-		err := os.RemoveAll(remoteNest.LocalLoc)
-		return err
-	}
-	return nil
-}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/be14580e/newt/cli/remoterepo.go
----------------------------------------------------------------------
diff --git a/newt/cli/remoterepo.go b/newt/cli/remoterepo.go
new file mode 100644
index 0000000..56b3dfa
--- /dev/null
+++ b/newt/cli/remoterepo.go
@@ -0,0 +1,121 @@
+/*
+ Copyright 2015 Runtime Inc.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cli
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+type RemoteRepo struct {
+	// Repository associated with the Pkgs
+	Repo *Repo
+
+	PkgList *PkgList
+
+	Name string
+
+	RemoteLoc string
+
+	LocalLoc string
+}
+
+// Allocate a new  structure, and initialize it.
+func NewRemoteRepo(pkgList *PkgList, branch string) (*RemoteRepo, error) {
+	remoteRepo := &RemoteRepo{
+		Name : pkgList.Name,
+		RemoteLoc: pkgList.RemoteUrl,
+		LocalLoc: "",
+	}
+
+	err := remoteRepo.Download(branch)
+	if err != nil {
+		return nil, err
+	}
+	return remoteRepo, nil
+}
+
+// Download it
+func (remoteRepo *RemoteRepo) Download(branch string) error {
+	dl, err := NewDownloader()
+	if err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_DEFAULT, "Downloading %s from %s/"+
+		"%s...", remoteRepo.Name, remoteRepo.RemoteLoc, branch)
+
+	dir, err := dl.GetRepo(remoteRepo.RemoteLoc, branch)
+	if err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_DEFAULT, OK_STRING)
+
+	remoteRepo.LocalLoc = dir
+
+	repo, err := NewRepoWithDir(dir)
+	if err != nil {
+		return err
+	}
+	remoteRepo.Repo = repo
+
+	pkgList, err := NewPkgList(repo)
+	if err != nil {
+		return err
+	}
+
+	err = pkgList.LoadConfigs(nil, false)
+	if err != nil {
+		return err
+	}
+	remoteRepo.PkgList = pkgList
+
+	return nil
+}
+
+func (remoteRepo *RemoteRepo) ResolvePkgName(pkgName string) (*Pkg, error) {
+	if remoteRepo.PkgList == nil {
+		return nil, NewNewtError(fmt.Sprintf("RemoteRepo %s not downloaded yet!",
+					remoteRepo.Name))
+	}
+	return remoteRepo.PkgList.ResolvePkgName(pkgName)
+}
+
+func (remoteRepo *RemoteRepo) fetchPkg(pkgName string, tgtBase string) error {
+	pkg, err := remoteRepo.ResolvePkgName(pkgName)
+	if err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_DEFAULT, "Installing %s\n", pkg.FullName)
+
+	srcDir := filepath.Join(remoteRepo.LocalLoc, pkg.FullName)
+	tgtDir := filepath.Join(tgtBase, pkg.FullName)
+
+	err = CopyDir(srcDir, tgtDir)
+	return err
+}
+
+// Remove local copy
+func (remoteRepo *RemoteRepo) Remove() error {
+	if remoteRepo.LocalLoc != "" {
+		err := os.RemoveAll(remoteRepo.LocalLoc)
+		return err
+	}
+	return nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/be14580e/newt/cli/repo.go
----------------------------------------------------------------------
diff --git a/newt/cli/repo.go b/newt/cli/repo.go
new file mode 100644
index 0000000..e66e0f3
--- /dev/null
+++ b/newt/cli/repo.go
@@ -0,0 +1,467 @@
+/*
+ Copyright 2015 Runtime Inc.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cli
+
+import (
+	"database/sql"
+	"fmt"
+	_ "github.com/mattn/go-sqlite3"
+	"io/ioutil"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+)
+
+type Repo struct {
+	// Name of the Repo
+	Name string
+
+	// Path to the Repo Store
+	StorePath string
+
+	// Path to the Repo PkgLists
+	PkgListPath string
+
+	// Repo File
+	RepoFile string
+
+	// Base path of the nest
+	BasePath string
+
+	// Store of PkgLists
+	PkgLists map[string]*PkgList
+
+	// Configuration
+	Config map[string]map[string]string
+
+	// The database handle for the nest configuration database
+	db *sql.DB
+}
+
+// Create a new Repo object and initialize it
+func NewRepo() (*Repo, error) {
+	n := &Repo{}
+
+	err := n.Init()
+	if err != nil {
+		return nil, err
+	}
+
+	return n, nil
+}
+
+// Create a Repo object constructed out of repo in given path
+func NewRepoWithDir(srcDir string) (*Repo, error) {
+	n := &Repo{}
+
+	err := n.InitPath(srcDir)
+	if err != nil {
+		return nil, err
+	}
+
+	return n, nil
+}
+
+func CreateRepo(nestName string, destDir string, tadpoleUrl string) error {
+	if tadpoleUrl == "" {
+		tadpoleUrl = "https://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole.git"
+	}
+
+	if NodeExist(destDir) {
+		return NewNewtError(fmt.Sprintf("Directory %s already exists, "+
+			" cannot create new newt nest", destDir))
+	}
+
+	dl, err := NewDownloader()
+	if err != nil {
+		return err
+	}
+
+	StatusMessage(VERBOSITY_DEFAULT, "Downloading nest skeleton from %s...",
+		tadpoleUrl)
+	if err := dl.DownloadFile(tadpoleUrl, "master", "/",
+		destDir); err != nil {
+		return err
+	}
+	StatusMessage(VERBOSITY_DEFAULT, OK_STRING)
+
+	// Overwrite nest.yml
+	contents := []byte(fmt.Sprintf("nest.name: %s\n", nestName))
+	if err := ioutil.WriteFile(destDir+"/nest.yml",
+		contents, 0644); err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	// DONE!
+
+	return nil
+}
+
+// Get a temporary directory to stick stuff in
+func (nest *Repo) GetTmpDir(dirName string, prefix string) (string, error) {
+	tmpDir := dirName
+	if NodeNotExist(tmpDir) {
+		if err := os.MkdirAll(tmpDir, 0700); err != nil {
+			return "", err
+		}
+	}
+
+	name, err := ioutil.TempDir(tmpDir, prefix)
+	if err != nil {
+		return "", err
+	}
+
+	return name, nil
+}
+
+// Find the repo file.  Searches the current directory, and then recurses
+// parent directories until it finds a file named .repo.yml
+// if no repo file found in the directory heirarchy, an error is returned
+func (nest *Repo) getRepoFile() (string, error) {
+	rFile := ""
+
+	curDir, err := os.Getwd()
+	if err != nil {
+		return rFile, NewNewtError(err.Error())
+	}
+
+	for {
+		rFile = curDir + "/nest.yml"
+		log.Printf("[DEBUG] Searching for nest file at %s", rFile)
+		if _, err := os.Stat(rFile); err == nil {
+			log.Printf("[DEBUG] Found nest file at %s!", rFile)
+			break
+		}
+
+		curDir = path.Clean(curDir + "../../")
+		if curDir == "/" {
+			rFile = ""
+			err = NewNewtError("No repo file found!")
+			break
+		}
+	}
+
+	return rFile, err
+}
+
+// Create the contents of the configuration database
+func (nest *Repo) createDb(db *sql.DB) error {
+	query := `
+	CREATE TABLE IF NOT EXISTS newt_cfg (
+		cfg_name VARCHAR(255) NOT NULL,
+		key VARCHAR(255) NOT NULL,
+		value TEXT
+	)
+	`
+	_, err := db.Exec(query)
+	if err != nil {
+		return NewNewtError(err.Error())
+	} else {
+		return nil
+	}
+}
+
+// Initialize the configuration database specified by dbName.  If the database
+// doesn't exist, create it.
+func (nest *Repo) initDb(dbName string) error {
+	db, err := sql.Open("sqlite3", dbName)
+	if err != nil {
+		return err
+	}
+	nest.db = db
+
+	err = nest.createDb(db)
+	if err != nil {
+		return err
+	}
+
+	// Populate repo configuration
+	log.Printf("[DEBUG] Populating Repo configuration from %s", dbName)
+
+	rows, err := db.Query("SELECT * FROM newt_cfg")
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+	defer rows.Close()
+
+	for rows.Next() {
+		var cfgName sql.NullString
+		var cfgKey sql.NullString
+		var cfgVal sql.NullString
+
+		err := rows.Scan(&cfgName, &cfgKey, &cfgVal)
+		if err != nil {
+			return NewNewtError(err.Error())
+		}
+
+		log.Printf("[DEBUG] Setting sect %s, key %s to val %s", cfgName.String,
+			cfgKey.String, cfgVal.String)
+
+		_, ok := nest.Config[cfgName.String]
+		if !ok {
+			nest.Config[cfgName.String] = make(map[string]string)
+		}
+
+		nest.Config[cfgName.String][cfgKey.String] = cfgVal.String
+	}
+
+	return nil
+}
+
+// Get a configuration variable in section sect, with key
+// error is populated if variable doesn't exist
+func (nest *Repo) GetConfig(sect string, key string) (string, error) {
+	sectMap, ok := nest.Config[sect]
+	if !ok {
+		return "", NewNewtError("No configuration section exists")
+	}
+
+	val, ok := sectMap[key]
+	if !ok {
+		return "", NewNewtError("No configuration variable exists")
+	}
+
+	return val, nil
+}
+
+func (nest *Repo) GetConfigSect(sect string) (map[string]string, error) {
+	sm, ok := nest.Config[sect]
+	if !ok {
+		return nil, NewNewtError("No configuration section exists")
+	}
+
+	return sm, nil
+}
+
+// Delete a configuration variable in section sect with key and val
+// Returns an error if configuration variable cannot be deleted
+// (most likely due to database error or key not existing)
+func (nest *Repo) DelConfig(sect string, key string) error {
+	db := nest.db
+
+	log.Printf("[DEBUG] Deleting sect %s, key %s", sect, key)
+
+	tx, err := db.Begin()
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	stmt, err := tx.Prepare("DELETE FROM newt_cfg WHERE cfg_name=? AND key=?")
+	if err != nil {
+		return err
+	}
+	defer stmt.Close()
+
+	res, err := stmt.Exec(sect, key)
+	if err != nil {
+		return err
+	}
+
+	tx.Commit()
+
+	if affected, err := res.RowsAffected(); affected > 0 && err == nil {
+		log.Printf("[DEBUG] sect %s, key %s successfully deleted from database",
+			sect, key)
+	} else {
+		log.Printf("[DEBUG] sect %s, key %s not found, considering \"delete\" successful",
+			sect, key)
+	}
+
+	return nil
+}
+
+// Set a configuration variable in section sect with key, and val
+// Returns an error if configuration variable cannot be set
+// (most likely not able to set it in database.)
+func (nest *Repo) SetConfig(sect string, key string, val string) error {
+	_, ok := nest.Config[sect]
+	if !ok {
+		nest.Config[sect] = make(map[string]string)
+	}
+	nest.Config[sect][key] = val
+
+	// Store config
+	log.Printf("[DEBUG] Storing value %s into key %s for section %s",
+		val, sect, key)
+	db := nest.db
+
+	tx, err := db.Begin()
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	stmt, err := tx.Prepare(
+		"UPDATE newt_cfg SET value=? WHERE cfg_name=? AND key=?")
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+	defer stmt.Close()
+
+	res, err := stmt.Exec(val, sect, key)
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	// Value already existed, and we updated it.  Mission accomplished!
+	// Exit
+	if affected, err := res.RowsAffected(); affected > 0 && err == nil {
+		tx.Commit()
+		log.Printf("[DEBUG] Key %s, sect %s successfully updated to %s", key, sect, val)
+		return nil
+	}
+
+	// Otherwise, insert a new row
+	stmt1, err := tx.Prepare("INSERT INTO newt_cfg VALUES (?, ?, ?)")
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+	defer stmt1.Close()
+
+	_, err = stmt1.Exec(sect, key, val)
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	tx.Commit()
+
+	log.Printf("[DEBUG] Key %s, sect %s successfully create, value set to %s",
+		key, sect, val)
+
+	return nil
+}
+
+// Load the repo configuration file
+func (nest *Repo) loadConfig() error {
+	v, err := ReadConfig(nest.BasePath, "nest")
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	nest.Name = v.GetString("nest.name")
+	if nest.Name == "" {
+		return NewNewtError("Repo file must specify nest name")
+	}
+
+	return nil
+}
+
+func (nest *Repo) LoadPkgLists() error {
+	files, err := ioutil.ReadDir(nest.PkgListPath)
+	if err != nil {
+		return err
+	}
+	for _, fileInfo := range files {
+		file := fileInfo.Name()
+		if filepath.Ext(file) == ".yml" {
+			name := file[:len(filepath.Base(file))-len(".yml")]
+			log.Printf("[DEBUG] Loading PkgList %s", name)
+			pkgList, err := NewPkgList(nest)
+			if err != nil {
+				return err
+			}
+			if err := pkgList.Load(name); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func (nest *Repo) InitPath(nestPath string) error {
+	cwd, err := os.Getwd()
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	if err = os.Chdir(nestPath); err != nil {
+		return NewNewtError(err.Error())
+	}
+
+	log.Printf("[DEBUG] Searching for repository, starting in directory %s", cwd)
+
+	if nest.RepoFile, err = nest.getRepoFile(); err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Repo file found, directory %s, loading configuration...",
+		nest.RepoFile)
+
+	nest.BasePath = filepath.ToSlash(path.Dir(nest.RepoFile))
+
+	if err = nest.loadConfig(); err != nil {
+		return err
+	}
+
+	if err = os.Chdir(cwd); err != nil {
+		return NewNewtError(err.Error())
+	}
+	return nil
+}
+
+// Initialze the repository
+// returns a NewtError on failure, and nil on success
+func (nest *Repo) Init() error {
+	var err error
+
+	cwd, err := os.Getwd()
+	if err != nil {
+		return NewNewtError(err.Error())
+	}
+	if err := nest.InitPath(cwd); err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Configuration loaded!  Initializing .nest database")
+
+	// Create Repo store directory
+	nest.StorePath = nest.BasePath + "/.nest/"
+	if NodeNotExist(nest.StorePath) {
+		if err := os.MkdirAll(nest.StorePath, 0755); err != nil {
+			return NewNewtError(err.Error())
+		}
+	}
+
+	// Create Repo configuration database
+	nest.Config = make(map[string]map[string]string)
+
+	dbName := nest.StorePath + "/nest.db"
+	if err := nest.initDb(dbName); err != nil {
+		return err
+	}
+
+	log.Printf("[DEBUG] Database initialized.")
+
+	// Load PkgLists for the current Repo
+	nest.PkgListPath = nest.StorePath + "/pkgLists/"
+	if NodeNotExist(nest.PkgListPath) {
+		if err := os.MkdirAll(nest.PkgListPath, 0755); err != nil {
+			return NewNewtError(err.Error())
+		}
+	}
+
+	nest.PkgLists = map[string]*PkgList{}
+
+	if err := nest.LoadPkgLists(); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (nest *Repo) GetPkgLists() (map[string]*PkgList, error) {
+	return nest.PkgLists, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/be14580e/newt/cli/target.go
----------------------------------------------------------------------
diff --git a/newt/cli/target.go b/newt/cli/target.go
index 789c0d6..77dd971 100644
--- a/newt/cli/target.go
+++ b/newt/cli/target.go
@@ -48,13 +48,13 @@ type Target struct {
 
 	Bsp string
 
-	Nest *Nest
+	Repo *Repo
 }
 
-// Check if the target specified by name exists for the Nest specified by
+// Check if the target specified by name exists for the Repo specified by
 // r
-func TargetExists(nest *Nest, name string) bool {
-	_, err := nest.GetConfig(TARGET_SECT_PREFIX+name, "name")
+func TargetExists(repo *Repo, name string) bool {
+	_, err := repo.GetConfig(TARGET_SECT_PREFIX+name, "name")
 	if err == nil {
 		return true
 	} else {
@@ -122,14 +122,14 @@ func (t *Target) HasIdentity(identity string) bool {
 }
 
 // Load the target specified by name for the repository specified by r
-func LoadTarget(nest *Nest, name string) (*Target, error) {
+func LoadTarget(repo *Repo, name string) (*Target, error) {
 	t := &Target{
-		Nest: nest,
+		Repo: repo,
 	}
 
 	var err error
 
-	t.Vars, err = nest.GetConfigSect(TARGET_SECT_PREFIX + name)
+	t.Vars, err = repo.GetConfigSect(TARGET_SECT_PREFIX + name)
 	if err != nil {
 		return nil, err
 	}
@@ -145,8 +145,8 @@ func LoadTarget(nest *Nest, name string) (*Target, error) {
 
 // Export a target, or all targets.  If exportAll is true, then all targets are exported, if false,
 // then only the target represented by targetName is exported
-func ExportTargets(nest *Nest, name string, exportAll bool, fp *os.File) error {
-	targets, err := GetTargets(nest)
+func ExportTargets(repo *Repo, name string, exportAll bool, fp *os.File) error {
+	targets, err := GetTargets(repo)
 	if err != nil {
 		return err
 	}
@@ -169,7 +169,7 @@ func ExportTargets(nest *Nest, name string, exportAll bool, fp *os.File) error {
 	return nil
 }
 
-func ImportTargets(nest *Nest, name string, importAll bool, fp *os.File) error {
+func ImportTargets(repo *Repo, name string, importAll bool, fp *os.File) error {
 	s := bufio.NewScanner(fp)
 
 	var currentTarget *Target = nil
@@ -206,7 +206,7 @@ func ImportTargets(nest *Nest, name string, importAll bool, fp *os.File) error {
 				if importAll || elements[1] == name {
 					// create a current target
 					currentTarget = &Target{
-						Nest: nest,
+						Repo: repo,
 					}
 
 					var err error
@@ -245,11 +245,11 @@ func ImportTargets(nest *Nest, name string, importAll bool, fp *os.File) error {
 }
 
 // Get a list of targets for the repository specified by r
-func GetTargets(nest *Nest) ([]*Target, error) {
+func GetTargets(repo *Repo) ([]*Target, error) {
 	targets := []*Target{}
-	for sect, _ := range nest.Config {
+	for sect, _ := range repo.Config {
 		if strings.HasPrefix(sect, TARGET_SECT_PREFIX) {
-			target, err := LoadTarget(nest, sect[len(TARGET_SECT_PREFIX):len(sect)])
+			target, err := LoadTarget(repo, sect[len(TARGET_SECT_PREFIX):len(sect)])
 			if err != nil {
 				return nil, err
 			}
@@ -267,7 +267,7 @@ func (t *Target) GetVars() map[string]string {
 
 // Return the compiler definition file for this target
 func (t *Target) GetCompiler() string {
-	path := t.Nest.BasePath + "/compiler/"
+	path := t.Repo.BasePath + "/compiler/"
 	if t.Vars["compiler"] != "" {
 		path += t.Vars["compiler"]
 	} else {
@@ -284,7 +284,7 @@ func (t *Target) Build() error {
 		StatusMessage(VERBOSITY_DEFAULT, "Building target %s (project = %s)\n",
 			t.Name, t.Vars["project"])
 		// Now load and build the project.
-		p, err := LoadProject(t.Nest, t, t.Vars["project"])
+		p, err := LoadProject(t.Repo, t, t.Vars["project"])
 		if err != nil {
 			return err
 		}
@@ -292,13 +292,13 @@ func (t *Target) Build() error {
 		if err = p.Build(); err != nil {
 			return err
 		}
-	} else if t.Vars["egg"] != "" {
-		clutch, err := NewClutch(t.Nest)
+	} else if t.Vars["pkg"] != "" {
+		pkgList, err := NewPkgList(t.Repo)
 		if err != nil {
 			return err
 		}
 
-		err = clutch.Build(t, t.Vars["egg"], nil, nil)
+		err = pkgList.Build(t, t.Vars["pkg"], nil, nil)
 		if err != nil {
 			return err
 		}
@@ -309,7 +309,7 @@ func (t *Target) Build() error {
 
 func (t *Target) BuildClean(cleanAll bool) error {
 	if t.Vars["project"] != "" {
-		p, err := LoadProject(t.Nest, t, t.Vars["project"])
+		p, err := LoadProject(t.Repo, t, t.Vars["project"])
 		if err != nil {
 			return err
 		}
@@ -318,12 +318,12 @@ func (t *Target) BuildClean(cleanAll bool) error {
 		if err = p.BuildClean(cleanAll); err != nil {
 			return err
 		}
-	} else if t.Vars["egg"] != "" {
-		clutch, err := NewClutch(t.Nest)
+	} else if t.Vars["pkg"] != "" {
+		pkgList, err := NewPkgList(t.Repo)
 		if err != nil {
 			return err
 		}
-		err = clutch.BuildClean(t, t.Vars["egg"], cleanAll)
+		err = pkgList.BuildClean(t, t.Vars["pkg"], cleanAll)
 		if err != nil {
 			return err
 		}
@@ -333,16 +333,16 @@ func (t *Target) BuildClean(cleanAll bool) error {
 }
 
 func (t *Target) Test(cmd string, flag bool) error {
-	clutch, err := NewClutch(t.Nest)
+	pkgList, err := NewPkgList(t.Repo)
 	if err != nil {
 		return err
 	}
 
 	switch cmd {
 	case "test":
-		err = clutch.Test(t, t.Vars["egg"], flag)
+		err = pkgList.Test(t, t.Vars["pkg"], flag)
 	case "testclean":
-		err = clutch.TestClean(t, t.Vars["egg"], flag)
+		err = pkgList.TestClean(t, t.Vars["pkg"], flag)
 	default:
 		err = NewNewtError("Unknown command to Test() " + cmd)
 	}
@@ -356,7 +356,7 @@ func (t *Target) Test(cmd string, flag bool) error {
 func (t *Target) DeleteVar(name string) error {
 	targetCfgSect := TARGET_SECT_PREFIX + t.Vars["name"]
 
-	if err := t.Nest.DelConfig(targetCfgSect, name); err != nil {
+	if err := t.Repo.DelConfig(targetCfgSect, name); err != nil {
 		return err
 	}
 
@@ -365,7 +365,7 @@ func (t *Target) DeleteVar(name string) error {
 
 // Save the target's configuration elements
 func (t *Target) Save() error {
-	nest := t.Nest
+	repo := t.Repo
 
 	if _, ok := t.Vars["name"]; !ok {
 		return NewNewtError("Cannot save a target without a name")
@@ -374,7 +374,7 @@ func (t *Target) Save() error {
 	targetCfg := TARGET_SECT_PREFIX + t.Vars["name"]
 
 	for k, v := range t.Vars {
-		if err := nest.SetConfig(targetCfg, k, v); err != nil {
+		if err := repo.SetConfig(targetCfg, k, v); err != nil {
 			return err
 		}
 	}
@@ -383,7 +383,7 @@ func (t *Target) Save() error {
 }
 
 func (t *Target) Remove() error {
-	nest := t.Nest
+	repo := t.Repo
 
 	if _, ok := t.Vars["name"]; !ok {
 		return NewNewtError("Cannot remove a target without a name")
@@ -392,7 +392,7 @@ func (t *Target) Remove() error {
 	cfgSect := TARGET_SECT_PREFIX + t.Vars["name"]
 
 	for k, _ := range t.Vars {
-		if err := nest.DelConfig(cfgSect, k); err != nil {
+		if err := repo.DelConfig(cfgSect, k); err != nil {
 			return err
 		}
 	}
@@ -401,36 +401,36 @@ func (t *Target) Remove() error {
 }
 
 func (t *Target) Download() error {
-	clutch, err := NewClutch(t.Nest)
+	pkgList, err := NewPkgList(t.Repo)
 	if err != nil {
 		return err
 	}
 
-	egg, err := clutch.ResolveEggName(t.Bsp)
+	pkg, err := pkgList.ResolvePkgName(t.Bsp)
 	if err != nil {
 		return err
 	}
 
-	err = egg.LoadConfig(t, false)
+	err = pkg.LoadConfig(t, false)
 	if err != nil {
 		return err
 	}
-	if egg.DownloadScript == "" {
-		return NewNewtError(fmt.Sprintf("No egg.downloadscript defined for %s",
-			egg.FullName))
+	if pkg.DownloadScript == "" {
+		return NewNewtError(fmt.Sprintf("No pkg.downloadscript defined for %s",
+			pkg.FullName))
 	}
-	downloadScript := filepath.Join(egg.BasePath, egg.DownloadScript)
+	downloadScript := filepath.Join(pkg.BasePath, pkg.DownloadScript)
 
 	if t.Vars["project"] == "" {
 		return NewNewtError(fmt.Sprintf("No project associated with target %s",
 			t.Name))
 	}
-	p, err := LoadProject(t.Nest, t, t.Vars["project"])
+	p, err := LoadProject(t.Repo, t, t.Vars["project"])
 	if err != nil {
 		return err
 	}
 
-	os.Chdir(t.Nest.BasePath)
+	os.Chdir(t.Repo.BasePath)
 
 	identString := ""
 	for ident, _ := range t.Identities {
@@ -449,36 +449,36 @@ func (t *Target) Download() error {
 }
 
 func (t *Target) Debug() error {
-	clutch, err := NewClutch(t.Nest)
+	pkgList, err := NewPkgList(t.Repo)
 	if err != nil {
 		return err
 	}
 
-	egg, err := clutch.ResolveEggName(t.Bsp)
+	pkg, err := pkgList.ResolvePkgName(t.Bsp)
 	if err != nil {
 		return err
 	}
 
-	err = egg.LoadConfig(t, false)
+	err = pkg.LoadConfig(t, false)
 	if err != nil {
 		return err
 	}
-	if egg.DebugScript == "" {
-		return NewNewtError(fmt.Sprintf("No egg.debugscript defined for %s",
-			egg.FullName))
+	if pkg.DebugScript == "" {
+		return NewNewtError(fmt.Sprintf("No pkg.debugscript defined for %s",
+			pkg.FullName))
 	}
-	debugScript := filepath.Join(egg.BasePath, egg.DebugScript)
+	debugScript := filepath.Join(pkg.BasePath, pkg.DebugScript)
 
 	if t.Vars["project"] == "" {
 		return NewNewtError(fmt.Sprintf("No project associated with target %s",
 			t.Name))
 	}
-	p, err := LoadProject(t.Nest, t, t.Vars["project"])
+	p, err := LoadProject(t.Repo, t, t.Vars["project"])
 	if err != nil {
 		return err
 	}
 
-	os.Chdir(t.Nest.BasePath)
+	os.Chdir(t.Repo.BasePath)
 
 	identString := ""
 	for ident, _ := range t.Identities {
@@ -536,40 +536,40 @@ func (m *MemSection) PartOf(addr uint64) bool {
 /*
  * We accumulate the size of libraries to elements in this.
  */
-type EggSize struct {
+type PkgSize struct {
 	Name  string
 	Sizes map[string]uint32 /* Sizes indexed by mem section name */
 }
 
-type EggSizeArray []*EggSize
+type PkgSizeArray []*PkgSize
 
-func (array EggSizeArray) Len() int {
+func (array PkgSizeArray) Len() int {
 	return len(array)
 }
 
-func (array EggSizeArray) Less(i, j int) bool {
+func (array PkgSizeArray) Less(i, j int) bool {
 	return array[i].Name < array[j].Name
 }
 
-func (array EggSizeArray) Swap(i, j int) {
+func (array PkgSizeArray) Swap(i, j int) {
 	array[i], array[j] = array[j], array[i]
 }
 
-func MakeEggSize(name string, memSections map[string]*MemSection) *EggSize {
-	eggSize := &EggSize{
+func MakePkgSize(name string, memSections map[string]*MemSection) *PkgSize {
+	pkgSize := &PkgSize{
 		Name: name,
 	}
-	eggSize.Sizes = make(map[string]uint32)
+	pkgSize.Sizes = make(map[string]uint32)
 	for secName, _ := range memSections {
-		eggSize.Sizes[secName] = 0
+		pkgSize.Sizes[secName] = 0
 	}
-	return eggSize
+	return pkgSize
 }
 
 /*
  * Go through GCC generated mapfile, and collect info about symbol sizes
  */
-func ParseMapFileSizes(fileName string) (map[string]*EggSize, map[string]*MemSection,
+func ParseMapFileSizes(fileName string) (map[string]*PkgSize, map[string]*MemSection,
 	error) {
 	var state int = 0
 
@@ -579,7 +579,7 @@ func ParseMapFileSizes(fileName string) (map[string]*EggSize, map[string]*MemSec
 	}
 
 	memSections := make(map[string]*MemSection)
-	eggSizes := make(map[string]*EggSize)
+	pkgSizes := make(map[string]*PkgSize)
 
 	scanner := bufio.NewScanner(file)
 	for scanner.Scan() {
@@ -713,13 +713,13 @@ func ParseMapFileSizes(fileName string) (map[string]*EggSize, map[string]*MemSec
 			srcLib := filepath.Base(tmpStrArr[0])
 			for name, section := range memSections {
 				if section.PartOf(addr) {
-					eggSize := eggSizes[srcLib]
-					if eggSize == nil {
-						eggSize =
-							MakeEggSize(srcLib, memSections)
-						eggSizes[srcLib] = eggSize
+					pkgSize := pkgSizes[srcLib]
+					if pkgSize == nil {
+						pkgSize =
+							MakePkgSize(srcLib, memSections)
+						pkgSizes[srcLib] = pkgSize
 					}
-					eggSize.Sizes[name] += uint32(size)
+					pkgSize.Sizes[name] += uint32(size)
 					break
 				}
 			}
@@ -732,13 +732,13 @@ func ParseMapFileSizes(fileName string) (map[string]*EggSize, map[string]*MemSec
 			name, section.Offset, section.EndOff)
 	}
 
-	return eggSizes, memSections, nil
+	return pkgSizes, memSections, nil
 }
 
 /*
  * Return a printable string containing size data for the libraries
  */
-func PrintSizes(libs map[string]*EggSize,
+func PrintSizes(libs map[string]*PkgSize,
 	sectMap map[string]*MemSection) (string, error) {
 	ret := ""
 
@@ -756,19 +756,19 @@ func PrintSizes(libs map[string]*EggSize,
 	/*
 	 * Order libraries by name, and display them in that order.
 	 */
-	eggSizes := make(EggSizeArray, len(libs))
+	pkgSizes := make(PkgSizeArray, len(libs))
 	i = 0
 	for _, es := range libs {
-		eggSizes[i] = es
+		pkgSizes[i] = es
 		i++
 	}
-	sort.Sort(eggSizes)
+	sort.Sort(pkgSizes)
 
 	for _, sec := range memSections {
 		ret += fmt.Sprintf("%7s ", sec.Name)
 	}
 	ret += "\n"
-	for _, es := range eggSizes {
+	for _, es := range pkgSizes {
 		for i := 0; i < len(memSections); i++ {
 			ret += fmt.Sprintf("%7d ", es.Sizes[memSections[i].Name])
 		}
@@ -782,7 +782,7 @@ func (t *Target) GetSize() (string, error) {
 		StatusMessage(VERBOSITY_DEFAULT, "Inspecting target %s (project = %s)\n",
 			t.Name, t.Vars["project"])
 		// Now load the project, mapfile settings
-		p, err := LoadProject(t.Nest, t, t.Vars["project"])
+		p, err := LoadProject(t.Repo, t, t.Vars["project"])
 		if err != nil {
 			return "", err
 		}
@@ -796,11 +796,11 @@ func (t *Target) GetSize() (string, error) {
 		}
 		mapFile := p.BinPath() + p.Name + ".elf.map"
 
-		eggSizes, memSections, err := ParseMapFileSizes(mapFile)
+		pkgSizes, memSections, err := ParseMapFileSizes(mapFile)
 		if err != nil {
 			return "", err
 		}
-		return PrintSizes(eggSizes, memSections)
+		return PrintSizes(pkgSizes, memSections)
 	}
 	return "", NewNewtError("Target needs a project")
 }


Mime
View raw message