diff --git a/cmd/helm/create.go b/cmd/helm/create.go
index 6e63fd305cfacfc128a45f395ded0b0835b6b9dc..5569a8e1cdc98a1aca4d2105fedacf4dbd1cb1fa 100644
--- a/cmd/helm/create.go
+++ b/cmd/helm/create.go
@@ -24,8 +24,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 )
 
 const createDesc = `
@@ -80,7 +80,7 @@ func (o *createOptions) run(out io.Writer) error {
 		Description: "A Helm chart for Kubernetes",
 		Version:     "0.1.0",
 		AppVersion:  "1.0",
-		APIVersion:  chartutil.APIVersionv1,
+		APIVersion:  chart.APIVersionv1,
 	}
 
 	if o.starter != "" {
diff --git a/cmd/helm/create_test.go b/cmd/helm/create_test.go
index 5ec69f67859d067c3aa8f8d7ad7a2c5d232d9be7..47fc885200bc7269e3736331ed72b0803f7d5ff5 100644
--- a/cmd/helm/create_test.go
+++ b/cmd/helm/create_test.go
@@ -23,8 +23,9 @@ import (
 	"path/filepath"
 	"testing"
 
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 )
 
 func TestCreateCmd(t *testing.T) {
@@ -46,15 +47,15 @@ func TestCreateCmd(t *testing.T) {
 		t.Fatalf("chart is not directory")
 	}
 
-	c, err := chartutil.LoadDir(cname)
+	c, err := loader.LoadDir(cname)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if c.Metadata.Name != cname {
-		t.Errorf("Expected %q name, got %q", cname, c.Metadata.Name)
+	if c.Name() != cname {
+		t.Errorf("Expected %q name, got %q", cname, c.Name())
 	}
-	if c.Metadata.APIVersion != chartutil.APIVersionv1 {
+	if c.Metadata.APIVersion != chart.APIVersionv1 {
 		t.Errorf("Wrong API version: %q", c.Metadata.APIVersion)
 	}
 }
@@ -97,15 +98,15 @@ func TestCreateStarterCmd(t *testing.T) {
 		t.Fatalf("chart is not directory")
 	}
 
-	c, err := chartutil.LoadDir(cname)
+	c, err := loader.LoadDir(cname)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if c.Metadata.Name != cname {
-		t.Errorf("Expected %q name, got %q", cname, c.Metadata.Name)
+	if c.Name() != cname {
+		t.Errorf("Expected %q name, got %q", cname, c.Name())
 	}
-	if c.Metadata.APIVersion != chartutil.APIVersionv1 {
+	if c.Metadata.APIVersion != chart.APIVersionv1 {
 		t.Errorf("Wrong API version: %q", c.Metadata.APIVersion)
 	}
 
diff --git a/cmd/helm/dependency.go b/cmd/helm/dependency.go
index e31c26000c925cc4998b585d7c87d8116fa50e69..d8eb41e777230db8d97311068528606059b1851c 100644
--- a/cmd/helm/dependency.go
+++ b/cmd/helm/dependency.go
@@ -26,7 +26,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 )
 
 const dependencyDesc = `
