hugo

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

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

deployConfig.go (4636B)

    1 // Copyright 2019 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 //go:build !nodeploy
   15 // +build !nodeploy
   16 
   17 package deploy
   18 
   19 import (
   20 	"fmt"
   21 	"regexp"
   22 
   23 	"errors"
   24 
   25 	"github.com/gobwas/glob"
   26 	"github.com/gohugoio/hugo/config"
   27 	hglob "github.com/gohugoio/hugo/hugofs/glob"
   28 	"github.com/gohugoio/hugo/media"
   29 	"github.com/mitchellh/mapstructure"
   30 )
   31 
   32 const deploymentConfigKey = "deployment"
   33 
   34 // deployConfig is the complete configuration for deployment.
   35 type deployConfig struct {
   36 	Targets  []*target
   37 	Matchers []*matcher
   38 	Order    []string
   39 
   40 	ordering   []*regexp.Regexp // compiled Order
   41 	mediaTypes media.Types
   42 }
   43 
   44 type target struct {
   45 	Name string
   46 	URL  string
   47 
   48 	CloudFrontDistributionID string
   49 
   50 	// GoogleCloudCDNOrigin specifies the Google Cloud project and CDN origin to
   51 	// invalidate when deploying this target.  It is specified as <project>/<origin>.
   52 	GoogleCloudCDNOrigin string
   53 
   54 	// Optional patterns of files to include/exclude for this target.
   55 	// Parsed using github.com/gobwas/glob.
   56 	Include string
   57 	Exclude string
   58 
   59 	// Parsed versions of Include/Exclude.
   60 	includeGlob glob.Glob
   61 	excludeGlob glob.Glob
   62 }
   63 
   64 func (tgt *target) parseIncludeExclude() error {
   65 	var err error
   66 	if tgt.Include != "" {
   67 		tgt.includeGlob, err = hglob.GetGlob(tgt.Include)
   68 		if err != nil {
   69 			return fmt.Errorf("invalid deployment.target.include %q: %v", tgt.Include, err)
   70 		}
   71 	}
   72 	if tgt.Exclude != "" {
   73 		tgt.excludeGlob, err = hglob.GetGlob(tgt.Exclude)
   74 		if err != nil {
   75 			return fmt.Errorf("invalid deployment.target.exclude %q: %v", tgt.Exclude, err)
   76 		}
   77 	}
   78 	return nil
   79 }
   80 
   81 // matcher represents configuration to be applied to files whose paths match
   82 // a specified pattern.
   83 type matcher struct {
   84 	// Pattern is the string pattern to match against paths.
   85 	// Matching is done against paths converted to use / as the path separator.
   86 	Pattern string
   87 
   88 	// CacheControl specifies caching attributes to use when serving the blob.
   89 	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
   90 	CacheControl string
   91 
   92 	// ContentEncoding specifies the encoding used for the blob's content, if any.
   93 	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
   94 	ContentEncoding string
   95 
   96 	// ContentType specifies the MIME type of the blob being written.
   97 	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
   98 	ContentType string
   99 
  100 	// Gzip determines whether the file should be gzipped before upload.
  101 	// If so, the ContentEncoding field will automatically be set to "gzip".
  102 	Gzip bool
  103 
  104 	// Force indicates that matching files should be re-uploaded. Useful when
  105 	// other route-determined metadata (e.g., ContentType) has changed.
  106 	Force bool
  107 
  108 	// re is Pattern compiled.
  109 	re *regexp.Regexp
  110 }
  111 
  112 func (m *matcher) Matches(path string) bool {
  113 	return m.re.MatchString(path)
  114 }
  115 
  116 // decode creates a config from a given Hugo configuration.
  117 func decodeConfig(cfg config.Provider) (deployConfig, error) {
  118 	var (
  119 		mediaTypesConfig []map[string]any
  120 		dcfg             deployConfig
  121 	)
  122 
  123 	if !cfg.IsSet(deploymentConfigKey) {
  124 		return dcfg, nil
  125 	}
  126 	if err := mapstructure.WeakDecode(cfg.GetStringMap(deploymentConfigKey), &dcfg); err != nil {
  127 		return dcfg, err
  128 	}
  129 	for _, tgt := range dcfg.Targets {
  130 		if *tgt == (target{}) {
  131 			return dcfg, errors.New("empty deployment target")
  132 		}
  133 		if err := tgt.parseIncludeExclude(); err != nil {
  134 			return dcfg, err
  135 		}
  136 	}
  137 	var err error
  138 	for _, m := range dcfg.Matchers {
  139 		if *m == (matcher{}) {
  140 			return dcfg, errors.New("empty deployment matcher")
  141 		}
  142 		m.re, err = regexp.Compile(m.Pattern)
  143 		if err != nil {
  144 			return dcfg, fmt.Errorf("invalid deployment.matchers.pattern: %v", err)
  145 		}
  146 	}
  147 	for _, o := range dcfg.Order {
  148 		re, err := regexp.Compile(o)
  149 		if err != nil {
  150 			return dcfg, fmt.Errorf("invalid deployment.orderings.pattern: %v", err)
  151 		}
  152 		dcfg.ordering = append(dcfg.ordering, re)
  153 	}
  154 
  155 	if cfg.IsSet("mediaTypes") {
  156 		mediaTypesConfig = append(mediaTypesConfig, cfg.GetStringMap("mediaTypes"))
  157 	}
  158 
  159 	dcfg.mediaTypes, err = media.DecodeTypes(mediaTypesConfig...)
  160 	if err != nil {
  161 		return dcfg, err
  162 	}
  163 	return dcfg, nil
  164 }