hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

os.go (3944B)

    1 // Copyright 2017 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 // Package os provides template functions for interacting with the operating
   15 // system.
   16 package os
   17 
   18 import (
   19 	"errors"
   20 	"fmt"
   21 	_os "os"
   22 	"path/filepath"
   23 
   24 	"github.com/bep/overlayfs"
   25 	"github.com/gohugoio/hugo/deps"
   26 	"github.com/spf13/afero"
   27 	"github.com/spf13/cast"
   28 )
   29 
   30 // New returns a new instance of the os-namespaced template functions.
   31 func New(d *deps.Deps) *Namespace {
   32 	var readFileFs, workFs afero.Fs
   33 
   34 	// The docshelper script does not have or need all the dependencies set up.
   35 	if d.PathSpec != nil {
   36 		readFileFs = overlayfs.New(overlayfs.Options{
   37 			Fss: []afero.Fs{
   38 				d.PathSpec.BaseFs.Work,
   39 				d.PathSpec.BaseFs.Content.Fs,
   40 			},
   41 		})
   42 		// See #9599
   43 		workFs = d.PathSpec.BaseFs.WorkDir
   44 	}
   45 
   46 	return &Namespace{
   47 		readFileFs: readFileFs,
   48 		workFs:     workFs,
   49 		deps:       d,
   50 	}
   51 }
   52 
   53 // Namespace provides template functions for the "os" namespace.
   54 type Namespace struct {
   55 	readFileFs afero.Fs
   56 	workFs     afero.Fs
   57 	deps       *deps.Deps
   58 }
   59 
   60 // Getenv retrieves the value of the environment variable named by the key.
   61 // It returns the value, which will be empty if the variable is not present.
   62 func (ns *Namespace) Getenv(key any) (string, error) {
   63 	skey, err := cast.ToStringE(key)
   64 	if err != nil {
   65 		return "", nil
   66 	}
   67 
   68 	if err = ns.deps.ExecHelper.Sec().CheckAllowedGetEnv(skey); err != nil {
   69 		return "", err
   70 	}
   71 
   72 	return _os.Getenv(skey), nil
   73 }
   74 
   75 // readFile reads the file named by filename in the given filesystem
   76 // and returns the contents as a string.
   77 func readFile(fs afero.Fs, filename string) (string, error) {
   78 	filename = filepath.Clean(filename)
   79 	if filename == "" || filename == "." || filename == string(_os.PathSeparator) {
   80 		return "", errors.New("invalid filename")
   81 	}
   82 
   83 	b, err := afero.ReadFile(fs, filename)
   84 	if err != nil {
   85 		return "", err
   86 	}
   87 
   88 	return string(b), nil
   89 }
   90 
   91 // ReadFile reads the file named by filename relative to the configured WorkingDir.
   92 // It returns the contents as a string.
   93 // There is an upper size limit set at 1 megabytes.
   94 func (ns *Namespace) ReadFile(i any) (string, error) {
   95 	s, err := cast.ToStringE(i)
   96 	if err != nil {
   97 		return "", err
   98 	}
   99 
  100 	if ns.deps.PathSpec != nil {
  101 		s = ns.deps.PathSpec.RelPathify(s)
  102 	}
  103 
  104 	return readFile(ns.readFileFs, s)
  105 }
  106 
  107 // ReadDir lists the directory contents relative to the configured WorkingDir.
  108 func (ns *Namespace) ReadDir(i any) ([]_os.FileInfo, error) {
  109 	path, err := cast.ToStringE(i)
  110 	if err != nil {
  111 		return nil, err
  112 	}
  113 
  114 	list, err := afero.ReadDir(ns.workFs, path)
  115 	if err != nil {
  116 		return nil, fmt.Errorf("failed to read directory %q: %s", path, err)
  117 	}
  118 
  119 	return list, nil
  120 }
  121 
  122 // FileExists checks whether a file exists under the given path.
  123 func (ns *Namespace) FileExists(i any) (bool, error) {
  124 	path, err := cast.ToStringE(i)
  125 	if err != nil {
  126 		return false, err
  127 	}
  128 
  129 	if path == "" {
  130 		return false, errors.New("fileExists needs a path to a file")
  131 	}
  132 
  133 	status, err := afero.Exists(ns.readFileFs, path)
  134 	if err != nil {
  135 		return false, err
  136 	}
  137 
  138 	return status, nil
  139 }
  140 
  141 // Stat returns the os.FileInfo structure describing file.
  142 func (ns *Namespace) Stat(i any) (_os.FileInfo, error) {
  143 	path, err := cast.ToStringE(i)
  144 	if err != nil {
  145 		return nil, err
  146 	}
  147 
  148 	if path == "" {
  149 		return nil, errors.New("fileStat needs a path to a file")
  150 	}
  151 
  152 	r, err := ns.readFileFs.Stat(path)
  153 	if err != nil {
  154 		return nil, err
  155 	}
  156 
  157 	return r, nil
  158 }