@@ -130,27 +131,23 @@ func newDependencyListCmd(out io.Writer) *cobra.Command {
 }
 
 func (o *dependencyLisOptions) run(out io.Writer) error {
-	c, err := chartutil.Load(o.chartpath)
+	c, err := loader.Load(o.chartpath)
 	if err != nil {
 		return err
 	}
 
-	r, err := chartutil.LoadRequirements(c)
-	if err != nil {
-		if err == chartutil.ErrRequirementsNotFound {
-			fmt.Fprintf(out, "WARNING: no requirements at %s/charts\n", o.chartpath)
-			return nil
-		}
-		return err
+	if c.Requirements == nil {
+		fmt.Fprintf(out, "WARNING: no requirements at %s/charts\n", o.chartpath)
+		return nil
 	}
 
-	o.printRequirements(out, r)
+	o.printRequirements(out, c.Requirements)
 	fmt.Fprintln(out)
-	o.printMissing(out, r)
+	o.printMissing(out, c.Requirements)
 	return nil
 }
 
-func (o *dependencyLisOptions) dependencyStatus(dep *chartutil.Dependency) string {
+func (o *dependencyLisOptions) dependencyStatus(dep *chart.Dependency) string {
 	filename := fmt.Sprintf("%s-%s.tgz", dep.Name, "*")
 	archives, err := filepath.Glob(filepath.Join(o.chartpath, "charts", filename))
 	if err != nil {
@@ -160,11 +157,11 @@ func (o *dependencyLisOptions) dependencyStatus(dep *chartutil.Dependency) strin
 	} else if len(archives) == 1 {
 		archive := archives[0]
 		if _, err := os.Stat(archive); err == nil {
-			c, err := chartutil.Load(archive)
+			c, err := loader.Load(archive)
 			if err != nil {
 				return "corrupt"
 			}
-			if c.Metadata.Name != dep.Name {
+			if c.Name() != dep.Name {
 				return "misnamed"
 			}
 
@@ -195,12 +192,12 @@ func (o *dependencyLisOptions) dependencyStatus(dep *chartutil.Dependency) strin
 		return "mispackaged"
 	}
 
-	c, err := chartutil.Load(folder)
+	c, err := loader.Load(folder)
 	if err != nil {
 		return "corrupt"
 	}
 
-	if c.Metadata.Name != dep.Name {
+	if c.Name() != dep.Name {
 		return "misnamed"
 	}
 
@@ -225,7 +222,7 @@ func (o *dependencyLisOptions) dependencyStatus(dep *chartutil.Dependency) strin
 }
 
 // printRequirements prints all of the requirements in the yaml file.
-func (o *dependencyLisOptions) printRequirements(out io.Writer, reqs *chartutil.Requirements) {
+func (o *dependencyLisOptions) printRequirements(out io.Writer, reqs *chart.Requirements) {
 	table := uitable.New()
 	table.MaxColWidth = 80
 	table.AddRow("NAME", "VERSION", "REPOSITORY", "STATUS")
@@ -236,7 +233,7 @@ func (o *dependencyLisOptions) printRequirements(out io.Writer, reqs *chartutil.
 }
 
 // printMissing prints warnings about charts that are present on disk, but are not in the requirements.
-func (o *dependencyLisOptions) printMissing(out io.Writer, reqs *chartutil.Requirements) {
+func (o *dependencyLisOptions) printMissing(out io.Writer, reqs *chart.Requirements) {
 	folder := filepath.Join(o.chartpath, "charts/*")
 	files, err := filepath.Glob(folder)
 	if err != nil {
@@ -253,14 +250,14 @@ func (o *dependencyLisOptions) printMissing(out io.Writer, reqs *chartutil.Requi
 		if !fi.IsDir() && filepath.Ext(f) != ".tgz" {
 			continue
 		}
-		c, err := chartutil.Load(f)
+		c, err := loader.Load(f)
 		if err != nil {
 			fmt.Fprintf(out, "WARNING: %q is not a chart.\n", f)
 			continue
 		}
 		found := false
 		for _, d := range reqs.Dependencies {
-			if d.Name == c.Metadata.Name {
+			if d.Name == c.Name() {
 				found = true
 				break
 			}
diff --git a/cmd/helm/dependency_update_test.go b/cmd/helm/dependency_update_test.go
index 212106af420aebf31164e3d38919dc372b312942..7401b75795398af0cca2c3f2006647ffa855ef9a 100644
--- a/cmd/helm/dependency_update_test.go
+++ b/cmd/helm/dependency_update_test.go
@@ -26,9 +26,8 @@ import (
 
 	"github.com/ghodss/yaml"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
-	"k8s.io/helm/pkg/helm/helmpath"
 	"k8s.io/helm/pkg/provenance"
 	"k8s.io/helm/pkg/repo"
 	"k8s.io/helm/pkg/repo/repotest"
@@ -88,8 +87,8 @@ func TestDependencyUpdateCmd(t *testing.T) {
 
 	// Now change the dependencies and update. This verifies that on update,
 	// old dependencies are cleansed and new dependencies are added.
-	reqfile := &chartutil.Requirements{
-		Dependencies: []*chartutil.Dependency{
+	reqfile := &chart.Requirements{
+		Dependencies: []*chart.Dependency{
 			{Name: "reqtest", Version: "0.1.0", Repository: srv.URL()},
 			{Name: "compressedchart", Version: "0.3.0", Repository: srv.URL()},
 		},
@@ -170,7 +169,7 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
 
 	out := bytes.NewBuffer(nil)
 	o := &dependencyUpdateOptions{}
-	o.helmhome = helmpath.Home(hh)
+	o.helmhome = hh
 	o.chartpath = hh.Path(chartname)
 
 	if err := o.run(out); err != nil {
@@ -223,8 +222,8 @@ func createTestingChart(dest, name, baseURL string) error {
 	if err != nil {
 		return err
 	}
-	req := &chartutil.Requirements{
-		Dependencies: []*chartutil.Dependency{
+	req := &chart.Requirements{
+		Dependencies: []*chart.Dependency{
 			{Name: "reqtest", Version: "0.1.0", Repository: baseURL},
 			{Name: "compressedchart", Version: "0.1.0", Repository: baseURL},
 		},
@@ -232,7 +231,7 @@ func createTestingChart(dest, name, baseURL string) error {
 	return writeRequirements(dir, req)
 }
 
-func writeRequirements(dir string, req *chartutil.Requirements) error {
+func writeRequirements(dir string, req *chart.Requirements) error {
 	data, err := yaml.Marshal(req)
 	if err != nil {
 		return err
diff --git a/cmd/helm/history.go b/cmd/helm/history.go
index 1139d96482844f7cb490de481edca19da29a741d..65eb7559077ac30debe9cb05f61c62afe88ef23a 100644
--- a/cmd/helm/history.go
+++ b/cmd/helm/history.go
@@ -27,7 +27,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/hapi/release"
 	"k8s.io/helm/pkg/helm"
 )
@@ -167,5 +167,5 @@ func formatChartname(c *chart.Chart) string {
 		// know how: https://github.com/kubernetes/helm/issues/1347
 		return "MISSING"
 	}
-	return fmt.Sprintf("%s-%s", c.Metadata.Name, c.Metadata.Version)
+	return fmt.Sprintf("%s-%s", c.Name(), c.Metadata.Version)
 }
diff --git a/cmd/helm/inspect.go b/cmd/helm/inspect.go
index 4f8327898e8dbabd9144b5e00b3c06fc496cc6c0..9862731583aaed6f0644c453f5f33d9113b87e0c 100644
--- a/cmd/helm/inspect.go
+++ b/cmd/helm/inspect.go
@@ -25,8 +25,8 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
-	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 )
 
 const inspectDesc = `
@@ -146,7 +146,7 @@ func newInspectCmd(out io.Writer) *cobra.Command {
 }
 
 func (i *inspectOptions) run(out io.Writer) error {
-	chrt, err := chartutil.Load(i.chartpath)
+	chrt, err := loader.Load(i.chartpath)
 	if err != nil {
 		return err
 	}
diff --git a/cmd/helm/install.go b/cmd/helm/install.go
index e7910d57e36648cccd7a4af663faf598c7984ec3..c953a2e4692f7a516dd5acc30545b46ff38d3700 100644
--- a/cmd/helm/install.go
+++ b/cmd/helm/install.go
@@ -28,10 +28,10 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/downloader"
 	"k8s.io/helm/pkg/getter"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 	"k8s.io/helm/pkg/helm"
 )
@@ -176,12 +176,12 @@ func (o *installOptions) run(out io.Writer) error {
 	}
 
 	// Check chart requirements to make sure all dependencies are present in /charts
-	chartRequested, err := chartutil.Load(o.chartPath)
+	chartRequested, err := loader.Load(o.chartPath)
 	if err != nil {
 		return err
 	}
 
-	if req, err := chartutil.LoadRequirements(chartRequested); err == nil {
+	if req := chartRequested.Requirements; req != nil {
 		// If checkDependencies returns an error, we have unfulfilled dependencies.
 		// As of Helm 2.4.0, this is treated as a stopping condition:
 		// https://github.com/kubernetes/helm/issues/2209
@@ -203,8 +203,6 @@ func (o *installOptions) run(out io.Writer) error {
 			}
 
 		}
-	} else if err != chartutil.ErrRequirementsNotFound {
-		return errors.Wrap(err, "cannot load requirements")
 	}
 
 	rel, err := o.client.InstallReleaseFromChart(
@@ -272,7 +270,6 @@ func (o *installOptions) printRelease(out io.Writer, rel *release.Release) {
 	if rel == nil {
 		return
 	}
-	// TODO: Switch to text/template like everything else.
 	fmt.Fprintf(out, "NAME:   %s\n", rel.Name)
 	if settings.Debug {
 		printRelease(out, rel)
@@ -286,27 +283,20 @@ func generateName(nameTemplate string) (string, error) {
 	}
 	var b bytes.Buffer
 	err = t.Execute(&b, nil)
-	if err != nil {
-		return "", err
-	}
-	return b.String(), nil
+	return b.String(), err
 }
 
-func checkDependencies(ch *chart.Chart, reqs *chartutil.Requirements) error {
-	missing := []string{}
+func checkDependencies(ch *chart.Chart, reqs *chart.Requirements) error {
+	var missing []string
 
-	deps := ch.Dependencies
+OUTER:
 	for _, r := range reqs.Dependencies {
-		found := false
-		for _, d := range deps {
-			if d.Metadata.Name == r.Name {
-				found = true
-				break
+		for _, d := range ch.Dependencies() {
+			if d.Name() == r.Name {
+				continue OUTER
 			}
 		}
-		if !found {
-			missing = append(missing, r.Name)
-		}
+		missing = append(missing, r.Name)
 	}
 
 	if len(missing) > 0 {
diff --git a/cmd/helm/package.go b/cmd/helm/package.go
index a41ee4f12954aa914cfc6e07daf5aadf268337df..1e99b1eae2f5abf546d2dde7acb55c059d418273 100644
--- a/cmd/helm/package.go
+++ b/cmd/helm/package.go
@@ -30,10 +30,11 @@ import (
 	"github.com/spf13/cobra"
 	"golang.org/x/crypto/ssh/terminal"
 
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
 	"k8s.io/helm/pkg/downloader"
 	"k8s.io/helm/pkg/getter"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/helm/helmpath"
 	"k8s.io/helm/pkg/provenance"
 )
@@ -129,7 +130,7 @@ func (o *packageOptions) run(out io.Writer) error {
 		}
 	}
 
-	ch, err := chartutil.LoadDir(path)
+	ch, err := loader.LoadDir(path)
 	if err != nil {
 		return err
 	}
@@ -161,18 +162,14 @@ func (o *packageOptions) run(out io.Writer) error {
 		debug("Setting appVersion to %s", o.appVersion)
 	}
 
-	if filepath.Base(path) != ch.Metadata.Name {
-		return errors.Errorf("directory name (%s) and Chart.yaml name (%s) must match", filepath.Base(path), ch.Metadata.Name)
+	if filepath.Base(path) != ch.Name() {
+		return errors.Errorf("directory name (%s) and Chart.yaml name (%s) must match", filepath.Base(path), ch.Name())
 	}
 
-	if reqs, err := chartutil.LoadRequirements(ch); err == nil {
+	if reqs := ch.Requirements; reqs != nil {
 		if err := checkDependencies(ch, reqs); err != nil {
 			return err
 		}
-	} else {
-		if err != chartutil.ErrRequirementsNotFound {
-			return err
-		}
 	}
 
 	var dest string
diff --git a/cmd/helm/package_test.go b/cmd/helm/package_test.go
index d7f0e0f9daede36c90c53421e76d9d332af06c98..b2a11eb98b0e7f9f3866f32f990e7053288f70f0 100644
--- a/cmd/helm/package_test.go
+++ b/cmd/helm/package_test.go
@@ -26,8 +26,9 @@ import (
 
 	"github.com/spf13/cobra"
 
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/helm/helmpath"
 )
 
@@ -206,7 +207,7 @@ func TestSetAppVersion(t *testing.T) {
 	tmp := testTempDir(t)
 
 	hh := testHelmHome(t)
-	settings.Home = helmpath.Home(hh)
+	settings.Home = hh
 
 	c := newPackageCmd(&bytes.Buffer{})
 	flags := map[string]string{
@@ -224,7 +225,7 @@ func TestSetAppVersion(t *testing.T) {
 	} else if fi.Size() == 0 {
 		t.Errorf("file %q has zero bytes.", chartPath)
 	}
-	ch, err := chartutil.Load(chartPath)
+	ch, err := loader.Load(chartPath)
 	if err != nil {
 		t.Errorf("unexpected error loading packaged chart: %v", err)
 	}
@@ -332,7 +333,7 @@ func createValuesFile(t *testing.T, data string) string {
 
 func getChartValues(chartPath string) (chartutil.Values, error) {
 
-	chart, err := chartutil.Load(chartPath)
+	chart, err := loader.Load(chartPath)
 	if err != nil {
 		return nil, err
 	}
diff --git a/cmd/helm/repo_update_test.go b/cmd/helm/repo_update_test.go
index b84cd7a2d678f79cb0d4bd7d55a25cb70a30eef3..b040bdc6e588a78440b2824fa96320ad56b9b0a6 100644
--- a/cmd/helm/repo_update_test.go
+++ b/cmd/helm/repo_update_test.go
@@ -45,7 +45,7 @@ func TestUpdateCmd(t *testing.T) {
 	}
 	o := &repoUpdateOptions{
 		update: updater,
-		home:   helmpath.Home(hh),
+		home:   hh,
 	}
 	if err := o.run(out); err != nil {
 		t.Fatal(err)
diff --git a/cmd/helm/search/search_test.go b/cmd/helm/search/search_test.go
index 19568d9ca6139074f39bbfc50f933cca5e2ba063..92bf6c97d0617113cd85a2f2d434883a28a37be9 100644
--- a/cmd/helm/search/search_test.go
+++ b/cmd/helm/search/search_test.go
@@ -20,7 +20,7 @@ import (
 	"strings"
 	"testing"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/repo"
 )
 
diff --git a/cmd/helm/template.go b/cmd/helm/template.go
index a69cd6c6fa98cd34428c9fc91ea58faf4294e11e..08682f2ffbe66abf78a5f7168b27ff3586e32ab4 100644
--- a/cmd/helm/template.go
+++ b/cmd/helm/template.go
@@ -31,12 +31,12 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
 	"k8s.io/helm/pkg/engine"
 	"k8s.io/helm/pkg/hapi/release"
 	util "k8s.io/helm/pkg/releaseutil"
 	"k8s.io/helm/pkg/tiller"
-	tversion "k8s.io/helm/pkg/version"
 )
 
 const defaultDirectoryPermission = 0755
@@ -152,17 +152,15 @@ func (o *templateOptions) run(out io.Writer) error {
 	}
 
 	// Check chart requirements to make sure all dependencies are present in /charts
-	c, err := chartutil.Load(o.chartPath)
+	c, err := loader.Load(o.chartPath)
 	if err != nil {
 		return err
 	}
 
-	if req, err := chartutil.LoadRequirements(c); err == nil {
+	if req := c.Requirements; req != nil {
 		if err := checkDependencies(c, req); err != nil {
 			return err
 		}
-	} else if err != chartutil.ErrRequirementsNotFound {
-		return errors.Wrap(err, "cannot load requirements")
 	}
 	options := chartutil.ReleaseOptions{
 		Name: o.releaseName,
@@ -178,22 +176,18 @@ func (o *templateOptions) run(out io.Writer) error {
 	// Set up engine.
 	renderer := engine.New()
 
-	caps := &chartutil.Capabilities{
-		APIVersions: chartutil.DefaultVersionSet,
-		KubeVersion: chartutil.DefaultKubeVersion,
-		HelmVersion: tversion.GetBuildInfo(),
-	}
-
 	// kubernetes version
 	kv, err := semver.NewVersion(o.kubeVersion)
 	if err != nil {
 		return errors.Wrap(err, "could not parse a kubernetes version")
 	}
+
+	caps := chartutil.DefaultCapabilities
 	caps.KubeVersion.Major = fmt.Sprint(kv.Major())
 	caps.KubeVersion.Minor = fmt.Sprint(kv.Minor())
 	caps.KubeVersion.GitVersion = fmt.Sprintf("v%d.%d.0", kv.Major(), kv.Minor())
 
-	vals, err := chartutil.ToRenderValuesCaps(c, config, options, caps)
+	vals, err := chartutil.ToRenderValues(c, config, options, caps)
 	if err != nil {
 		return err
 	}
diff --git a/cmd/helm/testdata/output/upgrade-with-bad-dependencies.txt b/cmd/helm/testdata/output/upgrade-with-bad-dependencies.txt
index c77fba18b32d53ca37c392e9f27e357681ef8bec..a50915b9be8d66f528b1a0828c1c1eb09f75c2fe 100644
--- a/cmd/helm/testdata/output/upgrade-with-bad-dependencies.txt
+++ b/cmd/helm/testdata/output/upgrade-with-bad-dependencies.txt
@@ -1 +1 @@
-Error: cannot load requirements: error converting YAML to JSON: yaml: line 2: did not find expected '-' indicator
+Error: cannot load requirements.yaml: error converting YAML to JSON: yaml: line 2: did not find expected '-' indicator
diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go
index 83e2bb24d072fb90e0e17a6d22dcab114da5899d..c7db6fb7e10c2596bd131ac375fc7ab680509428 100644
--- a/cmd/helm/upgrade.go
+++ b/cmd/helm/upgrade.go
@@ -25,7 +25,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"k8s.io/helm/cmd/helm/require"
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/helm"
 	"k8s.io/helm/pkg/storage/driver"
 )
@@ -150,17 +150,15 @@ func (o *upgradeOptions) run(out io.Writer) error {
 	}
 
 	// Check chart requirements to make sure all dependencies are present in /charts
-	if ch, err := chartutil.Load(chartPath); err == nil {
-		if req, err := chartutil.LoadRequirements(ch); err == nil {
-			if err := checkDependencies(ch, req); err != nil {
-				return err
-			}
-		} else if err != chartutil.ErrRequirementsNotFound {
-			return errors.Wrap(err, "cannot load requirements")
-		}
-	} else {
+	ch, err := loader.Load(chartPath)
+	if err != nil {
 		return err
 	}
+	if req := ch.Requirements; req != nil {
+		if err := checkDependencies(ch, req); err != nil {
+			return err
+		}
+	}
 
 	resp, err := o.client.UpdateRelease(
 		o.release,
diff --git a/cmd/helm/upgrade_test.go b/cmd/helm/upgrade_test.go
index c75b50b1ad14f8d49230dca07af61fa1109d6346..904085725ad40bd3efa5420bfd02bc0e9b73b6ce 100644
--- a/cmd/helm/upgrade_test.go
+++ b/cmd/helm/upgrade_test.go
@@ -19,8 +19,9 @@ package main
 import (
 	"testing"
 
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 	"k8s.io/helm/pkg/helm"
 )
@@ -36,7 +37,7 @@ func TestUpgradeCmd(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Error creating chart for upgrade: %v", err)
 	}
-	ch, err := chartutil.Load(chartPath)
+	ch, err := loader.Load(chartPath)
 	if err != nil {
 		t.Fatalf("Error loading chart: %v", err)
 	}
@@ -56,7 +57,7 @@ func TestUpgradeCmd(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Error creating chart: %v", err)
 	}
-	ch, err = chartutil.Load(chartPath)
+	ch, err = loader.Load(chartPath)
 	if err != nil {
 		t.Fatalf("Error loading updated chart: %v", err)
 	}
@@ -73,7 +74,7 @@ func TestUpgradeCmd(t *testing.T) {
 		t.Fatalf("Error creating chart: %v", err)
 	}
 	var ch2 *chart.Chart
-	ch2, err = chartutil.Load(chartPath)
+	ch2, err = loader.Load(chartPath)
 	if err != nil {
 		t.Fatalf("Error loading updated chart: %v", err)
 	}
diff --git a/docs/examples/nginx/charts/alpine/Chart.yaml b/docs/examples/nginx/charts/alpine/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f4b660d4f823f912aa59ab87bebd124c288b4f19
--- /dev/null
+++ b/docs/examples/nginx/charts/alpine/Chart.yaml
@@ -0,0 +1,7 @@
+name: alpine
+description: Deploy a basic Alpine Linux pod
+version: 0.1.0
+home: https://github.com/kubernetes/helm
+sources:
+  - https://github.com/kubernetes/helm
+appVersion: 3.3
diff --git a/docs/examples/nginx/charts/alpine/README.md b/docs/examples/nginx/charts/alpine/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3e354724c8a617be45ee96e3464f119a455e898f
--- /dev/null
+++ b/docs/examples/nginx/charts/alpine/README.md
@@ -0,0 +1,11 @@
+# Alpine: A simple Helm chart
+
+Run a single pod of Alpine Linux.
+
+The `templates/` directory contains a very simple pod resource with a
+couple of parameters.
+
+The `values.yaml` file contains the default values for the
+`alpine-pod.yaml` template.
+
+You can install this example using `helm install docs/examples/alpine`.
diff --git a/docs/examples/nginx/charts/alpine/templates/_helpers.tpl b/docs/examples/nginx/charts/alpine/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..3e9c25bed07e11b0ccda5a66f653a6856e32dda7
--- /dev/null
+++ b/docs/examples/nginx/charts/alpine/templates/_helpers.tpl
@@ -0,0 +1,16 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "alpine.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+*/}}
+{{- define "alpine.fullname" -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
diff --git a/docs/examples/nginx/charts/alpine/templates/alpine-pod.yaml b/docs/examples/nginx/charts/alpine/templates/alpine-pod.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..da9caef781b8ab57abce0cefb16fc81da56ec7f6
--- /dev/null
+++ b/docs/examples/nginx/charts/alpine/templates/alpine-pod.yaml
@@ -0,0 +1,23 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: {{ template "alpine.fullname" . }}
+  labels:
+    # The "heritage" label is used to track which tool deployed a given chart.
+    # It is useful for admins who want to see what releases a particular tool
+    # is responsible for.
+    heritage: {{ .Release.Service }}
+    # The "release" convention makes it easy to tie a release to all of the
+    # Kubernetes resources that were created as part of that release.
+    release: {{ .Release.Name }}
+    # This makes it easy to audit chart usage.
+    chart: {{ .Chart.Name }}-{{ .Chart.Version }}
+    app: {{ template "alpine.name" . }}
+spec:
+  # This shows how to use a simple value. This will look for a passed-in value called restartPolicy.
+  restartPolicy: {{ .Values.restartPolicy }}
+  containers:
+  - name: waiter
+    image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+    imagePullPolicy: {{ .Values.image.pullPolicy }}
+    command: ["/bin/sleep", "9000"]
diff --git a/docs/examples/nginx/charts/alpine/values.yaml b/docs/examples/nginx/charts/alpine/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..afe8cc6c0f683e8e82f1eba2d706deee178cf748
--- /dev/null
+++ b/docs/examples/nginx/charts/alpine/values.yaml
@@ -0,0 +1,6 @@
+image:
+  repository: alpine
+  tag: 3.3
+  pullPolicy: IfNotPresent
+
+restartPolicy: Never
diff --git a/docs/examples/nginx/templates/NOTES.txt b/docs/examples/nginx/templates/NOTES.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4bdf443f60c8c6bbdfad39cc1b2eca8bce9782b8
--- /dev/null
+++ b/docs/examples/nginx/templates/NOTES.txt
@@ -0,0 +1 @@
+Sample notes for {{ .Chart.Name }}
\ No newline at end of file
diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go
new file mode 100644
index 0000000000000000000000000000000000000000..b51bb5b90c92389658749d9ee5cf025c40266232
--- /dev/null
+++ b/pkg/chart/chart.go
@@ -0,0 +1,95 @@
+/*
+Copyright 2018 The Kubernetes Authors All rights reserved.
+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 chart
+
+// Chart is a helm package that contains metadata, a default config, zero or more
+// optionally parameterizable templates, and zero or more charts (dependencies).
+type Chart struct {
+	// Metadata is the contents of the Chartfile.
+	Metadata *Metadata
+	// Requirements is the contents of requirements.yaml.
+	Requirements *Requirements
+	// RequirementsLock is the contents of requirements.lock.
+	RequirementsLock *RequirementsLock
+	// Templates for this chart.
+	Templates []*File
+	// Values are default config for this template.
+	Values []byte
+	// Files are miscellaneous files in a chart archive,
+	// e.g. README, LICENSE, etc.
+	Files []*File
+
+	parent       *Chart
+	dependencies []*Chart
+}
+
+// SetDependencies replaces the chart dependencies.
+func (ch *Chart) SetDependencies(charts ...*Chart) {
+	ch.dependencies = nil
+	ch.AddDependency(charts...)
+}
+
+// Name returns the name of the chart.
+func (ch *Chart) Name() string {
+	if ch.Metadata == nil {
+		return ""
+	}
+	return ch.Metadata.Name
+}
+
+// AddDependency determines if the chart is a subchart.
+func (ch *Chart) AddDependency(charts ...*Chart) {
+	for i, x := range charts {
+		charts[i].parent = ch
+		ch.dependencies = append(ch.dependencies, x)
+	}
+}
+
+// Root finds the root chart.
+func (ch *Chart) Root() *Chart {
+	if ch.IsRoot() {
+		return ch
+	}
+	return ch.Parent().Root()
+}
+
+// Dependencies are the charts that this chart depends on.
+func (ch *Chart) Dependencies() []*Chart { return ch.dependencies }
+
+// IsRoot determines if the chart is the root chart.
+func (ch *Chart) IsRoot() bool { return ch.parent == nil }
+
+// Parent returns a subchart's parent chart.
+func (ch *Chart) Parent() *Chart { return ch.parent }
+
+// Parent sets a subchart's parent chart.
+func (ch *Chart) SetParent(chart *Chart) { ch.parent = chart }
+
+// ChartPath returns the full path to this chart in dot notation.
+func (ch *Chart) ChartPath() string {
+	if !ch.IsRoot() {
+		return ch.Parent().ChartPath() + "." + ch.Name()
+	}
+	return ch.Name()
+}
+
+// ChartFullPath returns the full path to this chart.
+func (ch *Chart) ChartFullPath() string {
+	if !ch.IsRoot() {
+		return ch.Parent().ChartFullPath() + "/charts/" + ch.Name()
+	}
+	return ch.Name()
+}
diff --git a/pkg/chartutil/transform.go b/pkg/chart/chartfile.go
similarity index 56%
rename from pkg/chartutil/transform.go
rename to pkg/chart/chartfile.go
index f360e4fad27db72f37021b8d28cf11acf1a769ef..b669b781b947a62c21d1045540aefd947ce9e6cf 100644
--- a/pkg/chartutil/transform.go
+++ b/pkg/chart/chartfile.go
@@ -1,11 +1,10 @@
 /*
-Copyright 2016 The Kubernetes Authors All rights reserved.
-
+Copyright 2018 The Kubernetes Authors All rights reserved.
 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
+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,
@@ -14,12 +13,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package chartutil
-
-import "strings"
+package chart
 
-// Transform performs a string replacement of the specified source for
-// a given key with the replacement string
-func Transform(src, key, replacement string) []byte {
-	return []byte(strings.Replace(src, key, replacement, -1))
-}
+// APIVersionv1 is the API version number for version 1.
+const APIVersionv1 = "v1"
diff --git a/pkg/hapi/chart/file.go b/pkg/chart/file.go
similarity index 92%
rename from pkg/hapi/chart/file.go
rename to pkg/chart/file.go
index 90edd59f108f091fc15cbaa35f12d49293d767a4..53ce89d3fbc185b1472618b283c060cf1ca79655 100644
--- a/pkg/hapi/chart/file.go
+++ b/pkg/chart/file.go
@@ -21,7 +21,7 @@ package chart
 // base directory.
 type File struct {
 	// Name is the path-like name of the template.
-	Name string `json:"name,omitempty"`
+	Name string
 	// Data is the template as byte data.
-	Data []byte `json:"data,omitempty"`
+	Data []byte
 }
diff --git a/pkg/chart/loader/archive.go b/pkg/chart/loader/archive.go
new file mode 100644
index 0000000000000000000000000000000000000000..dbdab98f994240f905dfece15c770ada0504c111
--- /dev/null
+++ b/pkg/chart/loader/archive.go
@@ -0,0 +1,110 @@
+/*
+Copyright 2016 The Kubernetes Authors All rights reserved.
+
+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 loader
+
+import (
+	"archive/tar"
+	"bytes"
+	"compress/gzip"
+	"io"
+	"os"
+	"strings"
+
+	"github.com/pkg/errors"
+
+	"k8s.io/helm/pkg/chart"
+)
+
+type FileLoader string
+
+func (l FileLoader) Load() (*chart.Chart, error) {
+	return LoadFile(string(l))
+}
+
+// LoadFile loads from an archive file.
+func LoadFile(name string) (*chart.Chart, error) {
+	if fi, err := os.Stat(name); err != nil {
+		return nil, err
+	} else if fi.IsDir() {
+		return nil, errors.New("cannot load a directory")
+	}
+
+	raw, err := os.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	defer raw.Close()
+
+	return LoadArchive(raw)
+}
+
+// LoadArchive loads from a reader containing a compressed tar archive.
+func LoadArchive(in io.Reader) (*chart.Chart, error) {
+	unzipped, err := gzip.NewReader(in)
+	if err != nil {
+		return &chart.Chart{}, err
+	}
+	defer unzipped.Close()
+
+	files := []*BufferedFile{}
+	tr := tar.NewReader(unzipped)
+	for {
+		b := bytes.NewBuffer(nil)
+		hd, err := tr.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return &chart.Chart{}, err
+		}
+
+		if hd.FileInfo().IsDir() {
+			// Use this instead of hd.Typeflag because we don't have to do any
+			// inference chasing.
+			continue
+		}
+
+		// Archive could contain \ if generated on Windows
+		delimiter := "/"
+		if strings.ContainsRune(hd.Name, '\\') {
+			delimiter = "\\"
+		}
+
+		parts := strings.Split(hd.Name, delimiter)
+		n := strings.Join(parts[1:], delimiter)
+
+		// Normalize the path to the / delimiter
+		n = strings.Replace(n, delimiter, "/", -1)
+
+		if parts[0] == "Chart.yaml" {
+			return nil, errors.New("chart yaml not in base directory")
+		}
+
+		if _, err := io.Copy(b, tr); err != nil {
+			return &chart.Chart{}, err
+		}
+
+		files = append(files, &BufferedFile{Name: n, Data: b.Bytes()})
+		b.Reset()
+	}
+
+	if len(files) == 0 {
+		return nil, errors.New("no files in chart archive")
+	}
+
+	return LoadFiles(files)
+}
diff --git a/pkg/chart/loader/directory.go b/pkg/chart/loader/directory.go
new file mode 100644
index 0000000000000000000000000000000000000000..f51620cfb61a3c59d601a74cf966fb7f5f96e8d1
--- /dev/null
+++ b/pkg/chart/loader/directory.go
@@ -0,0 +1,105 @@
+/*
+Copyright 2016 The Kubernetes Authors All rights reserved.
+
+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 loader
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/pkg/errors"
+
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/ignore"
+	"k8s.io/helm/pkg/sympath"
+)
+
+type DirLoader string
+
+func (l DirLoader) Load() (*chart.Chart, error) {
+	return LoadDir(string(l))
+}
+
+// LoadDir loads from a directory.
+//
+// This loads charts only from directories.
+func LoadDir(dir string) (*chart.Chart, error) {
+	topdir, err := filepath.Abs(dir)
+	if err != nil {
+		return nil, err
+	}
+
+	// Just used for errors.
+	c := &chart.Chart{}
+
+	rules := ignore.Empty()
+	ifile := filepath.Join(topdir, ignore.HelmIgnore)
+	if _, err := os.Stat(ifile); err == nil {
+		r, err := ignore.ParseFile(ifile)
+		if err != nil {
+			return c, err
+		}
+		rules = r
+	}
+	rules.AddDefaults()
+
+	files := []*BufferedFile{}
+	topdir += string(filepath.Separator)
+
+	walk := func(name string, fi os.FileInfo, err error) error {
+		n := strings.TrimPrefix(name, topdir)
+		if n == "" {
+			// No need to process top level. Avoid bug with helmignore .* matching
+			// empty names. See issue 1779.
+			return nil
+		}
+
+		// Normalize to / since it will also work on Windows
+		n = filepath.ToSlash(n)
+
+		if err != nil {
+			return err
+		}
+		if fi.IsDir() {
+			// Directory-based ignore rules should involve skipping the entire
+			// contents of that directory.
+			if rules.Ignore(n, fi) {
+				return filepath.SkipDir
+			}
+			return nil
+		}
+
+		// If a .helmignore file matches, skip this file.
+		if rules.Ignore(n, fi) {
+			return nil
+		}
+
+		data, err := ioutil.ReadFile(name)
+		if err != nil {
+			return errors.Wrapf(err, "error reading %s", n)
+		}
+
+		files = append(files, &BufferedFile{Name: n, Data: data})
+		return nil
+	}
+	if err = sympath.Walk(topdir, walk); err != nil {
+		return c, err
+	}
+
+	return LoadFiles(files)
+}
diff --git a/pkg/chart/loader/load.go b/pkg/chart/loader/load.go
new file mode 100644
index 0000000000000000000000000000000000000000..bbc0cca6336a3d51deb6fa163c1fd7835738d2b2
--- /dev/null
+++ b/pkg/chart/loader/load.go
@@ -0,0 +1,151 @@
+/*
+Copyright 2016 The Kubernetes Authors All rights reserved.
+
+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 loader
+
+import (
+	"bytes"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/ghodss/yaml"
+	"github.com/pkg/errors"
+
+	"k8s.io/helm/pkg/chart"
+)
+
+type ChartLoader interface {
+	Load() (*chart.Chart, error)
+}
+
+func Loader(name string) (ChartLoader, error) {
+	fi, err := os.Stat(name)
+	if err != nil {
+		return nil, err
+	}
+	if fi.IsDir() {
+		return DirLoader(name), nil
+	}
+	return FileLoader(name), nil
+
+}
+
+// Load takes a string name, tries to resolve it to a file or directory, and then loads it.
+//
+// This is the preferred way to load a chart. It will discover the chart encoding
+// and hand off to the appropriate chart reader.
+//
+// If a .helmignore file is present, the directory loader will skip loading any files
+// matching it. But .helmignore is not evaluated when reading out of an archive.
+func Load(name string) (*chart.Chart, error) {
+	l, err := Loader(name)
+	if err != nil {
+		return nil, err
+	}
+	return l.Load()
+}
+
+// BufferedFile represents an archive file buffered for later processing.
+type BufferedFile struct {
+	Name string
+	Data []byte
+}
+
+// LoadFiles loads from in-memory files.
+func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
+	c := new(chart.Chart)
+	subcharts := make(map[string][]*BufferedFile)
+
+	for _, f := range files {
+		switch {
+		case f.Name == "Chart.yaml":
+			c.Metadata = new(chart.Metadata)
+			if err := yaml.Unmarshal(f.Data, c.Metadata); err != nil {
+				return c, errors.Wrap(err, "cannot load Chart.yaml")
+			}
+		case f.Name == "requirements.yaml":
+			c.Requirements = new(chart.Requirements)
+			if err := yaml.Unmarshal(f.Data, c.Requirements); err != nil {
+				return c, errors.Wrap(err, "cannot load requirements.yaml")
+			}
+		case f.Name == "requirements.lock":
+			c.RequirementsLock = new(chart.RequirementsLock)
+			if err := yaml.Unmarshal(f.Data, &c.RequirementsLock); err != nil {
+				return c, errors.Wrap(err, "cannot load requirements.lock")
+			}
+		case f.Name == "values.yaml":
+			c.Values = f.Data
+		case strings.HasPrefix(f.Name, "templates/"):
+			c.Templates = append(c.Templates, &chart.File{Name: f.Name, Data: f.Data})
+		case strings.HasPrefix(f.Name, "charts/"):
+			if filepath.Ext(f.Name) == ".prov" {
+				c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
+				continue
+			}
+
+			fname := strings.TrimPrefix(f.Name, "charts/")
+			cname := strings.SplitN(fname, "/", 2)[0]
+			subcharts[cname] = append(subcharts[cname], &BufferedFile{Name: fname, Data: f.Data})
+		default:
+			c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
+		}
+	}
+
+	// Ensure that we got a Chart.yaml file
+	if c.Metadata == nil {
+		return c, errors.New("chart metadata (Chart.yaml) missing")
+	}
+	if c.Name() == "" {
+		return c, errors.New("invalid chart (Chart.yaml): name must not be empty")
+	}
+
+	for n, files := range subcharts {
+		var sc *chart.Chart
+		var err error
+		switch {
+		case strings.IndexAny(n, "_.") == 0:
+			continue
+		case filepath.Ext(n) == ".tgz":
+			file := files[0]
+			if file.Name != n {
+				return c, errors.Errorf("error unpacking tar in %s: expected %s, got %s", c.Name(), n, file.Name)
+			}
+			// Untar the chart and add to c.Dependencies
+			sc, err = LoadArchive(bytes.NewBuffer(file.Data))
+		default:
+			// We have to trim the prefix off of every file, and ignore any file
+			// that is in charts/, but isn't actually a chart.
+			buff := make([]*BufferedFile, 0, len(files))
+			for _, f := range files {
+				parts := strings.SplitN(f.Name, "/", 2)
+				if len(parts) < 2 {
+					continue
+				}
+				f.Name = parts[1]
+				buff = append(buff, f)
+			}
+			sc, err = LoadFiles(buff)
+		}
+
+		if err != nil {
+			return c, errors.Wrapf(err, "error unpacking %s in %s", n, c.Name())
+		}
+		c.AddDependency(sc)
+	}
+
+	return c, nil
+}
diff --git a/pkg/chartutil/load_test.go b/pkg/chart/loader/load_test.go
similarity index 63%
rename from pkg/chartutil/load_test.go
rename to pkg/chart/loader/load_test.go
index 36dc371852060bb9baadc84457bdb146acd5713e..aca2227806408d78043357ecf20a2d004ec9d62a 100644
--- a/pkg/chartutil/load_test.go
+++ b/pkg/chart/loader/load_test.go
@@ -14,27 +14,35 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package chartutil
+package loader
 
 import (
-	"path"
 	"testing"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 )
 
 func TestLoadDir(t *testing.T) {
-	c, err := Load("testdata/frobnitz")
+	l, err := Loader("testdata/frobnitz")
+	if err != nil {
+		t.Fatalf("Failed to load testdata: %s", err)
+	}
+	c, err := l.Load()
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 	verifyFrobnitz(t, c)
 	verifyChart(t, c)
 	verifyRequirements(t, c)
+	verifyRequirementsLock(t, c)
 }
 
 func TestLoadFile(t *testing.T) {
-	c, err := Load("testdata/frobnitz-1.2.3.tgz")
+	l, err := Loader("testdata/frobnitz-1.2.3.tgz")
+	if err != nil {
+		t.Fatalf("Failed to load testdata: %s", err)
+	}
+	c, err := l.Load()
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
@@ -46,7 +54,7 @@ func TestLoadFile(t *testing.T) {
 func TestLoadFiles(t *testing.T) {
 	goodFiles := []*BufferedFile{
 		{
-			Name: ChartfileName,
+			Name: "Chart.yaml",
 			Data: []byte(`apiVersion: v1
 name: frobnitz
 description: This is a frobnitz.
@@ -67,16 +75,16 @@ icon: https://example.com/64x64.png
 `),
 		},
 		{
-			Name: ValuesfileName,
-			Data: []byte(defaultValues),
+			Name: "values.yaml",
+			Data: []byte("some values"),
 		},
 		{
-			Name: path.Join("templates", DeploymentName),
-			Data: []byte(defaultDeployment),
+			Name: "templates/deployment.yaml",
+			Data: []byte("some deployment"),
 		},
 		{
-			Name: path.Join("templates", ServiceName),
-			Data: []byte(defaultService),
+			Name: "templates/service.yaml",
+			Data: []byte("some service"),
 		},
 	}
 
@@ -85,11 +93,11 @@ icon: https://example.com/64x64.png
 		t.Errorf("Expected good files to be loaded, got %v", err)
 	}
 
-	if c.Metadata.Name != "frobnitz" {
-		t.Errorf("Expected chart name to be 'frobnitz', got %s", c.Metadata.Name)
+	if c.Name() != "frobnitz" {
+		t.Errorf("Expected chart name to be 'frobnitz', got %s", c.Name())
 	}
 
-	if string(c.Values) != defaultValues {
+	if string(c.Values) != "some values" {
 		t.Error("Expected chart values to be populated with default values")
 	}
 
@@ -119,15 +127,16 @@ func TestLoadFileBackslash(t *testing.T) {
 }
 
 func verifyChart(t *testing.T, c *chart.Chart) {
-	if c.Metadata.Name == "" {
+	t.Helper()
+	if c.Name() == "" {
 		t.Fatalf("No chart metadata found on %v", c)
 	}
-	t.Logf("Verifying chart %s", c.Metadata.Name)
+	t.Logf("Verifying chart %s", c.Name())
 	if len(c.Templates) != 1 {
 		t.Errorf("Expected 1 template, got %d", len(c.Templates))
 	}
 
-	numfiles := 8
+	numfiles := 6
 	if len(c.Files) != numfiles {
 		t.Errorf("Expected %d extra files, got %d", numfiles, len(c.Files))
 		for _, n := range c.Files {
@@ -135,10 +144,10 @@ func verifyChart(t *testing.T, c *chart.Chart) {
 		}
 	}
 
-	if len(c.Dependencies) != 2 {
-		t.Errorf("Expected 2 dependencies, got %d (%v)", len(c.Dependencies), c.Dependencies)
-		for _, d := range c.Dependencies {
-			t.Logf("\tSubchart: %s\n", d.Metadata.Name)
+	if len(c.Dependencies()) != 2 {
+		t.Errorf("Expected 2 dependencies, got %d (%v)", len(c.Dependencies()), c.Dependencies())
+		for _, d := range c.Dependencies() {
+			t.Logf("\tSubchart: %s\n", d.Name())
 		}
 	}
 
@@ -151,35 +160,31 @@ func verifyChart(t *testing.T, c *chart.Chart) {
 		},
 	}
 
-	for _, dep := range c.Dependencies {
+	for _, dep := range c.Dependencies() {
 		if dep.Metadata == nil {
 			t.Fatalf("expected metadata on dependency: %v", dep)
 		}
-		exp, ok := expect[dep.Metadata.Name]
+		exp, ok := expect[dep.Name()]
 		if !ok {
-			t.Fatalf("Unknown dependency %s", dep.Metadata.Name)
+			t.Fatalf("Unknown dependency %s", dep.Name())
 		}
 		if exp["version"] != dep.Metadata.Version {
-			t.Errorf("Expected %s version %s, got %s", dep.Metadata.Name, exp["version"], dep.Metadata.Version)
+			t.Errorf("Expected %s version %s, got %s", dep.Name(), exp["version"], dep.Metadata.Version)
 		}
 	}
 
 }
 
 func verifyRequirements(t *testing.T, c *chart.Chart) {
-	r, err := LoadRequirements(c)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if len(r.Dependencies) != 2 {
-		t.Errorf("Expected 2 requirements, got %d", len(r.Dependencies))
+	if len(c.Requirements.Dependencies) != 2 {
+		t.Errorf("Expected 2 requirements, got %d", len(c.Requirements.Dependencies))
 	}
-	tests := []*Dependency{
+	tests := []*chart.Dependency{
 		{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
 		{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
 	}
 	for i, tt := range tests {
-		d := r.Dependencies[i]
+		d := c.Requirements.Dependencies[i]
 		if d.Name != tt.Name {
 			t.Errorf("Expected dependency named %q, got %q", tt.Name, d.Name)
 		}
@@ -191,20 +196,17 @@ func verifyRequirements(t *testing.T, c *chart.Chart) {
 		}
 	}
 }
+
 func verifyRequirementsLock(t *testing.T, c *chart.Chart) {
-	r, err := LoadRequirementsLock(c)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if len(r.Dependencies) != 2 {
-		t.Errorf("Expected 2 requirements, got %d", len(r.Dependencies))
+	if len(c.Requirements.Dependencies) != 2 {
+		t.Errorf("Expected 2 requirements, got %d", len(c.Requirements.Dependencies))
 	}
-	tests := []*Dependency{
+	tests := []*chart.Dependency{
 		{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
 		{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
 	}
 	for i, tt := range tests {
-		d := r.Dependencies[i]
+		d := c.Requirements.Dependencies[i]
 		if d.Name != tt.Name {
 			t.Errorf("Expected dependency named %q, got %q", tt.Name, d.Name)
 		}
@@ -223,17 +225,55 @@ func verifyFrobnitz(t *testing.T, c *chart.Chart) {
 
 func verifyChartFileAndTemplate(t *testing.T, c *chart.Chart, name string) {
 
-	verifyChartfile(t, c.Metadata, name)
-
+	if c.Metadata == nil {
+		t.Fatal("Metadata is nil")
+	}
+	if c.Name() != name {
+		t.Errorf("Expected %s, got %s", name, c.Name())
+	}
 	if len(c.Templates) != 1 {
 		t.Fatalf("Expected 1 template, got %d", len(c.Templates))
 	}
-
 	if c.Templates[0].Name != "templates/template.tpl" {
 		t.Errorf("Unexpected template: %s", c.Templates[0].Name)
 	}
-
 	if len(c.Templates[0].Data) == 0 {
 		t.Error("No template data.")
 	}
+	if len(c.Files) != 6 {
+		t.Fatalf("Expected 6 Files, got %d", len(c.Files))
+	}
+	if len(c.Dependencies()) != 2 {
+		t.Fatalf("Expected 2 Dependency, got %d", len(c.Dependencies()))
+	}
+	if len(c.Requirements.Dependencies) != 2 {
+		t.Fatalf("Expected 2 Requirements.Dependency, got %d", len(c.Requirements.Dependencies))
+	}
+	if len(c.RequirementsLock.Dependencies) != 2 {
+		t.Fatalf("Expected 2 RequirementsLock.Dependency, got %d", len(c.RequirementsLock.Dependencies))
+	}
+
+	for _, dep := range c.Dependencies() {
+		switch dep.Name() {
+		case "mariner":
+		case "alpine":
+			if len(dep.Templates) != 1 {
+				t.Fatalf("Expected 1 template, got %d", len(dep.Templates))
+			}
+			if dep.Templates[0].Name != "templates/alpine-pod.yaml" {
+				t.Errorf("Unexpected template: %s", dep.Templates[0].Name)
+			}
+			if len(dep.Templates[0].Data) == 0 {
+				t.Error("No template data.")
+			}
+			if len(dep.Files) != 1 {
+				t.Fatalf("Expected 1 Files, got %d", len(dep.Files))
+			}
+			if len(dep.Dependencies()) != 2 {
+				t.Fatalf("Expected 2 Dependency, got %d", len(dep.Dependencies()))
+			}
+		default:
+			t.Errorf("Unexpected dependeny %s", dep.Name())
+		}
+	}
 }
diff --git a/pkg/chart/loader/testdata/frobnitz-1.2.3.tgz b/pkg/chart/loader/testdata/frobnitz-1.2.3.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..fb21cd08fb08fd2f4e45e940634ce1cdb0421457
Binary files /dev/null and b/pkg/chart/loader/testdata/frobnitz-1.2.3.tgz differ
diff --git a/pkg/chart/loader/testdata/frobnitz/.helmignore b/pkg/chart/loader/testdata/frobnitz/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..9973a57b8035d98658162558e488aa24f7d8fa15
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/.helmignore
@@ -0,0 +1 @@
+ignore/
diff --git a/pkg/chart/loader/testdata/frobnitz/Chart.yaml b/pkg/chart/loader/testdata/frobnitz/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..134cd11090ae2e6ce3b5b715592afe6248c7f06b
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/Chart.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+name: frobnitz
+description: This is a frobnitz.
+version: "1.2.3"
+keywords:
+  - frobnitz
+  - sprocket
+  - dodad
+maintainers:
+  - name: The Helm Team
+    email: helm@example.com
+  - name: Someone Else
+    email: nobody@example.com
+sources:
+  - https://example.com/foo/bar
+home: http://example.com
+icon: https://example.com/64x64.png
+annotations:
+  extrakey: extravalue
+  anotherkey: anothervalue
diff --git a/pkg/chart/loader/testdata/frobnitz/INSTALL.txt b/pkg/chart/loader/testdata/frobnitz/INSTALL.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2010438c200050456edaa55cf626d158d671d02d
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/INSTALL.txt
@@ -0,0 +1 @@
+This is an install document. The client may display this.
diff --git a/pkg/chart/loader/testdata/frobnitz/LICENSE b/pkg/chart/loader/testdata/frobnitz/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..6121943b10a68319b2c1f66e659b8a69a4df7ed0
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/LICENSE
@@ -0,0 +1 @@
+LICENSE placeholder.
diff --git a/pkg/chart/loader/testdata/frobnitz/README.md b/pkg/chart/loader/testdata/frobnitz/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8cf4cc3d7c0f1d3c418e7ba4eab1335b606f063d
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/README.md
@@ -0,0 +1,11 @@
+# Frobnitz
+
+This is an example chart.
+
+## Usage
+
+This is an example. It has no usage.
+
+## Development
+
+For developer info, see the top-level repository.
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/_ignore_me b/pkg/chart/loader/testdata/frobnitz/charts/_ignore_me
new file mode 100644
index 0000000000000000000000000000000000000000..2cecca6824919777f7a23269d19f8f0137e527f3
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/_ignore_me
@@ -0,0 +1 @@
+This should be ignored by the loader, but may be included in a chart.
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/Chart.yaml b/pkg/chart/loader/testdata/frobnitz/charts/alpine/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..38a4aaa54c58e8f5cc77108df3ee8f895e9a388c
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/alpine/Chart.yaml
@@ -0,0 +1,4 @@
+name: alpine
+description: Deploy a basic Alpine Linux pod
+version: 0.1.0
+home: https://k8s.io/helm
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/README.md b/pkg/chart/loader/testdata/frobnitz/charts/alpine/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a7c84fc416caba955a2e10a5ddec21768130be54
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/alpine/README.md
@@ -0,0 +1,9 @@
+This example was generated using the command `helm create alpine`.
+
+The `templates/` directory contains a very simple pod resource with a
+couple of parameters.
+
+The `values.toml` file contains the default values for the
+`alpine-pod.yaml` template.
+
+You can install this example using `helm install docs/examples/alpine`.
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml b/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..171e361564676fc5d4bd77a52519557a1b8937f2
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast1/Chart.yaml
@@ -0,0 +1,4 @@
+name: mast1
+description: A Helm chart for Kubernetes
+version: 0.1.0
+home: ""
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast1/values.yaml b/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast1/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..42c39c262c314b9dd6992814944b894160a87ca4
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast1/values.yaml
@@ -0,0 +1,4 @@
+# Default values for mast1.
+# This is a YAML-formatted file.
+# Declare name/value pairs to be passed into your templates.
+# name = "value"
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast2-0.1.0.tgz b/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast2-0.1.0.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..ced5a4a6adf946f76033b6ee584affc12433cb78
Binary files /dev/null and b/pkg/chart/loader/testdata/frobnitz/charts/alpine/charts/mast2-0.1.0.tgz differ
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml b/pkg/chart/loader/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0c6980cf7fa33abf364184ef0c911a8b8efc438c
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/alpine/templates/alpine-pod.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: {{.Release.Name}}-{{.Chart.Name}}
+  labels:
+    heritage: {{.Release.Service}}
+    chartName: {{.Chart.Name}}
+    chartVersion: {{.Chart.Version | quote}}
+spec:
+  restartPolicy: {{default "Never" .restart_policy}}
+  containers:
+  - name: waiter
+    image: "alpine:3.3"
+    command: ["/bin/sleep","9000"]
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/alpine/values.yaml b/pkg/chart/loader/testdata/frobnitz/charts/alpine/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6c2aab7ba9df3f92832ce2844b001108f84013d0
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/charts/alpine/values.yaml
@@ -0,0 +1,2 @@
+# The pod name
+name: "my-alpine"
diff --git a/pkg/chart/loader/testdata/frobnitz/charts/mariner-4.3.2.tgz b/pkg/chart/loader/testdata/frobnitz/charts/mariner-4.3.2.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..3af333e76a3c268ce6d23f5ae8ba59387a75a38a
Binary files /dev/null and b/pkg/chart/loader/testdata/frobnitz/charts/mariner-4.3.2.tgz differ
diff --git a/pkg/chart/loader/testdata/frobnitz/docs/README.md b/pkg/chart/loader/testdata/frobnitz/docs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d40747cafd28860f06babbf27e85d56203e53e35
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/docs/README.md
@@ -0,0 +1 @@
+This is a placeholder for documentation.
diff --git a/pkg/chart/loader/testdata/frobnitz/icon.svg b/pkg/chart/loader/testdata/frobnitz/icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8921306066db91867ee2fd152c83ce75785c7803
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/icon.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    version="1.0" width="256" height="256" id="test">
+  <desc>Example icon</desc>
+  <rect id="first" x="2" y="2" width="40" height="60" fill="navy"/>
+  <rect id="second" x="15" y="4" width="40" height="60" fill="red"/>
+</svg>
diff --git a/pkg/chart/loader/testdata/frobnitz/ignore/me.txt b/pkg/chart/loader/testdata/frobnitz/ignore/me.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/pkg/chart/loader/testdata/frobnitz/requirements.lock b/pkg/chart/loader/testdata/frobnitz/requirements.lock
new file mode 100644
index 0000000000000000000000000000000000000000..6fcc2ed9fbeb693c4eb334d2fd572d0f6ac3a92f
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/requirements.lock
@@ -0,0 +1,8 @@
+dependencies:
+  - name: alpine
+    version: "0.1.0"
+    repository: https://example.com/charts
+  - name: mariner
+    version: "4.3.2"
+    repository: https://example.com/charts
+digest: invalid
diff --git a/pkg/chart/loader/testdata/frobnitz/requirements.yaml b/pkg/chart/loader/testdata/frobnitz/requirements.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5eb0bc98bc312f35c5c4a9d1fc6ad40c1ea2abba
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/requirements.yaml
@@ -0,0 +1,7 @@
+dependencies:
+  - name: alpine
+    version: "0.1.0"
+    repository: https://example.com/charts
+  - name: mariner
+    version: "4.3.2"
+    repository: https://example.com/charts
diff --git a/pkg/chart/loader/testdata/frobnitz/templates/template.tpl b/pkg/chart/loader/testdata/frobnitz/templates/template.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..c651ee6a03cc43f952aae1583ea967c622d55ddc
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/templates/template.tpl
@@ -0,0 +1 @@
+Hello {{.Name | default "world"}}
diff --git a/pkg/chart/loader/testdata/frobnitz/values.yaml b/pkg/chart/loader/testdata/frobnitz/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..61f501258835165a881de21520fe570295a53241
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz/values.yaml
@@ -0,0 +1,6 @@
+# A values file contains configuration.
+
+name: "Some Name"
+
+section:
+  name: "Name in a section"
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash-1.2.3.tgz b/pkg/chart/loader/testdata/frobnitz_backslash-1.2.3.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..692dd6aba5da8382262cd94fae736785709b339f
Binary files /dev/null and b/pkg/chart/loader/testdata/frobnitz_backslash-1.2.3.tgz differ
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/.helmignore b/pkg/chart/loader/testdata/frobnitz_backslash/.helmignore
new file mode 100755
index 0000000000000000000000000000000000000000..9973a57b8035d98658162558e488aa24f7d8fa15
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/.helmignore
@@ -0,0 +1 @@
+ignore/
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/Chart.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/Chart.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..49df2a0464991c03fe3351d36c581f25566fd3f3
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/Chart.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+name: frobnitz_backslash
+description: This is a frobnitz.
+version: "1.2.3"
+keywords:
+  - frobnitz
+  - sprocket
+  - dodad
+maintainers:
+  - name: The Helm Team
+    email: helm@example.com
+  - name: Someone Else
+    email: nobody@example.com
+sources:
+  - https://example.com/foo/bar
+home: http://example.com
+icon: https://example.com/64x64.png
+annotations:
+  extrakey: extravalue
+  anotherkey: anothervalue
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/INSTALL.txt b/pkg/chart/loader/testdata/frobnitz_backslash/INSTALL.txt
new file mode 100755
index 0000000000000000000000000000000000000000..2010438c200050456edaa55cf626d158d671d02d
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/INSTALL.txt
@@ -0,0 +1 @@
+This is an install document. The client may display this.
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/LICENSE b/pkg/chart/loader/testdata/frobnitz_backslash/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..6121943b10a68319b2c1f66e659b8a69a4df7ed0
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/LICENSE
@@ -0,0 +1 @@
+LICENSE placeholder.
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/README.md b/pkg/chart/loader/testdata/frobnitz_backslash/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..8cf4cc3d7c0f1d3c418e7ba4eab1335b606f063d
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/README.md
@@ -0,0 +1,11 @@
+# Frobnitz
+
+This is an example chart.
+
+## Usage
+
+This is an example. It has no usage.
+
+## Development
+
+For developer info, see the top-level repository.
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/_ignore_me b/pkg/chart/loader/testdata/frobnitz_backslash/charts/_ignore_me
new file mode 100755
index 0000000000000000000000000000000000000000..2cecca6824919777f7a23269d19f8f0137e527f3
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/_ignore_me
@@ -0,0 +1 @@
+This should be ignored by the loader, but may be included in a chart.
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/Chart.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/Chart.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..38a4aaa54c58e8f5cc77108df3ee8f895e9a388c
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/Chart.yaml
@@ -0,0 +1,4 @@
+name: alpine
+description: Deploy a basic Alpine Linux pod
+version: 0.1.0
+home: https://k8s.io/helm
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/README.md b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..a7c84fc416caba955a2e10a5ddec21768130be54
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/README.md
@@ -0,0 +1,9 @@
+This example was generated using the command `helm create alpine`.
+
+The `templates/` directory contains a very simple pod resource with a
+couple of parameters.
+
+The `values.toml` file contains the default values for the
+`alpine-pod.yaml` template.
+
+You can install this example using `helm install docs/examples/alpine`.
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast1/Chart.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast1/Chart.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..171e361564676fc5d4bd77a52519557a1b8937f2
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast1/Chart.yaml
@@ -0,0 +1,4 @@
+name: mast1
+description: A Helm chart for Kubernetes
+version: 0.1.0
+home: ""
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast1/values.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast1/values.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..42c39c262c314b9dd6992814944b894160a87ca4
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast1/values.yaml
@@ -0,0 +1,4 @@
+# Default values for mast1.
+# This is a YAML-formatted file.
+# Declare name/value pairs to be passed into your templates.
+# name = "value"
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast2-0.1.0.tgz b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast2-0.1.0.tgz
new file mode 100755
index 0000000000000000000000000000000000000000..ced5a4a6adf946f76033b6ee584affc12433cb78
Binary files /dev/null and b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/charts/mast2-0.1.0.tgz differ
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/templates/alpine-pod.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/templates/alpine-pod.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..0c6980cf7fa33abf364184ef0c911a8b8efc438c
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/templates/alpine-pod.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: {{.Release.Name}}-{{.Chart.Name}}
+  labels:
+    heritage: {{.Release.Service}}
+    chartName: {{.Chart.Name}}
+    chartVersion: {{.Chart.Version | quote}}
+spec:
+  restartPolicy: {{default "Never" .restart_policy}}
+  containers:
+  - name: waiter
+    image: "alpine:3.3"
+    command: ["/bin/sleep","9000"]
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/values.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/values.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..6c2aab7ba9df3f92832ce2844b001108f84013d0
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/charts/alpine/values.yaml
@@ -0,0 +1,2 @@
+# The pod name
+name: "my-alpine"
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/charts/mariner-4.3.2.tgz b/pkg/chart/loader/testdata/frobnitz_backslash/charts/mariner-4.3.2.tgz
new file mode 100755
index 0000000000000000000000000000000000000000..3af333e76a3c268ce6d23f5ae8ba59387a75a38a
Binary files /dev/null and b/pkg/chart/loader/testdata/frobnitz_backslash/charts/mariner-4.3.2.tgz differ
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/docs/README.md b/pkg/chart/loader/testdata/frobnitz_backslash/docs/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..d40747cafd28860f06babbf27e85d56203e53e35
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/docs/README.md
@@ -0,0 +1 @@
+This is a placeholder for documentation.
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/icon.svg b/pkg/chart/loader/testdata/frobnitz_backslash/icon.svg
new file mode 100755
index 0000000000000000000000000000000000000000..8921306066db91867ee2fd152c83ce75785c7803
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/icon.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    version="1.0" width="256" height="256" id="test">
+  <desc>Example icon</desc>
+  <rect id="first" x="2" y="2" width="40" height="60" fill="navy"/>
+  <rect id="second" x="15" y="4" width="40" height="60" fill="red"/>
+</svg>
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/ignore/me.txt b/pkg/chart/loader/testdata/frobnitz_backslash/ignore/me.txt
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/requirements.lock b/pkg/chart/loader/testdata/frobnitz_backslash/requirements.lock
new file mode 100755
index 0000000000000000000000000000000000000000..6fcc2ed9fbeb693c4eb334d2fd572d0f6ac3a92f
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/requirements.lock
@@ -0,0 +1,8 @@
+dependencies:
+  - name: alpine
+    version: "0.1.0"
+    repository: https://example.com/charts
+  - name: mariner
+    version: "4.3.2"
+    repository: https://example.com/charts
+digest: invalid
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/requirements.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/requirements.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..5eb0bc98bc312f35c5c4a9d1fc6ad40c1ea2abba
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/requirements.yaml
@@ -0,0 +1,7 @@
+dependencies:
+  - name: alpine
+    version: "0.1.0"
+    repository: https://example.com/charts
+  - name: mariner
+    version: "4.3.2"
+    repository: https://example.com/charts
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/templates/template.tpl b/pkg/chart/loader/testdata/frobnitz_backslash/templates/template.tpl
new file mode 100755
index 0000000000000000000000000000000000000000..c651ee6a03cc43f952aae1583ea967c622d55ddc
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/templates/template.tpl
@@ -0,0 +1 @@
+Hello {{.Name | default "world"}}
diff --git a/pkg/chart/loader/testdata/frobnitz_backslash/values.yaml b/pkg/chart/loader/testdata/frobnitz_backslash/values.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..61f501258835165a881de21520fe570295a53241
--- /dev/null
+++ b/pkg/chart/loader/testdata/frobnitz_backslash/values.yaml
@@ -0,0 +1,6 @@
+# A values file contains configuration.
+
+name: "Some Name"
+
+section:
+  name: "Name in a section"
diff --git a/pkg/hapi/chart/metadata.go b/pkg/chart/metadata.go
similarity index 100%
rename from pkg/hapi/chart/metadata.go
rename to pkg/chart/metadata.go
diff --git a/pkg/chart/requirements.go b/pkg/chart/requirements.go
new file mode 100644
index 0000000000000000000000000000000000000000..76b8ea8ab13cbfd0752bf69854015e0150a2ae31
--- /dev/null
+++ b/pkg/chart/requirements.go
@@ -0,0 +1,70 @@
+/*
+Copyright 2018 The Kubernetes Authors All rights reserved.
+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 chart
+
+import "time"
+
+// Dependency describes a chart upon which another chart depends.
+//
+// Dependencies can be used to express developer intent, or to capture the state
+// of a chart.
+type Dependency struct {
+	// Name is the name of the dependency.
+	//
+	// This must mach the name in the dependency's Chart.yaml.
+	Name string `json:"name"`
+	// Version is the version (range) of this chart.
+	//
+	// A lock file will always produce a single version, while a dependency
+	// may contain a semantic version range.
+	Version string `json:"version,omitempty"`
+	// The URL to the repository.
+	//
+	// Appending `index.yaml` to this string should result in a URL that can be
+	// used to fetch the repository index.
+	Repository string `json:"repository"`
+	// A yaml path that resolves to a boolean, used for enabling/disabling charts (e.g. subchart1.enabled )
+	Condition string `json:"condition,omitempty"`
+	// Tags can be used to group charts for enabling/disabling together
+	Tags []string `json:"tags,omitempty"`
+	// Enabled bool determines if chart should be loaded
+	Enabled bool `json:"enabled,omitempty"`
+	// ImportValues holds the mapping of source values to parent key to be imported. Each item can be a
+	// string or pair of child/parent sublist items.
+	ImportValues []interface{} `json:"import-values,omitempty"`
+	// Alias usable alias to be used for the chart
+	Alias string `json:"alias,omitempty"`
+}
+
+// Requirements is a list of requirements for a chart.
+//
+// Requirements are charts upon which this chart depends. This expresses
+// developer intent.
+type Requirements struct {
+	Dependencies []*Dependency `json:"dependencies"`
+}
+
+// RequirementsLock is a lock file for requirements.
+//
+// It represents the state that the dependencies should be in.
+type RequirementsLock struct {
+	// Genderated is the date the lock file was last generated.
+	Generated time.Time `json:"generated"`
+	// Digest is a hash of the requirements file used to generate it.
+	Digest string `json:"digest"`
+	// Dependencies is the list of dependencies that this lock file has locked.
+	Dependencies []*Dependency `json:"dependencies"`
+}
diff --git a/pkg/chartutil/capabilities.go b/pkg/chartutil/capabilities.go
index 06c117315d801336fce2a4d58bb4cbef94e33d8b..fdba95d7d424bd7e65b2149ea447a720daff15da 100644
--- a/pkg/chartutil/capabilities.go
+++ b/pkg/chartutil/capabilities.go
@@ -20,13 +20,14 @@ import (
 	"runtime"
 
 	"k8s.io/apimachinery/pkg/version"
+	"k8s.io/client-go/kubernetes/scheme"
 
 	tversion "k8s.io/helm/pkg/version"
 )
 
 var (
 	// DefaultVersionSet is the default version set, which includes only Core V1 ("v1").
-	DefaultVersionSet = NewVersionSet("v1")
+	DefaultVersionSet = allKnownVersions()
 
 	// DefaultKubeVersion is the default kubernetes version
 	DefaultKubeVersion = &version.Info{
@@ -37,6 +38,12 @@ var (
 		Compiler:   runtime.Compiler,
 		Platform:   fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
 	}
+
+	// DefaultCapabilities is the default set of capabilities.
+	DefaultCapabilities = &Capabilities{
+		APIVersions: DefaultVersionSet,
+		KubeVersion: DefaultKubeVersion,
+	}
 )
 
 // Capabilities describes the capabilities of the Kubernetes cluster that Tiller is attached to.
@@ -52,11 +59,11 @@ type Capabilities struct {
 }
 
 // VersionSet is a set of Kubernetes API versions.
-type VersionSet map[string]interface{}
+type VersionSet map[string]struct{}
 
 // NewVersionSet creates a new version set from a list of strings.
 func NewVersionSet(apiVersions ...string) VersionSet {
-	vs := VersionSet{}
+	vs := make(VersionSet)
 	for _, v := range apiVersions {
 		vs[v] = struct{}{}
 	}
@@ -70,3 +77,11 @@ func (v VersionSet) Has(apiVersion string) bool {
 	_, ok := v[apiVersion]
 	return ok
 }
+
+func allKnownVersions() VersionSet {
+	vs := make(VersionSet)
+	for gvk := range scheme.Scheme.AllKnownTypes() {
+		vs[gvk.GroupVersion().String()] = struct{}{}
+	}
+	return vs
+}
diff --git a/pkg/chartutil/capabilities_test.go b/pkg/chartutil/capabilities_test.go
index ac20f0038c31125a0d6cbc7d55cc497e1bad8692..385a866c981178e801eff28dc6021d35a2276840 100644
--- a/pkg/chartutil/capabilities_test.go
+++ b/pkg/chartutil/capabilities_test.go
@@ -38,9 +38,6 @@ func TestDefaultVersionSet(t *testing.T) {
 	if !DefaultVersionSet.Has("v1") {
 		t.Error("Expected core v1 version set")
 	}
-	if d := len(DefaultVersionSet); d != 1 {
-		t.Errorf("Expected only one version, got %d", d)
-	}
 }
 
 func TestCapabilities(t *testing.T) {
diff --git a/pkg/chartutil/chartfile.go b/pkg/chartutil/chartfile.go
index 461e47357415defd132a03ec12ef9027fb9d28db..e388496f77c09d8d7e05518ae2b767f42adb2d84 100644
--- a/pkg/chartutil/chartfile.go
+++ b/pkg/chartutil/chartfile.go
@@ -24,29 +24,18 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 )
 
-// APIVersionv1 is the API version number for version 1.
-const APIVersionv1 = "v1"
-
-// UnmarshalChartfile takes raw Chart.yaml data and unmarshals it.
-func UnmarshalChartfile(data []byte) (*chart.Metadata, error) {
-	y := &chart.Metadata{}
-	err := yaml.Unmarshal(data, y)
-	if err != nil {
-		return nil, err
-	}
-	return y, nil
-}
-
 // LoadChartfile loads a Chart.yaml file into a *chart.Metadata.
 func LoadChartfile(filename string) (*chart.Metadata, error) {
 	b, err := ioutil.ReadFile(filename)
 	if err != nil {
 		return nil, err
 	}
-	return UnmarshalChartfile(b)
+	y := new(chart.Metadata)
+	err = yaml.Unmarshal(b, y)
+	return y, err
 }
 
 // SaveChartfile saves the given metadata as a Chart.yaml file at the given path.
@@ -80,8 +69,8 @@ func IsChartDir(dirName string) (bool, error) {
 		return false, errors.Errorf("cannot read Chart.Yaml in directory %q", dirName)
 	}
 
-	chartContent, err := UnmarshalChartfile(chartYamlContent)
-	if err != nil {
+	chartContent := new(chart.Metadata)
+	if err := yaml.Unmarshal(chartYamlContent, &chartContent); err != nil {
 		return false, err
 	}
 	if chartContent == nil {
diff --git a/pkg/chartutil/chartfile_test.go b/pkg/chartutil/chartfile_test.go
index 49de60f6542d229af7bf56e90747df3d2c21dc41..35be0ab27e75dde4a8cc4abf413745b677131524 100644
--- a/pkg/chartutil/chartfile_test.go
+++ b/pkg/chartutil/chartfile_test.go
@@ -19,7 +19,7 @@ package chartutil
 import (
 	"testing"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 )
 
 const testfile = "testdata/chartfiletest.yaml"
@@ -40,8 +40,8 @@ func verifyChartfile(t *testing.T, f *chart.Metadata, name string) {
 	}
 
 	// Api instead of API because it was generated via protobuf.
-	if f.APIVersion != APIVersionv1 {
-		t.Errorf("Expected API Version %q, got %q", APIVersionv1, f.APIVersion)
+	if f.APIVersion != chart.APIVersionv1 {
+		t.Errorf("Expected API Version %q, got %q", chart.APIVersionv1, f.APIVersion)
 	}
 
 	if f.Name != name {
diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go
index a2e02404758d5ea2748c74191305a97fa687338e..8b27bd2f3dacb147af1f6044b855716f863caeea 100644
--- a/pkg/chartutil/create.go
+++ b/pkg/chartutil/create.go
@@ -21,10 +21,12 @@ import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
+	"strings"
 
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 )
 
 const (
@@ -294,7 +296,7 @@ Create chart name and version as used by the chart label.
 
 // CreateFrom creates a new chart, but scaffolds it from the src chart.
 func CreateFrom(chartfile *chart.Metadata, dest, src string) error {
-	schart, err := Load(src)
+	schart, err := loader.Load(src)
 	if err != nil {
 		return errors.Wrapf(err, "could not load %s", src)
 	}
@@ -304,12 +306,12 @@ func CreateFrom(chartfile *chart.Metadata, dest, src string) error {
 	var updatedTemplates []*chart.File
 
 	for _, template := range schart.Templates {
-		newData := Transform(string(template.Data), "<CHARTNAME>", schart.Metadata.Name)
+		newData := transform(string(template.Data), schart.Name())
 		updatedTemplates = append(updatedTemplates, &chart.File{Name: template.Name, Data: newData})
 	}
 
 	schart.Templates = updatedTemplates
-	schart.Values = Transform(string(schart.Values), "<CHARTNAME>", schart.Metadata.Name)
+	schart.Values = transform(string(schart.Values), schart.Name())
 
 	return SaveDir(schart, dest)
 }
@@ -378,27 +380,27 @@ func Create(chartfile *chart.Metadata, dir string) (string, error) {
 		{
 			// ingress.yaml
 			path:    filepath.Join(cdir, TemplatesDir, IngressFileName),
-			content: Transform(defaultIngress, "<CHARTNAME>", chartfile.Name),
+			content: transform(defaultIngress, chartfile.Name),
 		},
 		{
 			// deployment.yaml
 			path:    filepath.Join(cdir, TemplatesDir, DeploymentName),
-			content: Transform(defaultDeployment, "<CHARTNAME>", chartfile.Name),
+			content: transform(defaultDeployment, chartfile.Name),
 		},
 		{
 			// service.yaml
 			path:    filepath.Join(cdir, TemplatesDir, ServiceName),
-			content: Transform(defaultService, "<CHARTNAME>", chartfile.Name),
+			content: transform(defaultService, chartfile.Name),
 		},
 		{
 			// NOTES.txt
 			path:    filepath.Join(cdir, TemplatesDir, NotesName),
-			content: Transform(defaultNotes, "<CHARTNAME>", chartfile.Name),
+			content: transform(defaultNotes, chartfile.Name),
 		},
 		{
 			// _helpers.tpl
 			path:    filepath.Join(cdir, TemplatesDir, HelpersName),
-			content: Transform(defaultHelpers, "<CHARTNAME>", chartfile.Name),
+			content: transform(defaultHelpers, chartfile.Name),
 		},
 	}
 
@@ -413,3 +415,9 @@ func Create(chartfile *chart.Metadata, dir string) (string, error) {
 	}
 	return cdir, nil
 }
+
+// transform performs a string replacement of the specified source for
+// a given key with the replacement string
+func transform(src, replacement string) []byte {
+	return []byte(strings.Replace(src, "<CHARTNAME>", replacement, -1))
+}
diff --git a/pkg/chartutil/create_test.go b/pkg/chartutil/create_test.go
index 01f5902a9161b29f25c22949a3b25d6f6ea5d901..d932c5d1e009c2a68c26e7cea3a7ce0669142620 100644
--- a/pkg/chartutil/create_test.go
+++ b/pkg/chartutil/create_test.go
@@ -23,7 +23,8 @@ import (
 	"strings"
 	"testing"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 )
 
 func TestCreate(t *testing.T) {
@@ -42,13 +43,13 @@ func TestCreate(t *testing.T) {
 
 	dir := filepath.Join(tdir, "foo")
 
-	mychart, err := LoadDir(c)
+	mychart, err := loader.LoadDir(c)
 	if err != nil {
 		t.Fatalf("Failed to load newly created chart %q: %s", c, err)
 	}
 
-	if mychart.Metadata.Name != "foo" {
-		t.Errorf("Expected name to be 'foo', got %q", mychart.Metadata.Name)
+	if mychart.Name() != "foo" {
+		t.Errorf("Expected name to be 'foo', got %q", mychart.Name())
 	}
 
 	for _, d := range []string{TemplatesDir, ChartsDir} {
@@ -94,13 +95,13 @@ func TestCreateFrom(t *testing.T) {
 	dir := filepath.Join(tdir, "foo")
 
 	c := filepath.Join(tdir, cf.Name)
-	mychart, err := LoadDir(c)
+	mychart, err := loader.LoadDir(c)
 	if err != nil {
 		t.Fatalf("Failed to load newly created chart %q: %s", c, err)
 	}
 
-	if mychart.Metadata.Name != "foo" {
-		t.Errorf("Expected name to be 'foo', got %q", mychart.Metadata.Name)
+	if mychart.Name() != "foo" {
+		t.Errorf("Expected name to be 'foo', got %q", mychart.Name())
 	}
 
 	for _, d := range []string{TemplatesDir, ChartsDir} {
@@ -111,7 +112,7 @@ func TestCreateFrom(t *testing.T) {
 		}
 	}
 
-	for _, f := range []string{ChartfileName, ValuesfileName, "requirements.yaml"} {
+	for _, f := range []string{ChartfileName, ValuesfileName} {
 		if fi, err := os.Stat(filepath.Join(dir, f)); err != nil {
 			t.Errorf("Expected %s file: %s", f, err)
 		} else if fi.IsDir() {
diff --git a/pkg/chartutil/doc.go b/pkg/chartutil/doc.go
index 1190d968da3a032acf47bad252d775dc177dd97f..516f4c1cb51b515bdffc946fea22a996128a7de9 100644
--- a/pkg/chartutil/doc.go
+++ b/pkg/chartutil/doc.go
@@ -16,7 +16,7 @@ limitations under the License.
 
 /*Package chartutil contains tools for working with charts.
 
-Charts are described in the protocol buffer definition (pkg/proto/hapi/charts).
+Charts are described in the protocol buffer definition (pkg/proto/charts).
 This packe provides utilities for serializing and deserializing charts.
 
 A chart can be represented on the file system in one of two ways:
@@ -27,18 +27,18 @@ A chart can be represented on the file system in one of two ways:
 
 This package provides utilitites for working with those file formats.
 
-The preferred way of loading a chart is using 'chartutil.Load`:
+The preferred way of loading a chart is using 'loader.Load`:
 
-	chart, err := chartutil.Load(filename)
+	chart, err := loader.Load(filename)
 
 This will attempt to discover whether the file at 'filename' is a directory or
 a chart archive. It will then load accordingly.
 
 For accepting raw compressed tar file data from an io.Reader, the
-'chartutil.LoadArchive()' will read in the data, uncompress it, and unpack it
+'loader.LoadArchive()' will read in the data, uncompress it, and unpack it
 into a Chart.
 
-When creating charts in memory, use the 'k8s.io/helm/pkg/proto/hapi/chart'
+When creating charts in memory, use the 'k8s.io/helm/pkg/proto/chart'
 package directly.
 */
 package chartutil // import "k8s.io/helm/pkg/chartutil"
diff --git a/pkg/chartutil/expand.go b/pkg/chartutil/expand.go
index 126e14e80059e4b3039fbc2d2367646baddfd3ea..7f4fc8bd5e8b5498c37e42aaf67f9fcdb71fae2a 100644
--- a/pkg/chartutil/expand.go
+++ b/pkg/chartutil/expand.go
@@ -40,8 +40,8 @@ func Expand(dir string, r io.Reader) error {
 			return err
 		}
 
-		//split header name and create missing directories
-		d, _ := filepath.Split(header.Name)
+		// split header name and create missing directories
+		d := filepath.Dir(header.Name)
 		fullDir := filepath.Join(dir, d)
 		_, err = os.Stat(fullDir)
 		if err != nil && d != "" {
@@ -63,8 +63,7 @@ func Expand(dir string, r io.Reader) error {
 		if err != nil {
 			return err
 		}
-		_, err = io.Copy(file, tr)
-		if err != nil {
+		if _, err = io.Copy(file, tr); err != nil {
 			file.Close()
 			return err
 		}
diff --git a/pkg/chartutil/files.go b/pkg/chartutil/files.go
index ca149a5e71e96968e3533a456b6c823703adb6e5..af61a24a9ddaaed5992e64920e907523ab3a8fe8 100644
--- a/pkg/chartutil/files.go
+++ b/pkg/chartutil/files.go
@@ -26,7 +26,7 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/gobwas/glob"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 )
 
 // Files is a map of files in a chart that can be accessed from a template.
@@ -35,7 +35,7 @@ type Files map[string][]byte
 // NewFiles creates a new Files from chart files.
 // Given an []*any.Any (the format for files in a chart.Chart), extract a map of files.
 func NewFiles(from []*chart.File) Files {
-	files := map[string][]byte{}
+	files := make(map[string][]byte)
 	for _, f := range from {
 		files[f.Name] = f.Data
 	}
@@ -50,11 +50,10 @@ func NewFiles(from []*chart.File) Files {
 // This is intended to be accessed from within a template, so a missed key returns
 // an empty []byte.
 func (f Files) GetBytes(name string) []byte {
-	v, ok := f[name]
-	if !ok {
-		return []byte{}
+	if v, ok := f[name]; ok {
+		return v
 	}
-	return v
+	return []byte{}
 }
 
 // Get returns a string representation of the given file.
@@ -97,7 +96,7 @@ func (f Files) Glob(pattern string) Files {
 // (regardless of path) should be unique.
 //
 // This is designed to be called from a template, and will return empty string
-// (via ToYaml function) if it cannot be serialized to YAML, or if the Files
+// (via ToYAML function) if it cannot be serialized to YAML, or if the Files
 // object is nil.
 //
 // The output will not be indented, so you will want to pipe this to the
@@ -110,14 +109,14 @@ func (f Files) AsConfig() string {
 		return ""
 	}
 
-	m := map[string]string{}
+	m := make(map[string]string)
 
 	// Explicitly convert to strings, and file names
 	for k, v := range f {
 		m[path.Base(k)] = string(v)
 	}
 
-	return ToYaml(m)
+	return ToYAML(m)
 }
 
 // AsSecrets returns the base64-encoded value of a Files object suitable for
@@ -126,7 +125,7 @@ func (f Files) AsConfig() string {
 // (regardless of path) should be unique.
 //
 // This is designed to be called from a template, and will return empty string
-// (via ToYaml function) if it cannot be serialized to YAML, or if the Files
+// (via ToYAML function) if it cannot be serialized to YAML, or if the Files
 // object is nil.
 //
 // The output will not be indented, so you will want to pipe this to the
@@ -139,13 +138,13 @@ func (f Files) AsSecrets() string {
 		return ""
 	}
 
-	m := map[string]string{}
+	m := make(map[string]string)
 
 	for k, v := range f {
 		m[path.Base(k)] = base64.StdEncoding.EncodeToString(v)
 	}
 
-	return ToYaml(m)
+	return ToYAML(m)
 }
 
 // Lines returns each line of a named file (split by "\n") as a slice, so it can
@@ -163,11 +162,11 @@ func (f Files) Lines(path string) []string {
 	return strings.Split(string(f[path]), "\n")
 }
 
-// ToYaml takes an interface, marshals it to yaml, and returns a string. It will
+// ToYAML takes an interface, marshals it to yaml, and returns a string. It will
 // always return a string, even on marshal error (empty string).
 //
 // This is designed to be called from a template.
-func ToYaml(v interface{}) string {
+func ToYAML(v interface{}) string {
 	data, err := yaml.Marshal(v)
 	if err != nil {
 		// Swallow errors inside of a template.
@@ -176,13 +175,13 @@ func ToYaml(v interface{}) string {
 	return strings.TrimSuffix(string(data), "\n")
 }
 
-// FromYaml converts a YAML document into a map[string]interface{}.
+// FromYAML converts a YAML document into a map[string]interface{}.
 //
 // This is not a general-purpose YAML parser, and will not parse all valid
 // YAML documents. Additionally, because its intended use is within templates
 // it tolerates errors. It will insert the returned error message string into
 // m["Error"] in the returned map.
-func FromYaml(str string) map[string]interface{} {
+func FromYAML(str string) map[string]interface{} {
 	m := map[string]interface{}{}
 
 	if err := yaml.Unmarshal([]byte(str), &m); err != nil {
@@ -191,11 +190,11 @@ func FromYaml(str string) map[string]interface{} {
 	return m
 }
 
-// ToToml takes an interface, marshals it to toml, and returns a string. It will
+// ToTOML takes an interface, marshals it to toml, and returns a string. It will
 // always return a string, even on marshal error (empty string).
 //
 // This is designed to be called from a template.
-func ToToml(v interface{}) string {
+func ToTOML(v interface{}) string {
 	b := bytes.NewBuffer(nil)
 	e := toml.NewEncoder(b)
 	err := e.Encode(v)
@@ -205,11 +204,11 @@ func ToToml(v interface{}) string {
 	return b.String()
 }
 
-// ToJson takes an interface, marshals it to json, and returns a string. It will
+// ToJSON takes an interface, marshals it to json, and returns a string. It will
 // always return a string, even on marshal error (empty string).
 //
 // This is designed to be called from a template.
-func ToJson(v interface{}) string {
+func ToJSON(v interface{}) string {
 	data, err := json.Marshal(v)
 	if err != nil {
 		// Swallow errors inside of a template.
@@ -218,14 +217,14 @@ func ToJson(v interface{}) string {
 	return string(data)
 }
 
-// FromJson converts a JSON document into a map[string]interface{}.
+// FromJSON converts a JSON document into a map[string]interface{}.
 //
 // This is not a general-purpose JSON parser, and will not parse all valid
 // JSON documents. Additionally, because its intended use is within templates
 // it tolerates errors. It will insert the returned error message string into
 // m["Error"] in the returned map.
-func FromJson(str string) map[string]interface{} {
-	m := map[string]interface{}{}
+func FromJSON(str string) map[string]interface{} {
+	m := make(map[string]interface{})
 
 	if err := json.Unmarshal([]byte(str), &m); err != nil {
 		m["Error"] = err.Error()
diff --git a/pkg/chartutil/files_test.go b/pkg/chartutil/files_test.go
index a6c9d1b65b0b87c1cf08db2c809d498e241980da..d8174723d3dcf0ad5934711f9b3a58b516e9b572 100644
--- a/pkg/chartutil/files_test.go
+++ b/pkg/chartutil/files_test.go
@@ -97,7 +97,7 @@ func TestLines(t *testing.T) {
 	as.Equal("bar", out[0])
 }
 
-func TestToYaml(t *testing.T) {
+func TestToYAML(t *testing.T) {
 	expect := "foo: bar"
 	v := struct {
 		Foo string `json:"foo"`
@@ -105,12 +105,12 @@ func TestToYaml(t *testing.T) {
 		Foo: "bar",
 	}
 
-	if got := ToYaml(v); got != expect {
+	if got := ToYAML(v); got != expect {
 		t.Errorf("Expected %q, got %q", expect, got)
 	}
 }
 
-func TestToToml(t *testing.T) {
+func TestToTOML(t *testing.T) {
 	expect := "foo = \"bar\"\n"
 	v := struct {
 		Foo string `toml:"foo"`
@@ -118,7 +118,7 @@ func TestToToml(t *testing.T) {
 		Foo: "bar",
 	}
 
-	if got := ToToml(v); got != expect {
+	if got := ToTOML(v); got != expect {
 		t.Errorf("Expected %q, got %q", expect, got)
 	}
 
@@ -128,19 +128,19 @@ func TestToToml(t *testing.T) {
 			"sail": "white",
 		},
 	}
-	got := ToToml(dict)
+	got := ToTOML(dict)
 	expect = "[mast]\n  sail = \"white\"\n"
 	if got != expect {
 		t.Errorf("Expected:\n%s\nGot\n%s\n", expect, got)
 	}
 }
 
-func TestFromYaml(t *testing.T) {
+func TestFromYAML(t *testing.T) {
 	doc := `hello: world
 one:
   two: three
 `
-	dict := FromYaml(doc)
+	dict := FromYAML(doc)
 	if err, ok := dict["Error"]; ok {
 		t.Fatalf("Parse error: %s", err)
 	}
@@ -160,13 +160,13 @@ one:
 - two
 - three
 `
-	dict = FromYaml(doc2)
+	dict = FromYAML(doc2)
 	if _, ok := dict["Error"]; !ok {
 		t.Fatal("Expected parser error")
 	}
 }
 
-func TestToJson(t *testing.T) {
+func TestToJSON(t *testing.T) {
 	expect := `{"foo":"bar"}`
 	v := struct {
 		Foo string `json:"foo"`
@@ -174,12 +174,12 @@ func TestToJson(t *testing.T) {
 		Foo: "bar",
 	}
 
-	if got := ToJson(v); got != expect {
+	if got := ToJSON(v); got != expect {
 		t.Errorf("Expected %q, got %q", expect, got)
 	}
 }
 
-func TestFromJson(t *testing.T) {
+func TestFromJSON(t *testing.T) {
 	doc := `{
   "hello": "world",
   "one": {
@@ -187,7 +187,7 @@ func TestFromJson(t *testing.T) {
   }
 }
 `
-	dict := FromJson(doc)
+	dict := FromJSON(doc)
 	if err, ok := dict["Error"]; ok {
 		t.Fatalf("Parse error: %s", err)
 	}
@@ -209,7 +209,7 @@ func TestFromJson(t *testing.T) {
  "three"
 ]
 `
-	dict = FromJson(doc2)
+	dict = FromJSON(doc2)
 	if _, ok := dict["Error"]; !ok {
 		t.Fatal("Expected parser error")
 	}
diff --git a/pkg/chartutil/load.go b/pkg/chartutil/load.go
deleted file mode 100644
index 44bcbde0383d62ca9cd7f992179aabd7eaca5f4a..0000000000000000000000000000000000000000
--- a/pkg/chartutil/load.go
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-Copyright 2016 The Kubernetes Authors All rights reserved.
-
-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 chartutil
-
-import (
-	"archive/tar"
-	"bytes"
-	"compress/gzip"
-	"io"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"github.com/pkg/errors"
-
-	"k8s.io/helm/pkg/hapi/chart"
-	"k8s.io/helm/pkg/ignore"
-	"k8s.io/helm/pkg/sympath"
-)
-
-// Load takes a string name, tries to resolve it to a file or directory, and then loads it.
-//
-// This is the preferred way to load a chart. It will discover the chart encoding
-// and hand off to the appropriate chart reader.
-//
-// If a .helmignore file is present, the directory loader will skip loading any files
-// matching it. But .helmignore is not evaluated when reading out of an archive.
-func Load(name string) (*chart.Chart, error) {
-	fi, err := os.Stat(name)
-	if err != nil {
-		return nil, err
-	}
-	if fi.IsDir() {
-		if validChart, err := IsChartDir(name); !validChart {
-			return nil, err
-		}
-		return LoadDir(name)
-	}
-	return LoadFile(name)
-}
-
-// BufferedFile represents an archive file buffered for later processing.
-type BufferedFile struct {
-	Name string
-	Data []byte
-}
-
-// LoadArchive loads from a reader containing a compressed tar archive.
-func LoadArchive(in io.Reader) (*chart.Chart, error) {
-	unzipped, err := gzip.NewReader(in)
-	if err != nil {
-		return &chart.Chart{}, err
-	}
-	defer unzipped.Close()
-
-	files := []*BufferedFile{}
-	tr := tar.NewReader(unzipped)
-	for {
-		b := bytes.NewBuffer(nil)
-		hd, err := tr.Next()
-		if err == io.EOF {
-			break
-		}
-		if err != nil {
-			return &chart.Chart{}, err
-		}
-
-		if hd.FileInfo().IsDir() {
-			// Use this instead of hd.Typeflag because we don't have to do any
-			// inference chasing.
-			continue
-		}
-
-		// Archive could contain \ if generated on Windows
-		delimiter := "/"
-		if strings.ContainsRune(hd.Name, '\\') {
-			delimiter = "\\"
-		}
-
-		parts := strings.Split(hd.Name, delimiter)
-		n := strings.Join(parts[1:], delimiter)
-
-		// Normalize the path to the / delimiter
-		n = strings.Replace(n, delimiter, "/", -1)
-
-		if parts[0] == "Chart.yaml" {
-			return nil, errors.New("chart yaml not in base directory")
-		}
-
-		if _, err := io.Copy(b, tr); err != nil {
-			return &chart.Chart{}, err
-		}
-
-		files = append(files, &BufferedFile{Name: n, Data: b.Bytes()})
-		b.Reset()
-	}
-
-	if len(files) == 0 {
-		return nil, errors.New("no files in chart archive")
-	}
-
-	return LoadFiles(files)
-}
-
-// LoadFiles loads from in-memory files.
-func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
-	c := &chart.Chart{}
-	subcharts := map[string][]*BufferedFile{}
-
-	for _, f := range files {
-		if f.Name == "Chart.yaml" {
-			m, err := UnmarshalChartfile(f.Data)
-			if err != nil {
-				return c, err
-			}
-			c.Metadata = m
-		} else if f.Name == "values.toml" {
-			return c, errors.New("values.toml is illegal as of 2.0.0-alpha.2")
-		} else if f.Name == "values.yaml" {
-			c.Values = f.Data
-		} else if strings.HasPrefix(f.Name, "templates/") {
-			c.Templates = append(c.Templates, &chart.File{Name: f.Name, Data: f.Data})
-		} else if strings.HasPrefix(f.Name, "charts/") {
-			if filepath.Ext(f.Name) == ".prov" {
-				c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
-				continue
-			}
-			cname := strings.TrimPrefix(f.Name, "charts/")
-			if strings.IndexAny(cname, "._") == 0 {
-				// Ignore charts/ that start with . or _.
-				continue
-			}
-			parts := strings.SplitN(cname, "/", 2)
-			scname := parts[0]
-			subcharts[scname] = append(subcharts[scname], &BufferedFile{Name: cname, Data: f.Data})
-		} else {
-			c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data})
-		}
-	}
-
-	// Ensure that we got a Chart.yaml file
-	if c.Metadata == nil {
-		return c, errors.New("chart metadata (Chart.yaml) missing")
-	}
-	if c.Metadata.Name == "" {
-		return c, errors.New("invalid chart (Chart.yaml): name must not be empty")
-	}
-
-	for n, files := range subcharts {
-		var sc *chart.Chart
-		var err error
-		if strings.IndexAny(n, "_.") == 0 {
-			continue
-		} else if filepath.Ext(n) == ".tgz" {
-			file := files[0]
-			if file.Name != n {
-				return c, errors.Errorf("error unpacking tar in %s: expected %s, got %s", c.Metadata.Name, n, file.Name)
-			}
-			// Untar the chart and add to c.Dependencies
-			b := bytes.NewBuffer(file.Data)
-			sc, err = LoadArchive(b)
-		} else {
-			// We have to trim the prefix off of every file, and ignore any file
-			// that is in charts/, but isn't actually a chart.
-			buff := make([]*BufferedFile, 0, len(files))
-			for _, f := range files {
-				parts := strings.SplitN(f.Name, "/", 2)
-				if len(parts) < 2 {
-					continue
-				}
-				f.Name = parts[1]
-				buff = append(buff, f)
-			}
-			sc, err = LoadFiles(buff)
-		}
-
-		if err != nil {
-			return c, errors.Wrapf(err, "error unpacking %s in %s", n, c.Metadata.Name)
-		}
-
-		c.Dependencies = append(c.Dependencies, sc)
-	}
-
-	return c, nil
-}
-
-// LoadFile loads from an archive file.
-func LoadFile(name string) (*chart.Chart, error) {
-	if fi, err := os.Stat(name); err != nil {
-		return nil, err
-	} else if fi.IsDir() {
-		return nil, errors.New("cannot load a directory")
-	}
-
-	raw, err := os.Open(name)
-	if err != nil {
-		return nil, err
-	}
-	defer raw.Close()
-
-	return LoadArchive(raw)
-}
-
-// LoadDir loads from a directory.
-//
-// This loads charts only from directories.
-func LoadDir(dir string) (*chart.Chart, error) {
-	topdir, err := filepath.Abs(dir)
-	if err != nil {
-		return nil, err
-	}
-
-	// Just used for errors.
-	c := &chart.Chart{}
-
-	rules := ignore.Empty()
-	ifile := filepath.Join(topdir, ignore.HelmIgnore)
-	if _, err := os.Stat(ifile); err == nil {
-		r, err := ignore.ParseFile(ifile)
-		if err != nil {
-			return c, err
-		}
-		rules = r
-	}
-	rules.AddDefaults()
-
-	files := []*BufferedFile{}
-	topdir += string(filepath.Separator)
-
-	walk := func(name string, fi os.FileInfo, err error) error {
-		n := strings.TrimPrefix(name, topdir)
-		if n == "" {
-			// No need to process top level. Avoid bug with helmignore .* matching
-			// empty names. See issue 1779.
-			return nil
-		}
-
-		// Normalize to / since it will also work on Windows
-		n = filepath.ToSlash(n)
-
-		if err != nil {
-			return err
-		}
-		if fi.IsDir() {
-			// Directory-based ignore rules should involve skipping the entire
-			// contents of that directory.
-			if rules.Ignore(n, fi) {
-				return filepath.SkipDir
-			}
-			return nil
-		}
-
-		// If a .helmignore file matches, skip this file.
-		if rules.Ignore(n, fi) {
-			return nil
-		}
-
-		data, err := ioutil.ReadFile(name)
-		if err != nil {
-			return errors.Wrapf(err, "error reading %s", n)
-		}
-
-		files = append(files, &BufferedFile{Name: n, Data: data})
-		return nil
-	}
-	if err = sympath.Walk(topdir, walk); err != nil {
-		return c, err
-	}
-
-	return LoadFiles(files)
-}
diff --git a/pkg/chartutil/requirements.go b/pkg/chartutil/requirements.go
index e43c44e134d861a6967a598705e07a668561036e..218457cab34fbc2b60726368f1d299bc20ff4fe6 100644
--- a/pkg/chartutil/requirements.go
+++ b/pkg/chartutil/requirements.go
@@ -18,209 +18,88 @@ package chartutil
 import (
 	"log"
 	"strings"
-	"time"
 
 	"github.com/ghodss/yaml"
-	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/version"
 )
 
-const (
-	requirementsName = "requirements.yaml"
-	lockfileName     = "requirements.lock"
-)
-
-var (
-	// ErrRequirementsNotFound indicates that a requirements.yaml is not found.
-	ErrRequirementsNotFound = errors.New(requirementsName + " not found")
-	// ErrLockfileNotFound indicates that a requirements.lock is not found.
-	ErrLockfileNotFound = errors.New(lockfileName + " not found")
-)
-
-// Dependency describes a chart upon which another chart depends.
-//
-// Dependencies can be used to express developer intent, or to capture the state
-// of a chart.
-type Dependency struct {
-	// Name is the name of the dependency.
-	//
-	// This must mach the name in the dependency's Chart.yaml.
-	Name string `json:"name"`
-	// Version is the version (range) of this chart.
-	//
-	// A lock file will always produce a single version, while a dependency
-	// may contain a semantic version range.
-	Version string `json:"version,omitempty"`
-	// The URL to the repository.
-	//
-	// Appending `index.yaml` to this string should result in a URL that can be
-	// used to fetch the repository index.
-	Repository string `json:"repository"`
-	// A yaml path that resolves to a boolean, used for enabling/disabling charts (e.g. subchart1.enabled )
-	Condition string `json:"condition,omitempty"`
-	// Tags can be used to group charts for enabling/disabling together
-	Tags []string `json:"tags,omitempty"`
-	// Enabled bool determines if chart should be loaded
-	Enabled bool `json:"enabled,omitempty"`
-	// ImportValues holds the mapping of source values to parent key to be imported. Each item can be a
-	// string or pair of child/parent sublist items.
-	ImportValues []interface{} `json:"import-values,omitempty"`
-	// Alias usable alias to be used for the chart
-	Alias string `json:"alias,omitempty"`
-}
-
-// ErrNoRequirementsFile to detect error condition
-type ErrNoRequirementsFile error
-
-// Requirements is a list of requirements for a chart.
-//
-// Requirements are charts upon which this chart depends. This expresses
-// developer intent.
-type Requirements struct {
-	Dependencies []*Dependency `json:"dependencies"`
-}
-
-// RequirementsLock is a lock file for requirements.
-//
-// It represents the state that the dependencies should be in.
-type RequirementsLock struct {
-	// Genderated is the date the lock file was last generated.
-	Generated time.Time `json:"generated"`
-	// Digest is a hash of the requirements file used to generate it.
-	Digest string `json:"digest"`
-	// Dependencies is the list of dependencies that this lock file has locked.
-	Dependencies []*Dependency `json:"dependencies"`
-}
-
-// LoadRequirements loads a requirements file from an in-memory chart.
-func LoadRequirements(c *chart.Chart) (*Requirements, error) {
-	var data []byte
-	for _, f := range c.Files {
-		if f.Name == requirementsName {
-			data = f.Data
-		}
-	}
-	if len(data) == 0 {
-		return nil, ErrRequirementsNotFound
-	}
-	r := &Requirements{}
-	return r, yaml.Unmarshal(data, r)
-}
-
-// LoadRequirementsLock loads a requirements lock file.
-func LoadRequirementsLock(c *chart.Chart) (*RequirementsLock, error) {
-	var data []byte
-	for _, f := range c.Files {
-		if f.Name == lockfileName {
-			data = f.Data
-		}
-	}
-	if len(data) == 0 {
-		return nil, ErrLockfileNotFound
-	}
-	r := &RequirementsLock{}
-	return r, yaml.Unmarshal(data, r)
-}
-
 // ProcessRequirementsConditions disables charts based on condition path value in values
-func ProcessRequirementsConditions(reqs *Requirements, cvals Values) {
-	var cond string
-	var conds []string
-	if reqs == nil || len(reqs.Dependencies) == 0 {
+func ProcessRequirementsConditions(reqs *chart.Requirements, cvals Values) {
+	if reqs == nil {
 		return
 	}
 	for _, r := range reqs.Dependencies {
 		var hasTrue, hasFalse bool
-		cond = r.Condition
-		// check for list
-		if len(cond) > 0 {
-			if strings.Contains(cond, ",") {
-				conds = strings.Split(strings.TrimSpace(cond), ",")
-			} else {
-				conds = []string{strings.TrimSpace(cond)}
-			}
-			for _, c := range conds {
-				if len(c) > 0 {
-					// retrieve value
-					vv, err := cvals.PathValue(c)
-					if err == nil {
-						// if not bool, warn
-						if bv, ok := vv.(bool); ok {
-							if bv {
-								hasTrue = true
-							} else {
-								hasFalse = true
-							}
+		for _, c := range strings.Split(strings.TrimSpace(r.Condition), ",") {
+			if len(c) > 0 {
+				// retrieve value
+				vv, err := cvals.PathValue(c)
+				if err == nil {
+					// if not bool, warn
+					if bv, ok := vv.(bool); ok {
+						if bv {
+							hasTrue = true
 						} else {
-							log.Printf("Warning: Condition path '%s' for chart %s returned non-bool value", c, r.Name)
+							hasFalse = true
 						}
-					} else if _, ok := err.(ErrNoValue); !ok {
-						// this is a real error
-						log.Printf("Warning: PathValue returned error %v", err)
-
-					}
-					if vv != nil {
-						// got first value, break loop
-						break
+					} else {
+						log.Printf("Warning: Condition path '%s' for chart %s returned non-bool value", c, r.Name)
 					}
+				} else if _, ok := err.(ErrNoValue); !ok {
+					// this is a real error
+					log.Printf("Warning: PathValue returned error %v", err)
+				}
+				if vv != nil {
+					// got first value, break loop
+					break
 				}
-			}
-			if !hasTrue && hasFalse {
-				r.Enabled = false
-			} else if hasTrue {
-				r.Enabled = true
-
 			}
 		}
+		if !hasTrue && hasFalse {
+			r.Enabled = false
+		} else if hasTrue {
+			r.Enabled = true
 
+		}
 	}
-
 }
 
 // ProcessRequirementsTags disables charts based on tags in values
-func ProcessRequirementsTags(reqs *Requirements, cvals Values) {
-	vt, err := cvals.Table("tags")
-	if err != nil {
+func ProcessRequirementsTags(reqs *chart.Requirements, cvals Values) {
+	if reqs == nil {
 		return
-
 	}
-	if reqs == nil || len(reqs.Dependencies) == 0 {
+	vt, err := cvals.Table("tags")
+	if err != nil {
 		return
 	}
 	for _, r := range reqs.Dependencies {
-		if len(r.Tags) > 0 {
-			tags := r.Tags
-
-			var hasTrue, hasFalse bool
-			for _, k := range tags {
-				if b, ok := vt[k]; ok {
-					// if not bool, warn
-					if bv, ok := b.(bool); ok {
-						if bv {
-							hasTrue = true
-						} else {
-							hasFalse = true
-						}
+		var hasTrue, hasFalse bool
+		for _, k := range r.Tags {
+			if b, ok := vt[k]; ok {
+				// if not bool, warn
+				if bv, ok := b.(bool); ok {
+					if bv {
+						hasTrue = true
 					} else {
-						log.Printf("Warning: Tag '%s' for chart %s returned non-bool value", k, r.Name)
+						hasFalse = true
 					}
+				} else {
+					log.Printf("Warning: Tag '%s' for chart %s returned non-bool value", k, r.Name)
 				}
 			}
-			if !hasTrue && hasFalse {
-				r.Enabled = false
-			} else if hasTrue || !hasTrue && !hasFalse {
-				r.Enabled = true
-
-			}
-
+		}
+		if !hasTrue && hasFalse {
+			r.Enabled = false
+		} else if hasTrue || !hasTrue && !hasFalse {
+			r.Enabled = true
 		}
 	}
-
 }
 
-func getAliasDependency(charts []*chart.Chart, aliasChart *Dependency) *chart.Chart {
+func getAliasDependency(charts []*chart.Chart, aliasChart *chart.Dependency) *chart.Chart {
 	var chartFound chart.Chart
 	for _, existingChart := range charts {
 		if existingChart == nil {
@@ -248,14 +127,7 @@ func getAliasDependency(charts []*chart.Chart, aliasChart *Dependency) *chart.Ch
 
 // ProcessRequirementsEnabled removes disabled charts from dependencies
 func ProcessRequirementsEnabled(c *chart.Chart, v []byte) error {
-	reqs, err := LoadRequirements(c)
-	if err != nil {
-		// if not just missing requirements file, return error
-		if nerr, ok := err.(ErrNoRequirementsFile); !ok {
-			return nerr
-		}
-
-		// no requirements to process
+	if c.Requirements == nil {
 		return nil
 	}
 
@@ -265,9 +137,9 @@ func ProcessRequirementsEnabled(c *chart.Chart, v []byte) error {
 	// However, if the dependency is already specified in requirements.yaml
 	// we should not add it, as it would be anyways processed from requirements.yaml
 
-	for _, existingDependency := range c.Dependencies {
+	for _, existingDependency := range c.Dependencies() {
 		var dependencyFound bool
-		for _, req := range reqs.Dependencies {
+		for _, req := range c.Requirements.Dependencies {
 			if existingDependency.Metadata.Name == req.Name && version.IsCompatibleRange(req.Version, existingDependency.Metadata.Version) {
 				dependencyFound = true
 				break
@@ -278,18 +150,18 @@ func ProcessRequirementsEnabled(c *chart.Chart, v []byte) error {
 		}
 	}
 
-	for _, req := range reqs.Dependencies {
-		if chartDependency := getAliasDependency(c.Dependencies, req); chartDependency != nil {
+	for _, req := range c.Requirements.Dependencies {
+		if chartDependency := getAliasDependency(c.Dependencies(), req); chartDependency != nil {
 			chartDependencies = append(chartDependencies, chartDependency)
 		}
 		if req.Alias != "" {
 			req.Name = req.Alias
 		}
 	}
-	c.Dependencies = chartDependencies
+	c.SetDependencies(chartDependencies...)
 
 	// set all to true
-	for _, lr := range reqs.Dependencies {
+	for _, lr := range c.Requirements.Dependencies {
 		lr.Enabled = true
 	}
 	cvals, err := CoalesceValues(c, v)
@@ -302,34 +174,32 @@ func ProcessRequirementsEnabled(c *chart.Chart, v []byte) error {
 		return err
 	}
 	// flag dependencies as enabled/disabled
-	ProcessRequirementsTags(reqs, cvals)
-	ProcessRequirementsConditions(reqs, cvals)
+	ProcessRequirementsTags(c.Requirements, cvals)
+	ProcessRequirementsConditions(c.Requirements, cvals)
 	// make a map of charts to remove
-	rm := map[string]bool{}
-	for _, r := range reqs.Dependencies {
+	rm := map[string]struct{}{}
+	for _, r := range c.Requirements.Dependencies {
 		if !r.Enabled {
 			// remove disabled chart
-			rm[r.Name] = true
+			rm[r.Name] = struct{}{}
 		}
 	}
 	// don't keep disabled charts in new slice
 	cd := []*chart.Chart{}
-	copy(cd, c.Dependencies[:0])
-	for _, n := range c.Dependencies {
+	copy(cd, c.Dependencies()[:0])
+	for _, n := range c.Dependencies() {
 		if _, ok := rm[n.Metadata.Name]; !ok {
 			cd = append(cd, n)
 		}
-
 	}
+
 	// recursively call self to process sub dependencies
 	for _, t := range cd {
-		err := ProcessRequirementsEnabled(t, yvals)
-		// if its not just missing requirements file, return error
-		if nerr, ok := err.(ErrNoRequirementsFile); !ok && err != nil {
-			return nerr
+		if err := ProcessRequirementsEnabled(t, yvals); err != nil {
+			return err
 		}
 	}
-	c.Dependencies = cd
+	c.SetDependencies(cd...)
 
 	return nil
 }
@@ -361,30 +231,13 @@ func pathToMap(path string, data map[string]interface{}) map[string]interface{}
 			n[i][k] = n[z]
 		}
 	}
-
 	return n[0]
 }
 
-// getParents returns a slice of parent charts in reverse order.
-func getParents(c *chart.Chart, out []*chart.Chart) []*chart.Chart {
-	if len(out) == 0 {
-		out = []*chart.Chart{c}
-	}
-	for _, ch := range c.Dependencies {
-		if len(ch.Dependencies) > 0 {
-			out = append(out, ch)
-			out = getParents(ch, out)
-		}
-	}
-
-	return out
-}
-
 // processImportValues merges values from child to parent based on the chart's dependencies' ImportValues field.
 func processImportValues(c *chart.Chart) error {
-	reqs, err := LoadRequirements(c)
-	if err != nil {
-		return err
+	if c.Requirements == nil {
+		return nil
 	}
 	// combine chart values and empty config to get Values
 	cvals, err := CoalesceValues(c, []byte{})
@@ -393,45 +246,41 @@ func processImportValues(c *chart.Chart) error {
 	}
 	b := make(map[string]interface{})
 	// import values from each dependency if specified in import-values
-	for _, r := range reqs.Dependencies {
-		if len(r.ImportValues) > 0 {
-			var outiv []interface{}
-			for _, riv := range r.ImportValues {
-				switch iv := riv.(type) {
-				case map[string]interface{}:
-					nm := map[string]string{
-						"child":  iv["child"].(string),
-						"parent": iv["parent"].(string),
-					}
-					outiv = append(outiv, nm)
-					s := r.Name + "." + nm["child"]
-					// get child table
-					vv, err := cvals.Table(s)
-					if err != nil {
-						log.Printf("Warning: ImportValues missing table: %v", err)
-						continue
-					}
-					// create value map from child to be merged into parent
-					vm := pathToMap(nm["parent"], vv.AsMap())
-					b = coalesceTables(cvals, vm)
-				case string:
-					nm := map[string]string{
-						"child":  "exports." + iv,
-						"parent": ".",
-					}
-					outiv = append(outiv, nm)
-					s := r.Name + "." + nm["child"]
-					vm, err := cvals.Table(s)
-					if err != nil {
-						log.Printf("Warning: ImportValues missing table: %v", err)
-						continue
-					}
-					b = coalesceTables(b, vm.AsMap())
+	for _, r := range c.Requirements.Dependencies {
+		var outiv []interface{}
+		for _, riv := range r.ImportValues {
+			switch iv := riv.(type) {
+			case map[string]interface{}:
+				nm := map[string]string{
+					"child":  iv["child"].(string),
+					"parent": iv["parent"].(string),
+				}
+				outiv = append(outiv, nm)
+				// get child table
+				vv, err := cvals.Table(r.Name + "." + nm["child"])
+				if err != nil {
+					log.Printf("Warning: ImportValues missing table: %v", err)
+					continue
+				}
+				// create value map from child to be merged into parent
+				vm := pathToMap(nm["parent"], vv.AsMap())
+				b = coalesceTables(cvals, vm)
+			case string:
+				nm := map[string]string{
+					"child":  "exports." + iv,
+					"parent": ".",
 				}
+				outiv = append(outiv, nm)
+				vm, err := cvals.Table(r.Name + "." + nm["child"])
+				if err != nil {
+					log.Printf("Warning: ImportValues missing table: %v", err)
+					continue
+				}
+				b = coalesceTables(b, vm.AsMap())
 			}
-			// set our formatted import values
-			r.ImportValues = outiv
 		}
+		// set our formatted import values
+		r.ImportValues = outiv
 	}
 	b = coalesceTables(b, cvals)
 	y, err := yaml.Marshal(b)
@@ -447,10 +296,11 @@ func processImportValues(c *chart.Chart) error {
 
 // ProcessRequirementsImportValues imports specified chart values from child to parent.
 func ProcessRequirementsImportValues(c *chart.Chart) error {
-	pc := getParents(c, nil)
-	for i := len(pc) - 1; i >= 0; i-- {
-		processImportValues(pc[i])
+	for _, d := range c.Dependencies() {
+		// recurse
+		if err := ProcessRequirementsImportValues(d); err != nil {
+			return err
+		}
 	}
-
-	return nil
+	return processImportValues(c)
 }
diff --git a/pkg/chartutil/requirements_test.go b/pkg/chartutil/requirements_test.go
index 0206f0d2f0bff6f5045f9066f2af46640e542348..f5425e8f7a98fa1ecd7c5f8cb0319f6d21d3fd16 100644
--- a/pkg/chartutil/requirements_test.go
+++ b/pkg/chartutil/requirements_test.go
@@ -20,12 +20,13 @@ import (
 
 	"strconv"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/version"
 )
 
 func TestLoadRequirements(t *testing.T) {
-	c, err := Load("testdata/frobnitz")
+	c, err := loader.Load("testdata/frobnitz")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
@@ -33,158 +34,89 @@ func TestLoadRequirements(t *testing.T) {
 }
 
 func TestLoadRequirementsLock(t *testing.T) {
-	c, err := Load("testdata/frobnitz")
+	c, err := loader.Load("testdata/frobnitz")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 	verifyRequirementsLock(t, c)
 }
-func TestRequirementsTagsNonValue(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags with no effect
-	v := []byte("tags:\n  nothinguseful: false\n\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1", "subcharta", "subchartb"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsTagsDisabledL1(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags disabling a group
-	v := []byte("tags:\n  front-end: false\n\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsTagsEnabledL1(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags disabling a group and enabling a different group
-	v := []byte("tags:\n  front-end: false\n\n  back-end: true\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart2", "subchartb", "subchartc"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-
-func TestRequirementsTagsDisabledL2(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags disabling only children, children still enabled since tag front-end=true in values.yaml
-	v := []byte("tags:\n  subcharta: false\n\n  subchartb: false\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1", "subcharta", "subchartb"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsTagsDisabledL1Mixed(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags disabling all parents/children with additional tag re-enabling a parent
-	v := []byte("tags:\n  front-end: false\n\n  subchart1: true\n\n  back-end: false\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsConditionsNonValue(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags with no effect
-	v := []byte("subchart1:\n  nothinguseful: false\n\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1", "subcharta", "subchartb"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsConditionsEnabledL1Both(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// conditions enabling the parent charts, but back-end (b, c) is still disabled via values.yaml
-	v := []byte("subchart1:\n  enabled: true\nsubchart2:\n  enabled: true\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsConditionsDisabledL1Both(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// conditions disabling the parent charts, effectively disabling children
-	v := []byte("subchart1:\n  enabled: false\nsubchart2:\n  enabled: false\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-
-func TestRequirementsConditionsSecond(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// conditions a child using the second condition path of child's condition
-	v := []byte("subchart1:\n  subcharta:\n    enabled: false\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1", "subchartb"}
-
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsCombinedDisabledL2(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
-	}
-	// tags enabling a parent/child group with condition disabling one child
-	v := []byte("subchartc:\n  enabled: false\ntags:\n  back-end: true\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb", "subchartb"}
 
-	verifyRequirementsEnabled(t, c, v, e)
-}
-func TestRequirementsCombinedDisabledL1(t *testing.T) {
-	c, err := Load("testdata/subpop")
-	if err != nil {
-		t.Fatalf("Failed to load testdata: %s", err)
+func TestRequirementsEnabled(t *testing.T) {
+	tests := []struct {
+		name string
+		v    []byte
+		e    []string // expected charts including duplicates in alphanumeric order
+	}{{
+		"tags with no effect",
+		[]byte("tags:\n  nothinguseful: false\n\n"),
+		[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
+	}, {
+		"tags with no effect",
+		[]byte("tags:\n  nothinguseful: false\n\n"),
+		[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
+	}, {
+		"tags disabling a group",
+		[]byte("tags:\n  front-end: false\n\n"),
+		[]string{"parentchart"},
+	}, {
+		"tags disabling a group and enabling a different group",
+		[]byte("tags:\n  front-end: false\n\n  back-end: true\n"),
+		[]string{"parentchart", "subchart2", "subchartb", "subchartc"},
+	}, {
+		"tags disabling only children, children still enabled since tag front-end=true in values.yaml",
+		[]byte("tags:\n  subcharta: false\n\n  subchartb: false\n"),
+		[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
+	}, {
+		"tags disabling all parents/children with additional tag re-enabling a parent",
+		[]byte("tags:\n  front-end: false\n\n  subchart1: true\n\n  back-end: false\n"),
+		[]string{"parentchart", "subchart1"},
+	}, {
+		"tags with no effect",
+		[]byte("subchart1:\n  nothinguseful: false\n\n"),
+		[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
+	}, {
+		"conditions enabling the parent charts, but back-end (b, c) is still disabled via values.yaml",
+		[]byte("subchart1:\n  enabled: true\nsubchart2:\n  enabled: true\n"),
+		[]string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb"},
+	}, {
+		"conditions disabling the parent charts, effectively disabling children",
+		[]byte("subchart1:\n  enabled: false\nsubchart2:\n  enabled: false\n"),
+		[]string{"parentchart"},
+	}, {
+		"conditions a child using the second condition path of child's condition",
+		[]byte("subchart1:\n  subcharta:\n    enabled: false\n"),
+		[]string{"parentchart", "subchart1", "subchartb"},
+	}, {
+		"tags enabling a parent/child group with condition disabling one child",
+		[]byte("subchartc:\n  enabled: false\ntags:\n  back-end: true\n"),
+		[]string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb", "subchartb"},
+	}, {
+		"tags will not enable a child if parent is explicitly disabled with condition",
+		[]byte("subchart1:\n  enabled: false\ntags:\n  front-end: true\n"),
+		[]string{"parentchart"},
+	}}
+
+	for _, tc := range tests {
+		c, err := loader.Load("testdata/subpop")
+		if err != nil {
+			t.Fatalf("Failed to load testdata: %s", err)
+		}
+		t.Run(tc.name, func(t *testing.T) {
+			verifyRequirementsEnabled(t, c, tc.v, tc.e)
+		})
 	}
-	// tags will not enable a child if parent is explicitly disabled with condition
-	v := []byte("subchart1:\n  enabled: false\ntags:\n  front-end: true\n")
-	// expected charts including duplicates in alphanumeric order
-	e := []string{"parentchart"}
-
-	verifyRequirementsEnabled(t, c, v, e)
 }
 
 func verifyRequirementsEnabled(t *testing.T, c *chart.Chart, v []byte, e []string) {
-	out := []*chart.Chart{}
-	err := ProcessRequirementsEnabled(c, v)
-	if err != nil {
+	if err := ProcessRequirementsEnabled(c, v); err != nil {
 		t.Errorf("Error processing enabled requirements %v", err)
 	}
-	out = extractCharts(c, out)
+
+	out := extractCharts(c, nil)
 	// build list of chart names
-	p := []string{}
+	var p []string
 	for _, r := range out {
-		p = append(p, r.Metadata.Name)
+		p = append(p, r.Name())
 	}
 	//sort alphanumeric and compare to expectations
 	sort.Strings(p)
@@ -201,23 +133,21 @@ func verifyRequirementsEnabled(t *testing.T, c *chart.Chart, v []byte, e []strin
 
 // extractCharts recursively searches chart dependencies returning all charts found
 func extractCharts(c *chart.Chart, out []*chart.Chart) []*chart.Chart {
-
-	if len(c.Metadata.Name) > 0 {
+	if len(c.Name()) > 0 {
 		out = append(out, c)
 	}
-	for _, d := range c.Dependencies {
+	for _, d := range c.Dependencies() {
 		out = extractCharts(d, out)
 	}
 	return out
 }
+
 func TestProcessRequirementsImportValues(t *testing.T) {
-	c, err := Load("testdata/subpop")
+	c, err := loader.Load("testdata/subpop")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 
-	v := []byte{}
-
 	e := make(map[string]string)
 
 	e["imported-chart1.SC1bool"] = "true"
@@ -279,17 +209,16 @@ func TestProcessRequirementsImportValues(t *testing.T) {
 	e["SCBexported2A"] = "blaster"
 	e["global.SC1exported2.all.SC1exported3"] = "SC1expstr"
 
-	verifyRequirementsImportValues(t, c, v, e)
+	verifyRequirementsImportValues(t, c, e)
 }
-func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v []byte, e map[string]string) {
 
-	err := ProcessRequirementsImportValues(c)
-	if err != nil {
-		t.Errorf("Error processing import values requirements %v", err)
+func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, e map[string]string) {
+	if err := ProcessRequirementsImportValues(c); err != nil {
+		t.Fatalf("Error processing import values requirements %v", err)
 	}
 	cc, err := ReadValues(c.Values)
 	if err != nil {
-		t.Errorf("Error reading import values %v", err)
+		t.Fatalf("Error reading import values %v", err)
 	}
 	for kk, vv := range e {
 		pv, err := cc.PathValue(kk)
@@ -317,182 +246,203 @@ func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v []byte, e ma
 				return
 			}
 		}
-
 	}
 }
 
 func TestGetAliasDependency(t *testing.T) {
-	c, err := Load("testdata/frobnitz")
+	c, err := loader.Load("testdata/frobnitz")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
-	req, err := LoadRequirements(c)
-	if err != nil {
-		t.Fatalf("Failed to load requirement for testdata: %s", err)
-	}
+
+	req := c.Requirements
+
 	if len(req.Dependencies) == 0 {
 		t.Fatalf("There are no requirements to test")
 	}
 
 	// Success case
-	aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0])
+	aliasChart := getAliasDependency(c.Dependencies(), req.Dependencies[0])
 	if aliasChart == nil {
 		t.Fatalf("Failed to get dependency chart for alias %s", req.Dependencies[0].Name)
 	}
 	if req.Dependencies[0].Alias != "" {
-		if aliasChart.Metadata.Name != req.Dependencies[0].Alias {
-			t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Alias, aliasChart.Metadata.Name)
+		if aliasChart.Name() != req.Dependencies[0].Alias {
+			t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Alias, aliasChart.Name())
 		}
-	} else if aliasChart.Metadata.Name != req.Dependencies[0].Name {
-		t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Name, aliasChart.Metadata.Name)
+	} else if aliasChart.Name() != req.Dependencies[0].Name {
+		t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Name, aliasChart.Name())
 	}
 
 	if req.Dependencies[0].Version != "" {
 		if !version.IsCompatibleRange(req.Dependencies[0].Version, aliasChart.Metadata.Version) {
 			t.Fatalf("Dependency chart version is not in the compatible range")
 		}
-
 	}
 
 	// Failure case
 	req.Dependencies[0].Name = "something-else"
-	if aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0]); aliasChart != nil {
-		t.Fatalf("expected no chart but got %s", aliasChart.Metadata.Name)
+	if aliasChart := getAliasDependency(c.Dependencies(), req.Dependencies[0]); aliasChart != nil {
+		t.Fatalf("expected no chart but got %s", aliasChart.Name())
 	}
 
 	req.Dependencies[0].Version = "something else which is not in the compatible range"
 	if version.IsCompatibleRange(req.Dependencies[0].Version, aliasChart.Metadata.Version) {
 		t.Fatalf("Dependency chart version which is not in the compatible range should cause a failure other than a success ")
 	}
-
 }
 
 func TestDependentChartAliases(t *testing.T) {
-	c, err := Load("testdata/dependent-chart-alias")
+	c, err := loader.Load("testdata/dependent-chart-alias")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 
-	if len(c.Dependencies) == 0 {
+	if len(c.Dependencies()) == 0 {
 		t.Fatal("There are no dependencies to run this test")
 	}
 
-	origLength := len(c.Dependencies)
+	origLength := len(c.Dependencies())
 	if err := ProcessRequirementsEnabled(c, c.Values); err != nil {
 		t.Fatalf("Expected no errors but got %q", err)
 	}
 
-	if len(c.Dependencies) == origLength {
+	if len(c.Dependencies()) == origLength {
 		t.Fatal("Expected alias dependencies to be added, but did not got that")
 	}
 
-	reqmts, err := LoadRequirements(c)
-	if err != nil {
-		t.Fatalf("Cannot load requirements for test chart, %v", err)
-	}
-
-	if len(c.Dependencies) != len(reqmts.Dependencies) {
-		t.Fatalf("Expected number of chart dependencies %d, but got %d", len(reqmts.Dependencies), len(c.Dependencies))
+	if len(c.Dependencies()) != len(c.Requirements.Dependencies) {
+		t.Fatalf("Expected number of chart dependencies %d, but got %d", len(c.Requirements.Dependencies), len(c.Dependencies()))
 	}
-
 }
 
 func TestDependentChartWithSubChartsAbsentInRequirements(t *testing.T) {
-	c, err := Load("testdata/dependent-chart-no-requirements-yaml")
+	c, err := loader.Load("testdata/dependent-chart-no-requirements-yaml")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 
-	if len(c.Dependencies) != 2 {
-		t.Fatalf("Expected 2 dependencies for this chart, but got %d", len(c.Dependencies))
+	if len(c.Dependencies()) != 2 {
+		t.Fatalf("Expected 2 dependencies for this chart, but got %d", len(c.Dependencies()))
 	}
 
-	origLength := len(c.Dependencies)
+	origLength := len(c.Dependencies())
 	if err := ProcessRequirementsEnabled(c, c.Values); err != nil {
 		t.Fatalf("Expected no errors but got %q", err)
 	}
 
-	if len(c.Dependencies) != origLength {
+	if len(c.Dependencies()) != origLength {
 		t.Fatal("Expected no changes in dependencies to be, but did something got changed")
 	}
-
 }
 
 func TestDependentChartWithSubChartsHelmignore(t *testing.T) {
-	if _, err := Load("testdata/dependent-chart-helmignore"); err != nil {
+	if _, err := loader.Load("testdata/dependent-chart-helmignore"); err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 }
 
 func TestDependentChartsWithSubChartsSymlink(t *testing.T) {
-	c, err := Load("testdata/joonix")
+	c, err := loader.Load("testdata/joonix")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
-	if c.Metadata.Name != "joonix" {
-		t.Fatalf("Unexpected chart name: %s", c.Metadata.Name)
+	if c.Name() != "joonix" {
+		t.Fatalf("Unexpected chart name: %s", c.Name())
 	}
-	if n := len(c.Dependencies); n != 1 {
+	if n := len(c.Dependencies()); n != 1 {
 		t.Fatalf("Expected 1 dependency for this chart, but got %d", n)
 	}
 }
 
 func TestDependentChartsWithSubchartsAllSpecifiedInRequirements(t *testing.T) {
-	c, err := Load("testdata/dependent-chart-with-all-in-requirements-yaml")
+	c, err := loader.Load("testdata/dependent-chart-with-all-in-requirements-yaml")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 
-	if len(c.Dependencies) == 0 {
+	if len(c.Dependencies()) == 0 {
 		t.Fatal("There are no dependencies to run this test")
 	}
 
-	origLength := len(c.Dependencies)
+	origLength := len(c.Dependencies())
 	if err := ProcessRequirementsEnabled(c, c.Values); err != nil {
 		t.Fatalf("Expected no errors but got %q", err)
 	}
 
-	if len(c.Dependencies) != origLength {
+	if len(c.Dependencies()) != origLength {
 		t.Fatal("Expected no changes in dependencies to be, but did something got changed")
 	}
 
-	reqmts, err := LoadRequirements(c)
-	if err != nil {
-		t.Fatalf("Cannot load requirements for test chart, %v", err)
-	}
-
-	if len(c.Dependencies) != len(reqmts.Dependencies) {
-		t.Fatalf("Expected number of chart dependencies %d, but got %d", len(reqmts.Dependencies), len(c.Dependencies))
+	if len(c.Dependencies()) != len(c.Requirements.Dependencies) {
+		t.Fatalf("Expected number of chart dependencies %d, but got %d", len(c.Requirements.Dependencies), len(c.Dependencies()))
 	}
-
 }
 
 func TestDependentChartsWithSomeSubchartsSpecifiedInRequirements(t *testing.T) {
-	c, err := Load("testdata/dependent-chart-with-mixed-requirements-yaml")
+	c, err := loader.Load("testdata/dependent-chart-with-mixed-requirements-yaml")
 	if err != nil {
 		t.Fatalf("Failed to load testdata: %s", err)
 	}
 
-	if len(c.Dependencies) == 0 {
+	if len(c.Dependencies()) == 0 {
 		t.Fatal("There are no dependencies to run this test")
 	}
 
-	origLength := len(c.Dependencies)
+	origLength := len(c.Dependencies())
 	if err := ProcessRequirementsEnabled(c, c.Values); err != nil {
 		t.Fatalf("Expected no errors but got %q", err)
 	}
 
-	if len(c.Dependencies) != origLength {
+	if len(c.Dependencies()) != origLength {
 		t.Fatal("Expected no changes in dependencies to be, but did something got changed")
 	}
 
-	reqmts, err := LoadRequirements(c)
-	if err != nil {
-		t.Fatalf("Cannot load requirements for test chart, %v", err)
+	if len(c.Dependencies()) <= len(c.Requirements.Dependencies) {
+		t.Fatalf("Expected more dependencies than specified in requirements.yaml(%d), but got %d", len(c.Requirements.Dependencies), len(c.Dependencies()))
 	}
+}
 
-	if len(c.Dependencies) <= len(reqmts.Dependencies) {
-		t.Fatalf("Expected more dependencies than specified in requirements.yaml(%d), but got %d", len(reqmts.Dependencies), len(c.Dependencies))
+func verifyRequirements(t *testing.T, c *chart.Chart) {
+	if len(c.Requirements.Dependencies) != 2 {
+		t.Errorf("Expected 2 requirements, got %d", len(c.Requirements.Dependencies))
+	}
+	tests := []*chart.Dependency{
+		{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
+		{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
 	}
+	for i, tt := range tests {
+		d := c.Requirements.Dependencies[i]
+		if d.Name != tt.Name {
+			t.Errorf("Expected dependency named %q, got %q", tt.Name, d.Name)
+		}
+		if d.Version != tt.Version {
+			t.Errorf("Expected dependency named %q to have version %q, got %q", tt.Name, tt.Version, d.Version)
+		}
+		if d.Repository != tt.Repository {
+			t.Errorf("Expected dependency named %q to have repository %q, got %q", tt.Name, tt.Repository, d.Repository)
+		}
+	}
+}
 
+func verifyRequirementsLock(t *testing.T, c *chart.Chart) {
+	if len(c.Requirements.Dependencies) != 2 {
+		t.Errorf("Expected 2 requirements, got %d", len(c.Requirements.Dependencies))
+	}
+	tests := []*chart.Dependency{
+		{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
+		{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
+	}
+	for i, tt := range tests {
+		d := c.Requirements.Dependencies[i]
+		if d.Name != tt.Name {
+			t.Errorf("Expected dependency named %q, got %q", tt.Name, d.Name)
+		}
+		if d.Version != tt.Version {
+			t.Errorf("Expected dependency named %q to have version %q, got %q", tt.Name, tt.Version, d.Version)
+		}
+		if d.Repository != tt.Repository {
+			t.Errorf("Expected dependency named %q to have repository %q, got %q", tt.Name, tt.Repository, d.Repository)
+		}
+	}
 }
diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go
index 610f0aca04126a0381fde4a162d361f61cc80e3c..aac6ab1d43e9995ee2b3054ce2464858876ec223 100644
--- a/pkg/chartutil/save.go
+++ b/pkg/chartutil/save.go
@@ -27,7 +27,7 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 )
 
 var headerBytes = []byte("+aHR0cHM6Ly95b3V0dS5iZS96OVV6MWljandyTQo=")
@@ -35,7 +35,7 @@ var headerBytes = []byte("+aHR0cHM6Ly95b3V0dS5iZS96OVV6MWljandyTQo=")
 // SaveDir saves a chart as files in a directory.
 func SaveDir(c *chart.Chart, dest string) error {
 	// Create the chart directory
-	outdir := filepath.Join(dest, c.Metadata.Name)
+	outdir := filepath.Join(dest, c.Name())
 	if err := os.Mkdir(outdir, 0755); err != nil {
 		return err
 	}
@@ -83,7 +83,7 @@ func SaveDir(c *chart.Chart, dest string) error {
 
 	// Save dependencies
 	base := filepath.Join(outdir, ChartsDir)
-	for _, dep := range c.Dependencies {
+	for _, dep := range c.Dependencies() {
 		// Here, we write each dependency as a tar file.
 		if _, err := Save(dep, base); err != nil {
 			return err
@@ -158,7 +158,7 @@ func Save(c *chart.Chart, outDir string) (string, error) {
 }
 
 func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
-	base := filepath.Join(prefix, c.Metadata.Name)
+	base := filepath.Join(prefix, c.Name())
 
 	// Save Chart.yaml
 	cdata, err := yaml.Marshal(c.Metadata)
@@ -193,7 +193,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
 	}
 
 	// Save dependencies
-	for _, dep := range c.Dependencies {
+	for _, dep := range c.Dependencies() {
 		if err := writeTarContents(out, dep, base+"/charts"); err != nil {
 			return err
 		}
@@ -212,8 +212,6 @@ func writeToTar(out *tar.Writer, name string, body []byte) error {
 	if err := out.WriteHeader(h); err != nil {
 		return err
 	}
-	if _, err := out.Write(body); err != nil {
-		return err
-	}
-	return nil
+	_, err := out.Write(body)
+	return err
 }
diff --git a/pkg/chartutil/save_test.go b/pkg/chartutil/save_test.go
index 04db9cf8025e0decb7b85dfeb6bd53fd51ec960c..e1760dad544d4adbf29fa90b87a7dda6665c9670 100644
--- a/pkg/chartutil/save_test.go
+++ b/pkg/chartutil/save_test.go
@@ -23,7 +23,8 @@ import (
 	"strings"
 	"testing"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 )
 
 func TestSave(t *testing.T) {
@@ -55,13 +56,13 @@ func TestSave(t *testing.T) {
 		t.Fatalf("Expected %q to end with .tgz", where)
 	}
 
-	c2, err := LoadFile(where)
+	c2, err := loader.LoadFile(where)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if c2.Metadata.Name != c.Metadata.Name {
-		t.Fatalf("Expected chart archive to have %q, got %q", c.Metadata.Name, c2.Metadata.Name)
+	if c2.Name() != c.Name() {
+		t.Fatalf("Expected chart archive to have %q, got %q", c.Name(), c2.Name())
 	}
 	if !bytes.Equal(c2.Values, c.Values) {
 		t.Fatal("Values data did not match")
@@ -93,13 +94,13 @@ func TestSaveDir(t *testing.T) {
 		t.Fatalf("Failed to save: %s", err)
 	}
 
-	c2, err := LoadDir(tmp + "/ahab")
+	c2, err := loader.LoadDir(tmp + "/ahab")
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	if c2.Metadata.Name != c.Metadata.Name {
-		t.Fatalf("Expected chart archive to have %q, got %q", c.Metadata.Name, c2.Metadata.Name)
+	if c2.Name() != c.Name() {
+		t.Fatalf("Expected chart archive to have %q, got %q", c.Name(), c2.Name())
 	}
 	if !bytes.Equal(c2.Values, c.Values) {
 		t.Fatal("Values data did not match")
diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go
index ad499b687c45156162579de3067a862a21417656..a9195c9f0ef9de450e431ebf0b8305e89f0b54f8 100644
--- a/pkg/chartutil/values.go
+++ b/pkg/chartutil/values.go
@@ -25,7 +25,7 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 )
 
 // ErrNoTable indicates that a chart does not have a matching table.
@@ -59,11 +59,10 @@ func (v Values) YAML() (string, error) {
 //
 // An ErrNoTable is returned if the table does not exist.
 func (v Values) Table(name string) (Values, error) {
-	names := strings.Split(name, ".")
 	table := v
 	var err error
 
-	for _, n := range names {
+	for _, n := range strings.Split(name, ".") {
 		table, err = tableLookup(table, n)
 		if err != nil {
 			return table, err
@@ -110,7 +109,7 @@ func tableLookup(v Values, simple string) (Values, error) {
 	}
 
 	var e ErrNoTable = errors.Errorf("no table named %q", simple)
-	return map[string]interface{}{}, e
+	return Values{}, e
 }
 
 // ReadValues will parse YAML byte data into a Values.
@@ -141,23 +140,23 @@ func ReadValuesFile(filename string) (Values, error) {
 //	- A chart has access to all of the variables for it, as well as all of
 //		the values destined for its dependencies.
 func CoalesceValues(chrt *chart.Chart, vals []byte) (Values, error) {
+	var err error
 	cvals := Values{}
 	// Parse values if not nil. We merge these at the top level because
 	// the passed-in values are in the same namespace as the parent chart.
 	if vals != nil {
-		evals, err := ReadValues(vals)
-		if err != nil {
-			return cvals, err
-		}
-		cvals, err = coalesce(chrt, evals)
+		cvals, err = ReadValues(vals)
 		if err != nil {
 			return cvals, err
 		}
 	}
 
-	var err error
-	cvals, err = coalesceDeps(chrt, cvals)
-	return cvals, err
+	cvals, err = coalesce(chrt, cvals)
+	if err != nil {
+		return cvals, err
+	}
+
+	return coalesceDeps(chrt, cvals)
 }
 
 // coalesce coalesces the dest values and the chart values, giving priority to the dest values.
@@ -175,14 +174,14 @@ func coalesce(ch *chart.Chart, dest map[string]interface{}) (map[string]interfac
 
 // coalesceDeps coalesces the dependencies of the given chart.
 func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]interface{}, error) {
-	for _, subchart := range chrt.Dependencies {
-		if c, ok := dest[subchart.Metadata.Name]; !ok {
+	for _, subchart := range chrt.Dependencies() {
+		if c, ok := dest[subchart.Name()]; !ok {
 			// If dest doesn't already have the key, create it.
-			dest[subchart.Metadata.Name] = map[string]interface{}{}
+			dest[subchart.Name()] = make(map[string]interface{})
 		} else if !istable(c) {
-			return dest, errors.Errorf("type mismatch on %s: %t", subchart.Metadata.Name, c)
+			return dest, errors.Errorf("type mismatch on %s: %t", subchart.Name(), c)
 		}
-		if dv, ok := dest[subchart.Metadata.Name]; ok {
+		if dv, ok := dest[subchart.Name()]; ok {
 			dvmap := dv.(map[string]interface{})
 
 			// Get globals out of dest and merge them into dvmap.
@@ -190,7 +189,7 @@ func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]in
 
 			var err error
 			// Now coalesce the rest of the values.
-			dest[subchart.Metadata.Name], err = coalesce(subchart, dvmap)
+			dest[subchart.Name()], err = coalesce(subchart, dvmap)
 			if err != nil {
 				return dest, err
 			}
@@ -206,14 +205,14 @@ func coalesceGlobals(dest, src map[string]interface{}) map[string]interface{} {
 	var dg, sg map[string]interface{}
 
 	if destglob, ok := dest[GlobalKey]; !ok {
-		dg = map[string]interface{}{}
+		dg = make(map[string]interface{})
 	} else if dg, ok = destglob.(map[string]interface{}); !ok {
 		log.Printf("warning: skipping globals because destination %s is not a table.", GlobalKey)
 		return dg
 	}
 
 	if srcglob, ok := src[GlobalKey]; !ok {
-		sg = map[string]interface{}{}
+		sg = make(map[string]interface{})
 	} else if sg, ok = srcglob.(map[string]interface{}); !ok {
 		log.Printf("warning: skipping globals because source %s is not a table.", GlobalKey)
 		return dg
@@ -340,19 +339,8 @@ type ReleaseOptions struct {
 
 // ToRenderValues composes the struct from the data coming from the Releases, Charts and Values files
 //
-// WARNING: This function is deprecated for Helm > 2.1.99 Use ToRenderValuesCaps() instead. It will
-// remain in the codebase to stay SemVer compliant.
-//
-// In Helm 3.0, this will be changed to accept Capabilities as a fourth parameter.
-func ToRenderValues(chrt *chart.Chart, chrtVals []byte, options ReleaseOptions) (Values, error) {
-	caps := &Capabilities{APIVersions: DefaultVersionSet}
-	return ToRenderValuesCaps(chrt, chrtVals, options, caps)
-}
-
-// ToRenderValuesCaps composes the struct from the data coming from the Releases, Charts and Values files
-//
 // This takes both ReleaseOptions and Capabilities to merge into the render values.
-func ToRenderValuesCaps(chrt *chart.Chart, chrtVals []byte, options ReleaseOptions, caps *Capabilities) (Values, error) {
+func ToRenderValues(chrt *chart.Chart, chrtVals []byte, options ReleaseOptions, caps *Capabilities) (Values, error) {
 
 	top := map[string]interface{}{
 		"Release": map[string]interface{}{
diff --git a/pkg/chartutil/values_test.go b/pkg/chartutil/values_test.go
index 8fe1b3be55e889ab7f4f0b33c2daa57703bde834..907dba575060cb74cb8d11b911ebd42fb74065d6 100644
--- a/pkg/chartutil/values_test.go
+++ b/pkg/chartutil/values_test.go
@@ -25,7 +25,8 @@ import (
 
 	kversion "k8s.io/apimachinery/pkg/version"
 
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/version"
 )
 
@@ -89,16 +90,14 @@ where:
 		Metadata:  &chart.Metadata{Name: "test"},
 		Templates: []*chart.File{},
 		Values:    []byte(chartValues),
-		Dependencies: []*chart.Chart{
-			{
-				Metadata: &chart.Metadata{Name: "where"},
-				Values:   []byte{},
-			},
-		},
 		Files: []*chart.File{
 			{Name: "scheherazade/shahryar.txt", Data: []byte("1,001 Nights")},
 		},
 	}
+	c.AddDependency(&chart.Chart{
+		Metadata: &chart.Metadata{Name: "where"},
+		Values:   []byte{},
+	})
 	v := []byte(overideValues)
 
 	o := ReleaseOptions{
@@ -112,7 +111,7 @@ where:
 		KubeVersion: &kversion.Info{Major: "1"},
 	}
 
-	res, err := ToRenderValuesCaps(c, v, o, caps)
+	res, err := ToRenderValues(c, v, o, caps)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -259,10 +258,8 @@ func matchValues(t *testing.T, data map[string]interface{}) {
 func ttpl(tpl string, v map[string]interface{}) (string, error) {
 	var b bytes.Buffer
 	tt := template.Must(template.New("t").Parse(tpl))
-	if err := tt.Execute(&b, v); err != nil {
-		return "", err
-	}
-	return b.String(), nil
+	err := tt.Execute(&b, v)
+	return b.String(), err
 }
 
 // ref: http://www.yaml.org/spec/1.2/spec.html#id2803362
@@ -293,7 +290,7 @@ pequod:
 
 func TestCoalesceValues(t *testing.T) {
 	tchart := "testdata/moby"
-	c, err := LoadDir(tchart)
+	c, err := loader.LoadDir(tchart)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go
index a59e7dc0d6197abbde3a3afba518d8fb677e7982..d085966dcca5f891d158355e4697abdf75db7f5a 100644
--- a/pkg/downloader/manager.go
+++ b/pkg/downloader/manager.go
@@ -30,9 +30,10 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
 	"k8s.io/helm/pkg/getter"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/helm/helmpath"
 	"k8s.io/helm/pkg/repo"
 	"k8s.io/helm/pkg/resolver"
@@ -72,16 +73,13 @@ func (m *Manager) Build() error {
 
 	// If a lock file is found, run a build from that. Otherwise, just do
 	// an update.
-	lock, err := chartutil.LoadRequirementsLock(c)
-	if err != nil {
+	lock := c.RequirementsLock
+	if lock == nil {
 		return m.Update()
 	}
 
 	// A lock must accompany a requirements.yaml file.
-	req, err := chartutil.LoadRequirements(c)
-	if err != nil {
-		return errors.Wrap(err, "requirements.yaml cannot be opened")
-	}
+	req := c.Requirements
 	if sum, err := resolver.HashReq(req); err != nil || sum != lock.Digest {
 		return errors.New("requirements.lock is out of sync with requirements.yaml")
 	}
@@ -119,13 +117,9 @@ func (m *Manager) Update() error {
 
 	// If no requirements file is found, we consider this a successful
 	// completion.
-	req, err := chartutil.LoadRequirements(c)
-	if err != nil {
-		if err == chartutil.ErrRequirementsNotFound {
-			fmt.Fprintf(m.Out, "No requirements found in %s/charts.\n", m.ChartPath)
-			return nil
-		}
-		return err
+	req := c.Requirements
+	if req == nil {
+		return nil
 	}
 
 	// Hash requirements.yaml
@@ -161,8 +155,8 @@ func (m *Manager) Update() error {
 	}
 
 	// If the lock file hasn't changed, don't write a new one.
-	oldLock, err := chartutil.LoadRequirementsLock(c)
-	if err == nil && oldLock.Digest == lock.Digest {
+	oldLock := c.RequirementsLock
+	if oldLock != nil && oldLock.Digest == lock.Digest {
 		return nil
 	}
 
@@ -176,13 +170,13 @@ func (m *Manager) loadChartDir() (*chart.Chart, error) {
 	} else if !fi.IsDir() {
 		return nil, errors.New("only unpacked charts can be updated")
 	}
-	return chartutil.LoadDir(m.ChartPath)
+	return loader.LoadDir(m.ChartPath)
 }
 
 // resolve takes a list of requirements and translates them into an exact version to download.
 //
 // This returns a lock file, which has all of the requirements normalized to a specific version.
-func (m *Manager) resolve(req *chartutil.Requirements, repoNames map[string]string, hash string) (*chartutil.RequirementsLock, error) {
+func (m *Manager) resolve(req *chart.Requirements, repoNames map[string]string, hash string) (*chart.RequirementsLock, error) {
 	res := resolver.New(m.ChartPath, m.HelmHome)
 	return res.Resolve(req, repoNames, hash)
 }
@@ -191,7 +185,7 @@ func (m *Manager) resolve(req *chartutil.Requirements, repoNames map[string]stri
 //
 // It will delete versions of the chart that exist on disk and might cause
 // a conflict.
-func (m *Manager) downloadAll(deps []*chartutil.Dependency) error {
+func (m *Manager) downloadAll(deps []*chart.Dependency) error {
 	repos, err := m.loadChartRepositories()
 	if err != nil {
 		return err
@@ -307,12 +301,12 @@ func (m *Manager) safeDeleteDep(name, dir string) error {
 		return err
 	}
 	for _, fname := range files {
-		ch, err := chartutil.LoadFile(fname)
+		ch, err := loader.LoadFile(fname)
 		if err != nil {
 			fmt.Fprintf(m.Out, "Could not verify %s for deletion: %s (Skipping)", fname, err)
 			continue
 		}
-		if ch.Metadata.Name != name {
+		if ch.Name() != name {
 			// This is not the file you are looking for.
 			continue
 		}
@@ -325,7 +319,7 @@ func (m *Manager) safeDeleteDep(name, dir string) error {
 }
 
 // hasAllRepos ensures that all of the referenced deps are in the local repo cache.
-func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error {
+func (m *Manager) hasAllRepos(deps []*chart.Dependency) error {
 	rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile())
 	if err != nil {
 		return err
@@ -335,25 +329,22 @@ func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error {
 	// Verify that all repositories referenced in the deps are actually known
 	// by Helm.
 	missing := []string{}
+Loop:
 	for _, dd := range deps {
 		// If repo is from local path, continue
 		if strings.HasPrefix(dd.Repository, "file://") {
 			continue
 		}
 
-		found := false
 		if dd.Repository == "" {
-			found = true
-		} else {
-			for _, repo := range repos {
-				if urlutil.Equal(repo.URL, strings.TrimSuffix(dd.Repository, "/")) {
-					found = true
-				}
-			}
+			continue
 		}
-		if !found {
-			missing = append(missing, dd.Repository)
+		for _, repo := range repos {
+			if urlutil.Equal(repo.URL, strings.TrimSuffix(dd.Repository, "/")) {
+				continue Loop
+			}
 		}
+		missing = append(missing, dd.Repository)
 	}
 	if len(missing) > 0 {
 		return errors.Errorf("no repository definition for %s. Please add the missing repos via 'helm repo add'", strings.Join(missing, ", "))
@@ -362,7 +353,7 @@ func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error {
 }
 
 // getRepoNames returns the repo names of the referenced deps which can be used to fetch the cahced index file.
-func (m *Manager) getRepoNames(deps []*chartutil.Dependency) (map[string]string, error) {
+func (m *Manager) getRepoNames(deps []*chart.Dependency) (map[string]string, error) {
 	rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile())
 	if err != nil {
 		return nil, err
@@ -408,24 +399,22 @@ func (m *Manager) getRepoNames(deps []*chartutil.Dependency) (map[string]string,
 		}
 	}
 	if len(missing) > 0 {
-		if len(missing) > 0 {
-			errorMessage := fmt.Sprintf("no repository definition for %s. Please add them via 'helm repo add'", strings.Join(missing, ", "))
-			// It is common for people to try to enter "stable" as a repository instead of the actual URL.
-			// For this case, let's give them a suggestion.
-			containsNonURL := false
-			for _, repo := range missing {
-				if !strings.Contains(repo, "//") && !strings.HasPrefix(repo, "@") && !strings.HasPrefix(repo, "alias:") {
-					containsNonURL = true
-				}
+		errorMessage := fmt.Sprintf("no repository definition for %s. Please add them via 'helm repo add'", strings.Join(missing, ", "))
+		// It is common for people to try to enter "stable" as a repository instead of the actual URL.
+		// For this case, let's give them a suggestion.
+		containsNonURL := false
+		for _, repo := range missing {
+			if !strings.Contains(repo, "//") && !strings.HasPrefix(repo, "@") && !strings.HasPrefix(repo, "alias:") {
+				containsNonURL = true
 			}
-			if containsNonURL {
-				errorMessage += `
+		}
+		if containsNonURL {
+			errorMessage += `
 Note that repositories must be URLs or aliases. For example, to refer to the stable
 repository, use "https://kubernetes-charts.storage.googleapis.com/" or "@stable" instead of
 "stable". Don't forget to add the repo, too ('helm repo add').`
-			}
-			return nil, errors.New(errorMessage)
 		}
+		return nil, errors.New(errorMessage)
 	}
 	return reposMap, nil
 }
@@ -596,7 +585,7 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err
 }
 
 // writeLock writes a lockfile to disk
-func writeLock(chartpath string, lock *chartutil.RequirementsLock) error {
+func writeLock(chartpath string, lock *chart.RequirementsLock) error {
 	data, err := yaml.Marshal(lock)
 	if err != nil {
 		return err
@@ -618,7 +607,7 @@ func tarFromLocalDir(chartpath, name, repo, version string) (string, error) {
 		return "", err
 	}
 
-	ch, err := chartutil.LoadDir(origPath)
+	ch, err := loader.LoadDir(origPath)
 	if err != nil {
 		return "", err
 	}
diff --git a/pkg/downloader/manager_test.go b/pkg/downloader/manager_test.go
index 1ff2a9c173c570e4b7a85bdf175579228bbd0711..f5a252d0bf8d8288e424d7d17262bbd14fa04522 100644
--- a/pkg/downloader/manager_test.go
+++ b/pkg/downloader/manager_test.go
@@ -20,7 +20,7 @@ import (
 	"reflect"
 	"testing"
 
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/helm/helmpath"
 )
 
@@ -100,48 +100,48 @@ func TestGetRepoNames(t *testing.T) {
 	}
 	tests := []struct {
 		name   string
-		req    []*chartutil.Dependency
+		req    []*chart.Dependency
 		expect map[string]string
 		err    bool
 	}{
 		{
 			name: "no repo definition failure",
-			req: []*chartutil.Dependency{
+			req: []*chart.Dependency{
 				{Name: "oedipus-rex", Repository: "http://example.com/test"},
 			},
 			err: true,
 		},
 		{
 			name: "no repo definition failure -- stable repo",
-			req: []*chartutil.Dependency{
+			req: []*chart.Dependency{
 				{Name: "oedipus-rex", Repository: "stable"},
 			},
 			err: true,
 		},
 		{
 			name: "no repo definition failure",
-			req: []*chartutil.Dependency{
+			req: []*chart.Dependency{
 				{Name: "oedipus-rex", Repository: "http://example.com"},
 			},
 			expect: map[string]string{"oedipus-rex": "testing"},
 		},
 		{
 			name: "repo from local path",
-			req: []*chartutil.Dependency{
+			req: []*chart.Dependency{
 				{Name: "local-dep", Repository: "file://./testdata/signtest"},
 			},
 			expect: map[string]string{"local-dep": "file://./testdata/signtest"},
 		},
 		{
 			name: "repo alias (alias:)",
-			req: []*chartutil.Dependency{
+			req: []*chart.Dependency{
 				{Name: "oedipus-rex", Repository: "alias:testing"},
 			},
 			expect: map[string]string{"oedipus-rex": "testing"},
 		},
 		{
 			name: "repo alias (@)",
-			req: []*chartutil.Dependency{
+			req: []*chart.Dependency{
 				{Name: "oedipus-rex", Repository: "@testing"},
 			},
 			expect: map[string]string{"oedipus-rex": "testing"},
diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go
index f09a8ec7cae3abe4275134746735988444ffdcb3..2b330ecf31a9d5e1d8a745e04553bf874a40661b 100644
--- a/pkg/engine/engine.go
+++ b/pkg/engine/engine.go
@@ -17,7 +17,6 @@ limitations under the License.
 package engine
 
 import (
-	"bytes"
 	"path"
 	"sort"
 	"strings"
@@ -26,19 +25,19 @@ import (
 	"github.com/Masterminds/sprig"
 	"github.com/pkg/errors"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 )
 
 // Engine is an implementation of 'cmd/tiller/environment'.Engine that uses Go templates.
 type Engine struct {
 	// FuncMap contains the template functions that will be passed to each
 	// render call. This may only be modified before the first call to Render.
-	FuncMap template.FuncMap
+	funcMap template.FuncMap
 	// If strict is enabled, template rendering will fail if a template references
 	// a value that was not passed in.
 	Strict           bool
-	CurrentTemplates map[string]renderable
+	currentTemplates map[string]renderable
 }
 
 // New creates a new Go template Engine instance.
@@ -49,10 +48,7 @@ type Engine struct {
 // The FuncMap sets all of the Sprig functions except for those that provide
 // access to the underlying OS (env, expandenv).
 func New() *Engine {
-	f := FuncMap()
-	return &Engine{
-		FuncMap: f,
-	}
+	return &Engine{funcMap: FuncMap()}
 }
 
 // FuncMap returns a mapping of all of the functions that Engine has.
@@ -76,11 +72,11 @@ func FuncMap() template.FuncMap {
 
 	// Add some extra functionality
 	extra := template.FuncMap{
-		"toToml":   chartutil.ToToml,
-		"toYaml":   chartutil.ToYaml,
-		"fromYaml": chartutil.FromYaml,
-		"toJson":   chartutil.ToJson,
-		"fromJson": chartutil.FromJson,
+		"toToml":   chartutil.ToTOML,
+		"toYaml":   chartutil.ToYAML,
+		"fromYaml": chartutil.FromYAML,
+		"toJson":   chartutil.ToJSON,
+		"fromJson": chartutil.FromJSON,
 
 		// This is a placeholder for the "include" function, which is
 		// late-bound to a template. By declaring it here, we preserve the
@@ -119,8 +115,8 @@ func FuncMap() template.FuncMap {
 func (e *Engine) Render(chrt *chart.Chart, values chartutil.Values) (map[string]string, error) {
 	// Render the charts
 	tmap := allTemplates(chrt, values)
-	e.CurrentTemplates = tmap
-	return e.render(tmap)
+	e.currentTemplates = tmap
+	return e.render(chrt, tmap)
 }
 
 // renderable is an object that can be rendered.
@@ -138,18 +134,16 @@ type renderable struct {
 // The resulting FuncMap is only valid for the passed-in template.
 func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap {
 	// Clone the func map because we are adding context-specific functions.
-	var funcMap template.FuncMap = map[string]interface{}{}
-	for k, v := range e.FuncMap {
+	funcMap := make(template.FuncMap)
+	for k, v := range e.funcMap {
 		funcMap[k] = v
 	}
 
 	// Add the 'include' function here so we can close over t.
 	funcMap["include"] = func(name string, data interface{}) (string, error) {
-		buf := bytes.NewBuffer(nil)
-		if err := t.ExecuteTemplate(buf, name, data); err != nil {
-			return "", err
-		}
-		return buf.String(), nil
+		var buf strings.Builder
+		err := t.ExecuteTemplate(&buf, name, data)
+		return buf.String(), err
 	}
 
 	// Add the 'required' function here
@@ -177,15 +171,15 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap {
 			basePath: basePath.(string),
 		}
 
-		templates := map[string]renderable{}
 		templateName, err := vals.PathValue("Template.Name")
 		if err != nil {
 			return "", errors.Wrapf(err, "cannot retrieve Template.Name from values inside tpl function: %s", tpl)
 		}
 
+		templates := make(map[string]renderable)
 		templates[templateName.(string)] = r
 
-		result, err := e.render(templates)
+		result, err := e.render(nil, templates)
 		if err != nil {
 			return "", errors.Wrapf(err, "error during tpl function execution for %q", tpl)
 		}
@@ -196,7 +190,7 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap {
 }
 
 // render takes a map of templates/values and renders them.
-func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string, err error) {
+func (e *Engine) render(ch *chart.Chart, tpls map[string]renderable) (rendered map[string]string, err error) {
 	// Basically, what we do here is start with an empty parent template and then
 	// build up a list of templates -- one for each file. Once all of the templates
 	// have been parsed, we loop through again and execute every template.
@@ -228,8 +222,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string,
 
 	for _, fname := range keys {
 		r := tpls[fname]
-		t = t.New(fname).Funcs(funcMap)
-		if _, err := t.Parse(r.tpl); err != nil {
+		if _, err := t.New(fname).Funcs(funcMap).Parse(r.tpl); err != nil {
 			return map[string]string{}, errors.Wrapf(err, "parse error in %q", fname)
 		}
 		files = append(files, fname)
@@ -237,17 +230,15 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string,
 
 	// Adding the engine's currentTemplates to the template context
 	// so they can be referenced in the tpl function
-	for fname, r := range e.CurrentTemplates {
+	for fname, r := range e.currentTemplates {
 		if t.Lookup(fname) == nil {
-			t = t.New(fname).Funcs(funcMap)
-			if _, err := t.Parse(r.tpl); err != nil {
+			if _, err := t.New(fname).Funcs(funcMap).Parse(r.tpl); err != nil {
 				return map[string]string{}, errors.Wrapf(err, "parse error in %q", fname)
 			}
 		}
 	}
 
 	rendered = make(map[string]string, len(files))
-	var buf bytes.Buffer
 	for _, file := range files {
 		// Don't render partials. We don't care out the direct output of partials.
 		// They are only included from other templates.
@@ -256,7 +247,8 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string,
 		}
 		// At render time, add information about the template that is being rendered.
 		vals := tpls[file].vals
-		vals["Template"] = map[string]interface{}{"Name": file, "BasePath": tpls[file].basePath}
+		vals["Template"] = chartutil.Values{"Name": file, "BasePath": tpls[file].basePath}
+		var buf strings.Builder
 		if err := t.ExecuteTemplate(&buf, file, vals); err != nil {
 			return map[string]string{}, errors.Wrapf(err, "render error in %q", file)
 		}
@@ -264,8 +256,14 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string,
 		// Work around the issue where Go will emit "<no value>" even if Options(missing=zero)
 		// is set. Since missing=error will never get here, we do not need to handle
 		// the Strict case.
-		rendered[file] = strings.Replace(buf.String(), "<no value>", "", -1)
-		buf.Reset()
+		f := &chart.File{
+			Name: strings.Replace(file, "/templates", "/manifests", -1),
+			Data: []byte(strings.Replace(buf.String(), "<no value>", "", -1)),
+		}
+		rendered[file] = string(f.Data)
+		if ch != nil {
+			ch.Files = append(ch.Files, f)
+		}
 	}
 
 	return rendered, nil
@@ -299,8 +297,8 @@ func (p byPathLen) Less(i, j int) bool {
 //
 // As it goes, it also prepares the values in a scope-sensitive manner.
 func allTemplates(c *chart.Chart, vals chartutil.Values) map[string]renderable {
-	templates := map[string]renderable{}
-	recAllTpls(c, templates, vals, true, "")
+	templates := make(map[string]renderable)
+	recAllTpls(c, templates, vals)
 	return templates
 }
 
@@ -308,44 +306,32 @@ func allTemplates(c *chart.Chart, vals chartutil.Values) map[string]renderable {
 //
 // As it recurses, it also sets the values to be appropriate for the template
 // scope.
-func recAllTpls(c *chart.Chart, templates map[string]renderable, parentVals chartutil.Values, top bool, parentID string) {
+func recAllTpls(c *chart.Chart, templates map[string]renderable, parentVals chartutil.Values) {
 	// This should never evaluate to a nil map. That will cause problems when
 	// values are appended later.
-	cvals := chartutil.Values{}
-	if top {
-		// If this is the top of the rendering tree, assume that parentVals
-		// is already resolved to the authoritative values.
+	cvals := make(chartutil.Values)
+	if c.IsRoot() {
 		cvals = parentVals
-	} else if c.Metadata != nil && c.Metadata.Name != "" {
-		// If there is a {{.Values.ThisChart}} in the parent metadata,
-		// copy that into the {{.Values}} for this template.
-		newVals := chartutil.Values{}
-		if vs, err := parentVals.Table("Values"); err == nil {
-			if tmp, err := vs.Table(c.Metadata.Name); err == nil {
-				newVals = tmp
-			}
-		}
-
+	} else if c.Name() != "" {
 		cvals = map[string]interface{}{
-			"Values":       newVals,
+			"Values":       make(chartutil.Values),
 			"Release":      parentVals["Release"],
 			"Chart":        c.Metadata,
 			"Files":        chartutil.NewFiles(c.Files),
 			"Capabilities": parentVals["Capabilities"],
 		}
+		// If there is a {{.Values.ThisChart}} in the parent metadata,
+		// copy that into the {{.Values}} for this template.
+		if vs, err := parentVals.Table("Values." + c.Name()); err == nil {
+			cvals["Values"] = vs
+		}
 	}
 
-	newParentID := c.Metadata.Name
-	if parentID != "" {
-		// We artificially reconstruct the chart path to child templates. This
-		// creates a namespaced filename that can be used to track down the source
-		// of a particular template declaration.
-		newParentID = path.Join(parentID, "charts", newParentID)
+	for _, child := range c.Dependencies() {
+		recAllTpls(child, templates, cvals)
 	}
 
-	for _, child := range c.Dependencies {
-		recAllTpls(child, templates, cvals, false, newParentID)
-	}
+	newParentID := c.ChartFullPath()
 	for _, t := range c.Templates {
 		templates[path.Join(newParentID, t.Name)] = renderable{
 			tpl:      string(t.Data),
diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go
index be9aaa448ffb7318c2a5b72f8fbe5ddb4f7b89d7..3b1127d45a8e24082127667e89b2ee3f922359db 100644
--- a/pkg/engine/engine_test.go
+++ b/pkg/engine/engine_test.go
@@ -21,8 +21,8 @@ import (
 	"sync"
 	"testing"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 )
 
 func TestSortTemplates(t *testing.T) {
@@ -62,7 +62,7 @@ func TestEngine(t *testing.T) {
 	// Forbidden because they allow access to the host OS.
 	forbidden := []string{"env", "expandenv"}
 	for _, f := range forbidden {
-		if _, ok := e.FuncMap[f]; ok {
+		if _, ok := e.funcMap[f]; ok {
 			t.Errorf("Forbidden function %s exists in FuncMap.", f)
 		}
 	}
@@ -149,7 +149,7 @@ func TestRenderInternals(t *testing.T) {
 		"three": {tpl: `{{template "two" dict "Value" "three"}}`, vals: vals},
 	}
 
-	out, err := e.render(tpls)
+	out, err := e.render(nil, tpls)
 	if err != nil {
 		t.Fatalf("Failed template rendering: %s", err)
 	}
@@ -182,7 +182,7 @@ func TestParallelRenderInternals(t *testing.T) {
 			tt := fmt.Sprintf("expect-%d", i)
 			v := chartutil.Values{"val": tt}
 			tpls := map[string]renderable{fname: {tpl: `{{.val}}`, vals: v}}
-			out, err := e.render(tpls)
+			out, err := e.render(nil, tpls)
 			if err != nil {
 				t.Errorf("Failed to render %s: %s", tt, err)
 			}
@@ -202,22 +202,23 @@ func TestAllTemplates(t *testing.T) {
 			{Name: "templates/foo", Data: []byte("foo")},
 			{Name: "templates/bar", Data: []byte("bar")},
 		},
-		Dependencies: []*chart.Chart{
-			{
-				Metadata: &chart.Metadata{Name: "laboratory mice"},
-				Templates: []*chart.File{
-					{Name: "templates/pinky", Data: []byte("pinky")},
-					{Name: "templates/brain", Data: []byte("brain")},
-				},
-				Dependencies: []*chart.Chart{{
-					Metadata: &chart.Metadata{Name: "same thing we do every night"},
-					Templates: []*chart.File{
-						{Name: "templates/innermost", Data: []byte("innermost")},
-					}},
-				},
-			},
+	}
+	dep1 := &chart.Chart{
+		Metadata: &chart.Metadata{Name: "laboratory mice"},
+		Templates: []*chart.File{
+			{Name: "templates/pinky", Data: []byte("pinky")},
+			{Name: "templates/brain", Data: []byte("brain")},
+		},
+	}
+	ch1.AddDependency(dep1)
+
+	dep2 := &chart.Chart{
+		Metadata: &chart.Metadata{Name: "same thing we do every night"},
+		Templates: []*chart.File{
+			{Name: "templates/innermost", Data: []byte("innermost")},
 		},
 	}
+	dep1.AddDependency(dep2)
 
 	var v chartutil.Values
 	tpls := allTemplates(ch1, v)
@@ -235,18 +236,15 @@ func TestRenderDependency(t *testing.T) {
 		Templates: []*chart.File{
 			{Name: "templates/outer", Data: []byte(toptpl)},
 		},
-		Dependencies: []*chart.Chart{
-			{
-				Metadata: &chart.Metadata{Name: "innerchart"},
-				Templates: []*chart.File{
-					{Name: "templates/inner", Data: []byte(deptpl)},
-				},
-			},
-		},
 	}
+	ch.AddDependency(&chart.Chart{
+		Metadata: &chart.Metadata{Name: "innerchart"},
+		Templates: []*chart.File{
+			{Name: "templates/inner", Data: []byte(deptpl)},
+		},
+	})
 
 	out, err := e.Render(ch, map[string]interface{}{})
-
 	if err != nil {
 		t.Fatalf("failed to render chart: %s", err)
 	}
@@ -285,9 +283,9 @@ func TestRenderNestedValues(t *testing.T) {
 		Templates: []*chart.File{
 			{Name: innerpath, Data: []byte(`Old {{.Values.who}} is still a-flyin'`)},
 		},
-		Values:       []byte(`who: "Robert"`),
-		Dependencies: []*chart.Chart{deepest},
+		Values: []byte(`who: "Robert"`),
 	}
+	inner.AddDependency(deepest)
 
 	outer := &chart.Chart{
 		Metadata: &chart.Metadata{Name: "top"},
@@ -299,8 +297,8 @@ what: stinkweed
 who: me
 herrick:
     who: time`),
-		Dependencies: []*chart.Chart{inner},
 	}
+	outer.AddDependency(inner)
 
 	injValues := []byte(`
 what: rosebuds
@@ -358,8 +356,6 @@ func TestRenderBuiltinValues(t *testing.T) {
 			{Name: "templates/Lavinia", Data: []byte(`{{.Template.Name}}{{.Chart.Name}}{{.Release.Name}}`)},
 			{Name: "templates/From", Data: []byte(`{{.Files.author | printf "%s"}} {{.Files.Get "book/title.txt"}}`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{},
 		Files: []*chart.File{
 			{Name: "author", Data: []byte("Virgil")},
 			{Name: "book/title.txt", Data: []byte("Aeneid")},
@@ -371,9 +367,8 @@ func TestRenderBuiltinValues(t *testing.T) {
 		Templates: []*chart.File{
 			{Name: "templates/Aeneas", Data: []byte(`{{.Template.Name}}{{.Chart.Name}}{{.Release.Name}}`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{inner},
 	}
+	outer.AddDependency(inner)
 
 	inject := chartutil.Values{
 		"Values": "",
@@ -403,15 +398,13 @@ func TestRenderBuiltinValues(t *testing.T) {
 
 }
 
-func TestAlterFuncMap(t *testing.T) {
+func TestAlterFuncMap_include(t *testing.T) {
 	c := &chart.Chart{
 		Metadata: &chart.Metadata{Name: "conrad"},
 		Templates: []*chart.File{
 			{Name: "templates/quote", Data: []byte(`{{include "conrad/templates/_partial" . | indent 2}} dead.`)},
 			{Name: "templates/_partial", Data: []byte(`{{.Release.Name}} - he`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{},
 	}
 
 	v := chartutil.Values{
@@ -431,127 +424,127 @@ func TestAlterFuncMap(t *testing.T) {
 	if got := out["conrad/templates/quote"]; got != expect {
 		t.Errorf("Expected %q, got %q (%v)", expect, got, out)
 	}
+}
 
-	reqChart := &chart.Chart{
+func TestAlterFuncMap_require(t *testing.T) {
+	c := &chart.Chart{
 		Metadata: &chart.Metadata{Name: "conan"},
 		Templates: []*chart.File{
 			{Name: "templates/quote", Data: []byte(`All your base are belong to {{ required "A valid 'who' is required" .Values.who }}`)},
 			{Name: "templates/bases", Data: []byte(`All {{ required "A valid 'bases' is required" .Values.bases }} of them!`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{},
 	}
 
-	reqValues := chartutil.Values{
+	v := chartutil.Values{
 		"Values": chartutil.Values{
 			"who":   "us",
 			"bases": 2,
 		},
-		"Chart": reqChart.Metadata,
+		"Chart": c.Metadata,
 		"Release": chartutil.Values{
 			"Name": "That 90s meme",
 		},
 	}
 
-	outReq, err := New().Render(reqChart, reqValues)
+	out, err := New().Render(c, v)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	expectStr := "All your base are belong to us"
-	if gotStr := outReq["conan/templates/quote"]; gotStr != expectStr {
-		t.Errorf("Expected %q, got %q (%v)", expectStr, gotStr, outReq)
+	if gotStr := out["conan/templates/quote"]; gotStr != expectStr {
+		t.Errorf("Expected %q, got %q (%v)", expectStr, gotStr, out)
 	}
 	expectNum := "All 2 of them!"
-	if gotNum := outReq["conan/templates/bases"]; gotNum != expectNum {
-		t.Errorf("Expected %q, got %q (%v)", expectNum, gotNum, outReq)
+	if gotNum := out["conan/templates/bases"]; gotNum != expectNum {
+		t.Errorf("Expected %q, got %q (%v)", expectNum, gotNum, out)
 	}
+}
 
-	tplChart := &chart.Chart{
+func TestAlterFuncMap_tpl(t *testing.T) {
+	c := &chart.Chart{
 		Metadata: &chart.Metadata{Name: "TplFunction"},
 		Templates: []*chart.File{
 			{Name: "templates/base", Data: []byte(`Evaluate tpl {{tpl "Value: {{ .Values.value}}" .}}`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{},
 	}
 
-	tplValues := chartutil.Values{
+	v := chartutil.Values{
 		"Values": chartutil.Values{
 			"value": "myvalue",
 		},
-		"Chart": tplChart.Metadata,
+		"Chart": c.Metadata,
 		"Release": chartutil.Values{
 			"Name": "TestRelease",
 		},
 	}
 
-	outTpl, err := New().Render(tplChart, tplValues)
+	out, err := New().Render(c, v)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	expectTplStr := "Evaluate tpl Value: myvalue"
-	if gotStrTpl := outTpl["TplFunction/templates/base"]; gotStrTpl != expectTplStr {
-		t.Errorf("Expected %q, got %q (%v)", expectTplStr, gotStrTpl, outTpl)
+	expect := "Evaluate tpl Value: myvalue"
+	if got := out["TplFunction/templates/base"]; got != expect {
+		t.Errorf("Expected %q, got %q (%v)", expect, got, out)
 	}
+}
 
-	tplChartWithFunction := &chart.Chart{
+func TestAlterFuncMap_tplfunc(t *testing.T) {
+	c := &chart.Chart{
 		Metadata: &chart.Metadata{Name: "TplFunction"},
 		Templates: []*chart.File{
 			{Name: "templates/base", Data: []byte(`Evaluate tpl {{tpl "Value: {{ .Values.value | quote}}" .}}`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{},
 	}
 
-	tplValuesWithFunction := chartutil.Values{
+	v := chartutil.Values{
 		"Values": chartutil.Values{
 			"value": "myvalue",
 		},
-		"Chart": tplChartWithFunction.Metadata,
+		"Chart": c.Metadata,
 		"Release": chartutil.Values{
 			"Name": "TestRelease",
 		},
 	}
 
-	outTplWithFunction, err := New().Render(tplChartWithFunction, tplValuesWithFunction)
+	out, err := New().Render(c, v)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	expectTplStrWithFunction := "Evaluate tpl Value: \"myvalue\""
-	if gotStrTplWithFunction := outTplWithFunction["TplFunction/templates/base"]; gotStrTplWithFunction != expectTplStrWithFunction {
-		t.Errorf("Expected %q, got %q (%v)", expectTplStrWithFunction, gotStrTplWithFunction, outTplWithFunction)
+	expect := "Evaluate tpl Value: \"myvalue\""
+	if got := out["TplFunction/templates/base"]; got != expect {
+		t.Errorf("Expected %q, got %q (%v)", expect, got, out)
 	}
+}
 
-	tplChartWithInclude := &chart.Chart{
+func TestAlterFuncMap_tplinclude(t *testing.T) {
+	c := &chart.Chart{
 		Metadata: &chart.Metadata{Name: "TplFunction"},
 		Templates: []*chart.File{
 			{Name: "templates/base", Data: []byte(`{{ tpl "{{include ` + "`" + `TplFunction/templates/_partial` + "`" + ` .  | quote }}" .}}`)},
 			{Name: "templates/_partial", Data: []byte(`{{.Template.Name}}`)},
 		},
-		Values:       []byte{},
-		Dependencies: []*chart.Chart{},
 	}
-	tplValueWithInclude := chartutil.Values{
+	v := chartutil.Values{
 		"Values": chartutil.Values{
 			"value": "myvalue",
 		},
-		"Chart": tplChartWithInclude.Metadata,
+		"Chart": c.Metadata,
 		"Release": chartutil.Values{
 			"Name": "TestRelease",
 		},
 	}
 
-	outTplWithInclude, err := New().Render(tplChartWithInclude, tplValueWithInclude)
+	out, err := New().Render(c, v)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	expectedTplStrWithInclude := "\"TplFunction/templates/base\""
-	if gotStrTplWithInclude := outTplWithInclude["TplFunction/templates/base"]; gotStrTplWithInclude != expectedTplStrWithInclude {
-		t.Errorf("Expected %q, got %q (%v)", expectedTplStrWithInclude, gotStrTplWithInclude, outTplWithInclude)
+	expect := "\"TplFunction/templates/base\""
+	if got := out["TplFunction/templates/base"]; got != expect {
+		t.Errorf("Expected %q, got %q (%v)", expect, got, out)
 	}
 
 }
diff --git a/pkg/hapi/chart/chart.go b/pkg/hapi/chart/chart.go
deleted file mode 100644
index 711bee61d4d0d171a78875b9a213fd396f60ad4f..0000000000000000000000000000000000000000
--- a/pkg/hapi/chart/chart.go
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-Copyright 2018 The Kubernetes Authors All rights reserved.
-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 chart
-
-// Chart is a helm package that contains metadata, a default config, zero or more
-// optionally parameterizable templates, and zero or more charts (dependencies).
-type Chart struct {
-	// Metadata is the contents of the Chartfile.
-	Metadata *Metadata `json:"metadata,omitempty"`
-	// Templates for this chart.
-	Templates []*File `json:"templates,omitempty"`
-	// Dependencies are the charts that this chart depends on.
-	Dependencies []*Chart `json:"dependencies,omitempty"`
-	// Values are default config for this template.
-	Values []byte `json:"values,omitempty"`
-	// Files are miscellaneous files in a chart archive,
-	// e.g. README, LICENSE, etc.
-	Files []*File `json:"files,omitempty"`
-}
diff --git a/pkg/hapi/release/release.go b/pkg/hapi/release/release.go
index f8b7394683d6be250370c84620109087996e5283..b850f74a677501b2effeeeaed06db3666eb8416e 100644
--- a/pkg/hapi/release/release.go
+++ b/pkg/hapi/release/release.go
@@ -15,7 +15,7 @@ limitations under the License.
 
 package release
 
-import "k8s.io/helm/pkg/hapi/chart"
+import "k8s.io/helm/pkg/chart"
 
 // Release describes a deployment of a chart, together with the chart
 // and the variables used to deploy that chart.
diff --git a/pkg/hapi/tiller.go b/pkg/hapi/tiller.go
index ee30f561958ed08fbecb6b76bf7a259e7ef63bab..f0fc89a1f1bfe7a186e26bf00b0575d01cfd283f 100644
--- a/pkg/hapi/tiller.go
+++ b/pkg/hapi/tiller.go
@@ -16,7 +16,7 @@ limitations under the License.
 package hapi
 
 import (
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/hapi/release"
 )
 
diff --git a/pkg/helm/client.go b/pkg/helm/client.go
index 8925b604306d3b12148a20bf9dd367cd6aeaa95c..83b3c8e497c03b02f572154976385f3bcf5e32b3 100644
--- a/pkg/helm/client.go
+++ b/pkg/helm/client.go
@@ -17,13 +17,13 @@ limitations under the License.
 package helm // import "k8s.io/helm/pkg/helm"
 
 import (
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 	"k8s.io/helm/pkg/storage"
 	"k8s.io/helm/pkg/tiller"
-	"k8s.io/helm/pkg/tiller/environment"
 )
 
 // Client manages client side of the Helm-Tiller protocol.
@@ -39,8 +39,7 @@ func NewClient(opts ...Option) *Client {
 }
 
 func (c *Client) init() *Client {
-	env := environment.New()
-	c.tiller = tiller.NewReleaseServer(env, c.opts.discovery, c.opts.kubeClient)
+	c.tiller = tiller.NewReleaseServer(c.opts.discovery, c.opts.kubeClient)
 	c.tiller.Releases = storage.Init(c.opts.driver)
 	return c
 }
@@ -69,7 +68,7 @@ func (c *Client) ListReleases(opts ...ReleaseListOption) ([]*release.Release, er
 // InstallRelease loads a chart from chstr, installs it, and returns the release response.
 func (c *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*release.Release, error) {
 	// load the chart to install
-	chart, err := chartutil.Load(chstr)
+	chart, err := loader.Load(chstr)
 	if err != nil {
 		return nil, err
 	}
@@ -136,7 +135,7 @@ func (c *Client) UninstallRelease(rlsName string, opts ...UninstallOption) (*hap
 // UpdateRelease loads a chart from chstr and updates a release to a new/different chart.
 func (c *Client) UpdateRelease(rlsName, chstr string, opts ...UpdateOption) (*release.Release, error) {
 	// load the chart to update
-	chart, err := chartutil.Load(chstr)
+	chart, err := loader.Load(chstr)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/helm/fake.go b/pkg/helm/fake.go
index d7f5e01fd98e34f96690e2e6b310646a9375765e..03f3747000970b38ab25c86ff18b3bf9461807ad 100644
--- a/pkg/helm/fake.go
+++ b/pkg/helm/fake.go
@@ -23,8 +23,8 @@ import (
 
 	"github.com/pkg/errors"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 )
 
diff --git a/pkg/helm/fake_test.go b/pkg/helm/fake_test.go
index 12114328a959be1e07c611d7c7e6f1a6720061cc..97f127507787b91f5dc6713417b68c7c62d1aa39 100644
--- a/pkg/helm/fake_test.go
+++ b/pkg/helm/fake_test.go
@@ -20,8 +20,8 @@ import (
 	"reflect"
 	"testing"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 )
 
diff --git a/pkg/helm/helm_test.go b/pkg/helm/helm_test.go
index 94207077f1812c93d06475d775530c0e422ecdf7..d2a369488bd504c90a1db6bd143ccc7decbe397b 100644
--- a/pkg/helm/helm_test.go
+++ b/pkg/helm/helm_test.go
@@ -23,9 +23,9 @@ import (
 
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/chartutil"
+	cpb "k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/hapi"
-	cpb "k8s.io/helm/pkg/hapi/chart"
 	rls "k8s.io/helm/pkg/hapi/release"
 )
 
@@ -349,7 +349,7 @@ func assert(t *testing.T, expect, actual interface{}) {
 }
 
 func loadChart(t *testing.T, name string) *cpb.Chart {
-	c, err := chartutil.Load(filepath.Join(chartsDir, name))
+	c, err := loader.Load(filepath.Join(chartsDir, name))
 	if err != nil {
 		t.Fatalf("failed to load test chart (%q): %s\n", name, err)
 	}
diff --git a/pkg/helm/interface.go b/pkg/helm/interface.go
index 25b96a0a8b8a1bd1b0b82950a951507523090abe..fff653fbabbc091a7e481f106405a1795e76005c 100644
--- a/pkg/helm/interface.go
+++ b/pkg/helm/interface.go
@@ -17,8 +17,8 @@ limitations under the License.
 package helm
 
 import (
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 )
 
diff --git a/pkg/kube/converter.go b/pkg/kube/converter.go
new file mode 100644
index 0000000000000000000000000000000000000000..b1093a7377d1d679614e80c0d91999134ce37240
--- /dev/null
+++ b/pkg/kube/converter.go
@@ -0,0 +1,40 @@
+/*
+Copyright 2016 The Kubernetes Authors All rights reserved.
+
+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 kube // import "k8s.io/helm/pkg/kube"
+
+import (
+	"k8s.io/apimachinery/pkg/api/meta"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/kubernetes/pkg/api/legacyscheme"
+)
+
+// AsDefaultVersionedOrOriginal returns the object as a Go object in the external form if possible (matching the
+// group version kind of the mapping if provided, a best guess based on serialization if not provided, or obj if it cannot be converted.
+// TODO update call sites to specify the scheme they want on their builder.
+func AsDefaultVersionedOrOriginal(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object {
+	converter := runtime.ObjectConvertor(legacyscheme.Scheme)
+	groupVersioner := runtime.GroupVersioner(schema.GroupVersions(legacyscheme.Scheme.PrioritizedVersionsAllGroups()))
+	if mapping != nil {
+		groupVersioner = mapping.GroupVersionKind.GroupVersion()
+	}
+
+	if obj, err := converter.ConvertToVersion(obj, groupVersioner); err == nil {
+		return obj
+	}
+	return obj
+}
diff --git a/pkg/lint/rules/chartfile.go b/pkg/lint/rules/chartfile.go
index 30691c5009594ea795c98fffcbed8bf38a4b7814..9f39253e881fe510506bc68385a8389287305576 100644
--- a/pkg/lint/rules/chartfile.go
+++ b/pkg/lint/rules/chartfile.go
@@ -24,8 +24,8 @@ import (
 	"github.com/asaskevich/govalidator"
 	"github.com/pkg/errors"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/lint/support"
 )
 
diff --git a/pkg/lint/rules/chartfile_test.go b/pkg/lint/rules/chartfile_test.go
index 4af73422eb55347ef8cfdbea0758905acd1845f7..a2bf8c0fa783d76cabe5acb5c4864e11429f78cc 100644
--- a/pkg/lint/rules/chartfile_test.go
+++ b/pkg/lint/rules/chartfile_test.go
@@ -24,8 +24,8 @@ import (
 
 	"github.com/pkg/errors"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/lint/support"
 )
 
diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go
index 6b2a7502752fbfea96a3d1dac9c151d5cbc9312e..fe1168ccd17c24e5e0d532ac7c7acbd8d1ea50ca 100644
--- a/pkg/lint/rules/template.go
+++ b/pkg/lint/rules/template.go
@@ -23,10 +23,10 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/chartutil"
 	"k8s.io/helm/pkg/engine"
 	"k8s.io/helm/pkg/lint/support"
-	tversion "k8s.io/helm/pkg/version"
 )
 
 // Templates lints the templates in the Linter.
@@ -42,7 +42,7 @@ func Templates(linter *support.Linter, values []byte, namespace string, strict b
 	}
 
 	// Load chart and parse templates, based on tiller/release_server
-	chart, err := chartutil.Load(linter.ChartDir)
+	chart, err := loader.Load(linter.ChartDir)
 
 	chartLoaded := linter.RunLinterRule(support.ErrorSev, path, err)
 
@@ -51,11 +51,7 @@ func Templates(linter *support.Linter, values []byte, namespace string, strict b
 	}
 
 	options := chartutil.ReleaseOptions{Name: "testRelease"}
-	caps := &chartutil.Capabilities{
-		APIVersions: chartutil.DefaultVersionSet,
-		KubeVersion: chartutil.DefaultKubeVersion,
-		HelmVersion: tversion.GetBuildInfo(),
-	}
+
 	cvals, err := chartutil.CoalesceValues(chart, values)
 	if err != nil {
 		return
@@ -65,7 +61,8 @@ func Templates(linter *support.Linter, values []byte, namespace string, strict b
 	if err != nil {
 		return
 	}
-	valuesToRender, err := chartutil.ToRenderValuesCaps(chart, yvals, options, caps)
+	caps := chartutil.DefaultCapabilities
+	valuesToRender, err := chartutil.ToRenderValues(chart, yvals, options, caps)
 	if err != nil {
 		// FIXME: This seems to generate a duplicate, but I can't find where the first
 		// error is coming from.
@@ -109,7 +106,7 @@ func Templates(linter *support.Linter, values []byte, namespace string, strict b
 		// NOTE: disabled for now, Refs https://github.com/kubernetes/helm/issues/1037
 		// linter.RunLinterRule(support.WarningSev, path, validateQuotes(string(preExecutedTemplate)))
 
-		renderedContent := renderedContentMap[filepath.Join(chart.Metadata.Name, fileName)]
+		renderedContent := renderedContentMap[filepath.Join(chart.Name(), fileName)]
 		var yamlStruct K8sYamlStruct
 		// Even though K8sYamlStruct only defines Metadata namespace, an error in any other
 		// key will be raised as well
diff --git a/pkg/provenance/sign.go b/pkg/provenance/sign.go
index 4d1803454443c696916c1ea2b9d9a1a36e9a14c4..62e9462c1c0eeec5bc66ba5b8079991d275acadc 100644
--- a/pkg/provenance/sign.go
+++ b/pkg/provenance/sign.go
@@ -31,8 +31,8 @@ import (
 	"golang.org/x/crypto/openpgp/clearsign"
 	"golang.org/x/crypto/openpgp/packet"
 
-	"k8s.io/helm/pkg/chartutil"
-	hapi "k8s.io/helm/pkg/hapi/chart"
+	hapi "k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 )
 
 var defaultPGPConfig = packet.Config{
@@ -317,7 +317,7 @@ func messageBlock(chartpath string) (*bytes.Buffer, error) {
 	}
 
 	// Load the archive into memory.
-	chart, err := chartutil.LoadFile(chartpath)
+	chart, err := loader.LoadFile(chartpath)
 	if err != nil {
 		return b, err
 	}
diff --git a/pkg/releaseutil/manifest.go b/pkg/releaseutil/manifest.go
index a0449cc551c9e95d20b3431061ab1463e732342b..d233fc106a9578c089265d67050155524107ae05 100644
--- a/pkg/releaseutil/manifest.go
+++ b/pkg/releaseutil/manifest.go
@@ -46,7 +46,6 @@ func SplitManifests(bigFile string) map[string]string {
 	docs := sep.Split(bigFileTmp, -1)
 	var count int
 	for _, d := range docs {
-
 		if d == "" {
 			continue
 		}
diff --git a/pkg/releaseutil/sorter.go b/pkg/releaseutil/sorter.go
index cd90e58166c4dd610288fa4d94a4e99712cd04a2..31f8367dd3d40b0e2e46c9e6b87c9bf1e70c48d1 100644
--- a/pkg/releaseutil/sorter.go
+++ b/pkg/releaseutil/sorter.go
@@ -22,14 +22,28 @@ import (
 	rspb "k8s.io/helm/pkg/hapi/release"
 )
 
-type sorter struct {
-	list []*rspb.Release
-	less func(int, int) bool
+type list []*rspb.Release
+
+func (s list) Len() int      { return len(s) }
+func (s list) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+type ByName struct{ list }
+
+func (s ByName) Less(i, j int) bool { return s.list[i].Name < s.list[j].Name }
+
+type ByDate struct{ list }
+
+func (s ByDate) Less(i, j int) bool {
+	ti := s.list[i].Info.LastDeployed.Second()
+	tj := s.list[j].Info.LastDeployed.Second()
+	return ti < tj
 }
 
-func (s *sorter) Len() int           { return len(s.list) }
-func (s *sorter) Less(i, j int) bool { return s.less(i, j) }
-func (s *sorter) Swap(i, j int)      { s.list[i], s.list[j] = s.list[j], s.list[i] }
+type ByRevision struct{ list }
+
+func (s ByRevision) Less(i, j int) bool {
+	return s.list[i].Version < s.list[j].Version
+}
 
 // Reverse reverses the list of releases sorted by the sort func.
 func Reverse(list []*rspb.Release, sortFn func([]*rspb.Release)) {
@@ -42,36 +56,17 @@ func Reverse(list []*rspb.Release, sortFn func([]*rspb.Release)) {
 // SortByName returns the list of releases sorted
 // in lexicographical order.
 func SortByName(list []*rspb.Release) {
-	s := &sorter{list: list}
-	s.less = func(i, j int) bool {
-		ni := s.list[i].Name
-		nj := s.list[j].Name
-		return ni < nj
-	}
-	sort.Sort(s)
+	sort.Sort(ByName{list})
 }
 
 // SortByDate returns the list of releases sorted by a
 // release's last deployed time (in seconds).
 func SortByDate(list []*rspb.Release) {
-	s := &sorter{list: list}
-
-	s.less = func(i, j int) bool {
-		ti := s.list[i].Info.LastDeployed.Second()
-		tj := s.list[j].Info.LastDeployed.Second()
-		return ti < tj
-	}
-	sort.Sort(s)
+	sort.Sort(ByDate{list})
 }
 
 // SortByRevision returns the list of releases sorted by a
 // release's revision number (release.Version).
 func SortByRevision(list []*rspb.Release) {
-	s := &sorter{list: list}
-	s.less = func(i, j int) bool {
-		vi := s.list[i].Version
-		vj := s.list[j].Version
-		return vi < vj
-	}
-	sort.Sort(s)
+	sort.Sort(ByRevision{list})
 }
diff --git a/pkg/repo/chartrepo.go b/pkg/repo/chartrepo.go
index 708b15043a07605104ad75464c0b19d070ebcb19..03d89fe2fab357770cd49dd915cebb1c13e227c9 100644
--- a/pkg/repo/chartrepo.go
+++ b/pkg/repo/chartrepo.go
@@ -27,7 +27,7 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/getter"
 	"k8s.io/helm/pkg/provenance"
 )
@@ -172,7 +172,7 @@ func (r *ChartRepository) saveIndexFile() error {
 
 func (r *ChartRepository) generateIndex() error {
 	for _, path := range r.ChartPaths {
-		ch, err := chartutil.Load(path)
+		ch, err := loader.Load(path)
 		if err != nil {
 			return err
 		}
@@ -182,7 +182,7 @@ func (r *ChartRepository) generateIndex() error {
 			return err
 		}
 
-		if !r.IndexFile.Has(ch.Metadata.Name, ch.Metadata.Version) {
+		if !r.IndexFile.Has(ch.Name(), ch.Metadata.Version) {
 			r.IndexFile.Add(ch.Metadata, path, r.Config.URL, digest)
 		}
 		// TODO: If a chart exists, but has a different Digest, should we error?
diff --git a/pkg/repo/chartrepo_test.go b/pkg/repo/chartrepo_test.go
index b1c066cedc1747d26f308b0bf18ec7dceaf5897c..01563a31e02656e26b56356104a8e16ef8b8c315 100644
--- a/pkg/repo/chartrepo_test.go
+++ b/pkg/repo/chartrepo_test.go
@@ -27,8 +27,8 @@ import (
 	"testing"
 	"time"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/getter"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/helm/environment"
 )
 
diff --git a/pkg/repo/index.go b/pkg/repo/index.go
index 9cd6159fcac85161f02339c666aaa24275537b3b..d64b065b8d85063eb34897c4b75f67bc1816777d 100644
--- a/pkg/repo/index.go
+++ b/pkg/repo/index.go
@@ -30,8 +30,8 @@ import (
 	"github.com/ghodss/yaml"
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chart/loader"
 	"k8s.io/helm/pkg/provenance"
 	"k8s.io/helm/pkg/urlutil"
 )
@@ -251,7 +251,7 @@ func IndexDirectory(dir, baseURL string) (*IndexFile, error) {
 			parentURL = filepath.Join(baseURL, parentDir)
 		}
 
-		c, err := chartutil.Load(arch)
+		c, err := loader.Load(arch)
 		if err != nil {
 			// Assume this is not a chart.
 			continue
diff --git a/pkg/repo/index_test.go b/pkg/repo/index_test.go
index c3199290a404d1f61b0b49772f619977d092352e..68f8c7176adb6f2f4501d8fd63d31024f4e7e1ac 100644
--- a/pkg/repo/index_test.go
+++ b/pkg/repo/index_test.go
@@ -22,8 +22,8 @@ import (
 	"path/filepath"
 	"testing"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/getter"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/helm/environment"
 )
 
diff --git a/pkg/resolver/resolver.go b/pkg/resolver/resolver.go
index 2d2fba018fe6945d84962a6d979ffa4dfbcb3516..4df51181aea5d3b3bd0f369c70ba59d31fab203c 100644
--- a/pkg/resolver/resolver.go
+++ b/pkg/resolver/resolver.go
@@ -26,7 +26,7 @@ import (
 	"github.com/Masterminds/semver"
 	"github.com/pkg/errors"
 
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/helm/helmpath"
 	"k8s.io/helm/pkg/provenance"
 	"k8s.io/helm/pkg/repo"
@@ -47,10 +47,10 @@ func New(chartpath string, helmhome helmpath.Home) *Resolver {
 }
 
 // Resolve resolves dependencies and returns a lock file with the resolution.
-func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]string, d string) (*chartutil.RequirementsLock, error) {
+func (r *Resolver) Resolve(reqs *chart.Requirements, repoNames map[string]string, d string) (*chart.RequirementsLock, error) {
 
 	// Now we clone the dependencies, locking as we go.
-	locked := make([]*chartutil.Dependency, len(reqs.Dependencies))
+	locked := make([]*chart.Dependency, len(reqs.Dependencies))
 	missing := []string{}
 	for i, d := range reqs.Dependencies {
 		if strings.HasPrefix(d.Repository, "file://") {
@@ -59,7 +59,7 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st
 				return nil, err
 			}
 
-			locked[i] = &chartutil.Dependency{
+			locked[i] = &chart.Dependency{
 				Name:       d.Name,
 				Repository: d.Repository,
 				Version:    d.Version,
@@ -81,7 +81,7 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st
 			return nil, errors.Errorf("%s chart not found in repo %s", d.Name, d.Repository)
 		}
 
-		locked[i] = &chartutil.Dependency{
+		locked[i] = &chart.Dependency{
 			Name:       d.Name,
 			Repository: d.Repository,
 		}
@@ -107,7 +107,7 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st
 	if len(missing) > 0 {
 		return nil, errors.Errorf("can't get a valid version for repositories %s. Try changing the version constraint in requirements.yaml", strings.Join(missing, ", "))
 	}
-	return &chartutil.RequirementsLock{
+	return &chart.RequirementsLock{
 		Generated:    time.Now(),
 		Digest:       d,
 		Dependencies: locked,
@@ -118,7 +118,7 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st
 //
 // This should be used only to compare against another hash generated by this
 // function.
-func HashReq(req *chartutil.Requirements) (string, error) {
+func HashReq(req *chart.Requirements) (string, error) {
 	data, err := json.Marshal(req)
 	if err != nil {
 		return "", err
diff --git a/pkg/resolver/resolver_test.go b/pkg/resolver/resolver_test.go
index 78a0bc46c50992105df51ff35102e6b29ec6ce6d..decf3b59a91727e183d916038ec08e763391f29a 100644
--- a/pkg/resolver/resolver_test.go
+++ b/pkg/resolver/resolver_test.go
@@ -18,20 +18,20 @@ package resolver
 import (
 	"testing"
 
-	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/chart"
 )
 
 func TestResolve(t *testing.T) {
 	tests := []struct {
 		name   string
-		req    *chartutil.Requirements
-		expect *chartutil.RequirementsLock
+		req    *chart.Requirements
+		expect *chart.RequirementsLock
 		err    bool
 	}{
 		{
 			name: "version failure",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "oedipus-rex", Repository: "http://example.com", Version: ">a1"},
 				},
 			},
@@ -39,8 +39,8 @@ func TestResolve(t *testing.T) {
 		},
 		{
 			name: "cache index failure",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "oedipus-rex", Repository: "http://example.com", Version: "1.0.0"},
 				},
 			},
@@ -48,8 +48,8 @@ func TestResolve(t *testing.T) {
 		},
 		{
 			name: "chart not found failure",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "redis", Repository: "http://example.com", Version: "1.0.0"},
 				},
 			},
@@ -57,8 +57,8 @@ func TestResolve(t *testing.T) {
 		},
 		{
 			name: "constraint not satisfied failure",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "alpine", Repository: "http://example.com", Version: ">=1.0.0"},
 				},
 			},
@@ -66,34 +66,34 @@ func TestResolve(t *testing.T) {
 		},
 		{
 			name: "valid lock",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "alpine", Repository: "http://example.com", Version: ">=0.1.0"},
 				},
 			},
-			expect: &chartutil.RequirementsLock{
-				Dependencies: []*chartutil.Dependency{
+			expect: &chart.RequirementsLock{
+				Dependencies: []*chart.Dependency{
 					{Name: "alpine", Repository: "http://example.com", Version: "0.2.0"},
 				},
 			},
 		},
 		{
 			name: "repo from valid local path",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "signtest", Repository: "file://../../../../cmd/helm/testdata/testcharts/signtest", Version: "0.1.0"},
 				},
 			},
-			expect: &chartutil.RequirementsLock{
-				Dependencies: []*chartutil.Dependency{
+			expect: &chart.RequirementsLock{
+				Dependencies: []*chart.Dependency{
 					{Name: "signtest", Repository: "file://../../../../cmd/helm/testdata/testcharts/signtest", Version: "0.1.0"},
 				},
 			},
 		},
 		{
 			name: "repo from invalid local path",
-			req: &chartutil.Requirements{
-				Dependencies: []*chartutil.Dependency{
+			req: &chart.Requirements{
+				Dependencies: []*chart.Dependency{
 					{Name: "notexist", Repository: "file://../testdata/notexist", Version: "0.1.0"},
 				},
 			},
@@ -147,8 +147,8 @@ func TestResolve(t *testing.T) {
 
 func TestHashReq(t *testing.T) {
 	expect := "sha256:e70e41f8922e19558a8bf62f591a8b70c8e4622e3c03e5415f09aba881f13885"
-	req := &chartutil.Requirements{
-		Dependencies: []*chartutil.Dependency{
+	req := &chart.Requirements{
+		Dependencies: []*chart.Dependency{
 			{Name: "alpine", Version: "0.1.0", Repository: "http://localhost:8879/charts"},
 		},
 	}
@@ -160,7 +160,7 @@ func TestHashReq(t *testing.T) {
 		t.Errorf("Expected %q, got %q", expect, h)
 	}
 
-	req = &chartutil.Requirements{Dependencies: []*chartutil.Dependency{}}
+	req = &chart.Requirements{Dependencies: []*chart.Dependency{}}
 	h, err = HashReq(req)
 	if err != nil {
 		t.Fatal(err)
diff --git a/pkg/tiller/engine.go b/pkg/tiller/engine.go
new file mode 100644
index 0000000000000000000000000000000000000000..06e27c53f65375139f9774f32ce4f93e06e65806
--- /dev/null
+++ b/pkg/tiller/engine.go
@@ -0,0 +1,40 @@
+/*
+Copyright 2016 The Kubernetes Authors All rights reserved.
+
+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 tiller
+
+import (
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/chartutil"
+)
+
+// Engine represents a template engine that can render templates.
+//
+// For some engines, "rendering" includes both compiling and executing. (Other
+// engines do not distinguish between phases.)
+//
+// The engine returns a map where the key is the named output entity (usually
+// a file name) and the value is the rendered content of the template.
+//
+// An Engine must be capable of executing multiple concurrent requests, but
+// without tainting one request's environment with data from another request.
+type Engine interface {
+	// Render renders a chart.
+	//
+	// It receives a chart, a config, and a map of overrides to the config.
+	// Overrides are assumed to be passed from the system, not the user.
+	Render(*chart.Chart, chartutil.Values) (map[string]string, error)
+}
diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go
index fb2293789fc59f2919e5493f60553bd319cb99ae..8815b2d2d7ea2642d397da55b8789be25b0c62cb 100644
--- a/pkg/tiller/environment/environment.go
+++ b/pkg/tiller/environment/environment.go
@@ -29,64 +29,9 @@ import (
 	"k8s.io/kubernetes/pkg/apis/core"
 	"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
 
-	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/engine"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/kube"
 )
 
-// GoTplEngine is the name of the Go template engine, as registered in the EngineYard.
-const GoTplEngine = "gotpl"
-
-// DefaultEngine points to the engine that the EngineYard should treat as the
-// default. A chart that does not specify an engine may be run through the
-// default engine.
-var DefaultEngine = GoTplEngine
-
-// EngineYard maps engine names to engine implementations.
-type EngineYard map[string]Engine
-
-// Get retrieves a template engine by name.
-//
-// If no matching template engine is found, the second return value will
-// be false.
-func (y EngineYard) Get(k string) (Engine, bool) {
-	e, ok := y[k]
-	return e, ok
-}
-
-// Default returns the default template engine.
-//
-// The default is specified by DefaultEngine.
-//
-// If the default template engine cannot be found, this panics.
-func (y EngineYard) Default() Engine {
-	d, ok := y[DefaultEngine]
-	if !ok {
-		// This is a developer error!
-		panic("Default template engine does not exist")
-	}
-	return d
-}
-
-// Engine represents a template engine that can render templates.
-//
-// For some engines, "rendering" includes both compiling and executing. (Other
-// engines do not distinguish between phases.)
-//
-// The engine returns a map where the key is the named output entity (usually
-// a file name) and the value is the rendered content of the template.
-//
-// An Engine must be capable of executing multiple concurrent requests, but
-// without tainting one request's environment with data from another request.
-type Engine interface {
-	// Render renders a chart.
-	//
-	// It receives a chart, a config, and a map of overrides to the config.
-	// Overrides are assumed to be passed from the system, not the user.
-	Render(*chart.Chart, chartutil.Values) (map[string]string, error)
-}
-
 // KubeClient represents a client capable of communicating with the Kubernetes API.
 //
 // A KubeClient must be concurrency safe.
@@ -193,25 +138,3 @@ func (p *PrintingKubeClient) WaitAndGetCompletedPodPhase(namespace string, reade
 	_, err := io.Copy(p.Out, reader)
 	return core.PodUnknown, err
 }
-
-// Environment provides the context for executing a client request.
-//
-// All services in a context are concurrency safe.
-type Environment struct {
-	// EngineYard provides access to the known template engines.
-	EngineYard EngineYard
-}
-
-// New returns an environment initialized with the defaults.
-func New() *Environment {
-	e := engine.New()
-	var ey EngineYard = map[string]Engine{
-		// Currently, the only template engine we support is the GoTpl one. But
-		// we can easily add some here.
-		GoTplEngine: e,
-	}
-
-	return &Environment{
-		EngineYard: ey,
-	}
-}
diff --git a/pkg/tiller/environment/environment_test.go b/pkg/tiller/environment/environment_test.go
index 616163e4c5fba171c74a6fc1a7a35011034cc3fc..47299c6b65a2bfe598eb2699479158a52227af74 100644
--- a/pkg/tiller/environment/environment_test.go
+++ b/pkg/tiller/environment/environment_test.go
@@ -25,19 +25,9 @@ import (
 	"k8s.io/kubernetes/pkg/apis/core"
 	"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
 
-	"k8s.io/helm/pkg/chartutil"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/kube"
 )
 
-type mockEngine struct {
-	out map[string]string
-}
-
-func (e *mockEngine) Render(chrt *chart.Chart, v chartutil.Values) (map[string]string, error) {
-	return e.out, nil
-}
-
 type mockKubeClient struct{}
 
 func (k *mockKubeClient) Create(ns string, r io.Reader, timeout int64, shouldWait bool) error {
@@ -69,25 +59,9 @@ func (k *mockKubeClient) WaitAndGetCompletedPodStatus(namespace string, reader i
 	return "", nil
 }
 
-var _ Engine = &mockEngine{}
 var _ KubeClient = &mockKubeClient{}
 var _ KubeClient = &PrintingKubeClient{}
 
-func TestEngine(t *testing.T) {
-	eng := &mockEngine{out: map[string]string{"albatross": "test"}}
-
-	env := New()
-	env.EngineYard = EngineYard(map[string]Engine{"test": eng})
-
-	if engine, ok := env.EngineYard.Get("test"); !ok {
-		t.Errorf("failed to get engine from EngineYard")
-	} else if out, err := engine.Render(&chart.Chart{}, map[string]interface{}{}); err != nil {
-		t.Errorf("unexpected template error: %s", err)
-	} else if out["albatross"] != "test" {
-		t.Errorf("expected 'test', got %q", out["albatross"])
-	}
-}
-
 func TestKubeClient(t *testing.T) {
 	kc := &mockKubeClient{}
 
diff --git a/pkg/tiller/hook_sorter.go b/pkg/tiller/hook_sorter.go
index cc6e7e992302891d511e31ef213fe08234af2ea6..4643dc439fabf942c71b392d56ea3c14547b9100 100644
--- a/pkg/tiller/hook_sorter.go
+++ b/pkg/tiller/hook_sorter.go
@@ -17,37 +17,16 @@ limitations under the License.
 package tiller
 
 import (
-	"sort"
-
 	"k8s.io/helm/pkg/hapi/release"
 )
 
-// sortByHookWeight does an in-place sort of hooks by their supplied weight.
-func sortByHookWeight(hooks []*release.Hook) []*release.Hook {
-	hs := newHookWeightSorter(hooks)
-	sort.Sort(hs)
-	return hs.hooks
-}
-
-type hookWeightSorter struct {
-	hooks []*release.Hook
-}
-
-func newHookWeightSorter(h []*release.Hook) *hookWeightSorter {
-	return &hookWeightSorter{
-		hooks: h,
-	}
-}
-
-func (hs *hookWeightSorter) Len() int { return len(hs.hooks) }
-
-func (hs *hookWeightSorter) Swap(i, j int) {
-	hs.hooks[i], hs.hooks[j] = hs.hooks[j], hs.hooks[i]
-}
+type hookByWeight []*release.Hook
 
-func (hs *hookWeightSorter) Less(i, j int) bool {
-	if hs.hooks[i].Weight == hs.hooks[j].Weight {
-		return hs.hooks[i].Name < hs.hooks[j].Name
+func (x hookByWeight) Len() int      { return len(x) }
+func (x hookByWeight) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x hookByWeight) Less(i, j int) bool {
+	if x[i].Weight == x[j].Weight {
+		return x[i].Name < x[j].Name
 	}
-	return hs.hooks[i].Weight < hs.hooks[j].Weight
+	return x[i].Weight < x[j].Weight
 }
diff --git a/pkg/tiller/hook_sorter_test.go b/pkg/tiller/hook_sorter_test.go
index 4e33bdad4edc4278df7e0cef51b6826a879c6320..3360fcbd116f755c79c2de9f6f53fcdcb21affbc 100644
--- a/pkg/tiller/hook_sorter_test.go
+++ b/pkg/tiller/hook_sorter_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package tiller
 
 import (
+	"sort"
 	"testing"
 
 	"k8s.io/helm/pkg/hapi/release"
@@ -61,10 +62,10 @@ func TestHookSorter(t *testing.T) {
 		},
 	}
 
-	res := sortByHookWeight(hooks)
+	sort.Sort(hookByWeight(hooks))
 	got := ""
 	expect := "abcdefg"
-	for _, r := range res {
+	for _, r := range hooks {
 		got += r.Name
 	}
 	if got != expect {
diff --git a/pkg/tiller/hooks.go b/pkg/tiller/hooks.go
index 29c3115097686e2d227bbf608630a9d70c8db353..55e748a66fb084c58e36849fe12f3501ff47126d 100644
--- a/pkg/tiller/hooks.go
+++ b/pkg/tiller/hooks.go
@@ -78,7 +78,7 @@ type manifestFile struct {
 //
 // Files that do not parse into the expected format are simply placed into a map and
 // returned.
-func sortManifests(files map[string]string, apis chartutil.VersionSet, sort SortOrder) ([]*release.Hook, []Manifest, error) {
+func SortManifests(files map[string]string, apis chartutil.VersionSet, sort SortOrder) ([]*release.Hook, []Manifest, error) {
 	result := &result{}
 
 	for filePath, c := range files {
diff --git a/pkg/tiller/hooks_test.go b/pkg/tiller/hooks_test.go
index 694c1cab1ac462190202a6ec4bcf899ff60fef73..ef0fdbd409f5c9fba84582dd867b2bb57f0f2dee 100644
--- a/pkg/tiller/hooks_test.go
+++ b/pkg/tiller/hooks_test.go
@@ -140,7 +140,7 @@ metadata:
 		manifests[o.path] = o.manifest
 	}
 
-	hs, generic, err := sortManifests(manifests, chartutil.NewVersionSet("v1", "v1beta1"), InstallOrder)
+	hs, generic, err := SortManifests(manifests, chartutil.NewVersionSet("v1", "v1beta1"), InstallOrder)
 	if err != nil {
 		t.Fatalf("Unexpected error: %s", err)
 	}
diff --git a/pkg/tiller/release_content_test.go b/pkg/tiller/release_content_test.go
index b5947fc57c88bdf20aa216efe68ea1cefe776cdb..71b5a3e022c82653f1290da39d3f3736abe5fce0 100644
--- a/pkg/tiller/release_content_test.go
+++ b/pkg/tiller/release_content_test.go
@@ -34,7 +34,7 @@ func TestGetReleaseContent(t *testing.T) {
 		t.Errorf("Error getting release content: %s", err)
 	}
 
-	if res.Chart.Metadata.Name != rel.Chart.Metadata.Name {
-		t.Errorf("Expected %q, got %q", rel.Chart.Metadata.Name, res.Chart.Metadata.Name)
+	if res.Chart.Name() != rel.Chart.Name() {
+		t.Errorf("Expected %q, got %q", rel.Chart.Name(), res.Chart.Name())
 	}
 }
diff --git a/pkg/tiller/release_install.go b/pkg/tiller/release_install.go
index db07249f570993a66049c73b7dba4c59aa94e893..c9087ffd7b4322c3f9df2077b0e94c301b1e0696 100644
--- a/pkg/tiller/release_install.go
+++ b/pkg/tiller/release_install.go
@@ -66,16 +66,16 @@ func (s *ReleaseServer) prepareRelease(req *hapi.InstallReleaseRequest) (*releas
 	}
 
 	revision := 1
-	ts := time.Now()
 	options := chartutil.ReleaseOptions{
 		Name:      name,
 		IsInstall: true,
 	}
-	valuesToRender, err := chartutil.ToRenderValuesCaps(req.Chart, req.Values, options, caps)
+	valuesToRender, err := chartutil.ToRenderValues(req.Chart, req.Values, options, caps)
 	if err != nil {
 		return nil, err
 	}
 
+	ts := time.Now()
 	hooks, manifestDoc, notesTxt, err := s.renderResources(req.Chart, valuesToRender, caps.APIVersions)
 	if err != nil {
 		// Return a release with partial data so that client can show debugging
diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go
index a6201489e2e63e8b97e1f3c0f2941106b0c37e8a..511babb7100b1134e24668c5d68c6781e339b3e2 100644
--- a/pkg/tiller/release_server.go
+++ b/pkg/tiller/release_server.go
@@ -20,6 +20,7 @@ import (
 	"bytes"
 	"path"
 	"regexp"
+	"sort"
 	"strings"
 	"time"
 
@@ -29,9 +30,10 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/discovery"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/chartutil"
+	"k8s.io/helm/pkg/engine"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 	"k8s.io/helm/pkg/hooks"
 	relutil "k8s.io/helm/pkg/releaseutil"
@@ -78,7 +80,7 @@ var ValidName = regexp.MustCompile("^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+
 
 // ReleaseServer implements the server-side gRPC endpoint for the HAPI services.
 type ReleaseServer struct {
-	env       *environment.Environment
+	engine    Engine
 	discovery discovery.DiscoveryInterface
 
 	// Releases stores records of releases.
@@ -90,9 +92,9 @@ type ReleaseServer struct {
 }
 
 // NewReleaseServer creates a new release server.
-func NewReleaseServer(env *environment.Environment, discovery discovery.DiscoveryInterface, kubeClient environment.KubeClient) *ReleaseServer {
+func NewReleaseServer(discovery discovery.DiscoveryInterface, kubeClient environment.KubeClient) *ReleaseServer {
 	return &ReleaseServer{
-		env:        env,
+		engine:     engine.New(),
 		discovery:  discovery,
 		Releases:   storage.Init(driver.NewMemory()),
 		KubeClient: kubeClient,
@@ -204,18 +206,6 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) {
 	return "ERROR", errors.New("no available release name found")
 }
 
-func (s *ReleaseServer) engine(ch *chart.Chart) environment.Engine {
-	renderer := s.env.EngineYard.Default()
-	if ch.Metadata.Engine != "" {
-		if r, ok := s.env.EngineYard.Get(ch.Metadata.Engine); ok {
-			renderer = r
-		} else {
-			s.Log("warning: %s requested non-existent template engine %s", ch.Metadata.Name, ch.Metadata.Engine)
-		}
-	}
-	return renderer
-}
-
 // capabilities builds a Capabilities from discovery information.
 func capabilities(disc discovery.DiscoveryInterface) (*chartutil.Capabilities, error) {
 	sv, err := disc.ServerVersion()
@@ -269,9 +259,8 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values
 		}
 	}
 
-	s.Log("rendering %s chart using values", ch.Metadata.Name)
-	renderer := s.engine(ch)
-	files, err := renderer.Render(ch, values)
+	s.Log("rendering %s chart using values", ch.Name())
+	files, err := s.engine.Render(ch, values)
 	if err != nil {
 		return nil, nil, "", err
 	}
@@ -286,7 +275,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values
 		if strings.HasSuffix(k, notesFileSuffix) {
 			// Only apply the notes if it belongs to the parent chart
 			// Note: Do not use filePath.Join since it creates a path with \ which is not expected
-			if k == path.Join(ch.Metadata.Name, "templates", notesFileSuffix) {
+			if k == path.Join(ch.Name(), "templates", notesFileSuffix) {
 				notes = v
 			}
 			delete(files, k)
@@ -296,7 +285,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values
 	// Sort hooks, manifests, and partials. Only hooks and manifests are returned,
 	// as partials are not used after renderer.Render. Empty manifests are also
 	// removed here.
-	hooks, manifests, err := sortManifests(files, vs, InstallOrder)
+	hooks, manifests, err := SortManifests(files, vs, InstallOrder)
 	if err != nil {
 		// By catching parse errors here, we can prevent bogus releases from going
 		// to Kubernetes.
@@ -351,7 +340,7 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
 		}
 	}
 
-	executingHooks = sortByHookWeight(executingHooks)
+	sort.Sort(hookByWeight(executingHooks))
 
 	for _, h := range executingHooks {
 		if err := s.deleteHookIfShouldBeDeletedByDeletePolicy(h, hooks.BeforeHookCreation, name, namespace, hook, s.KubeClient); err != nil {
diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go
index 9840c4731244a11a36573d93b17699594888461f..97b4b19f9d20b9079e72ba48ead1853ce8be60c3 100644
--- a/pkg/tiller/release_server_test.go
+++ b/pkg/tiller/release_server_test.go
@@ -32,8 +32,9 @@ import (
 	"k8s.io/kubernetes/pkg/apis/core"
 	"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
 
+	"k8s.io/helm/pkg/chart"
+	"k8s.io/helm/pkg/engine"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 	"k8s.io/helm/pkg/hooks"
 	"k8s.io/helm/pkg/kube"
@@ -93,10 +94,9 @@ data:
 func rsFixture(t *testing.T) *ReleaseServer {
 	t.Helper()
 
-	env := environment.New()
 	dc := fake.NewSimpleClientset().Discovery()
 	kc := &environment.PrintingKubeClient{Out: ioutil.Discard}
-	rs := NewReleaseServer(env, dc, kc)
+	rs := NewReleaseServer(dc, kc)
 	rs.Log = func(format string, v ...interface{}) {
 		t.Helper()
 		if *verbose {
@@ -142,7 +142,7 @@ func withKube(version string) chartOption {
 
 func withDependency(dependencyOpts ...chartOption) chartOption {
 	return func(opts *chartOptions) {
-		opts.Dependencies = append(opts.Dependencies, buildChart(dependencyOpts...))
+		opts.AddDependency(buildChart(dependencyOpts...))
 	}
 }
 
@@ -483,26 +483,23 @@ func (kc *mockHooksKubeClient) WatchUntilReady(ns string, r io.Reader, timeout i
 
 	return nil
 }
-func (kc *mockHooksKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force, recreate bool, timeout int64, shouldWait bool) error {
+func (kc *mockHooksKubeClient) Update(_ string, _, _ io.Reader, _, _ bool, _ int64, _ bool) error {
 	return nil
 }
-func (kc *mockHooksKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) {
+func (kc *mockHooksKubeClient) Build(_ string, _ io.Reader) (kube.Result, error) {
 	return []*resource.Info{}, nil
 }
-func (kc *mockHooksKubeClient) BuildUnstructured(ns string, reader io.Reader) (kube.Result, error) {
+func (kc *mockHooksKubeClient) BuildUnstructured(_ string, _ io.Reader) (kube.Result, error) {
 	return []*resource.Info{}, nil
 }
-func (kc *mockHooksKubeClient) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (core.PodPhase, error) {
+func (kc *mockHooksKubeClient) WaitAndGetCompletedPodPhase(_ string, _ io.Reader, _ time.Duration) (core.PodPhase, error) {
 	return core.PodUnknown, nil
 }
 
 func deletePolicyStub(kubeClient *mockHooksKubeClient) *ReleaseServer {
-	e := environment.New()
-
-	dc := fake.NewSimpleClientset().Discovery()
 	return &ReleaseServer{
-		env:        e,
-		discovery:  dc,
+		engine:     engine.New(),
+		discovery:  fake.NewSimpleClientset().Discovery(),
 		KubeClient: kubeClient,
 		Log:        func(_ string, _ ...interface{}) {},
 	}
diff --git a/pkg/tiller/release_uninstall.go b/pkg/tiller/release_uninstall.go
index 9abb7559c9e4fb404f3a078ab8969a300382e524..b39e9a2b6a4346bab0ad949f9181832794fbe3c9 100644
--- a/pkg/tiller/release_uninstall.go
+++ b/pkg/tiller/release_uninstall.go
@@ -132,7 +132,7 @@ func (s *ReleaseServer) deleteRelease(rel *release.Release) (kept string, errs [
 	}
 
 	manifests := relutil.SplitManifests(rel.Manifest)
-	_, files, err := sortManifests(manifests, vs, UninstallOrder)
+	_, files, err := SortManifests(manifests, vs, UninstallOrder)
 	if err != nil {
 		// We could instead just delete everything in no particular order.
 		// FIXME: One way to delete at this point would be to try a label-based
diff --git a/pkg/tiller/release_update.go b/pkg/tiller/release_update.go
index 763c49bfbdf70d14740cba40253f96787efcbb49..2d86b65b067084445549281e9d330d9ff5b18b19 100644
--- a/pkg/tiller/release_update.go
+++ b/pkg/tiller/release_update.go
@@ -105,7 +105,7 @@ func (s *ReleaseServer) prepareUpdate(req *hapi.UpdateReleaseRequest) (*release.
 	if err != nil {
 		return nil, nil, err
 	}
-	valuesToRender, err := chartutil.ToRenderValuesCaps(req.Chart, req.Values, options, caps)
+	valuesToRender, err := chartutil.ToRenderValues(req.Chart, req.Values, options, caps)
 	if err != nil {
 		return nil, nil, err
 	}
diff --git a/pkg/tiller/release_update_test.go b/pkg/tiller/release_update_test.go
index 08a119ff286bfd37072d9a5f27c1e4bfb01889a1..15c36731108e2a01a8d5a85728b6d453ca5bb339 100644
--- a/pkg/tiller/release_update_test.go
+++ b/pkg/tiller/release_update_test.go
@@ -22,8 +22,8 @@ import (
 	"strings"
 	"testing"
 
+	"k8s.io/helm/pkg/chart"
 	"k8s.io/helm/pkg/hapi"
-	"k8s.io/helm/pkg/hapi/chart"
 	"k8s.io/helm/pkg/hapi/release"
 )