github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/chart/loader/directory.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package loader
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"path/filepath"
    25  	"strings"
    26  
    27  	"github.com/pkg/errors"
    28  
    29  	"github.com/stefanmcshane/helm/internal/ignore"
    30  	"github.com/stefanmcshane/helm/internal/sympath"
    31  	"github.com/stefanmcshane/helm/pkg/chart"
    32  )
    33  
    34  var utf8bom = []byte{0xEF, 0xBB, 0xBF}
    35  
    36  // DirLoader loads a chart from a directory
    37  type DirLoader string
    38  
    39  // Load loads the chart
    40  func (l DirLoader) Load() (*chart.Chart, error) {
    41  	return LoadDir(string(l))
    42  }
    43  
    44  // LoadDir loads from a directory.
    45  //
    46  // This loads charts only from directories.
    47  func LoadDir(dir string) (*chart.Chart, error) {
    48  	topdir, err := filepath.Abs(dir)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	// Just used for errors.
    54  	c := &chart.Chart{}
    55  
    56  	rules := ignore.Empty()
    57  	ifile := filepath.Join(topdir, ignore.HelmIgnore)
    58  	if _, err := os.Stat(ifile); err == nil {
    59  		r, err := ignore.ParseFile(ifile)
    60  		if err != nil {
    61  			return c, err
    62  		}
    63  		rules = r
    64  	}
    65  	rules.AddDefaults()
    66  
    67  	files := []*BufferedFile{}
    68  	topdir += string(filepath.Separator)
    69  
    70  	walk := func(name string, fi os.FileInfo, err error) error {
    71  		n := strings.TrimPrefix(name, topdir)
    72  		if n == "" {
    73  			// No need to process top level. Avoid bug with helmignore .* matching
    74  			// empty names. See issue 1779.
    75  			return nil
    76  		}
    77  
    78  		// Normalize to / since it will also work on Windows
    79  		n = filepath.ToSlash(n)
    80  
    81  		if err != nil {
    82  			return err
    83  		}
    84  		if fi.IsDir() {
    85  			// Directory-based ignore rules should involve skipping the entire
    86  			// contents of that directory.
    87  			if rules.Ignore(n, fi) {
    88  				return filepath.SkipDir
    89  			}
    90  			return nil
    91  		}
    92  
    93  		// If a .helmignore file matches, skip this file.
    94  		if rules.Ignore(n, fi) {
    95  			return nil
    96  		}
    97  
    98  		// Irregular files include devices, sockets, and other uses of files that
    99  		// are not regular files. In Go they have a file mode type bit set.
   100  		// See https://golang.org/pkg/os/#FileMode for examples.
   101  		if !fi.Mode().IsRegular() {
   102  			return fmt.Errorf("cannot load irregular file %s as it has file mode type bits set", name)
   103  		}
   104  
   105  		data, err := ioutil.ReadFile(name)
   106  		if err != nil {
   107  			return errors.Wrapf(err, "error reading %s", n)
   108  		}
   109  
   110  		data = bytes.TrimPrefix(data, utf8bom)
   111  
   112  		files = append(files, &BufferedFile{Name: n, Data: data})
   113  		return nil
   114  	}
   115  	if err = sympath.Walk(topdir, walk); err != nil {
   116  		return c, err
   117  	}
   118  
   119  	return LoadFiles(files)
   120  }