diff --git a/cmd/helm/fetch.go b/cmd/helm/fetch.go index ca962ffb8..bcd4d520f 100644 --- a/cmd/helm/fetch.go +++ b/cmd/helm/fetch.go @@ -13,8 +13,15 @@ import ( "github.com/spf13/cobra" ) +var untarFile bool + +// TODO(vaikas): Is there a well known directory for these?? +var untarDir string + func init() { RootCommand.AddCommand(fetchCmd) + fetchCmd.Flags().BoolVar(&untarFile, "untar", false, "If set to true, will untar the chart after downloading it.") + fetchCmd.Flags().StringVar(&untarDir, "untardir", ".", "If untar is specified, this flag specifies where to untar the chart.") } var fetchCmd = &cobra.Command{ @@ -49,10 +56,8 @@ func fetch(cmd *cobra.Command, args []string) error { } defer resp.Body.Close() - // TODO(vaikas): Implement untar / flag - untar := false - if untar { - return untarChart(resp.Body) + if untarFile { + return chart.Expand(untarDir, resp.Body) } p := strings.Split(u.String(), "/") return saveChartFile(p[len(p)-1], resp.Body) @@ -84,18 +89,6 @@ func mapRepoArg(arg string, r map[string]string) (*url.URL, error) { return nil, fmt.Errorf("Invalid chart url format: %s", arg) } -func untarChart(r io.Reader) error { - c, err := chart.LoadDataFromReader(r) - if err != nil { - return err - } - if c == nil { - return fmt.Errorf("Failed to untar the chart") - } - return fmt.Errorf("Not implemented yee") - -} - func saveChartFile(c string, r io.Reader) error { // Grab the chart name that we'll use for the name of the file to download to. out, err := os.Create(c) diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go index b64823ced..19e76dfbf 100644 --- a/pkg/chart/chart.go +++ b/pkg/chart/chart.go @@ -88,7 +88,7 @@ func (c *Chart) TemplatesDir() string { return filepath.Join(c.loader.dir(), preTemplates) } -// ChartsDir returns teh directory where dependency charts are stored. +// ChartsDir returns the directory where dependency charts are stored. func (c *Chart) ChartsDir() string { return filepath.Join(c.loader.dir(), preCharts) } @@ -214,6 +214,44 @@ func Create(chartfile *Chartfile, dir string) (*Chart, error) { }, nil } +// Expand uncompresses and extracts a chart into the specified directory. +func Expand(dir string, r io.Reader) error { + gr, err := gzip.NewReader(r) + if err != nil { + return err + } + defer gr.Close() + tr := tar.NewReader(gr) + for { + header, err := tr.Next() + if err == io.EOF { + break + } else if err != nil { + return err + } + + path := filepath.Clean(filepath.Join(dir, header.Name)) + info := header.FileInfo() + if info.IsDir() { + if err = os.MkdirAll(path, info.Mode()); err != nil { + return err + } + continue + } + + file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode()) + if err != nil { + return err + } + defer file.Close() + _, err = io.Copy(file, tr) + if err != nil { + return err + } + } + return nil +} + // fname prepares names for the filesystem func fname(name string) string { // Right now, we don't do anything. Do we need to encode any particular diff --git a/pkg/chart/chart_test.go b/pkg/chart/chart_test.go index e14ffe396..f7c804c1e 100644 --- a/pkg/chart/chart_test.go +++ b/pkg/chart/chart_test.go @@ -26,10 +26,11 @@ import ( ) const ( - testfile = "testdata/frobnitz/Chart.yaml" - testdir = "testdata/frobnitz/" - testarchive = "testdata/frobnitz-0.0.1.tgz" - testmember = "templates/template.tpl" + testfile = "testdata/frobnitz/Chart.yaml" + testdir = "testdata/frobnitz/" + testarchive = "testdata/frobnitz-0.0.1.tgz" + testmember = "templates/template.tpl" + expectedTemplate = "Hello {{.Name | default \"world\"}}\n" ) // Type canaries. If these fail, they will fail at compile time. @@ -270,3 +271,42 @@ func compareContent(filename string, content []byte) error { return nil } + +func TestExpand(t *testing.T) { + r, err := os.Open(testarchive) + if err != nil { + t.Errorf("Failed to read testarchive file: %s", err) + return + } + + td, err := ioutil.TempDir("", "helm-unittest-chart-") + if err != nil { + t.Errorf("Failed to create tempdir: %s", err) + return + } + + err = Expand(td, r) + if err != nil { + t.Errorf("Failed to expand testarchive file: %s", err) + } + + fi, err := os.Lstat(td + "/frobnitz/Chart.yaml") + if err != nil { + t.Errorf("Failed to stat Chart.yaml from expanded archive: %s", err) + } + if fi.Name() != "Chart.yaml" { + t.Errorf("Didn't get the right file name from stat, expected Chart.yaml, got: %s", fi.Name()) + } + + tr, err := os.Open(td + "/frobnitz/templates/template.tpl") + if err != nil { + t.Errorf("Failed to open template.tpl from expanded archive: %s", err) + } + c, err := ioutil.ReadAll(tr) + if err != nil { + t.Errorf("Failed to read contents of template.tpl from expanded archive: %s", err) + } + if string(c) != expectedTemplate { + t.Errorf("Contents of the expanded template differ, wanted '%s' got '%s'", expectedTemplate, c) + } +}