mirror of
https://github.com/gohugoio/hugo.git
synced 2026-08-25 07:48:52 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 694bc3a08c | |||
| e9c3ce16ab | |||
| 79932e7225 | |||
| 9eb9b70a29 | |||
| 0ff4a9326f | |||
| 45e1084ff2 | |||
| c98348416c | |||
| 2de393c791 | |||
| 7efb35680f | |||
| ddbcc67122 | |||
| fd75f129b2 | |||
| 14878ca0a0 | |||
| e88873b803 | |||
| 4219993b0c | |||
| 988e1417a0 | |||
| 42529882ce | |||
| 45f1b1cfc5 | |||
| 369bdf22f8 | |||
| d1b03a093f | |||
| 941c28ab0c | |||
| ffbdcc75ab | |||
| 95d9764518 | |||
| b66f9f2665 | |||
| f7e00c039f | |||
| f5ba6fd45c | |||
| c4bbc1eeeb | |||
| 0e0fb1b648 | |||
| b017f7cb01 | |||
| 7fb28085ac | |||
| 0cd1929b9c | |||
| cbdaff2135 | |||
| 3fefea06b8 | |||
| 5c48ba9343 | |||
| 21562e3aad | |||
| 9c24b86e4b |
+96
-33
@@ -1,51 +1,114 @@
|
||||
defaults: &defaults
|
||||
docker:
|
||||
- image: bepsays/ci-goreleaser:1.1800.300
|
||||
environment:
|
||||
CGO_ENABLED: "0"
|
||||
parameters:
|
||||
|
||||
# v2: 11m.
|
||||
defaults: &defaults
|
||||
resource_class: large
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser:1.21900.20001
|
||||
environment: &buildenv
|
||||
GOMODCACHE: /root/project/gomodcache
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
<<: *defaults
|
||||
prepare_release:
|
||||
<<: *defaults
|
||||
environment: &buildenv
|
||||
GOMODCACHE: /root/project/gomodcache
|
||||
steps:
|
||||
- checkout:
|
||||
- &remote-docker
|
||||
setup_remote_docker:
|
||||
version: 20.10.14
|
||||
- checkout:
|
||||
path: hugo
|
||||
- &git-config
|
||||
run:
|
||||
command: |
|
||||
git config --global user.email "bjorn.erik.pedersen+hugoreleaser@gmail.com"
|
||||
git config --global user.name "hugoreleaser"
|
||||
- run:
|
||||
command: |
|
||||
git clone git@github.com:gohugoio/hugoDocs.git
|
||||
cd hugo
|
||||
go mod download
|
||||
sleep 5
|
||||
go mod verify
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: .
|
||||
release:
|
||||
<<: *defaults
|
||||
command: |
|
||||
cd hugo
|
||||
go mod download
|
||||
go run -tags release main.go release --step 1
|
||||
- save_cache:
|
||||
key: git-sha-{{ .Revision }}
|
||||
paths:
|
||||
- hugo
|
||||
- gomodcache
|
||||
build_container1:
|
||||
<<: [*defaults]
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /root/project
|
||||
- &restore-cache
|
||||
restore_cache:
|
||||
key: git-sha-{{ .Revision }}
|
||||
- run:
|
||||
command: |
|
||||
cd hugo
|
||||
git config --global user.email "bjorn.erik.pedersen+hugoreleaser@gmail.com"
|
||||
git config --global user.name "hugoreleaser"
|
||||
go run -tags release main.go release -r ${CIRCLE_BRANCH}
|
||||
|
||||
no_output_timeout: 20m
|
||||
command: |
|
||||
mkdir -p /tmp/files/dist1
|
||||
cd hugo
|
||||
hugoreleaser build -paths "builds/container1/**" -workers 3 -dist /tmp/files/dist1 -chunks $CIRCLE_NODE_TOTAL -chunk-index $CIRCLE_NODE_INDEX
|
||||
- &persist-workspace
|
||||
persist_to_workspace:
|
||||
root: /tmp/files
|
||||
paths:
|
||||
- dist1
|
||||
- dist2
|
||||
parallelism: 7
|
||||
build_container2:
|
||||
<<: [*defaults]
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.21900.20001
|
||||
steps:
|
||||
- *restore-cache
|
||||
- &attach-workspace
|
||||
attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: |
|
||||
mkdir -p /tmp/files/dist2
|
||||
cd hugo
|
||||
hugoreleaser build -paths "builds/container2/**" -workers 1 -dist /tmp/files/dist2
|
||||
- *persist-workspace
|
||||
archive_and_release:
|
||||
<<: [*defaults]
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
steps:
|
||||
- *restore-cache
|
||||
- *attach-workspace
|
||||
- *git-config
|
||||
- run:
|
||||
command: |
|
||||
cp -a /tmp/workspace/dist1/. ./hugo/dist
|
||||
cp -a /tmp/workspace/dist2/. ./hugo/dist
|
||||
- run:
|
||||
command: |
|
||||
cd hugo
|
||||
hugoreleaser archive
|
||||
hugoreleaser release
|
||||
go run -tags release main.go release --step 2
|
||||
workflows:
|
||||
version: 2
|
||||
release:
|
||||
jobs:
|
||||
- build:
|
||||
- prepare_release:
|
||||
filters:
|
||||
branches:
|
||||
only: /release-.*/
|
||||
- hold:
|
||||
type: approval
|
||||
- build_container1:
|
||||
requires:
|
||||
- build
|
||||
- release:
|
||||
- prepare_release
|
||||
- build_container2:
|
||||
requires:
|
||||
- prepare_release
|
||||
- archive_and_release:
|
||||
context: org-global
|
||||
requires:
|
||||
- hold
|
||||
- build_container1
|
||||
- build_container2
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
# Go 1.18 had some breaking changes on the source level which means Hugo cannot be built
|
||||
# with older Go versions, but the improvements in Go 1.18 were too good to pass on (e.g. break and continue).
|
||||
# Note that you don't need Go (or Go 1.18) to run a pre-built binary.
|
||||
go-version: [1.18.x]
|
||||
go-version: [1.18.x,1.19.x]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
@@ -49,9 +49,11 @@ jobs:
|
||||
brew install pandoc
|
||||
- if: matrix.os == 'windows-latest'
|
||||
run: |
|
||||
choco install pandoc
|
||||
choco install mingw --version 10.2.0 --allow-downgrade
|
||||
Choco-Install -PackageName pandoc
|
||||
- run: pandoc -v
|
||||
- if: matrix.os == 'windows-latest'
|
||||
run: |
|
||||
Choco-Install -PackageName mingw -ArgumentList "--version","10.2.0","--allow-downgrade"
|
||||
- if: matrix.os == 'ubuntu-latest'
|
||||
name: Install dart-sass-embedded Linux
|
||||
run: |
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright 2022 The Hugo Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<a href="https://gohugo.io/"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/static/images/hugo-logo-wide.svg?sanitize=true" alt="Hugo" width="565"></a>
|
||||
|
||||
A Fast and Flexible Static Site Generator built with love by [bep](https://github.com/bep), [spf13](https://spf13.com/) and [friends](https://github.com/gohugoio/hugo/graphs/contributors) in [Go][].
|
||||
A Fast and Flexible Static Site Generator built with love by [bep](https://github.com/bep), [spf13](https://spf13.com/) and [friends](https://github.com/gohugoio/hugo/graphs/contributors) in [Go](https://go.dev/).
|
||||
|
||||
[Website](https://gohugo.io) |
|
||||
[Forum](https://discourse.gohugo.io) |
|
||||
@@ -13,9 +13,18 @@ A Fast and Flexible Static Site Generator built with love by [bep](https://githu
|
||||
[](https://github.com/gohugoio/hugo/actions?query=workflow%3ATest)
|
||||
[](https://goreportcard.com/report/github.com/gohugoio/hugo)
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Supported Architectures](#supported-architectures)
|
||||
* [Choose How to Install](#choose-how-to-install)
|
||||
* [Install Hugo as Your Site Generator (Binary Install)](#install-hugo-as-your-site-generator-binary-install)
|
||||
* [Build and Install the Binaries from Source (Advanced Install)](#build-and-install-the-binaries-from-source-advanced-install)
|
||||
* [The Hugo Documentation](#the-hugo-documentation)
|
||||
* [Contributing to Hugo](#contributing-code-to-hugo)
|
||||
* [Dependencies](#dependencies)
|
||||
|
||||
## Overview
|
||||
|
||||
Hugo is a static HTML and CSS website generator written in [Go][].
|
||||
Hugo is a static HTML and CSS website generator written in [Go](https://go.dev/).
|
||||
It is optimized for speed, ease of use, and configurability.
|
||||
Hugo takes a directory with content and templates and renders them into a full HTML website.
|
||||
|
||||
@@ -27,7 +36,7 @@ A good rule of thumb is that each piece of content renders in around 1 milliseco
|
||||
|
||||
Hugo is designed to work well for any kind of website including blogs, tumbles, and docs.
|
||||
|
||||
#### Supported Architectures
|
||||
## Supported Architectures
|
||||
|
||||
Currently, we provide pre-built Hugo binaries for Windows, Linux, FreeBSD, NetBSD, DragonFly BSD, OpenBSD, macOS (Darwin), and [Android](https://gist.github.com/bep/a0d8a26cf6b4f8bc992729b8e50b480b) for x64, i386 and ARM architectures.
|
||||
|
||||
@@ -38,7 +47,6 @@ Hugo may also be compiled from source wherever the Go compiler tool chain can ru
|
||||
## Choose How to Install
|
||||
|
||||
If you want to use Hugo as your site generator, simply install the Hugo binaries.
|
||||
The Hugo binaries have no external dependencies.
|
||||
|
||||
To contribute to the Hugo source code or documentation, you should [fork the Hugo GitHub project](https://github.com/gohugoio/hugo#fork-destination-box) and clone it to your local machine.
|
||||
|
||||
@@ -83,7 +91,7 @@ The Hugo documentation now lives in its own repository, see https://github.com/g
|
||||
```bash
|
||||
git clone git@github.com:gohugoio/hugo.git
|
||||
```
|
||||
## Contributing to Hugo
|
||||
## Contributing code to Hugo
|
||||
|
||||
**Note March 16th 2022:** We are currently very constrained on human resources to do code reviews, so we currently require any new Pull Requests to be limited to bug fixes closing an existing issue. Also, we have updated to Go 1.18, but we will currently not accept any generic rewrites, "interface{} to any" replacements and similar.
|
||||
|
||||
@@ -96,34 +104,18 @@ helping to manage issues, etc.
|
||||
|
||||
The Hugo community and maintainers are [very active](https://github.com/gohugoio/hugo/pulse/monthly) and helpful, and the project benefits greatly from this activity.
|
||||
|
||||
### Asking Support Questions
|
||||
## Asking Support Questions
|
||||
|
||||
We have an active [discussion forum](https://discourse.gohugo.io) where users and developers can ask questions.
|
||||
Please don't use the GitHub issue tracker to ask questions.
|
||||
|
||||
### Reporting Issues
|
||||
## Reporting Issues
|
||||
|
||||
If you believe you have found a defect in Hugo or its documentation, use
|
||||
the GitHub issue tracker to report the problem to the Hugo maintainers.
|
||||
If you're not sure if it's a bug or not, start by asking in the [discussion forum](https://discourse.gohugo.io).
|
||||
When reporting the issue, please provide the version of Hugo in use (`hugo version`).
|
||||
|
||||
### Submitting Patches
|
||||
|
||||
The Hugo project welcomes all contributors and contributions regardless of skill or experience level.
|
||||
If you are interested in helping with the project, we will help you with your contribution.
|
||||
Hugo is a very active project with many contributions happening daily.
|
||||
|
||||
We want to create the best possible product for our users and the best contribution experience for our developers,
|
||||
we have a set of guidelines which ensure that all contributions are acceptable.
|
||||
The guidelines are not intended as a filter or barrier to participation.
|
||||
If you are unfamiliar with the contribution process, the Hugo team will help you and teach you how to bring your contribution in accordance with the guidelines.
|
||||
|
||||
For a complete guide to contributing code to Hugo, see the [Contribution Guide](CONTRIBUTING.md).
|
||||
|
||||
[Go]: https://golang.org/
|
||||
[Hugo Documentation]: https://gohugo.io/overview/introduction/
|
||||
|
||||
## Dependencies
|
||||
|
||||
Hugo stands on the shoulder of many great open source libraries.
|
||||
|
||||
+11
-12
@@ -17,8 +17,6 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/releaser"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -29,10 +27,9 @@ var _ cmder = (*releaseCommandeer)(nil)
|
||||
type releaseCommandeer struct {
|
||||
cmd *cobra.Command
|
||||
|
||||
version string
|
||||
|
||||
skipPublish bool
|
||||
try bool
|
||||
step int
|
||||
skipPush bool
|
||||
try bool
|
||||
}
|
||||
|
||||
func createReleaser() cmder {
|
||||
@@ -50,9 +47,9 @@ func createReleaser() cmder {
|
||||
return r.release()
|
||||
}
|
||||
|
||||
r.cmd.PersistentFlags().StringVarP(&r.version, "rel", "r", "", "new release version, i.e. 0.25.1")
|
||||
r.cmd.PersistentFlags().BoolVarP(&r.skipPublish, "skip-publish", "", false, "skip all publishing pipes of the release")
|
||||
r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "simulate a release, i.e. no changes")
|
||||
r.cmd.PersistentFlags().BoolVarP(&r.skipPush, "skip-push", "", false, "skip pushing to remote")
|
||||
r.cmd.PersistentFlags().BoolVarP(&r.try, "try", "", false, "no changes")
|
||||
r.cmd.PersistentFlags().IntVarP(&r.step, "step", "", 0, "step to run (1: set new version 2: prepare next dev version)")
|
||||
|
||||
return r
|
||||
}
|
||||
@@ -65,8 +62,10 @@ func (c *releaseCommandeer) flagsToConfig(cfg config.Provider) {
|
||||
}
|
||||
|
||||
func (r *releaseCommandeer) release() error {
|
||||
if r.version == "" {
|
||||
return errors.New("must set the --rel flag to the relevant version number")
|
||||
rel, err := releaser.New(r.skipPush, r.try, r.step)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return releaser.New(r.version, r.skipPublish, r.try).Run()
|
||||
|
||||
return rel.Run()
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ package hugio
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
@@ -53,7 +51,7 @@ func CopyFile(fs afero.Fs, from, to string) error {
|
||||
|
||||
// CopyDir copies a directory.
|
||||
func CopyDir(fs afero.Fs, from, to string, shouldCopy func(filename string) bool) error {
|
||||
fi, err := os.Stat(from)
|
||||
fi, err := fs.Stat(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -67,7 +65,7 @@ func CopyDir(fs afero.Fs, from, to string, shouldCopy func(filename string) bool
|
||||
return err
|
||||
}
|
||||
|
||||
entries, _ := ioutil.ReadDir(from)
|
||||
entries, _ := afero.ReadDir(fs, from)
|
||||
for _, entry := range entries {
|
||||
fromFilename := filepath.Join(from, entry.Name())
|
||||
toFilename := filepath.Join(to, entry.Name())
|
||||
|
||||
@@ -17,7 +17,7 @@ package hugo
|
||||
// This should be the only one.
|
||||
var CurrentVersion = Version{
|
||||
Major: 0,
|
||||
Minor: 102,
|
||||
Minor: 103,
|
||||
PatchLevel: 0,
|
||||
Suffix: "-DEV",
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ func TestToTOML(t *testing.T) {
|
||||
got := DefaultConfig.ToTOML()
|
||||
|
||||
c.Assert(got, qt.Equals,
|
||||
"[security]\n enableInlineShortcodes = false\n [security.exec]\n allow = ['^dart-sass-embedded$', '^go$', '^npx$', '^postcss$']\n osEnv = ['(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM)$']\n\n [security.funcs]\n getenv = ['^HUGO_']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['.*']",
|
||||
"[security]\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^dart-sass-embedded$', '^go$', '^npx$', '^postcss$']\n osEnv = ['(?i)^(PATH|PATHEXT|APPDATA|TMP|TEMP|TERM)$']\n\n [security.funcs]\n getenv = ['^HUGO_']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['.*']",
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ require (
|
||||
github.com/cli/safeexec v1.0.0
|
||||
github.com/disintegration/gift v1.2.1
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/evanw/esbuild v0.14.43
|
||||
github.com/evanw/esbuild v0.15.5
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/frankban/quicktest v1.14.3
|
||||
github.com/fsnotify/fsnotify v1.5.4
|
||||
github.com/getkin/kin-openapi v0.97.0
|
||||
github.com/getkin/kin-openapi v0.98.0
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/gobuffalo/flect v0.2.5
|
||||
github.com/gobwas/glob v0.2.3
|
||||
@@ -36,28 +36,28 @@ require (
|
||||
github.com/hairyhenderson/go-codeowners v0.2.3-0.20201026200250-cdc7c0759690
|
||||
github.com/jdkato/prose v1.2.1
|
||||
github.com/kylelemons/godebug v1.1.0
|
||||
github.com/kyokomi/emoji/v2 v2.2.9
|
||||
github.com/kyokomi/emoji/v2 v2.2.10
|
||||
github.com/magefile/mage v1.13.0
|
||||
github.com/mattn/go-isatty v0.0.14
|
||||
github.com/mattn/go-isatty v0.0.16
|
||||
github.com/mitchellh/hashstructure v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/muesli/smartcrop v0.3.0
|
||||
github.com/niklasfasching/go-org v1.6.5
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pelletier/go-toml/v2 v2.0.2
|
||||
github.com/rogpeppe/go-internal v1.8.1
|
||||
github.com/pelletier/go-toml/v2 v2.0.4
|
||||
github.com/rogpeppe/go-internal v1.9.0
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
|
||||
github.com/sanity-io/litter v1.5.5
|
||||
github.com/spf13/afero v1.8.2
|
||||
github.com/spf13/afero v1.9.2
|
||||
github.com/spf13/cast v1.5.0
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/fsync v0.9.0
|
||||
github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/tdewolff/minify/v2 v2.11.10
|
||||
github.com/tdewolff/parse/v2 v2.6.0
|
||||
github.com/yuin/goldmark v1.4.12
|
||||
go.uber.org/atomic v1.9.0
|
||||
github.com/tdewolff/minify/v2 v2.12.0
|
||||
github.com/tdewolff/parse/v2 v2.6.2
|
||||
github.com/yuin/goldmark v1.4.13
|
||||
go.uber.org/atomic v1.10.0
|
||||
gocloud.dev v0.24.0
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d
|
||||
@@ -91,7 +91,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.4.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.0 // indirect
|
||||
github.com/aws/smithy-go v1.8.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.5 // indirect
|
||||
@@ -115,7 +115,7 @@ require (
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220426171045-31bebdecfb46 // indirect
|
||||
|
||||
@@ -131,8 +131,6 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alecthomas/chroma/v2 v2.1.0 h1:ZG9L5/RsxO/xIONrBy8Cgo+5si3d9x3osweXc4VHl0o=
|
||||
github.com/alecthomas/chroma/v2 v2.1.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY=
|
||||
@@ -209,8 +207,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -239,8 +237,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanw/esbuild v0.14.43 h1:4WIYkAf2fLmru3KYtKUB6mdBl4dgpoVcq7hqXhXGVG0=
|
||||
github.com/evanw/esbuild v0.14.43/go.mod h1:GG+zjdi59yh3ehDn4ZWfPcATxjPDUH53iU4ZJbp7dkY=
|
||||
github.com/evanw/esbuild v0.15.5 h1:5nAef2JVECs/dYSdtTQTDlXrM97lOfMRtvMBpOT1L8c=
|
||||
github.com/evanw/esbuild v0.15.5/go.mod h1:iINY06rn799hi48UqEnaQvVfZWe6W9bET78LbvN8VWk=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
@@ -253,8 +251,8 @@ github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUork
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/getkin/kin-openapi v0.97.0 h1:bsvXZeuGiCW43ZKy6xOY5qfT5fCRYmnJwierblSrHCU=
|
||||
github.com/getkin/kin-openapi v0.97.0/go.mod h1:w4lRPHiyOdwGbOkLIyk+P0qCwlu7TXPCHD/64nSXzgE=
|
||||
github.com/getkin/kin-openapi v0.98.0 h1:lIACvCG9cxmFsEywz+LCoVhcZHFLUy+Nv5QSkb43eAE=
|
||||
github.com/getkin/kin-openapi v0.98.0/go.mod h1:w4lRPHiyOdwGbOkLIyk+P0qCwlu7TXPCHD/64nSXzgE=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
@@ -430,8 +428,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/kyokomi/emoji/v2 v2.2.9 h1:UWYkjplPZ4rMPvLxc+/e12/xTqoRcn55oUySkpZ554g=
|
||||
github.com/kyokomi/emoji/v2 v2.2.9/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.10 h1:1z5eMVcxFifsmEoNpdeq4UahbcicgQ4FEHuzrCVwmiI=
|
||||
github.com/kyokomi/emoji/v2 v2.2.10/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magefile/mage v1.13.0 h1:XtLJl8bcCM7EFoO8FyH8XK3t7G5hQAeK+i4tq+veT9M=
|
||||
@@ -443,8 +441,8 @@ github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O
|
||||
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
|
||||
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
@@ -467,9 +465,8 @@ github.com/niklasfasching/go-org v1.6.5 h1:5YAIqNTdl6lAOb7lD2AyQ1RuFGPVrAKvUexph
|
||||
github.com/niklasfasching/go-org v1.6.5/go.mod h1:ybv0eGDnxylFUfFE+ySaQc734j/L3+/ChKZ/h63a2wM=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
|
||||
github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pelletier/go-toml/v2 v2.0.4 h1:MHHO+ZUPwPZQ6BmnnT81iQg5cuurp78CRH7rNsguSMk=
|
||||
github.com/pelletier/go-toml/v2 v2.0.4/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -481,8 +478,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
|
||||
@@ -492,12 +489,12 @@ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF
|
||||
github.com/shogo82148/go-shuffle v0.0.0-20180218125048-27e6095f230d/go.mod h1:2htx6lmL0NGLHlO8ZCf+lQBGBHIbEujyywxJArf+2Yc=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
|
||||
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/fsync v0.9.0 h1:f9CEt3DOB2mnHxZaftmEOFWjABEvKM/xpf3cUwJrGOY=
|
||||
github.com/spf13/fsync v0.9.0/go.mod h1:fNtJEfG3HiltN3y4cPOz6MLjos9+2pIEqLIgszqhp/0=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
@@ -506,6 +503,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
@@ -513,14 +511,17 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/tdewolff/minify/v2 v2.11.10 h1:2tk9nuKfc8YOTD8glZ7JF/VtE8W5HOgmepWdjcPtRro=
|
||||
github.com/tdewolff/minify/v2 v2.11.10/go.mod h1:dHOS3dk+nJ0M3q3uM3VlNzTb70cou+ov0ki7C4PAFgM=
|
||||
github.com/tdewolff/parse/v2 v2.6.0 h1:f2D7w32JtqjCv6SczWkfwK+m15et42qEtDnZXHoNY70=
|
||||
github.com/tdewolff/parse/v2 v2.6.0/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/tdewolff/minify/v2 v2.12.0 h1:ZyvMKeciyR3vzJrK/oHyBcSmpttQ/V+ah7qOqTZclaU=
|
||||
github.com/tdewolff/minify/v2 v2.12.0/go.mod h1:8mvf+KglD7XurfvvFZDUYvVURy6bA/r0oTvmakXMnyg=
|
||||
github.com/tdewolff/parse/v2 v2.6.1/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/parse/v2 v2.6.2 h1:RDExtQ7ThRGSucatK0nri3p+HD/tSreYh1IDtDDAS/I=
|
||||
github.com/tdewolff/parse/v2 v2.6.2/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
|
||||
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
|
||||
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -528,8 +529,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.12 h1:6hffw6vALvEDqJ19dOJvJKOoAOKe4NDaTqvd2sktGN0=
|
||||
github.com/yuin/goldmark v1.4.12/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
@@ -542,8 +543,9 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
@@ -746,8 +748,9 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
project_name: hugo
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- GOPROXY=https://proxy.golang.org
|
||||
before:
|
||||
hooks:
|
||||
- go mod download
|
||||
builds:
|
||||
-
|
||||
binary: hugo
|
||||
id: hugo
|
||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
flags:
|
||||
- -buildmode
|
||||
- exe
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 7
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
-
|
||||
binary: hugo
|
||||
id: hugo_unix
|
||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
flags:
|
||||
- -buildmode
|
||||
- exe
|
||||
goos:
|
||||
- freebsd
|
||||
- netbsd
|
||||
- openbsd
|
||||
- dragonfly
|
||||
goarch:
|
||||
- amd64
|
||||
-
|
||||
binary: hugo
|
||||
id: hugo_extended_windows
|
||||
ldflags:
|
||||
- -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
||||
- "-extldflags '-static'"
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
- CC=x86_64-w64-mingw32-gcc
|
||||
- CXX=x86_64-w64-mingw32-g++
|
||||
flags:
|
||||
- -buildmode
|
||||
- exe
|
||||
- -tags
|
||||
- extended
|
||||
goos:
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
- binary: hugo
|
||||
id: hugo_extended_darwin
|
||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
- CC=o64-clang
|
||||
- CXX=o64-clang++
|
||||
flags:
|
||||
- -buildmode
|
||||
- exe
|
||||
- -tags
|
||||
- extended
|
||||
goos:
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- binary: hugo
|
||||
id: hugo_extended_linux
|
||||
ldflags: -s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
flags:
|
||||
- -buildmode
|
||||
- exe
|
||||
- -tags
|
||||
- extended
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
hooks:
|
||||
post: ./goreleaser-hook-post-linux.sh
|
||||
release:
|
||||
draft: true
|
||||
|
||||
archives:
|
||||
-
|
||||
id: "hugo"
|
||||
builds: ['hugo', 'hugo_unix']
|
||||
format: tar.gz
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
|
||||
replacements:
|
||||
amd64: 64bit
|
||||
386: 32bit
|
||||
arm: ARM
|
||||
arm64: ARM64
|
||||
darwin: macOS
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
openbsd: OpenBSD
|
||||
netbsd: NetBSD
|
||||
freebsd: FreeBSD
|
||||
dragonfly: DragonFlyBSD
|
||||
files:
|
||||
- README.md
|
||||
- LICENSE
|
||||
-
|
||||
id: "hugo_extended"
|
||||
builds: ['hugo_extended_windows', 'hugo_extended_linux', 'hugo_extended_darwin']
|
||||
format: tar.gz
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
name_template: "{{.ProjectName}}_extended_{{.Version}}_{{.Os}}-{{.Arch}}"
|
||||
replacements:
|
||||
amd64: 64bit
|
||||
386: 32bit
|
||||
arm: ARM
|
||||
arm64: ARM64
|
||||
darwin: macOS
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
openbsd: OpenBSD
|
||||
netbsd: NetBSD
|
||||
freebsd: FreeBSD
|
||||
dragonfly: DragonFlyBSD
|
||||
files:
|
||||
- README.md
|
||||
- LICENSE
|
||||
|
||||
nfpms:
|
||||
-
|
||||
id: "hugo"
|
||||
builds: ['hugo']
|
||||
formats:
|
||||
- deb
|
||||
vendor: "gohugo.io"
|
||||
homepage: "https://gohugo.io/"
|
||||
maintainer: "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
||||
description: "A Fast and Flexible Static Site Generator built with love in GoLang."
|
||||
license: "Apache-2.0"
|
||||
file_name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
|
||||
replacements:
|
||||
amd64: 64bit
|
||||
386: 32bit
|
||||
arm: ARM
|
||||
arm64: ARM64
|
||||
darwin: macOS
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
openbsd: OpenBSD
|
||||
netbsd: NetBSD
|
||||
freebsd: FreeBSD
|
||||
dragonfly: DragonFlyBSD
|
||||
-
|
||||
id: "hugo_extended"
|
||||
builds: ['hugo_extended_linux']
|
||||
formats:
|
||||
- deb
|
||||
vendor: "gohugo.io"
|
||||
homepage: "https://gohugo.io/"
|
||||
maintainer: "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
||||
description: "A Fast and Flexible Static Site Generator built with love in GoLang."
|
||||
license: "Apache-2.0"
|
||||
file_name_template: "{{.ProjectName}}_extended_{{.Version}}_{{.Os}}-{{.Arch}}"
|
||||
replacements:
|
||||
amd64: 64bit
|
||||
386: 32bit
|
||||
arm: ARM
|
||||
arm64: ARM64
|
||||
darwin: macOS
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
openbsd: OpenBSD
|
||||
netbsd: NetBSD
|
||||
freebsd: FreeBSD
|
||||
dragonfly: DragonFlyBSD
|
||||
@@ -0,0 +1,5 @@
|
||||
# Release env.
|
||||
# These will be replaced by script before release.
|
||||
HUGORELEASER_TAG=v0.102.1
|
||||
HUGORELEASER_COMMITISH=e9c3ce16abc391ee5be38f88b0499d0e8e19104c
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
project = "hugo"
|
||||
|
||||
[go_settings]
|
||||
go_proxy = "https://proxy.golang.org"
|
||||
go_exe = "go"
|
||||
|
||||
[build_settings]
|
||||
binary = "hugo"
|
||||
flags = ["-buildmode", "exe"]
|
||||
env = ["CGO_ENABLED=0"]
|
||||
ldflags = "-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio"
|
||||
|
||||
[archive_settings]
|
||||
name_template = "{{ .Project }}_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||
extra_files = [
|
||||
{ source_path = "README.md", target_path = "README.md" },
|
||||
{ source_path = "LICENSE", target_path = "LICENSE" },
|
||||
]
|
||||
[archive_settings.type]
|
||||
format = "tar.gz"
|
||||
extension = ".tar.gz"
|
||||
[archive_settings.replacements]
|
||||
amd64 = "64bit"
|
||||
386 = "32bit"
|
||||
arm = "ARM"
|
||||
arm64 = "ARM64"
|
||||
darwin = "macOS"
|
||||
linux = "Linux"
|
||||
windows = "Windows"
|
||||
openbsd = "OpenBSD"
|
||||
netbsd = "NetBSD"
|
||||
freebsd = "FreeBSD"
|
||||
dragonfly = "DragonFlyBSD"
|
||||
|
||||
[release_settings]
|
||||
name = "${HUGORELEASER_TAG}"
|
||||
type = "github"
|
||||
repository = "hugo"
|
||||
repository_owner = "gohugoio"
|
||||
draft = true
|
||||
prerelease = false
|
||||
|
||||
[release_settings.release_notes_settings]
|
||||
# Use Hugoreleaser's autogenerated release notes.
|
||||
generate = true
|
||||
|
||||
# Collapse relases with < 10 changes below one title.
|
||||
short_threshold = 10
|
||||
short_title = "What's Changed"
|
||||
|
||||
groups = [
|
||||
# Group the changes in the release notes by title.
|
||||
# You need at least one.
|
||||
# The groups will be tested in order until a match is found.
|
||||
# The titles will so be listed in the given order in the release note.
|
||||
# Any match with ignore=true title will be dropped.
|
||||
{ regexp = "Merge commit|Squashed", ignore = true },
|
||||
{ title = "Bug fixes", regexp = "fix", ordinal = 10 },
|
||||
{ title = "Dependency Updates", regexp = "deps", ordinal = 30 },
|
||||
{ title = "Build Setup", regexp = "(snap|release|update to)", ordinal = 40 },
|
||||
{ title = "Documentation", regexp = "(doc|readme)", ordinal = 40 },
|
||||
{ title = "Improvements", regexp = ".*", ordinal = 20 },
|
||||
]
|
||||
|
||||
[[builds]]
|
||||
path = "container1/unix/regular"
|
||||
|
||||
[[builds.os]]
|
||||
goos = "darwin"
|
||||
[[builds.os.archs]]
|
||||
goarch = "universal"
|
||||
[[builds.os]]
|
||||
goos = "linux"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
[[builds.os.archs]]
|
||||
goarch = "arm64"
|
||||
[[builds.os.archs]]
|
||||
goarch = "arm"
|
||||
[builds.os.archs.build_settings]
|
||||
env = ["CGO_ENABLED=0", "GOARM=7"]
|
||||
|
||||
# Unix BSD variants
|
||||
[[builds.os]]
|
||||
goos = "dragonfly"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
[[builds.os]]
|
||||
goos = "freebsd"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
[[builds.os]]
|
||||
goos = "netbsd"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
[[builds.os]]
|
||||
goos = "openbsd"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
|
||||
[[builds]]
|
||||
path = "container1/unix/extended"
|
||||
|
||||
[builds.build_settings]
|
||||
flags = ["-buildmode", "exe", "-tags", "extended"]
|
||||
env = ["CGO_ENABLED=1"]
|
||||
|
||||
[[builds.os]]
|
||||
goos = "darwin"
|
||||
[builds.os.build_settings]
|
||||
env = ["CGO_ENABLED=1", "CC=o64-clang", "CXX=o64-clang++"]
|
||||
[[builds.os.archs]]
|
||||
goarch = "universal"
|
||||
[[builds.os]]
|
||||
goos = "linux"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
|
||||
[[builds]]
|
||||
path = "container2/linux/extended"
|
||||
|
||||
[builds.build_settings]
|
||||
flags = ["-buildmode", "exe", "-tags", "extended"]
|
||||
|
||||
[[builds.os]]
|
||||
goos = "linux"
|
||||
[builds.os.build_settings]
|
||||
env = [
|
||||
"CGO_ENABLED=1",
|
||||
"CC=aarch64-linux-gnu-gcc",
|
||||
"CXX=aarch64-linux-gnu-g++",
|
||||
]
|
||||
[[builds.os.archs]]
|
||||
goarch = "arm64"
|
||||
|
||||
[[builds]]
|
||||
path = "container1/windows/regular"
|
||||
|
||||
[[builds.os]]
|
||||
goos = "windows"
|
||||
[builds.os.build_settings]
|
||||
binary = "hugo.exe"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
[[builds.os.archs]]
|
||||
goarch = "arm64"
|
||||
|
||||
[[builds]]
|
||||
path = "container1/windows/extended"
|
||||
|
||||
[builds.build_settings]
|
||||
flags = ["-buildmode", "exe", "-tags", "extended"]
|
||||
env = [
|
||||
"CGO_ENABLED=1",
|
||||
"CC=x86_64-w64-mingw32-gcc",
|
||||
"CXX=x86_64-w64-mingw32-g++",
|
||||
]
|
||||
ldflags = "-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio -extldflags '-static'"
|
||||
|
||||
[[builds.os]]
|
||||
goos = "windows"
|
||||
[builds.os.build_settings]
|
||||
binary = "hugo.exe"
|
||||
[[builds.os.archs]]
|
||||
goarch = "amd64"
|
||||
|
||||
[[archives]]
|
||||
paths = ["builds/container1/unix/regular/**"]
|
||||
[[archives]]
|
||||
paths = ["builds/container1/unix/extended/**"]
|
||||
[archives.archive_settings]
|
||||
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||
[[archives]]
|
||||
# Only extended builds in container2.
|
||||
paths = ["builds/container2/**"]
|
||||
[archives.archive_settings]
|
||||
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||
[[archives]]
|
||||
paths = ["builds/**/windows/regular/**"]
|
||||
[archives.archive_settings.type]
|
||||
format = "zip"
|
||||
extension = ".zip"
|
||||
[[archives]]
|
||||
paths = ["builds/**/windows/extended/**"]
|
||||
[archives.archive_settings]
|
||||
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||
[archives.archive_settings.type]
|
||||
format = "zip"
|
||||
extension = ".zip"
|
||||
[[archives]]
|
||||
paths = ["builds/**/regular/linux/{arm64,amd64}"]
|
||||
[archives.archive_settings]
|
||||
binary_dir = "/usr/local/bin"
|
||||
extra_files = []
|
||||
[archives.archive_settings.type]
|
||||
format = "_plugin"
|
||||
extension = ".deb"
|
||||
[archives.archive_settings.plugin]
|
||||
id = "deb"
|
||||
type = "gorun"
|
||||
command = "github.com/gohugoio/hugoreleaser-archive-plugins/deb@v0.5.0"
|
||||
[archives.archive_settings.custom_settings]
|
||||
vendor = "gohugo.io"
|
||||
homepage = "https://github.com/gohugoio/hugoreleaser"
|
||||
maintainer = "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
||||
description = "Build, archive and release Go programs."
|
||||
license = "Apache-2.0"
|
||||
[[archives]]
|
||||
paths = ["builds/**/extended/linux/{arm64,amd64}"]
|
||||
[archives.archive_settings]
|
||||
binary_dir = "/usr/local/bin"
|
||||
extra_files = []
|
||||
name_template = "{{ .Project }}_extended_{{ .Tag | trimPrefix `v` }}_{{ .Goos }}-{{ .Goarch }}"
|
||||
[archives.archive_settings.type]
|
||||
format = "_plugin"
|
||||
extension = ".deb"
|
||||
[archives.archive_settings.plugin]
|
||||
id = "deb"
|
||||
type = "gorun"
|
||||
command = "github.com/gohugoio/hugoreleaser-archive-plugins/deb@latest"
|
||||
[archives.archive_settings.custom_settings]
|
||||
vendor = "gohugo.io"
|
||||
homepage = "https://github.com/gohugoio/hugoreleaser"
|
||||
maintainer = "Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>"
|
||||
description = "Build, archive and release Go programs."
|
||||
license = "Apache-2.0"
|
||||
|
||||
[[releases]]
|
||||
paths = ["archives/**"]
|
||||
path = "r1"
|
||||
|
||||
# The above should allow the following build commands:
|
||||
# hugoreleaser build -paths "builds/container1/**"
|
||||
# hugoreleaser build -paths "builds/container2/**"
|
||||
# hugoreleaser archive
|
||||
# hugoreleaser release
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -265,6 +265,39 @@ Position: {{ .Position | safeHTML }}
|
||||
b.AssertFileContent("public/p1/index.html", filepath.FromSlash("Position: \"/content/p1.md:7:1\""))
|
||||
}
|
||||
|
||||
// Issue 10118
|
||||
func TestAttributes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- config.toml --
|
||||
-- content/p1.md --
|
||||
---
|
||||
title: "p1"
|
||||
---
|
||||
|
||||
## Issue 10118
|
||||
|
||||
§§§ {foo="bar"}
|
||||
Hello, World!
|
||||
§§§
|
||||
|
||||
-- layouts/_default/single.html --
|
||||
{{ .Content }}
|
||||
-- layouts/_default/_markup/render-codeblock.html --
|
||||
Attributes: {{ .Attributes }}|Type: {{ .Type }}|
|
||||
`
|
||||
|
||||
b := hugolib.NewIntegrationTestBuilder(
|
||||
hugolib.IntegrationTestConfig{
|
||||
T: t,
|
||||
TxtarString: files,
|
||||
},
|
||||
).Build()
|
||||
|
||||
b.AssertFileContent("public/p1/index.html", "<h2 id=\"issue-10118\">Issue 10118</h2>\nAttributes: map[foo:bar]|Type: |")
|
||||
}
|
||||
|
||||
// Issue 9571
|
||||
func TestAttributesChroma(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -16,6 +16,7 @@ package codeblocks
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/alecthomas/chroma/v2/lexers"
|
||||
@@ -69,7 +70,7 @@ func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.No
|
||||
}
|
||||
|
||||
n := node.(*codeBlock)
|
||||
lang := string(n.b.Language(src))
|
||||
lang := getLang(n.b, src)
|
||||
renderer := ctx.RenderContext().GetRenderer(hooks.CodeBlockRendererType, lang)
|
||||
if renderer == nil {
|
||||
return ast.WalkStop, fmt.Errorf("no code renderer found for %q", lang)
|
||||
@@ -174,6 +175,12 @@ func (c *codeBlockContext) Position() htext.Position {
|
||||
return c.pos
|
||||
}
|
||||
|
||||
func getLang(node *ast.FencedCodeBlock, src []byte) string {
|
||||
langWithAttributes := string(node.Language(src))
|
||||
lang, _, _ := strings.Cut(langWithAttributes, "{")
|
||||
return lang
|
||||
}
|
||||
|
||||
func getAttributes(node *ast.FencedCodeBlock, infostr []byte) []ast.Attribute {
|
||||
if node.Attributes() != nil {
|
||||
return node.Attributes()
|
||||
@@ -188,7 +195,7 @@ func getAttributes(node *ast.FencedCodeBlock, infostr []byte) []ast.Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
if attrStartIdx > 0 {
|
||||
if attrStartIdx != -1 {
|
||||
n := ast.NewTextBlock() // dummy node for storing attributes
|
||||
attrStr := infostr[attrStartIdx:]
|
||||
if attrs, hasAttr := parser.ParseAttributes(text.NewReader(attrStr)); hasAttr {
|
||||
|
||||
-253
@@ -1,253 +0,0 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package releaser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
)
|
||||
|
||||
var issueRe = regexp.MustCompile(`(?i)(?:Updates?|Closes?|Fix.*|See) #(\d+)`)
|
||||
|
||||
type changeLog struct {
|
||||
Version string
|
||||
Notes gitInfos
|
||||
All gitInfos
|
||||
Docs gitInfos
|
||||
|
||||
// Overall stats
|
||||
Repo *gitHubRepo
|
||||
ContributorCount int
|
||||
ThemeCount int
|
||||
}
|
||||
|
||||
func newChangeLog(infos, docInfos gitInfos) *changeLog {
|
||||
log := &changeLog{
|
||||
Docs: docInfos,
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
// TODO(bep) improve
|
||||
if regexp.MustCompile("(?i)deprecate|note").MatchString(info.Subject) {
|
||||
log.Notes = append(log.Notes, info)
|
||||
}
|
||||
|
||||
log.All = append(log.All, info)
|
||||
info.Subject = strings.TrimSpace(info.Subject)
|
||||
|
||||
}
|
||||
|
||||
return log
|
||||
}
|
||||
|
||||
type gitInfo struct {
|
||||
Hash string
|
||||
Author string
|
||||
Subject string
|
||||
Body string
|
||||
|
||||
GitHubCommit *gitHubCommit
|
||||
}
|
||||
|
||||
func (g gitInfo) Issues() []int {
|
||||
return extractIssues(g.Body)
|
||||
}
|
||||
|
||||
func (g gitInfo) AuthorID() string {
|
||||
if g.GitHubCommit != nil {
|
||||
return g.GitHubCommit.Author.Login
|
||||
}
|
||||
return g.Author
|
||||
}
|
||||
|
||||
func extractIssues(body string) []int {
|
||||
var i []int
|
||||
m := issueRe.FindAllStringSubmatch(body, -1)
|
||||
for _, mm := range m {
|
||||
issueID, err := strconv.Atoi(mm[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
i = append(i, issueID)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
type gitInfos []gitInfo
|
||||
|
||||
func git(args ...string) (string, error) {
|
||||
cmd, _ := hexec.SafeCommand("git", args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("git failed: %q: %q (%q)", err, out, args)
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func getGitInfos(tag, repo, repoPath string, remote bool) (gitInfos, error) {
|
||||
return getGitInfosBefore("HEAD", tag, repo, repoPath, remote)
|
||||
}
|
||||
|
||||
type countribCount struct {
|
||||
Author string
|
||||
GitHubAuthor gitHubAuthor
|
||||
Count int
|
||||
}
|
||||
|
||||
func (c countribCount) AuthorLink() string {
|
||||
if c.GitHubAuthor.HTMLURL != "" {
|
||||
return fmt.Sprintf("[@%s](%s)", c.GitHubAuthor.Login, c.GitHubAuthor.HTMLURL)
|
||||
}
|
||||
|
||||
if !strings.Contains(c.Author, "@") {
|
||||
return c.Author
|
||||
}
|
||||
|
||||
return c.Author[:strings.Index(c.Author, "@")]
|
||||
}
|
||||
|
||||
type contribCounts []countribCount
|
||||
|
||||
func (c contribCounts) Less(i, j int) bool { return c[i].Count > c[j].Count }
|
||||
func (c contribCounts) Len() int { return len(c) }
|
||||
func (c contribCounts) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
|
||||
func (g gitInfos) ContribCountPerAuthor() contribCounts {
|
||||
var c contribCounts
|
||||
|
||||
counters := make(map[string]countribCount)
|
||||
|
||||
for _, gi := range g {
|
||||
authorID := gi.AuthorID()
|
||||
if count, ok := counters[authorID]; ok {
|
||||
count.Count = count.Count + 1
|
||||
counters[authorID] = count
|
||||
} else {
|
||||
var ghA gitHubAuthor
|
||||
if gi.GitHubCommit != nil {
|
||||
ghA = gi.GitHubCommit.Author
|
||||
}
|
||||
authorCount := countribCount{Count: 1, Author: gi.Author, GitHubAuthor: ghA}
|
||||
counters[authorID] = authorCount
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range counters {
|
||||
c = append(c, v)
|
||||
}
|
||||
|
||||
sort.Sort(c)
|
||||
return c
|
||||
}
|
||||
|
||||
func getGitInfosBefore(ref, tag, repo, repoPath string, remote bool) (gitInfos, error) {
|
||||
client := newGitHubAPI(repo)
|
||||
var g gitInfos
|
||||
|
||||
log, err := gitLogBefore(ref, tag, repoPath)
|
||||
if err != nil {
|
||||
return g, err
|
||||
}
|
||||
|
||||
log = strings.Trim(log, "\n\x1e'")
|
||||
entries := strings.Split(log, "\x1e")
|
||||
|
||||
for _, entry := range entries {
|
||||
items := strings.Split(entry, "\x1f")
|
||||
gi := gitInfo{}
|
||||
|
||||
if len(items) > 0 {
|
||||
gi.Hash = items[0]
|
||||
}
|
||||
if len(items) > 1 {
|
||||
gi.Author = items[1]
|
||||
}
|
||||
if len(items) > 2 {
|
||||
gi.Subject = items[2]
|
||||
}
|
||||
if len(items) > 3 {
|
||||
gi.Body = items[3]
|
||||
}
|
||||
|
||||
if remote && gi.Hash != "" {
|
||||
gc, err := client.fetchCommit(gi.Hash)
|
||||
if err == nil {
|
||||
gi.GitHubCommit = &gc
|
||||
}
|
||||
}
|
||||
g = append(g, gi)
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// Ignore autogenerated commits etc. in change log. This is a regexp.
|
||||
const ignoredCommits = "snapcraft:|Merge commit|Squashed"
|
||||
|
||||
func gitLogBefore(ref, tag, repoPath string) (string, error) {
|
||||
var prevTag string
|
||||
var err error
|
||||
if tag != "" {
|
||||
prevTag = tag
|
||||
} else {
|
||||
prevTag, err = gitVersionTagBefore(ref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
defaultArgs := []string{"log", "-E", fmt.Sprintf("--grep=%s", ignoredCommits), "--invert-grep", "--pretty=format:%x1e%h%x1f%aE%x1f%s%x1f%b", "--abbrev-commit", prevTag + ".." + ref}
|
||||
|
||||
var args []string
|
||||
|
||||
if repoPath != "" {
|
||||
args = append([]string{"-C", repoPath}, defaultArgs...)
|
||||
} else {
|
||||
args = defaultArgs
|
||||
}
|
||||
|
||||
log, err := git(args...)
|
||||
if err != nil {
|
||||
return ",", err
|
||||
}
|
||||
|
||||
return log, err
|
||||
}
|
||||
|
||||
func gitVersionTagBefore(ref string) (string, error) {
|
||||
return gitShort("describe", "--tags", "--abbrev=0", "--always", "--match", "v[0-9]*", ref+"^")
|
||||
}
|
||||
|
||||
func gitShort(args ...string) (output string, err error) {
|
||||
output, err = git(args...)
|
||||
return strings.Replace(strings.Split(output, "\n")[0], "'", "", -1), err
|
||||
}
|
||||
|
||||
func tagExists(tag string) (bool, error) {
|
||||
out, err := git("tag", "-l", tag)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if strings.Contains(out, tag) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package releaser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestGitInfos(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
skipIfCI(t)
|
||||
infos, err := getGitInfos("v0.20", "hugo", "", false)
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(infos) > 0, qt.Equals, true)
|
||||
}
|
||||
|
||||
func TestIssuesRe(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
body := `
|
||||
This is a commit message.
|
||||
|
||||
Updates #123
|
||||
Fix #345
|
||||
closes #543
|
||||
See #456
|
||||
`
|
||||
|
||||
issues := extractIssues(body)
|
||||
|
||||
c.Assert(len(issues), qt.Equals, 4)
|
||||
c.Assert(issues[0], qt.Equals, 123)
|
||||
c.Assert(issues[2], qt.Equals, 543)
|
||||
|
||||
bodyNoIssues := `
|
||||
This is a commit message without issue refs.
|
||||
|
||||
But it has e #10 to make old regexp confused.
|
||||
Streets #20.
|
||||
`
|
||||
|
||||
emptyIssuesList := extractIssues(bodyNoIssues)
|
||||
c.Assert(len(emptyIssuesList), qt.Equals, 0)
|
||||
}
|
||||
|
||||
func TestGitVersionTagBefore(t *testing.T) {
|
||||
skipIfCI(t)
|
||||
c := qt.New(t)
|
||||
v1, err := gitVersionTagBefore("v0.18")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(v1, qt.Equals, "v0.17")
|
||||
}
|
||||
|
||||
func TestTagExists(t *testing.T) {
|
||||
skipIfCI(t)
|
||||
c := qt.New(t)
|
||||
b1, err := tagExists("v0.18")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(b1, qt.Equals, true)
|
||||
|
||||
b2, err := tagExists("adfagdsfg")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(b2, qt.Equals, false)
|
||||
}
|
||||
|
||||
func skipIfCI(t *testing.T) {
|
||||
if isCI() {
|
||||
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
||||
// Also Travis clones very shallowly, making some of the tests above shaky.
|
||||
t.Skip("Skip git test on Linux to make Travis happy.")
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package releaser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
gitHubCommitsAPI = "https://api.github.com/repos/gohugoio/REPO/commits/%s"
|
||||
gitHubRepoAPI = "https://api.github.com/repos/gohugoio/REPO"
|
||||
gitHubContributorsAPI = "https://api.github.com/repos/gohugoio/REPO/contributors"
|
||||
)
|
||||
|
||||
type gitHubAPI struct {
|
||||
commitsAPITemplate string
|
||||
repoAPI string
|
||||
contributorsAPITemplate string
|
||||
}
|
||||
|
||||
func newGitHubAPI(repo string) *gitHubAPI {
|
||||
return &gitHubAPI{
|
||||
commitsAPITemplate: strings.Replace(gitHubCommitsAPI, "REPO", repo, -1),
|
||||
repoAPI: strings.Replace(gitHubRepoAPI, "REPO", repo, -1),
|
||||
contributorsAPITemplate: strings.Replace(gitHubContributorsAPI, "REPO", repo, -1),
|
||||
}
|
||||
}
|
||||
|
||||
type gitHubCommit struct {
|
||||
Author gitHubAuthor `json:"author"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
}
|
||||
|
||||
type gitHubAuthor struct {
|
||||
ID int `json:"id"`
|
||||
Login string `json:"login"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
type gitHubRepo struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
Stars int `json:"stargazers_count"`
|
||||
Contributors []gitHubContributor
|
||||
}
|
||||
|
||||
type gitHubContributor struct {
|
||||
ID int `json:"id"`
|
||||
Login string `json:"login"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
Contributions int `json:"contributions"`
|
||||
}
|
||||
|
||||
func (g *gitHubAPI) fetchCommit(ref string) (gitHubCommit, error) {
|
||||
var commit gitHubCommit
|
||||
|
||||
u := fmt.Sprintf(g.commitsAPITemplate, ref)
|
||||
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return commit, err
|
||||
}
|
||||
|
||||
err = doGitHubRequest(req, &commit)
|
||||
|
||||
return commit, err
|
||||
}
|
||||
|
||||
func (g *gitHubAPI) fetchRepo() (gitHubRepo, error) {
|
||||
var repo gitHubRepo
|
||||
|
||||
req, err := http.NewRequest("GET", g.repoAPI, nil)
|
||||
if err != nil {
|
||||
return repo, err
|
||||
}
|
||||
|
||||
err = doGitHubRequest(req, &repo)
|
||||
if err != nil {
|
||||
return repo, err
|
||||
}
|
||||
|
||||
var contributors []gitHubContributor
|
||||
page := 0
|
||||
for {
|
||||
page++
|
||||
var currPage []gitHubContributor
|
||||
url := fmt.Sprintf(g.contributorsAPITemplate+"?page=%d", page)
|
||||
|
||||
req, err = http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return repo, err
|
||||
}
|
||||
|
||||
err = doGitHubRequest(req, &currPage)
|
||||
if err != nil {
|
||||
return repo, err
|
||||
}
|
||||
if len(currPage) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
contributors = append(contributors, currPage...)
|
||||
|
||||
}
|
||||
|
||||
repo.Contributors = contributors
|
||||
|
||||
return repo, err
|
||||
}
|
||||
|
||||
func doGitHubRequest(req *http.Request, v any) error {
|
||||
addGitHubToken(req)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if isError(resp) {
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("GitHub lookup failed: %s", string(b))
|
||||
}
|
||||
|
||||
return json.NewDecoder(resp.Body).Decode(v)
|
||||
}
|
||||
|
||||
func isError(resp *http.Response) bool {
|
||||
return resp.StatusCode < 200 || resp.StatusCode > 299
|
||||
}
|
||||
|
||||
func addGitHubToken(req *http.Request) {
|
||||
gitHubToken := os.Getenv("GITHUB_TOKEN")
|
||||
if gitHubToken != "" {
|
||||
req.Header.Add("Authorization", "token "+gitHubToken)
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package releaser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestGitHubLookupCommit(t *testing.T) {
|
||||
skipIfNoToken(t)
|
||||
c := qt.New(t)
|
||||
client := newGitHubAPI("hugo")
|
||||
commit, err := client.fetchCommit("793554108763c0984f1a1b1a6ee5744b560d78d0")
|
||||
c.Assert(err, qt.IsNil)
|
||||
fmt.Println(commit)
|
||||
}
|
||||
|
||||
func TestFetchRepo(t *testing.T) {
|
||||
skipIfNoToken(t)
|
||||
c := qt.New(t)
|
||||
client := newGitHubAPI("hugo")
|
||||
repo, err := client.fetchRepo()
|
||||
c.Assert(err, qt.IsNil)
|
||||
fmt.Println(">>", len(repo.Contributors))
|
||||
}
|
||||
|
||||
func skipIfNoToken(t *testing.T) {
|
||||
if os.Getenv("GITHUB_TOKEN") == "" {
|
||||
t.Skip("Skip test against GitHub as no GITHUB_TOKEN set.")
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package releaser implements a set of utilities and a wrapper around Goreleaser
|
||||
// to help automate the Hugo release process.
|
||||
package releaser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const (
|
||||
issueLinkTemplate = "#%d"
|
||||
linkTemplate = "[%s](%s)"
|
||||
releaseNotesMarkdownTemplatePatchRelease = `
|
||||
{{ if eq (len .All) 1 }}
|
||||
This is a bug-fix release with one important fix.
|
||||
{{ else }}
|
||||
This is a bug-fix release with a couple of important fixes.
|
||||
{{ end }}
|
||||
{{ range .All }}
|
||||
{{- if .GitHubCommit -}}
|
||||
* {{ .Subject }} {{ .Hash }} {{ . | author }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
||||
{{ else -}}
|
||||
* {{ .Subject }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
||||
{{ end -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
`
|
||||
releaseNotesMarkdownTemplate = `
|
||||
{{- $contribsPerAuthor := .All.ContribCountPerAuthor -}}
|
||||
{{- $docsContribsPerAuthor := .Docs.ContribCountPerAuthor -}}
|
||||
|
||||
This release represents **{{ len .All }} contributions by {{ len $contribsPerAuthor }} contributors** to the main Hugo code base.
|
||||
|
||||
{{- if gt (len $contribsPerAuthor) 3 -}}
|
||||
{{- $u1 := index $contribsPerAuthor 0 -}}
|
||||
{{- $u2 := index $contribsPerAuthor 1 -}}
|
||||
{{- $u3 := index $contribsPerAuthor 2 -}}
|
||||
{{- $u4 := index $contribsPerAuthor 3 -}}
|
||||
{{- $u1.AuthorLink }} leads the Hugo development with a significant amount of contributions, but also a big shoutout to {{ $u2.AuthorLink }}, {{ $u3.AuthorLink }}, and {{ $u4.AuthorLink }} for their ongoing contributions.
|
||||
And thanks to [@digitalcraftsman](https://github.com/digitalcraftsman) for his ongoing work on keeping the themes site in pristine condition.
|
||||
{{ end }}
|
||||
Many have also been busy writing and fixing the documentation in [hugoDocs](https://github.com/gohugoio/hugoDocs),
|
||||
which has received **{{ len .Docs }} contributions by {{ len $docsContribsPerAuthor }} contributors**.
|
||||
{{- if gt (len $docsContribsPerAuthor) 3 -}}
|
||||
{{- $u1 := index $docsContribsPerAuthor 0 -}}
|
||||
{{- $u2 := index $docsContribsPerAuthor 1 -}}
|
||||
{{- $u3 := index $docsContribsPerAuthor 2 -}}
|
||||
{{- $u4 := index $docsContribsPerAuthor 3 }} A special thanks to {{ $u1.AuthorLink }}, {{ $u2.AuthorLink }}, {{ $u3.AuthorLink }}, and {{ $u4.AuthorLink }} for their work on the documentation site.
|
||||
{{ end }}
|
||||
|
||||
Hugo now has:
|
||||
|
||||
{{ with .Repo -}}
|
||||
* {{ .Stars }}+ [stars](https://github.com/gohugoio/hugo/stargazers)
|
||||
* {{ len .Contributors }}+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
|
||||
{{- end -}}
|
||||
{{ with .ThemeCount }}
|
||||
* {{ . }}+ [themes](http://themes.gohugo.io/)
|
||||
{{ end }}
|
||||
{{ with .Notes }}
|
||||
## Notes
|
||||
{{ template "change-section" . }}
|
||||
{{- end -}}
|
||||
{{ with .All }}
|
||||
## Changes
|
||||
{{ template "change-section" . }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "change-section" }}
|
||||
{{ range . }}
|
||||
{{- if .GitHubCommit -}}
|
||||
* {{ .Subject }} {{ .Hash }} {{ . | author }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
||||
{{ else -}}
|
||||
* {{ .Subject }} {{ range .Issues }}{{ . | issue }} {{ end }}
|
||||
{{ end -}}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
`
|
||||
)
|
||||
|
||||
var templateFuncs = template.FuncMap{
|
||||
"isPatch": func(c changeLog) bool {
|
||||
return !strings.HasSuffix(c.Version, "0")
|
||||
},
|
||||
"issue": func(id int) string {
|
||||
return fmt.Sprintf(issueLinkTemplate, id)
|
||||
},
|
||||
"commitURL": func(info gitInfo) string {
|
||||
if info.GitHubCommit.HTMLURL == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(linkTemplate, info.Hash, info.GitHubCommit.HTMLURL)
|
||||
},
|
||||
"author": func(info gitInfo) string {
|
||||
return "@" + info.GitHubCommit.Author.Login
|
||||
},
|
||||
}
|
||||
|
||||
func writeReleaseNotes(version string, infosMain, infosDocs gitInfos, to io.Writer) error {
|
||||
client := newGitHubAPI("hugo")
|
||||
changes := newChangeLog(infosMain, infosDocs)
|
||||
changes.Version = version
|
||||
repo, err := client.fetchRepo()
|
||||
if err == nil {
|
||||
changes.Repo = &repo
|
||||
}
|
||||
themeCount, err := fetchThemeCount()
|
||||
if err == nil {
|
||||
changes.ThemeCount = themeCount
|
||||
}
|
||||
|
||||
mtempl := releaseNotesMarkdownTemplate
|
||||
|
||||
if !strings.HasSuffix(version, "0") {
|
||||
mtempl = releaseNotesMarkdownTemplatePatchRelease
|
||||
}
|
||||
|
||||
tmpl, err := template.New("").Funcs(templateFuncs).Parse(mtempl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tmpl.Execute(to, changes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchThemeCount() (int, error) {
|
||||
resp, err := http.Get("https://raw.githubusercontent.com/gohugoio/hugoThemesSiteBuilder/main/themes.txt")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
return bytes.Count(b, []byte("\n")) - bytes.Count(b, []byte("#")), nil
|
||||
}
|
||||
|
||||
func getReleaseNotesFilename(version string) string {
|
||||
return filepath.FromSlash(fmt.Sprintf("temp/%s-relnotes-ready.md", version))
|
||||
}
|
||||
|
||||
func (r *ReleaseHandler) writeReleaseNotesToTemp(version string, isPatch bool, infosMain, infosDocs gitInfos) (string, error) {
|
||||
filename := getReleaseNotesFilename(version)
|
||||
|
||||
var w io.WriteCloser
|
||||
|
||||
if !r.try {
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
w = f
|
||||
|
||||
} else {
|
||||
w = os.Stdout
|
||||
}
|
||||
|
||||
if err := writeReleaseNotes(version, infosMain, infosDocs, w); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filename, nil
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package commands defines and implements command-line commands and flags
|
||||
// used by Hugo. Commands and flags are implemented using Cobra.
|
||||
|
||||
package releaser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func _TestReleaseNotesWriter(t *testing.T) {
|
||||
skipIfNoToken(t)
|
||||
if os.Getenv("CI") != "" {
|
||||
// Travis has an ancient git with no --invert-grep: https://github.com/travis-ci/travis-ci/issues/6328
|
||||
t.Skip("Skip git test on CI to make Travis happy..")
|
||||
}
|
||||
|
||||
c := qt.New(t)
|
||||
|
||||
var b bytes.Buffer
|
||||
|
||||
// TODO(bep) consider to query GitHub directly for the gitlog with author info, probably faster.
|
||||
infos, err := getGitInfosBefore("HEAD", "v0.89.0", "hugo", "", false)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
c.Assert(writeReleaseNotes("0.89.0", infos, infos, &b), qt.IsNil)
|
||||
|
||||
fmt.Println(b.String())
|
||||
}
|
||||
+105
-168
@@ -17,7 +17,6 @@ package releaser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -25,22 +24,59 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hexec"
|
||||
|
||||
"errors"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
)
|
||||
|
||||
const commitPrefix = "releaser:"
|
||||
|
||||
// New initialises a ReleaseHandler.
|
||||
func New(skipPush, try bool, step int) (*ReleaseHandler, error) {
|
||||
if step < 1 || step > 2 {
|
||||
return nil, fmt.Errorf("step must be 1 or 2")
|
||||
}
|
||||
|
||||
prefix := "release-"
|
||||
branch, err := git("rev-parse", "--abbrev-ref", "HEAD")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch = strings.TrimSpace(branch)
|
||||
|
||||
if !strings.HasPrefix(branch, prefix) {
|
||||
return nil, fmt.Errorf("branch %q is not a release branch", branch)
|
||||
}
|
||||
|
||||
version := strings.TrimPrefix(branch, prefix)
|
||||
version = strings.TrimPrefix(version, "v")
|
||||
|
||||
logf("Branch: %s|Version: v%s\n", branch, version)
|
||||
|
||||
rh := &ReleaseHandler{branchVersion: version, skipPush: skipPush, try: try, step: step}
|
||||
|
||||
if try {
|
||||
rh.git = func(args ...string) (string, error) {
|
||||
logln("git", strings.Join(args, " "))
|
||||
return "", nil
|
||||
}
|
||||
} else {
|
||||
rh.git = git
|
||||
}
|
||||
|
||||
return rh, nil
|
||||
}
|
||||
|
||||
// ReleaseHandler provides functionality to release a new version of Hugo.
|
||||
// Test this locally without doing an actual release:
|
||||
// go run -tags release main.go release --skip-publish --try -r 0.90.0
|
||||
// Or a variation of the above -- the skip-publish flag makes sure that any changes are performed to the local Git only.
|
||||
type ReleaseHandler struct {
|
||||
cliVersion string
|
||||
branchVersion string
|
||||
|
||||
skipPublish bool
|
||||
// 1 or 2.
|
||||
step int
|
||||
|
||||
// No remote pushes.
|
||||
skipPush bool
|
||||
|
||||
// Just simulate, no actual changes.
|
||||
try bool
|
||||
@@ -48,144 +84,48 @@ type ReleaseHandler struct {
|
||||
git func(args ...string) (string, error)
|
||||
}
|
||||
|
||||
func (r ReleaseHandler) calculateVersions() (hugo.Version, hugo.Version) {
|
||||
newVersion := hugo.MustParseVersion(r.cliVersion)
|
||||
finalVersion := newVersion.Next()
|
||||
finalVersion.PatchLevel = 0
|
||||
|
||||
if newVersion.Suffix != "-test" {
|
||||
newVersion.Suffix = ""
|
||||
}
|
||||
|
||||
finalVersion.Suffix = "-DEV"
|
||||
|
||||
return newVersion, finalVersion
|
||||
}
|
||||
|
||||
// New initialises a ReleaseHandler.
|
||||
func New(version string, skipPublish, try bool) *ReleaseHandler {
|
||||
// When triggered from CI release branch
|
||||
version = strings.TrimPrefix(version, "release-")
|
||||
version = strings.TrimPrefix(version, "v")
|
||||
rh := &ReleaseHandler{cliVersion: version, skipPublish: skipPublish, try: try}
|
||||
|
||||
if try {
|
||||
rh.git = func(args ...string) (string, error) {
|
||||
fmt.Println("git", strings.Join(args, " "))
|
||||
return "", nil
|
||||
}
|
||||
} else {
|
||||
rh.git = git
|
||||
}
|
||||
|
||||
return rh
|
||||
}
|
||||
|
||||
// Run creates a new release.
|
||||
func (r *ReleaseHandler) Run() error {
|
||||
if os.Getenv("GITHUB_TOKEN") == "" {
|
||||
return errors.New("GITHUB_TOKEN not set, create one here with the repo scope selected: https://github.com/settings/tokens/new")
|
||||
}
|
||||
|
||||
fmt.Printf("Start release from %q\n", wd())
|
||||
|
||||
newVersion, finalVersion := r.calculateVersions()
|
||||
|
||||
version := newVersion.String()
|
||||
tag := "v" + version
|
||||
isPatch := newVersion.PatchLevel > 0
|
||||
mainVersion := newVersion
|
||||
mainVersion.PatchLevel = 0
|
||||
|
||||
// Exit early if tag already exists
|
||||
exists, err := tagExists(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.gitPush()
|
||||
|
||||
if exists {
|
||||
return fmt.Errorf("tag %q already exists", tag)
|
||||
}
|
||||
|
||||
var changeLogFromTag string
|
||||
|
||||
if newVersion.PatchLevel == 0 {
|
||||
// There may have been patch releases between, so set the tag explicitly.
|
||||
changeLogFromTag = "v" + newVersion.Prev().String()
|
||||
exists, _ := tagExists(changeLogFromTag)
|
||||
if !exists {
|
||||
// fall back to one that exists.
|
||||
changeLogFromTag = ""
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
gitCommits gitInfos
|
||||
gitCommitsDocs gitInfos
|
||||
)
|
||||
|
||||
defer r.gitPush() // TODO(bep)
|
||||
|
||||
gitCommits, err = getGitInfos(changeLogFromTag, "hugo", "", !r.try)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(bep) explicit tag?
|
||||
gitCommitsDocs, err = getGitInfos("", "hugoDocs", "../hugoDocs", !r.try)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
releaseNotesFile, err := r.writeReleaseNotesToTemp(version, isPatch, gitCommits, gitCommitsDocs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := r.git("add", releaseNotesFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commitMsg := fmt.Sprintf("%s Add release notes for %s", commitPrefix, newVersion)
|
||||
commitMsg += "\n[ci skip]"
|
||||
|
||||
if _, err := r.git("commit", "-m", commitMsg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.bumpVersions(newVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := r.git("tag", "-a", tag, "-m", fmt.Sprintf("%s %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !r.skipPublish {
|
||||
if _, err := r.git("push", "origin", tag); err != nil {
|
||||
if r.step == 1 {
|
||||
if err := r.bumpVersions(newVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.release(releaseNotesFile); err != nil {
|
||||
return err
|
||||
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Bump versions for release of %s\n\n[ci skip]", commitPrefix, newVersion)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The above commit will be the target for this release, so print it to the console in a env friendly way.
|
||||
sha, err := git("rev-parse", "HEAD")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Hugoreleaser will do the actual release using these values.
|
||||
if err := r.replaceInFile("hugoreleaser.env",
|
||||
`HUGORELEASER_TAG=(\S*)`, "HUGORELEASER_TAG="+tag,
|
||||
`HUGORELEASER_COMMITISH=(\S*)`, "HUGORELEASER_COMMITISH="+sha,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
logf("HUGORELEASER_TAG=%s\n", tag)
|
||||
logf("HUGORELEASER_COMMITISH=%s\n", sha)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := r.bumpVersions(finalVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !r.try {
|
||||
// No longer needed.
|
||||
if err := os.Remove(releaseNotesFile); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := r.git("commit", "-a", "-m", fmt.Sprintf("%s Prepare repository for %s\n\n[ci skip]", commitPrefix, finalVersion)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -193,36 +133,6 @@ func (r *ReleaseHandler) Run() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReleaseHandler) gitPush() {
|
||||
if r.skipPublish {
|
||||
return
|
||||
}
|
||||
if _, err := r.git("push", "origin", "HEAD"); err != nil {
|
||||
log.Fatal("push failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReleaseHandler) release(releaseNotesFile string) error {
|
||||
if r.try {
|
||||
fmt.Println("Skip goreleaser...")
|
||||
return nil
|
||||
}
|
||||
|
||||
args := []string{"--parallelism", "2", "--timeout", "120m", "--rm-dist", "--release-notes", releaseNotesFile}
|
||||
if r.skipPublish {
|
||||
args = append(args, "--skip-publish")
|
||||
}
|
||||
|
||||
cmd, _ := hexec.SafeCommand("goreleaser", args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("goreleaser failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error {
|
||||
toDev := ""
|
||||
|
||||
@@ -264,6 +174,29 @@ func (r *ReleaseHandler) bumpVersions(ver hugo.Version) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r ReleaseHandler) calculateVersions() (hugo.Version, hugo.Version) {
|
||||
newVersion := hugo.MustParseVersion(r.branchVersion)
|
||||
finalVersion := newVersion.Next()
|
||||
finalVersion.PatchLevel = 0
|
||||
|
||||
if newVersion.Suffix != "-test" {
|
||||
newVersion.Suffix = ""
|
||||
}
|
||||
|
||||
finalVersion.Suffix = "-DEV"
|
||||
|
||||
return newVersion, finalVersion
|
||||
}
|
||||
|
||||
func (r *ReleaseHandler) gitPush() {
|
||||
if r.skipPush {
|
||||
return
|
||||
}
|
||||
if _, err := r.git("push", "origin", "HEAD"); err != nil {
|
||||
log.Fatal("push failed:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error {
|
||||
filename = filepath.FromSlash(filename)
|
||||
fi, err := os.Stat(filename)
|
||||
@@ -272,11 +205,11 @@ func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error
|
||||
}
|
||||
|
||||
if r.try {
|
||||
fmt.Printf("Replace in %q: %q\n", filename, oldNew)
|
||||
logf("Replace in %q: %q\n", filename, oldNew)
|
||||
return nil
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -287,18 +220,22 @@ func (r *ReleaseHandler) replaceInFile(filename string, oldNew ...string) error
|
||||
newContent = re.ReplaceAllString(newContent, oldNew[i+1])
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(filename, []byte(newContent), fi.Mode())
|
||||
return os.WriteFile(filename, []byte(newContent), fi.Mode())
|
||||
}
|
||||
|
||||
func isCI() bool {
|
||||
return os.Getenv("CI") != ""
|
||||
}
|
||||
|
||||
func wd() string {
|
||||
p, err := os.Getwd()
|
||||
func git(args ...string) (string, error) {
|
||||
cmd, _ := hexec.SafeCommand("git", args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return "", fmt.Errorf("git failed: %q: %q (%q)", err, out, args)
|
||||
}
|
||||
return p
|
||||
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func logf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, format, args...)
|
||||
}
|
||||
|
||||
func logln(args ...interface{}) {
|
||||
fmt.Fprintln(os.Stderr, args...)
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
options:
|
||||
source:
|
||||
required: true
|
||||
source-type:
|
||||
source-tag:
|
||||
source-branch:
|
||||
nodejs-target:
|
||||
required: true
|
||||
@@ -1,332 +0,0 @@
|
||||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
||||
#
|
||||
# Modified by Anthony Fok on 2018-10-01 to add support for ppc64el and s390x
|
||||
#
|
||||
# Copyright (C) 2015-2017 Canonical Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""The nodejs plugin is useful for node/npm based parts.
|
||||
|
||||
The plugin uses node to install dependencies from `package.json`. It
|
||||
also sets up binaries defined in `package.json` into the `PATH`.
|
||||
|
||||
This plugin uses the common plugin keywords as well as those for "sources".
|
||||
For more information check the 'plugins' topic for the former and the
|
||||
'sources' topic for the latter.
|
||||
|
||||
Additionally, this plugin uses the following plugin-specific keywords:
|
||||
|
||||
- node-packages:
|
||||
(list)
|
||||
A list of dependencies to fetch using npm.
|
||||
- node-engine:
|
||||
(string)
|
||||
The version of nodejs you want the snap to run on.
|
||||
- npm-run:
|
||||
(list)
|
||||
A list of targets to `npm run`.
|
||||
These targets will be run in order, after `npm install`
|
||||
- npm-flags:
|
||||
(list)
|
||||
A list of flags for npm.
|
||||
- node-package-manager
|
||||
(string; default: npm)
|
||||
The language package manager to use to drive installation
|
||||
of node packages. Can be either `npm` (default) or `yarn`.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import contextlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import snapcraft
|
||||
from snapcraft import sources
|
||||
from snapcraft.file_utils import link_or_copy_tree
|
||||
from snapcraft.internal import errors
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_NODEJS_BASE = "node-v{version}-linux-{arch}"
|
||||
_NODEJS_VERSION = "12.18.4"
|
||||
_NODEJS_TMPL = "https://nodejs.org/dist/v{version}/{base}.tar.gz"
|
||||
_NODEJS_ARCHES = {"i386": "x86", "amd64": "x64", "armhf": "armv7l", "arm64": "arm64", "ppc64el": "ppc64le", "s390x": "s390x"}
|
||||
_YARN_URL = "https://yarnpkg.com/latest.tar.gz"
|
||||
|
||||
|
||||
class NodePlugin(snapcraft.BasePlugin):
|
||||
@classmethod
|
||||
def schema(cls):
|
||||
schema = super().schema()
|
||||
|
||||
schema["properties"]["node-packages"] = {
|
||||
"type": "array",
|
||||
"minitems": 1,
|
||||
"uniqueItems": True,
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
}
|
||||
schema["properties"]["node-engine"] = {
|
||||
"type": "string",
|
||||
"default": _NODEJS_VERSION,
|
||||
}
|
||||
schema["properties"]["node-package-manager"] = {
|
||||
"type": "string",
|
||||
"default": "npm",
|
||||
"enum": ["npm", "yarn"],
|
||||
}
|
||||
schema["properties"]["npm-run"] = {
|
||||
"type": "array",
|
||||
"minitems": 1,
|
||||
"uniqueItems": False,
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
}
|
||||
schema["properties"]["npm-flags"] = {
|
||||
"type": "array",
|
||||
"minitems": 1,
|
||||
"uniqueItems": False,
|
||||
"items": {"type": "string"},
|
||||
"default": [],
|
||||
}
|
||||
|
||||
if "required" in schema:
|
||||
del schema["required"]
|
||||
|
||||
return schema
|
||||
|
||||
@classmethod
|
||||
def get_build_properties(cls):
|
||||
# Inform Snapcraft of the properties associated with building. If these
|
||||
# change in the YAML Snapcraft will consider the build step dirty.
|
||||
return ["node-packages", "npm-run", "npm-flags"]
|
||||
|
||||
@classmethod
|
||||
def get_pull_properties(cls):
|
||||
# Inform Snapcraft of the properties associated with pulling. If these
|
||||
# change in the YAML Snapcraft will consider the build step dirty.
|
||||
return ["node-engine", "node-package-manager"]
|
||||
|
||||
@property
|
||||
def _nodejs_tar(self):
|
||||
if self._nodejs_tar_handle is None:
|
||||
self._nodejs_tar_handle = sources.Tar(
|
||||
self._nodejs_release_uri, self._npm_dir
|
||||
)
|
||||
return self._nodejs_tar_handle
|
||||
|
||||
@property
|
||||
def _yarn_tar(self):
|
||||
if self._yarn_tar_handle is None:
|
||||
self._yarn_tar_handle = sources.Tar(_YARN_URL, self._npm_dir)
|
||||
return self._yarn_tar_handle
|
||||
|
||||
def __init__(self, name, options, project):
|
||||
super().__init__(name, options, project)
|
||||
self._source_package_json = os.path.join(
|
||||
os.path.abspath(self.options.source), "package.json"
|
||||
)
|
||||
self._npm_dir = os.path.join(self.partdir, "npm")
|
||||
self._manifest = collections.OrderedDict()
|
||||
self._nodejs_release_uri = get_nodejs_release(
|
||||
self.options.node_engine, self.project.deb_arch
|
||||
)
|
||||
self._nodejs_tar_handle = None
|
||||
self._yarn_tar_handle = None
|
||||
|
||||
def pull(self):
|
||||
super().pull()
|
||||
os.makedirs(self._npm_dir, exist_ok=True)
|
||||
self._nodejs_tar.download()
|
||||
if self.options.node_package_manager == "yarn":
|
||||
self._yarn_tar.download()
|
||||
# do the install in the pull phase to download all dependencies.
|
||||
if self.options.node_package_manager == "npm":
|
||||
self._npm_install(rootdir=self.sourcedir)
|
||||
else:
|
||||
self._yarn_install(rootdir=self.sourcedir)
|
||||
|
||||
def clean_pull(self):
|
||||
super().clean_pull()
|
||||
|
||||
# Remove the npm directory (if any)
|
||||
if os.path.exists(self._npm_dir):
|
||||
shutil.rmtree(self._npm_dir)
|
||||
|
||||
def build(self):
|
||||
super().build()
|
||||
if self.options.node_package_manager == "npm":
|
||||
installed_node_packages = self._npm_install(rootdir=self.builddir)
|
||||
# Copy the content of the symlink to the build directory
|
||||
# LP: #1702661
|
||||
modules_dir = os.path.join(self.installdir, "lib", "node_modules")
|
||||
_copy_symlinked_content(modules_dir)
|
||||
else:
|
||||
installed_node_packages = self._yarn_install(rootdir=self.builddir)
|
||||
lock_file_path = os.path.join(self.sourcedir, "yarn.lock")
|
||||
if os.path.isfile(lock_file_path):
|
||||
with open(lock_file_path) as lock_file:
|
||||
self._manifest["yarn-lock-contents"] = lock_file.read()
|
||||
|
||||
self._manifest["node-packages"] = [
|
||||
"{}={}".format(name, installed_node_packages[name])
|
||||
for name in installed_node_packages
|
||||
]
|
||||
|
||||
def _npm_install(self, rootdir):
|
||||
self._nodejs_tar.provision(
|
||||
self.installdir, clean_target=False, keep_tarball=True
|
||||
)
|
||||
npm_cmd = ["npm"] + self.options.npm_flags
|
||||
npm_install = npm_cmd + ["--cache-min=Infinity", "install"]
|
||||
for pkg in self.options.node_packages:
|
||||
self.run(npm_install + ["--global"] + [pkg], cwd=rootdir)
|
||||
if os.path.exists(os.path.join(rootdir, "package.json")):
|
||||
self.run(npm_install, cwd=rootdir)
|
||||
self.run(npm_install + ["--global"], cwd=rootdir)
|
||||
for target in self.options.npm_run:
|
||||
self.run(npm_cmd + ["run", target], cwd=rootdir)
|
||||
return self._get_installed_node_packages("npm", self.installdir)
|
||||
|
||||
def _yarn_install(self, rootdir):
|
||||
self._nodejs_tar.provision(
|
||||
self.installdir, clean_target=False, keep_tarball=True
|
||||
)
|
||||
self._yarn_tar.provision(self._npm_dir, clean_target=False, keep_tarball=True)
|
||||
yarn_cmd = [os.path.join(self._npm_dir, "bin", "yarn")]
|
||||
yarn_cmd.extend(self.options.npm_flags)
|
||||
if "http_proxy" in os.environ:
|
||||
yarn_cmd.extend(["--proxy", os.environ["http_proxy"]])
|
||||
if "https_proxy" in os.environ:
|
||||
yarn_cmd.extend(["--https-proxy", os.environ["https_proxy"]])
|
||||
flags = []
|
||||
if rootdir == self.builddir:
|
||||
yarn_add = yarn_cmd + ["global", "add"]
|
||||
flags.extend(
|
||||
[
|
||||
"--offline",
|
||||
"--prod",
|
||||
"--global-folder",
|
||||
self.installdir,
|
||||
"--prefix",
|
||||
self.installdir,
|
||||
]
|
||||
)
|
||||
else:
|
||||
yarn_add = yarn_cmd + ["add"]
|
||||
for pkg in self.options.node_packages:
|
||||
self.run(yarn_add + [pkg] + flags, cwd=rootdir)
|
||||
|
||||
# local packages need to be added as if they were remote, we
|
||||
# remove the local package.json so `yarn add` doesn't pollute it.
|
||||
if os.path.exists(self._source_package_json):
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
os.unlink(os.path.join(rootdir, "package.json"))
|
||||
shutil.copy(
|
||||
self._source_package_json, os.path.join(rootdir, "package.json")
|
||||
)
|
||||
self.run(yarn_add + ["file:{}".format(rootdir)] + flags, cwd=rootdir)
|
||||
|
||||
# npm run would require to bring back package.json
|
||||
if self.options.npm_run and os.path.exists(self._source_package_json):
|
||||
# The current package.json is the yarn prefilled one.
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
os.unlink(os.path.join(rootdir, "package.json"))
|
||||
os.link(self._source_package_json, os.path.join(rootdir, "package.json"))
|
||||
for target in self.options.npm_run:
|
||||
self.run(
|
||||
yarn_cmd + ["run", target],
|
||||
cwd=rootdir,
|
||||
env=self._build_environment(rootdir),
|
||||
)
|
||||
return self._get_installed_node_packages("npm", self.installdir)
|
||||
|
||||
def _get_installed_node_packages(self, package_manager, cwd):
|
||||
try:
|
||||
output = self.run_output(
|
||||
[package_manager, "ls", "--global", "--json"], cwd=cwd
|
||||
)
|
||||
except subprocess.CalledProcessError as error:
|
||||
# XXX When dependencies have missing dependencies, an error like
|
||||
# this is printed to stderr:
|
||||
# npm ERR! peer dep missing: glob@*, required by glob-promise@3.1.0
|
||||
# retcode is not 0, which raises an exception.
|
||||
output = error.output.decode(sys.getfilesystemencoding()).strip()
|
||||
packages = collections.OrderedDict()
|
||||
dependencies = json.loads(output, object_pairs_hook=collections.OrderedDict)[
|
||||
"dependencies"
|
||||
]
|
||||
while dependencies:
|
||||
key, value = dependencies.popitem(last=False)
|
||||
# XXX Just as above, dependencies without version are the ones
|
||||
# missing.
|
||||
if "version" in value:
|
||||
packages[key] = value["version"]
|
||||
if "dependencies" in value:
|
||||
dependencies.update(value["dependencies"])
|
||||
return packages
|
||||
|
||||
def get_manifest(self):
|
||||
return self._manifest
|
||||
|
||||
def _build_environment(self, rootdir):
|
||||
env = os.environ.copy()
|
||||
if rootdir.endswith("src"):
|
||||
hidden_path = os.path.join(rootdir, "node_modules", ".bin")
|
||||
if env.get("PATH"):
|
||||
new_path = "{}:{}".format(hidden_path, env.get("PATH"))
|
||||
else:
|
||||
new_path = hidden_path
|
||||
env["PATH"] = new_path
|
||||
return env
|
||||
|
||||
|
||||
def _get_nodejs_base(node_engine, machine):
|
||||
if machine not in _NODEJS_ARCHES:
|
||||
raise errors.SnapcraftEnvironmentError(
|
||||
"architecture not supported ({})".format(machine)
|
||||
)
|
||||
return _NODEJS_BASE.format(version=node_engine, arch=_NODEJS_ARCHES[machine])
|
||||
|
||||
|
||||
def get_nodejs_release(node_engine, arch):
|
||||
return _NODEJS_TMPL.format(
|
||||
version=node_engine, base=_get_nodejs_base(node_engine, arch)
|
||||
)
|
||||
|
||||
|
||||
def _copy_symlinked_content(modules_dir):
|
||||
"""Copy symlinked content.
|
||||
|
||||
When running newer versions of npm, symlinks to the local tree are
|
||||
created from the part's installdir to the root of the builddir of the
|
||||
part (this only affects some build configurations in some projects)
|
||||
which is valid when running from the context of the part but invalid
|
||||
as soon as the artifacts migrate across the steps,
|
||||
i.e.; stage and prime.
|
||||
|
||||
If modules_dir does not exist we simply return.
|
||||
"""
|
||||
if not os.path.exists(modules_dir):
|
||||
return
|
||||
modules = [os.path.join(modules_dir, d) for d in os.listdir(modules_dir)]
|
||||
symlinks = [l for l in modules if os.path.islink(l)]
|
||||
for link_path in symlinks:
|
||||
link_target = os.path.realpath(link_path)
|
||||
os.unlink(link_path)
|
||||
link_or_copy_tree(link_target, link_path)
|
||||
+1
-1
@@ -53,7 +53,7 @@ parts:
|
||||
|
||||
hugo:
|
||||
plugin: nil
|
||||
build-snaps: [go/1.18/stable]
|
||||
build-snaps: [go/1.19/stable]
|
||||
source: .
|
||||
override-build: |
|
||||
set -ex
|
||||
|
||||
+12
-8
@@ -153,7 +153,7 @@ func newTemplateExec(d *deps.Deps) (*templateExec, error) {
|
||||
Deps: d,
|
||||
layoutHandler: output.NewLayoutHandler(),
|
||||
layoutsFs: d.BaseFs.Layouts.Fs,
|
||||
layoutTemplateCache: make(map[layoutCacheKey]tpl.Template),
|
||||
layoutTemplateCache: make(map[layoutCacheKey]layoutCacheEntry),
|
||||
|
||||
templateUsageTracker: templateUsageTracker,
|
||||
}
|
||||
@@ -328,7 +328,7 @@ type templateHandler struct {
|
||||
|
||||
layoutHandler *output.LayoutHandler
|
||||
|
||||
layoutTemplateCache map[layoutCacheKey]tpl.Template
|
||||
layoutTemplateCache map[layoutCacheKey]layoutCacheEntry
|
||||
layoutTemplateCacheMu sync.RWMutex
|
||||
|
||||
*deps.Deps
|
||||
@@ -357,6 +357,12 @@ type templateHandler struct {
|
||||
templateUsageTrackerMu sync.Mutex
|
||||
}
|
||||
|
||||
type layoutCacheEntry struct {
|
||||
found bool
|
||||
templ tpl.Template
|
||||
err error
|
||||
}
|
||||
|
||||
// AddTemplate parses and adds a template to the collection.
|
||||
// Templates with name prefixed with "_text" will be handled as plain
|
||||
// text templates.
|
||||
@@ -382,7 +388,7 @@ func (t *templateHandler) LookupLayout(d output.LayoutDescriptor, f output.Forma
|
||||
t.layoutTemplateCacheMu.RLock()
|
||||
if cacheVal, found := t.layoutTemplateCache[key]; found {
|
||||
t.layoutTemplateCacheMu.RUnlock()
|
||||
return cacheVal, true, nil
|
||||
return cacheVal.templ, cacheVal.found, cacheVal.err
|
||||
}
|
||||
t.layoutTemplateCacheMu.RUnlock()
|
||||
|
||||
@@ -390,12 +396,10 @@ func (t *templateHandler) LookupLayout(d output.LayoutDescriptor, f output.Forma
|
||||
defer t.layoutTemplateCacheMu.Unlock()
|
||||
|
||||
templ, found, err := t.findLayout(d, f)
|
||||
if err == nil && found {
|
||||
t.layoutTemplateCache[key] = templ
|
||||
return templ, true, nil
|
||||
}
|
||||
cacheVal := layoutCacheEntry{found: found, templ: templ, err: err}
|
||||
t.layoutTemplateCache[key] = cacheVal
|
||||
return cacheVal.templ, cacheVal.found, cacheVal.err
|
||||
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// This currently only applies to shortcodes and what we get here is the
|
||||
|
||||
@@ -180,7 +180,7 @@ a = "b"
|
||||
|
||||
converted, err := ns.Remarshal("toml", input)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(converted, qt.Equals, "[params]\n [params.variables]\n a = 'b'\n\n\n")
|
||||
c.Assert(converted, qt.Equals, "[params]\n [params.variables]\n a = 'b'\n")
|
||||
})
|
||||
|
||||
c.Run("Map input", func(c *qt.C) {
|
||||
|
||||
@@ -24,16 +24,24 @@ import (
|
||||
"github.com/gohugoio/hugo/transform"
|
||||
)
|
||||
|
||||
const warnMessage = `"head" or "body" tag is required in html to append livereload script. ` +
|
||||
"As a fallback, Hugo injects it somewhere but it might not work properly."
|
||||
|
||||
var warnScript = fmt.Sprintf(`<script data-no-instant defer>console.warn('%s');</script>`, warnMessage)
|
||||
|
||||
type tag struct {
|
||||
markup []byte
|
||||
appendScript bool
|
||||
warnRequired bool
|
||||
}
|
||||
|
||||
var tags = []tag{
|
||||
{markup: []byte("<head>"), appendScript: true},
|
||||
{markup: []byte("<HEAD>"), appendScript: true},
|
||||
{markup: []byte("<head"), appendScript: true},
|
||||
{markup: []byte("<HEAD"), appendScript: true},
|
||||
{markup: []byte("</body>")},
|
||||
{markup: []byte("</BODY>")},
|
||||
{markup: []byte("<html"), appendScript: true, warnRequired: true},
|
||||
{markup: []byte("<HTML"), appendScript: true, warnRequired: true},
|
||||
}
|
||||
|
||||
// New creates a function that can be used
|
||||
@@ -64,15 +72,19 @@ func New(baseURL url.URL) transform.Transformer {
|
||||
copy(c, b)
|
||||
|
||||
if idx == -1 {
|
||||
_, err := ft.To().Write(c)
|
||||
return err
|
||||
idx = len(b)
|
||||
match = tag{warnRequired: true}
|
||||
}
|
||||
|
||||
script := []byte(fmt.Sprintf(`<script src="%s" data-no-instant defer></script>`, html.EscapeString(src)))
|
||||
|
||||
i := idx
|
||||
if match.appendScript {
|
||||
i += len(match.markup)
|
||||
i += bytes.Index(b[i:], []byte(">")) + 1
|
||||
}
|
||||
|
||||
if match.warnRequired {
|
||||
script = append(script, []byte(warnScript)...)
|
||||
}
|
||||
|
||||
c = append(c[:i], append(script, c[i:]...)...)
|
||||
|
||||
@@ -58,7 +58,15 @@ func TestLiveReloadInject(t *testing.T) {
|
||||
c.Assert(apply("foo</BODY>"), qt.Equals, "foo"+expectBase+"</BODY>")
|
||||
})
|
||||
|
||||
c.Run("Html upper", func(c *qt.C) {
|
||||
c.Assert(apply("<html>foo"), qt.Equals, "<html>"+expectBase+warnScript+"foo")
|
||||
})
|
||||
|
||||
c.Run("Html upper with attr", func(c *qt.C) {
|
||||
c.Assert(apply(`<html lang="en">foo`), qt.Equals, `<html lang="en">`+expectBase+warnScript+"foo")
|
||||
})
|
||||
|
||||
c.Run("No match", func(c *qt.C) {
|
||||
c.Assert(apply("<h1>No match</h1>"), qt.Equals, "<h1>No match</h1>")
|
||||
c.Assert(apply("<h1>No match</h1>"), qt.Equals, "<h1>No match</h1>"+expectBase+warnScript)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user