github.com/gohugoio/hugo@v0.88.1/deploy/deployConfig.go (about)

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