diff --git a/go.mod b/go.mod index 383f0b73..594d508b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/DelineaXPM/dsv-sdk-go/v2 v2.1.2 github.com/magefile/mage v1.15.0 github.com/pterm/pterm v0.12.79 - github.com/sheldonhull/magetools v1.0.1 + github.com/sheldonhull/magetools v1.0.2 ) require ( @@ -29,7 +29,7 @@ require ( github.com/vmihailenco/tagparser v0.1.2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/protobuf v1.33.0 // indirect - mvdan.cc/sh/v3 v3.6.0 // indirect + mvdan.cc/sh/v3 v3.7.0 // indirect ) require ( @@ -42,7 +42,7 @@ require ( github.com/aws/aws-sdk-go v1.50.3 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.0 // indirect - github.com/bitfield/script v0.22.0 // indirect + github.com/bitfield/script v0.22.1 // indirect github.com/containerd/console v1.0.3 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.13.0 // indirect @@ -64,13 +64,13 @@ require ( github.com/hashicorp/terraform-plugin-sdk v1.17.2 github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/itchyny/gojq v0.12.12 // indirect + github.com/itchyny/gojq v0.12.13 // indirect github.com/itchyny/timefmt-go v0.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.15.11 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/cli v1.1.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -90,7 +90,7 @@ require ( github.com/ztrue/tracerr v0.4.0 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/crypto v0.21.0 // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.23.0 // indirect; indirect // indirect golang.org/x/oauth2 v0.7.0 // indirect golang.org/x/sys v0.18.0 // indirect diff --git a/go.sum b/go.sum index bcd230d3..a47fbf71 100644 --- a/go.sum +++ b/go.sum @@ -258,6 +258,8 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitfield/script v0.22.0 h1:LA7QHuEsXMPD52YLtxWrlqCCy+9FOpzNYfsRHC5Gsrc= github.com/bitfield/script v0.22.0/go.mod h1:ms4w+9B8f2/W0mbsgWDVTtl7K94bYuZc3AunnJC4Ebs= +github.com/bitfield/script v0.22.1 h1:DphxoC5ssYciwd0ZS+N0Xae46geAD/0mVWh6a2NUxM4= +github.com/bitfield/script v0.22.1/go.mod h1:fv+6x4OzVsRs6qAlc7wiGq8fq1b5orhtQdtW0dwjUHI= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -486,6 +488,8 @@ github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/itchyny/gojq v0.12.12 h1:x+xGI9BXqKoJQZkr95ibpe3cdrTbY8D9lonrK433rcA= github.com/itchyny/gojq v0.12.12/go.mod h1:j+3sVkjxwd7A7Z5jrbKibgOLn0ZfLWkV+Awxr/pyzJE= +github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= +github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= @@ -543,6 +547,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -613,6 +619,8 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sheldonhull/magetools v1.0.1 h1:EzTRk0JUNl2MijssyrA2Cx+J/7SyjcTgXQmsMccDpaI= github.com/sheldonhull/magetools v1.0.1/go.mod h1:K5W5pCBkaBlDqnheO2mSWZ8s9t8IOsKehxvj70g8kpg= +github.com/sheldonhull/magetools v1.0.2 h1:d6+jt0sugXvIMl4eWf2H7dAVAaSd5sD3nV0pWE9eEyg= +github.com/sheldonhull/magetools v1.0.2/go.mod h1:+SSxBtmxx4p07Zequ/wc+v88rGTnKwRtNssMkj1ZaAU= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -739,6 +747,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -914,6 +924,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1258,6 +1269,8 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0= mvdan.cc/sh/v3 v3.6.0 h1:gtva4EXJ0dFNvl5bHjcUEvws+KRcDslT8VKheTYkbGU= mvdan.cc/sh/v3 v3.6.0/go.mod h1:U4mhtBLZ32iWhif5/lD+ygy1zrgaQhUu+XFy7C8+TTA= +mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= +mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/vendor/github.com/bitfield/script/README.md b/vendor/github.com/bitfield/script/README.md index b57324e7..a06a70c1 100644 --- a/vendor/github.com/bitfield/script/README.md +++ b/vendor/github.com/bitfield/script/README.md @@ -313,7 +313,7 @@ Filters are methods on an existing pipe that also return a pipe, allowing you to | [`SHA256Sums`](https://pkg.go.dev/github.com/bitfield/script#Pipe.SHA256Sums) | SHA-256 hashes of each listed file | | [`Tee`](https://pkg.go.dev/github.com/bitfield/script#Pipe.Tee) | input copied to supplied writers | -Note that filters run concurrently, rather than producing nothing until each stage has fully read its input. This is convenient for executing long-running comands, for example. If you do need to wait for the pipeline to complete, call [`Wait`](https://pkg.go.dev/github.com/bitfield/script#Pipe.Wait). +Note that filters run concurrently, rather than producing nothing until each stage has fully read its input. This is convenient for executing long-running commands, for example. If you do need to wait for the pipeline to complete, call [`Wait`](https://pkg.go.dev/github.com/bitfield/script#Pipe.Wait). ## Sinks diff --git a/vendor/github.com/bitfield/script/script.go b/vendor/github.com/bitfield/script/script.go index da7e2fe5..c471f74b 100644 --- a/vendor/github.com/bitfield/script/script.go +++ b/vendor/github.com/bitfield/script/script.go @@ -104,10 +104,10 @@ func FindFiles(dir string) *Pipe { return Slice(paths) } -// Get creates a pipe that makes an HTTP GET request to URL, and produces the +// Get creates a pipe that makes an HTTP GET request to url, and produces the // response. See [Pipe.Do] for how the HTTP response status is interpreted. -func Get(URL string) *Pipe { - return NewPipe().Get(URL) +func Get(url string) *Pipe { + return NewPipe().Get(url) } // IfExists tests whether path exists, and creates a pipe whose error status @@ -169,11 +169,11 @@ func NewPipe() *Pipe { } } -// Post creates a pipe that makes an HTTP POST request to URL, with an empty +// Post creates a pipe that makes an HTTP POST request to url, with an empty // body, and produces the response. See [Pipe.Do] for how the HTTP response // status is interpreted. -func Post(URL string) *Pipe { - return NewPipe().Post(URL) +func Post(url string) *Pipe { + return NewPipe().Post(url) } // Slice creates a pipe containing each element of s, one per line. @@ -514,7 +514,8 @@ func (p *Pipe) FilterScan(filter func(string, io.Writer)) *Pipe { // First produces only the first n lines of the pipe's contents, or all the // lines if there are less than n. If n is zero or negative, there is no output -// at all. +// at all. When n lines have been produced, First stops reading its input and +// sends EOF to its output. func (p *Pipe) First(n int) *Pipe { if p.Error() != nil { return p @@ -522,13 +523,15 @@ func (p *Pipe) First(n int) *Pipe { if n <= 0 { return NewPipe() } - i := 0 - return p.FilterScan(func(line string, w io.Writer) { - if i >= n { - return + return p.Filter(func(r io.Reader, w io.Writer) error { + scanner := newScanner(r) + for i := 0; i < n && scanner.Scan(); i++ { + _, err := fmt.Fprintln(w, scanner.Text()) + if err != nil { + return err + } } - fmt.Fprintln(w, line) - i++ + return scanner.Err() }) } @@ -584,11 +587,11 @@ func (p *Pipe) Freq() *Pipe { }) } -// Get makes an HTTP GET request to URL, sending the contents of the pipe as +// Get makes an HTTP GET request to url, sending the contents of the pipe as // the request body, and produces the server's response. See [Pipe.Do] for how // the HTTP response status is interpreted. -func (p *Pipe) Get(URL string) *Pipe { - req, err := http.NewRequest(http.MethodGet, URL, p.Reader) +func (p *Pipe) Get(url string) *Pipe { + req, err := http.NewRequest(http.MethodGet, url, p.Reader) if err != nil { return p.WithError(err) } @@ -693,11 +696,11 @@ func (p *Pipe) MatchRegexp(re *regexp.Regexp) *Pipe { }) } -// Post makes an HTTP POST request to URL, using the contents of the pipe as +// Post makes an HTTP POST request to url, using the contents of the pipe as // the request body, and produces the server's response. See [Pipe.Do] for how // the HTTP response status is interpreted. -func (p *Pipe) Post(URL string) *Pipe { - req, err := http.NewRequest(http.MethodPost, URL, p.Reader) +func (p *Pipe) Post(url string) *Pipe { + req, err := http.NewRequest(http.MethodPost, url, p.Reader) if err != nil { return p.WithError(err) } @@ -731,8 +734,8 @@ func (p *Pipe) Replace(search, replace string) *Pipe { } // ReplaceRegexp replaces all matches of the compiled regexp re with the string -// re. $x variables in the replace string are interpreted as by -// [regexp.Expand]; for example, $1 represents the text of the first submatch. +// replace. $x variables in the replace string are interpreted as by +// [regexp#Regexp.Expand]; for example, $1 represents the text of the first submatch. func (p *Pipe) ReplaceRegexp(re *regexp.Regexp, replace string) *Pipe { return p.FilterLine(func(line string) string { return re.ReplaceAllString(line, replace) @@ -849,7 +852,7 @@ func (p *Pipe) Tee(writers ...io.Writer) *Pipe { // useful for waiting until concurrent filters have completed (see // [Pipe.Filter]). func (p *Pipe) Wait() { - _, err := io.ReadAll(p) + _, err := io.Copy(io.Discard, p) if err != nil { p.SetError(err) } @@ -905,7 +908,7 @@ func (p *Pipe) writeOrAppendFile(path string, mode int) (int64, error) { if p.Error() != nil { return 0, p.Error() } - out, err := os.OpenFile(path, mode, 0666) + out, err := os.OpenFile(path, mode, 0o666) if err != nil { p.SetError(err) return 0, err @@ -942,7 +945,7 @@ func (ra ReadAutoCloser) Close() error { if ra.r == nil { return nil } - return ra.r.(io.Closer).Close() + return ra.r.Close() } // Read reads up to len(b) bytes from ra's reader into b. It returns the number diff --git a/vendor/github.com/itchyny/gojq/.dockerignore b/vendor/github.com/itchyny/gojq/.dockerignore index c8e02dc8..ac001636 100644 --- a/vendor/github.com/itchyny/gojq/.dockerignore +++ b/vendor/github.com/itchyny/gojq/.dockerignore @@ -6,4 +6,12 @@ *.exe *.test *.out -/.github/ +*.md +*.y +**/*.jq +**/*.json +**/*.yaml +**/*_test.go +.github +_gojq +_tools diff --git a/vendor/github.com/itchyny/gojq/CHANGELOG.md b/vendor/github.com/itchyny/gojq/CHANGELOG.md index 65e605fb..8477cd38 100644 --- a/vendor/github.com/itchyny/gojq/CHANGELOG.md +++ b/vendor/github.com/itchyny/gojq/CHANGELOG.md @@ -1,4 +1,9 @@ # Changelog +## [v0.12.13](https://github.com/itchyny/gojq/compare/v0.12.12..v0.12.13) (2023-06-01) +* implement `@urid` format string to decode URI values +* fix functions returning arrays not to emit nil slices (`flatten`, `group_by`, + `unique`, `unique_by`, `nth`, `indices`, `path`, and `modulemeta.deps`) + ## [v0.12.12](https://github.com/itchyny/gojq/compare/v0.12.11..v0.12.12) (2023-03-01) * fix assignment operator (`=`) with overlapping paths and multiple values (`[[]] | .. = ..`) * fix crash on multiplying large numbers to an empty string (`9223372036854775807 * ""`) diff --git a/vendor/github.com/itchyny/gojq/Dockerfile b/vendor/github.com/itchyny/gojq/Dockerfile index 284ece77..51f8632e 100644 --- a/vendor/github.com/itchyny/gojq/Dockerfile +++ b/vendor/github.com/itchyny/gojq/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19 AS builder +FROM golang:1.20 AS builder WORKDIR /app COPY . . diff --git a/vendor/github.com/itchyny/gojq/README.md b/vendor/github.com/itchyny/gojq/README.md index 6370e440..ca13b2f6 100644 --- a/vendor/github.com/itchyny/gojq/README.md +++ b/vendor/github.com/itchyny/gojq/README.md @@ -5,7 +5,7 @@ [![release](https://img.shields.io/github/release/itchyny/gojq/all.svg)](https://github.com/itchyny/gojq/releases) [![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/gojq)](https://pkg.go.dev/github.com/itchyny/gojq) -### Pure Go implementation of [jq](https://github.com/stedolan/jq) +### Pure Go implementation of [jq](https://github.com/jqlang/jq) This is an implementation of jq command written in Go language. You can also embed gojq as a library to your Go products. @@ -77,10 +77,10 @@ docker run -i --rm ghcr.io/itchyny/gojq - gojq implements nice error messages for invalid query and JSON input. The error message of jq is sometimes difficult to tell where to fix the query. - gojq does not keep the order of object keys. I understand this might cause problems for some scripts but basically, we should not rely on the order of object keys. Due to this limitation, gojq does not have `keys_unsorted` function and `--sort-keys` (`-S`) option. I would implement when ordered map is implemented in the standard library of Go but I'm less motivated. - gojq supports arbitrary-precision integer calculation while jq does not; jq loses the precision of large integers when calculation is involved. Note that even with gojq, all mathematical functions, including `floor` and `round`, convert integers to floating-point numbers; only addition, subtraction, multiplication, modulo, and division operators (when divisible) keep the integer precision. To calculate floor division of integers without losing the precision, use `def idivide($n): (. - . % $n) / $n;`. To round down floating-point numbers to integers, use `def ifloor: floor | tostring | tonumber;`, but note that this function does not work with large floating-point numbers and also loses the precision of large integers. -- gojq fixes various bugs of jq. gojq correctly deletes elements of arrays by `|= empty` ([jq#2051](https://github.com/stedolan/jq/issues/2051)). gojq fixes `try`/`catch` handling ([jq#1859](https://github.com/stedolan/jq/issues/1859), [jq#1885](https://github.com/stedolan/jq/issues/1885), [jq#2140](https://github.com/stedolan/jq/issues/2140)). gojq fixes `nth/2` to output nothing when the count is equal to or larger than the stream size ([jq#1867](https://github.com/stedolan/jq/issues/1867)). gojq consistently counts by characters (not by bytes) in `index`, `rindex`, and `indices` functions; `"12345" | .[index("3"):]` results in `"345"` ([jq#1430](https://github.com/stedolan/jq/issues/1430), [jq#1624](https://github.com/stedolan/jq/issues/1624)). gojq handles overlapping occurrence differently in `rindex` and `indices`; `"ababa" | [rindex("aba"), indices("aba")]` results in `[2,[0,2]]` ([jq#2433](https://github.com/stedolan/jq/issues/2433)). gojq supports string indexing; `"abcde"[2]` ([jq#1520](https://github.com/stedolan/jq/issues/1520)). gojq accepts indexing query `.e0` ([jq#1526](https://github.com/stedolan/jq/issues/1526), [jq#1651](https://github.com/stedolan/jq/issues/1651)), and allows `gsub` to handle patterns including `"^"` ([jq#2148](https://github.com/stedolan/jq/issues/2148)). gojq improves variable lexer to allow using keywords for variable names, especially in binding patterns, also disallows spaces after `$` ([jq#526](https://github.com/stedolan/jq/issues/526)). gojq fixes handling files with no newline characters at the end ([jq#2374](https://github.com/stedolan/jq/issues/2374)). -- gojq truncates down floating-point numbers on indexing (`[0] | .[0.5]` results in `0` not `null`), and slicing (`[0,1,2] | .[0.5:1.5]` results in `[0]` not `[0,1]`). gojq parses unary operators with higher precedence than variable binding (`[-1 as $x | 1,$x]` results in `[1,-1]` not `[-1,-1]`). gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/stedolan/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/stedolan/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/stedolan/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/stedolan/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/stedolan/jq/issues/929), [jq#2195](https://github.com/stedolan/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/stedolan/jq/issues/1912)). gojq supports nanoseconds in date and time functions. +- gojq fixes various bugs of jq. gojq correctly deletes elements of arrays by `|= empty` ([jq#2051](https://github.com/jqlang/jq/issues/2051)). gojq fixes `try`/`catch` handling ([jq#1859](https://github.com/jqlang/jq/issues/1859), [jq#1885](https://github.com/jqlang/jq/issues/1885), [jq#2140](https://github.com/jqlang/jq/issues/2140)). gojq fixes `nth/2` to output nothing when the count is equal to or larger than the stream size ([jq#1867](https://github.com/jqlang/jq/issues/1867)). gojq consistently counts by characters (not by bytes) in `index`, `rindex`, and `indices` functions; `"12345" | .[index("3"):]` results in `"345"` ([jq#1430](https://github.com/jqlang/jq/issues/1430), [jq#1624](https://github.com/jqlang/jq/issues/1624)). gojq handles overlapping occurrence differently in `rindex` and `indices`; `"ababa" | [rindex("aba"), indices("aba")]` results in `[2,[0,2]]` ([jq#2433](https://github.com/jqlang/jq/issues/2433)). gojq supports string indexing; `"abcde"[2]` ([jq#1520](https://github.com/jqlang/jq/issues/1520)). gojq accepts indexing query `.e0` ([jq#1526](https://github.com/jqlang/jq/issues/1526), [jq#1651](https://github.com/jqlang/jq/issues/1651)), and allows `gsub` to handle patterns including `"^"` ([jq#2148](https://github.com/jqlang/jq/issues/2148)). gojq improves variable lexer to allow using keywords for variable names, especially in binding patterns, also disallows spaces after `$` ([jq#526](https://github.com/jqlang/jq/issues/526)). gojq fixes handling files with no newline characters at the end ([jq#2374](https://github.com/jqlang/jq/issues/2374)). +- gojq truncates down floating-point numbers on indexing (`[0] | .[0.5]` results in `0` not `null`), and slicing (`[0,1,2] | .[0.5:1.5]` results in `[0]` not `[0,1]`). gojq parses unary operators with higher precedence than variable binding (`[-1 as $x | 1,$x]` results in `[1,-1]` not `[-1,-1]`). gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/jqlang/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/jqlang/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/jqlang/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/jqlang/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/jqlang/jq/issues/929), [jq#2195](https://github.com/jqlang/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/jqlang/jq/issues/1912)). gojq supports nanoseconds in date and time functions. - gojq does not support some functions intentionally; `get_jq_origin`, `get_prog_origin`, `get_search_list` (unstable, not listed in jq document), `input_line_number`, `$__loc__` (performance issue), `recurse_down` (deprecated in jq). gojq does not support some flags; `--ascii-output, -a` (performance issue), `--seq` (not used commonly), `--sort-keys, -S` (sorts by default because `map[string]any` does not keep the order), `--unbuffered` (unbuffered by default). gojq does not parse JSON extensions supported by jq; `NaN`, `Infinity`, and `[000]`. gojq normalizes floating-point numbers to fit to double-precision floating-point numbers. gojq does not support or behaves differently with some regular expression metacharacters and flags (regular expression engine differences). gojq does not support BOM (`encoding/json` does not support this). gojq disallows using keywords for function names (`def true: .; true` is a confusing query), and module name prefixes in function declarations (using module prefixes like `def m::f: .;` is undocumented). -- gojq supports reading from YAML input (`--yaml-input`) while jq does not. gojq also supports YAML output (`--yaml-output`). +- gojq supports reading from YAML input (`--yaml-input`) while jq does not. gojq also supports YAML output (`--yaml-output`). gojq supports a few filters missing in jq; `scan/2` ([jq#2207](https://github.com/jqlang/jq/pull/2207)), and `@urid` format string ([jq#2261](https://github.com/jqlang/jq/issues/2261)). ### Color configuration The gojq command automatically disables coloring output when the output is not a tty. diff --git a/vendor/github.com/itchyny/gojq/compiler.go b/vendor/github.com/itchyny/gojq/compiler.go index 135387fa..de5f9a10 100644 --- a/vendor/github.com/itchyny/gojq/compiler.go +++ b/vendor/github.com/itchyny/gojq/compiler.go @@ -1172,7 +1172,7 @@ func (c *compiler) funcInput(any, []any) any { func (c *compiler) funcModulemeta(v any, _ []any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"modulemeta", v} + return &func0TypeError{"modulemeta", v} } if c.moduleLoader == nil { return fmt.Errorf("cannot load module: %q", s) @@ -1196,7 +1196,7 @@ func (c *compiler) funcModulemeta(v any, _ []any) any { if meta == nil { meta = make(map[string]any) } - var deps []any + deps := []any{} for _, i := range q.Imports { v := i.Meta.ToValue() if v == nil { @@ -1409,6 +1409,8 @@ func formatToFunc(format string) *Func { return &Func{Name: "_tohtml"} case "@uri": return &Func{Name: "_touri"} + case "@urid": + return &Func{Name: "_tourid"} case "@csv": return &Func{Name: "_tocsv"} case "@tsv": diff --git a/vendor/github.com/itchyny/gojq/error.go b/vendor/github.com/itchyny/gojq/error.go index 695463f3..16865877 100644 --- a/vendor/github.com/itchyny/gojq/error.go +++ b/vendor/github.com/itchyny/gojq/error.go @@ -27,20 +27,20 @@ func (err *expectedArrayError) Error() string { return "expected an array but got: " + typeErrorPreview(err.v) } -type expectedStringError struct { +type iteratorError struct { v any } -func (err *expectedStringError) Error() string { - return "expected a string but got: " + typeErrorPreview(err.v) +func (err *iteratorError) Error() string { + return "cannot iterate over: " + typeErrorPreview(err.v) } -type iteratorError struct { - v any +type arrayIndexNegativeError struct { + v int } -func (err *iteratorError) Error() string { - return "cannot iterate over: " + typeErrorPreview(err.v) +func (err *arrayIndexNegativeError) Error() string { + return "array index should not be negative: " + Preview(err.v) } type arrayIndexTooLargeError struct { @@ -83,13 +83,10 @@ func (err *expectedStartEndError) Error() string { return `expected "start" and "end" for slicing but got: ` + typeErrorPreview(err.v) } -type lengthMismatchError struct { - name string - v, x []any -} +type lengthMismatchError struct{} func (err *lengthMismatchError) Error() string { - return "length mismatch in " + err.name + ": " + typeErrorPreview(err.v) + ", " + typeErrorPreview(err.x) + return "length mismatch" } type inputNotAllowedError struct{} @@ -106,15 +103,63 @@ func (err *funcNotFoundError) Error() string { return "function not defined: " + err.f.Name + "/" + strconv.Itoa(len(err.f.Args)) } -type funcTypeError struct { +type func0TypeError struct { name string v any } -func (err *funcTypeError) Error() string { +func (err *func0TypeError) Error() string { return err.name + " cannot be applied to: " + typeErrorPreview(err.v) } +type func1TypeError struct { + name string + v, w any +} + +func (err *func1TypeError) Error() string { + return err.name + "(" + Preview(err.w) + ") cannot be applied to: " + typeErrorPreview(err.v) +} + +type func2TypeError struct { + name string + v, w, x any +} + +func (err *func2TypeError) Error() string { + return err.name + "(" + Preview(err.w) + "; " + Preview(err.x) + ") cannot be applied to: " + typeErrorPreview(err.v) +} + +type func0WrapError struct { + name string + v any + err error +} + +func (err *func0WrapError) Error() string { + return err.name + " cannot be applied to " + Preview(err.v) + ": " + err.err.Error() +} + +type func1WrapError struct { + name string + v, w any + err error +} + +func (err *func1WrapError) Error() string { + return err.name + "(" + Preview(err.w) + ") cannot be applied to " + Preview(err.v) + ": " + err.err.Error() +} + +type func2WrapError struct { + name string + v, w, x any + err error +} + +func (err *func2WrapError) Error() string { + return err.name + "(" + Preview(err.w) + "; " + Preview(err.x) + ") cannot be applied to " + Preview(err.v) + ": " + err.err.Error() +} + type exitCodeError struct { value any code int @@ -144,28 +189,12 @@ func (err *exitCodeError) IsHaltError() bool { return err.halt } -type containsTypeError struct { - l, r any -} - -func (err *containsTypeError) Error() string { - return "cannot check contains(" + Preview(err.r) + "): " + typeErrorPreview(err.l) -} - -type hasKeyTypeError struct { - l, r any -} - -func (err *hasKeyTypeError) Error() string { - return "cannot check whether " + typeErrorPreview(err.l) + " has a key: " + typeErrorPreview(err.r) -} - type flattenDepthError struct { v float64 } func (err *flattenDepthError) Error() string { - return "flatten depth must not be negative: " + typeErrorPreview(err.v) + return "flatten depth should not be negative: " + Preview(err.v) } type joinTypeError struct { @@ -173,7 +202,13 @@ type joinTypeError struct { } func (err *joinTypeError) Error() string { - return "cannot join: " + typeErrorPreview(err.v) + return "join cannot be applied to an array including: " + typeErrorPreview(err.v) +} + +type timeArrayError struct{} + +func (err *timeArrayError) Error() string { + return "expected an array of 8 numbers" } type unaryTypeError struct { @@ -294,14 +329,6 @@ func (err *invalidPathIterError) Error() string { return "invalid path on iterating against: " + typeErrorPreview(err.v) } -type getpathError struct { - v, path any -} - -func (err *getpathError) Error() string { - return "cannot getpath with " + Preview(err.path) + " against: " + typeErrorPreview(err.v) -} - type queryParseError struct { fname, contents string err error diff --git a/vendor/github.com/itchyny/gojq/execute.go b/vendor/github.com/itchyny/gojq/execute.go index d43ef3e9..dcf9d984 100644 --- a/vendor/github.com/itchyny/gojq/execute.go +++ b/vendor/github.com/itchyny/gojq/execute.go @@ -436,7 +436,7 @@ func (env *env) pathIntact(v any) bool { } func (env *env) poppaths() []any { - var xs []any + xs := []any{} for { p := env.paths.pop().(pathValue) if p.path == nil { diff --git a/vendor/github.com/itchyny/gojq/func.go b/vendor/github.com/itchyny/gojq/func.go index d94a7a47..6e8d1500 100644 --- a/vendor/github.com/itchyny/gojq/func.go +++ b/vendor/github.com/itchyny/gojq/func.go @@ -3,6 +3,7 @@ package gojq import ( "encoding/base64" "encoding/json" + "errors" "fmt" "io" "math" @@ -78,6 +79,7 @@ func init() { "format": argFunc1(funcFormat), "_tohtml": argFunc0(funcToHTML), "_touri": argFunc0(funcToURI), + "_tourid": argFunc0(funcToURId), "_tocsv": argFunc0(funcToCSV), "_totsv": argFunc0(funcToTSV), "_tosh": argFunc0(funcToSh), @@ -234,7 +236,7 @@ func mathFunc(name string, f func(float64) float64) function { return argFunc0(func(v any) any { x, ok := toFloat(v) if !ok { - return &funcTypeError{name, v} + return &func0TypeError{name, v} } return f(x) }) @@ -244,11 +246,11 @@ func mathFunc2(name string, f func(_, _ float64) float64) function { return argFunc2(func(_, x, y any) any { l, ok := toFloat(x) if !ok { - return &funcTypeError{name, x} + return &func0TypeError{name, x} } r, ok := toFloat(y) if !ok { - return &funcTypeError{name, y} + return &func0TypeError{name, y} } return f(l, r) }) @@ -258,15 +260,15 @@ func mathFunc3(name string, f func(_, _, _ float64) float64) function { return argFunc3(func(_, a, b, c any) any { x, ok := toFloat(a) if !ok { - return &funcTypeError{name, a} + return &func0TypeError{name, a} } y, ok := toFloat(b) if !ok { - return &funcTypeError{name, b} + return &func0TypeError{name, b} } z, ok := toFloat(c) if !ok { - return &funcTypeError{name, c} + return &func0TypeError{name, c} } return f(x, y, z) }) @@ -295,14 +297,14 @@ func funcLength(v any) any { case map[string]any: return len(v) default: - return &funcTypeError{"length", v} + return &func0TypeError{"length", v} } } func funcUtf8ByteLength(v any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"utf8bytelength", v} + return &func0TypeError{"utf8bytelength", v} } return len(s) } @@ -322,7 +324,7 @@ func funcKeys(v any) any { } return w default: - return &funcTypeError{"keys", v} + return &func0TypeError{"keys", v} } } @@ -366,7 +368,7 @@ func funcHas(v, x any) any { case nil: return false } - return &hasKeyTypeError{v, x} + return &func1TypeError{"has", v, x} } func funcToEntries(v any) any { @@ -384,14 +386,14 @@ func funcToEntries(v any) any { } return w default: - return &funcTypeError{"to_entries", v} + return &func0TypeError{"to_entries", v} } } func funcFromEntries(v any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"from_entries", v} + return &func0TypeError{"from_entries", v} } w := make(map[string]any, len(vs)) for _, v := range vs { @@ -405,13 +407,13 @@ func funcFromEntries(v any) any { for _, k := range [4]string{"key", "Key", "name", "Name"} { if k := v[k]; k != nil && k != false { if key, ok = k.(string); !ok { - return &objectKeyNotStringError{k} + return &func0WrapError{"from_entries", vs, &objectKeyNotStringError{k}} } break } } if !ok { - return &objectKeyNotStringError{nil} + return &func0WrapError{"from_entries", vs, &objectKeyNotStringError{nil}} } for _, k := range [2]string{"value", "Value"} { if value, ok = v[k]; ok { @@ -420,7 +422,7 @@ func funcFromEntries(v any) any { } w[key] = value default: - return &funcTypeError{"from_entries", v} + return &func0TypeError{"from_entries", v} } } return w @@ -429,7 +431,7 @@ func funcFromEntries(v any) any { func funcAdd(v any) any { vs, ok := values(v) if !ok { - return &funcTypeError{"add", v} + return &func0TypeError{"add", v} } v = nil for _, x := range vs { @@ -494,11 +496,11 @@ func funcToNumber(v any) any { return v case string: if !newLexer(v).validNumber() { - return fmt.Errorf("invalid number: %q", v) + return &func0WrapError{"tonumber", v, errors.New("invalid number")} } return toNumber(v) default: - return &funcTypeError{"tonumber", v} + return &func0TypeError{"tonumber", v} } } @@ -520,7 +522,7 @@ func funcType(v any) any { func funcReverse(v any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"reverse", v} + return &func0TypeError{"reverse", v} } ws := make([]any, len(vs)) for i, v := range vs { @@ -562,17 +564,17 @@ func funcContains(v, x any) any { if l == r { return true } - return &containsTypeError{l, r} + return &func1TypeError{"contains", l, r} }, ) } func funcIndices(v, x any) any { - return indexFunc(v, x, indices) + return indexFunc("indices", v, x, indices) } func indices(vs, xs []any) any { - var rs []any + rs := []any{} if len(xs) == 0 { return rs } @@ -585,7 +587,7 @@ func indices(vs, xs []any) any { } func funcIndex(v, x any) any { - return indexFunc(v, x, func(vs, xs []any) any { + return indexFunc("index", v, x, func(vs, xs []any) any { if len(xs) == 0 { return nil } @@ -599,7 +601,7 @@ func funcIndex(v, x any) any { } func funcRindex(v, x any) any { - return indexFunc(v, x, func(vs, xs []any) any { + return indexFunc("rindex", v, x, func(vs, xs []any) any { if len(xs) == 0 { return nil } @@ -612,7 +614,7 @@ func funcRindex(v, x any) any { }) } -func indexFunc(v, x any, f func(_, _ []any) any) any { +func indexFunc(name string, v, x any, f func(_, _ []any) any) any { switch v := v.(type) { case nil: return nil @@ -627,20 +629,20 @@ func indexFunc(v, x any, f func(_, _ []any) any) any { if x, ok := x.(string); ok { return f(explode(v), explode(x)) } - return &expectedStringError{x} + return &func1TypeError{name, v, x} default: - return &expectedArrayError{v} + return &func1TypeError{name, v, x} } } func funcStartsWith(v, x any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"startswith", v} + return &func1TypeError{"startswith", v, x} } t, ok := x.(string) if !ok { - return &funcTypeError{"startswith", x} + return &func1TypeError{"startswith", v, x} } return strings.HasPrefix(s, t) } @@ -648,11 +650,11 @@ func funcStartsWith(v, x any) any { func funcEndsWith(v, x any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"endswith", v} + return &func1TypeError{"endswith", v, x} } t, ok := x.(string) if !ok { - return &funcTypeError{"endswith", x} + return &func1TypeError{"endswith", v, x} } return strings.HasSuffix(s, t) } @@ -684,7 +686,7 @@ func funcRtrimstr(v, x any) any { func funcExplode(v any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"explode", v} + return &func0TypeError{"explode", v} } return explode(s) } @@ -702,7 +704,7 @@ func explode(s string) []any { func funcImplode(v any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"implode", v} + return &func0TypeError{"implode", v} } var sb strings.Builder sb.Grow(len(vs)) @@ -710,7 +712,7 @@ func funcImplode(v any) any { if r, ok := toInt(v); ok && 0 <= r && r <= utf8.MaxRune { sb.WriteRune(rune(r)) } else { - return &funcTypeError{"implode", vs} + return &func0TypeError{"implode", vs} } } return sb.String() @@ -719,11 +721,11 @@ func funcImplode(v any) any { func funcSplit(v any, args []any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"split", v} + return &func0TypeError{"split", v} } x, ok := args[0].(string) if !ok { - return &funcTypeError{"split", x} + return &func0TypeError{"split", x} } var ss []string if len(args) == 1 { @@ -733,7 +735,7 @@ func funcSplit(v any, args []any) any { if args[1] != nil { v, ok := args[1].(string) if !ok { - return &funcTypeError{"split", args[1]} + return &func0TypeError{"split", args[1]} } flags = v } @@ -753,7 +755,7 @@ func funcSplit(v any, args []any) any { func funcASCIIDowncase(v any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"ascii_downcase", v} + return &func0TypeError{"ascii_downcase", v} } return strings.Map(func(r rune) rune { if 'A' <= r && r <= 'Z' { @@ -766,7 +768,7 @@ func funcASCIIDowncase(v any) any { func funcASCIIUpcase(v any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"ascii_upcase", v} + return &func0TypeError{"ascii_upcase", v} } return strings.Map(func(r rune) rune { if 'a' <= r && r <= 'z' { @@ -783,16 +785,16 @@ func funcToJSON(v any) any { func funcFromJSON(v any) any { s, ok := v.(string) if !ok { - return &funcTypeError{"fromjson", v} + return &func0TypeError{"fromjson", v} } var w any dec := json.NewDecoder(strings.NewReader(s)) dec.UseNumber() if err := dec.Decode(&w); err != nil { - return err + return &func0WrapError{"fromjson", v, err} } if _, err := dec.Token(); err != io.EOF { - return &funcTypeError{"fromjson", v} + return &func0TypeError{"fromjson", v} } return normalizeNumbers(w) } @@ -800,7 +802,7 @@ func funcFromJSON(v any) any { func funcFormat(v, x any) any { s, ok := x.(string) if !ok { - return &funcTypeError{"format", x} + return &func0TypeError{"format", x} } format := "@" + s f := formatToFunc(format) @@ -836,6 +838,19 @@ func funcToURI(v any) any { } } +func funcToURId(v any) any { + switch x := funcToString(v).(type) { + case string: + x, err := url.QueryUnescape(x) + if err != nil { + return &func0WrapError{"@urid", v, err} + } + return x + default: + return x + } +} + var csvEscaper = strings.NewReplacer( `"`, `""`, "\x00", `\0`, @@ -876,7 +891,7 @@ func funcToSh(v any) any { func formatJoin(typ string, v any, sep string, escape func(string) string) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"@" + typ, v} + return &func0TypeError{"@" + typ, v} } ss := make([]string, len(vs)) for i, v := range vs { @@ -911,7 +926,7 @@ func funcToBase64d(v any) any { } y, err := base64.RawStdEncoding.DecodeString(x) if err != nil { - return err + return &func0WrapError{"@base64d", v, err} } return string(y) default: @@ -1089,7 +1104,7 @@ func clampIndex(i, min, max int) int { func funcFlatten(v any, args []any) any { vs, ok := values(v) if !ok { - return &funcTypeError{"flatten", v} + return &func0TypeError{"flatten", v} } var depth float64 if len(args) == 0 { @@ -1097,13 +1112,13 @@ func funcFlatten(v any, args []any) any { } else { depth, ok = toFloat(args[0]) if !ok { - return &funcTypeError{"flatten", args[0]} + return &func0TypeError{"flatten", args[0]} } if depth < 0 { return &flattenDepthError{depth} } } - return flatten(nil, vs, depth) + return flatten([]any{}, vs, depth) } func flatten(xs, vs []any, depth float64) []any { @@ -1135,7 +1150,7 @@ func funcRange(_ any, xs []any) any { switch x.(type) { case int, float64, *big.Int: default: - return &funcTypeError{"range", x} + return &func0TypeError{"range", x} } } return &rangeIter{xs[0], xs[1], xs[2]} @@ -1144,7 +1159,7 @@ func funcRange(_ any, xs []any) any { func funcMin(v any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"min", v} + return &func0TypeError{"min", v} } return minMaxBy(vs, vs, true) } @@ -1152,14 +1167,14 @@ func funcMin(v any) any { func funcMinBy(v, x any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"min_by", v} + return &func1TypeError{"min_by", v, x} } xs, ok := x.([]any) if !ok { - return &funcTypeError{"min_by", x} + return &func1TypeError{"min_by", v, x} } if len(vs) != len(xs) { - return &lengthMismatchError{"min_by", vs, xs} + return &func1WrapError{"min_by", v, x, &lengthMismatchError{}} } return minMaxBy(vs, xs, true) } @@ -1167,7 +1182,7 @@ func funcMinBy(v, x any) any { func funcMax(v any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"max", v} + return &func0TypeError{"max", v} } return minMaxBy(vs, vs, false) } @@ -1175,14 +1190,14 @@ func funcMax(v any) any { func funcMaxBy(v, x any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"max_by", v} + return &func1TypeError{"max_by", v, x} } xs, ok := x.([]any) if !ok { - return &funcTypeError{"max_by", x} + return &func1TypeError{"max_by", v, x} } if len(vs) != len(xs) { - return &lengthMismatchError{"max_by", vs, xs} + return &func1WrapError{"max_by", v, x, &lengthMismatchError{}} } return minMaxBy(vs, xs, false) } @@ -1207,14 +1222,17 @@ type sortItem struct { func sortItems(name string, v, x any) ([]*sortItem, error) { vs, ok := v.([]any) if !ok { - return nil, &funcTypeError{name, v} + if strings.HasSuffix(name, "_by") { + return nil, &func1TypeError{name, v, x} + } + return nil, &func0TypeError{name, v} } xs, ok := x.([]any) if !ok { - return nil, &funcTypeError{name, x} + return nil, &func1TypeError{name, v, x} } if len(vs) != len(xs) { - return nil, &lengthMismatchError{name, vs, xs} + return nil, &func1WrapError{name, v, x, &lengthMismatchError{}} } items := make([]*sortItem, len(vs)) for i, v := range vs { @@ -1251,7 +1269,7 @@ func funcGroupBy(v, x any) any { if err != nil { return err } - var rs []any + rs := []any{} var last any for i, r := range items { if i == 0 || compare(last, r.key) != 0 { @@ -1276,7 +1294,7 @@ func uniqueBy(name string, v, x any) any { if err != nil { return err } - var rs []any + rs := []any{} var last any for i, r := range items { if i == 0 || compare(last, r.key) != 0 { @@ -1289,14 +1307,14 @@ func uniqueBy(name string, v, x any) any { func funcJoin(v, x any) any { vs, ok := values(v) if !ok { - return &funcTypeError{"join", v} + return &func1TypeError{"join", v, x} } if len(vs) == 0 { return "" } sep, ok := x.(string) if len(vs) > 1 && !ok { - return &funcTypeError{"join", x} + return &func1TypeError{"join", v, x} } ss := make([]string, len(vs)) for i, v := range vs { @@ -1333,7 +1351,7 @@ func funcExp10(v float64) float64 { func funcFrexp(v any) any { x, ok := toFloat(v) if !ok { - return &funcTypeError{"frexp", v} + return &func0TypeError{"frexp", v} } f, e := math.Frexp(x) return []any{f, e} @@ -1342,7 +1360,7 @@ func funcFrexp(v any) any { func funcModf(v any) any { x, ok := toFloat(v) if !ok { - return &funcTypeError{"modf", v} + return &func0TypeError{"modf", v} } i, f := math.Modf(x) return []any{f, i} @@ -1405,7 +1423,7 @@ func funcIsnan(v any) any { if v == nil { return false } - return &funcTypeError{"isnan", v} + return &func0TypeError{"isnan", v} } return math.IsNaN(x) } @@ -1465,16 +1483,13 @@ func funcSetpathWithAllocator(v any, args []any) any { func setpath(v, p, n any, a allocator) any { path, ok := p.([]any) if !ok { - return &funcTypeError{"setpath", p} + return &func1TypeError{"setpath", v, p} } - var err error - if v, err = update(v, path, n, a); err != nil { - if err, ok := err.(*funcTypeError); ok { - err.name = "setpath" - } - return err + u, err := update(v, path, n, a) + if err != nil { + return &func2WrapError{"setpath", v, p, n, err} } - return v + return u } func funcDelpaths(v, p any) any { @@ -1489,7 +1504,7 @@ func funcDelpathsWithAllocator(v any, args []any) any { func delpaths(v, p any, a allocator) any { paths, ok := p.([]any) if !ok { - return &funcTypeError{"delpaths", p} + return &func1TypeError{"delpaths", v, p} } if len(paths) == 0 { return v @@ -1499,16 +1514,18 @@ func delpaths(v, p any, a allocator) any { // jq -n "[0, 1, 2, 3] | delpaths([[1], [2]])" #=> [0, 3]. var empty struct{} var err error - for _, p := range paths { - path, ok := p.([]any) + u := v + for _, q := range paths { + path, ok := q.([]any) if !ok { - return &funcTypeError{"delpaths", p} + return &func1WrapError{"delpaths", v, p, &expectedArrayError{q}} } - if v, err = update(v, path, empty, a); err != nil { - return err + u, err = update(u, path, empty, a) + if err != nil { + return &func1WrapError{"delpaths", v, p, err} } } - return deleteEmpty(v) + return deleteEmpty(u) } func update(v any, path []any, n any, a allocator) (any, error) { @@ -1587,7 +1604,7 @@ func updateArrayIndex(v []any, i int, path []any, n any, a allocator) (any, erro if n == struct{}{} { return v, nil } - return nil, &funcTypeError{v: i} + return nil, &arrayIndexNegativeError{i} } else if j < len(v) { i = j x = v[i] @@ -1708,20 +1725,20 @@ func deleteEmpty(v any) any { } func funcGetpath(v, p any) any { - keys, ok := p.([]any) + path, ok := p.([]any) if !ok { - return &funcTypeError{"getpath", p} + return &func1TypeError{"getpath", v, p} } u := v - for _, x := range keys { + for _, x := range path { switch v.(type) { case nil, []any, map[string]any: v = funcIndex2(nil, v, x) - if _, ok := v.(error); ok { - return &getpathError{u, p} + if err, ok := v.(error); ok { + return &func1WrapError{"getpath", u, p, err} } default: - return &getpathError{u, p} + return &func1TypeError{"getpath", u, p} } } return v @@ -1730,7 +1747,7 @@ func funcGetpath(v, p any) any { func funcTranspose(v any) any { vss, ok := v.([]any) if !ok { - return &funcTypeError{"transpose", v} + return &func0TypeError{"transpose", v} } if len(vss) == 0 { return []any{} @@ -1739,7 +1756,7 @@ func funcTranspose(v any) any { for _, vs := range vss { vs, ok := vs.([]any) if !ok { - return &funcTypeError{"transpose", v} + return &func0TypeError{"transpose", v} } if k := len(vs); l < k { l = k @@ -1763,7 +1780,7 @@ func funcTranspose(v any) any { func funcBsearch(v, t any) any { vs, ok := v.([]any) if !ok { - return &funcTypeError{"bsearch", v} + return &func1TypeError{"bsearch", v, t} } i := sort.Search(len(vs), func(i int) bool { return compare(vs[i], t) >= 0 @@ -1778,14 +1795,14 @@ func funcGmtime(v any) any { if v, ok := toFloat(v); ok { return epochToArray(v, time.UTC) } - return &funcTypeError{"gmtime", v} + return &func0TypeError{"gmtime", v} } func funcLocaltime(v any) any { if v, ok := toFloat(v); ok { return epochToArray(v, time.Local) } - return &funcTypeError{"localtime", v} + return &func0TypeError{"localtime", v} } func epochToArray(v float64, loc *time.Location) []any { @@ -1803,14 +1820,15 @@ func epochToArray(v float64, loc *time.Location) []any { } func funcMktime(v any) any { - if a, ok := v.([]any); ok { - t, err := arrayToTime("mktime", a, time.UTC) - if err != nil { - return err - } - return timeToEpoch(t) + a, ok := v.([]any) + if !ok { + return &func0TypeError{"mktime", v} } - return &funcTypeError{"mktime", v} + t, err := arrayToTime(a, time.UTC) + if err != nil { + return &func0WrapError{"mktime", v, err} + } + return timeToEpoch(t) } func timeToEpoch(t time.Time) float64 { @@ -1821,90 +1839,95 @@ func funcStrftime(v, x any) any { if w, ok := toFloat(v); ok { v = epochToArray(w, time.UTC) } - if a, ok := v.([]any); ok { - if format, ok := x.(string); ok { - t, err := arrayToTime("strftime", a, time.UTC) - if err != nil { - return err - } - return timefmt.Format(t, format) - } - return &funcTypeError{"strftime", x} + a, ok := v.([]any) + if !ok { + return &func1TypeError{"strftime", v, x} + } + format, ok := x.(string) + if !ok { + return &func1TypeError{"strftime", v, x} } - return &funcTypeError{"strftime", v} + t, err := arrayToTime(a, time.UTC) + if err != nil { + return &func1WrapError{"strftime", v, x, err} + } + return timefmt.Format(t, format) } func funcStrflocaltime(v, x any) any { if w, ok := toFloat(v); ok { v = epochToArray(w, time.Local) } - if a, ok := v.([]any); ok { - if format, ok := x.(string); ok { - t, err := arrayToTime("strflocaltime", a, time.Local) - if err != nil { - return err - } - return timefmt.Format(t, format) - } - return &funcTypeError{"strflocaltime", x} + a, ok := v.([]any) + if !ok { + return &func1TypeError{"strflocaltime", v, x} + } + format, ok := x.(string) + if !ok { + return &func1TypeError{"strflocaltime", v, x} } - return &funcTypeError{"strflocaltime", v} + t, err := arrayToTime(a, time.Local) + if err != nil { + return &func1WrapError{"strflocaltime", v, x, err} + } + return timefmt.Format(t, format) } func funcStrptime(v, x any) any { - if v, ok := v.(string); ok { - if format, ok := x.(string); ok { - t, err := timefmt.Parse(v, format) - if err != nil { - return err - } - var s time.Time - if t == s { - return &funcTypeError{"strptime", v} - } - return epochToArray(timeToEpoch(t), time.UTC) - } - return &funcTypeError{"strptime", x} + s, ok := v.(string) + if !ok { + return &func1TypeError{"strptime", v, x} + } + format, ok := x.(string) + if !ok { + return &func1TypeError{"strptime", v, x} + } + t, err := timefmt.Parse(s, format) + if err != nil { + return &func1WrapError{"strptime", v, x, err} + } + var u time.Time + if t == u { + return &func1TypeError{"strptime", v, x} } - return &funcTypeError{"strptime", v} + return epochToArray(timeToEpoch(t), time.UTC) } -func arrayToTime(name string, a []any, loc *time.Location) (time.Time, error) { +func arrayToTime(a []any, loc *time.Location) (time.Time, error) { var t time.Time if len(a) != 8 { - return t, &funcTypeError{name, a} + return t, &timeArrayError{} } var y, m, d, h, min, sec, nsec int - if x, ok := toInt(a[0]); ok { - y = x - } else { - return t, &funcTypeError{name, a} + var ok bool + if y, ok = toInt(a[0]); !ok { + return t, &timeArrayError{} } - if x, ok := toInt(a[1]); ok { - m = x + 1 + if m, ok = toInt(a[1]); ok { + m++ } else { - return t, &funcTypeError{name, a} + return t, &timeArrayError{} } - if x, ok := toInt(a[2]); ok { - d = x - } else { - return t, &funcTypeError{name, a} + if d, ok = toInt(a[2]); !ok { + return t, &timeArrayError{} } - if x, ok := toInt(a[3]); ok { - h = x - } else { - return t, &funcTypeError{name, a} + if h, ok = toInt(a[3]); !ok { + return t, &timeArrayError{} } - if x, ok := toInt(a[4]); ok { - min = x - } else { - return t, &funcTypeError{name, a} + if min, ok = toInt(a[4]); !ok { + return t, &timeArrayError{} } if x, ok := toFloat(a[5]); ok { sec = int(x) nsec = int((x - math.Floor(x)) * 1e9) } else { - return t, &funcTypeError{name, a} + return t, &timeArrayError{} + } + if _, ok = toFloat(a[6]); !ok { + return t, &timeArrayError{} + } + if _, ok = toFloat(a[7]); !ok { + return t, &timeArrayError{} } return time.Date(y, time.Month(m), d, h, min, sec, nsec, loc), nil } @@ -1914,21 +1937,25 @@ func funcNow(any) any { } func funcMatch(v, re, fs, testing any) any { + name := "match" + if testing == true { + name = "test" + } var flags string if fs != nil { v, ok := fs.(string) if !ok { - return &funcTypeError{"match", fs} + return &func2TypeError{name, v, re, fs} } flags = v } s, ok := v.(string) if !ok { - return &funcTypeError{"match", v} + return &func2TypeError{name, v, re, fs} } restr, ok := re.(string) if !ok { - return &funcTypeError{"match", v} + return &func2TypeError{name, v, re, fs} } r, err := compileRegexp(restr, flags) if err != nil { @@ -2041,7 +2068,7 @@ func funcHaltError(v any, args []any) any { if len(args) > 0 { var ok bool if code, ok = toInt(args[0]); !ok { - return &funcTypeError{"halt_error", args[0]} + return &func0TypeError{"halt_error", args[0]} } } return &exitCodeError{v, code, true} diff --git a/vendor/github.com/itchyny/gojq/module_loader.go b/vendor/github.com/itchyny/gojq/module_loader.go index 6e9ba48c..599e37bf 100644 --- a/vendor/github.com/itchyny/gojq/module_loader.go +++ b/vendor/github.com/itchyny/gojq/module_loader.go @@ -84,7 +84,7 @@ func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]any) (any, return nil, err } defer f.Close() - var vals []any + vals := []any{} dec := json.NewDecoder(f) dec.UseNumber() for { diff --git a/vendor/github.com/sheldonhull/magetools/gotools/gotools.go b/vendor/github.com/sheldonhull/magetools/gotools/gotools.go index 3bf5cc17..f43371bb 100644 --- a/vendor/github.com/sheldonhull/magetools/gotools/gotools.go +++ b/vendor/github.com/sheldonhull/magetools/gotools/gotools.go @@ -25,7 +25,7 @@ import ( "github.com/sheldonhull/magetools/pkg/req" "github.com/sheldonhull/magetools/tooling" "github.com/ztrue/tracerr" - modfile "golang.org/x/mod/modfile" + "golang.org/x/mod/modfile" ) type ( @@ -141,7 +141,7 @@ func (Go) Test() error { // // - Test running manually like this from current repo: GOTEST_DISABLE_RACE=1 mage -d magefiles -w . -v go:testsum ./pkg/... // -//nolint:funlen,cyclop // Not refactoring this right now, it works and that's what matters ;-) +//nolint:funlen,cyclop,revive // Not refactoring this right now, it works and that's what matters ;-) func (Go) TestSum(path string) error { magetoolsutils.CheckPtermDebug() pterm.DefaultHeader.Println("GOTESTSUM") @@ -292,7 +292,7 @@ func (Go) Fix() error { if err != nil { pterm.Error.WithShowLineNumber(true). WithLineNumberOffset(1). - Printfln("unable to find %s: %v", "golangci-lint", err) + Printfln("unable to find %s: %v", "golangci-lint", err) //nolint: revive // allow constant return err } @@ -411,7 +411,7 @@ func (Go) LintConfig() error { golangcilint, err := req.ResolveBinaryByInstall( "golangci-lint", - "github.com/golangci/golangci-lint/cmd/golangci-lint@latest", + "github.com/golangci/golangci-lint/cmd/golangci-lint@latest", //nolint: revive // allow constant ) if err != nil { pterm.Error.WithShowLineNumber(true). diff --git a/vendor/github.com/sheldonhull/magetools/pkg/req/req.go b/vendor/github.com/sheldonhull/magetools/pkg/req/req.go index 8bdaee3e..e668d7b6 100644 --- a/vendor/github.com/sheldonhull/magetools/pkg/req/req.go +++ b/vendor/github.com/sheldonhull/magetools/pkg/req/req.go @@ -42,7 +42,6 @@ func GetGoPath() (gopath string) { // This can help with running in CI and not having to have a lot of setup code. func ResolveBinaryByInstall(app, goInstallCmd string) (qualifiedBinary string, err error) { qualifiedBinary, err = QualifyGoBinary(app) - if err != nil { pterm.Info.Printfln("Couldn't find %s, so will attempt to install it from source", app) err := tooling.SilentInstallTools([]string{goInstallCmd}) @@ -82,7 +81,6 @@ func ResolveBinaryByInstall(app, goInstallCmd string) (qualifiedBinary string, e // QualifyGoBinary provides a fully qualified path for an installed Go binary to avoid path issues. // This uses exec.LookPath to allow resolution of the binary from any provided `PATH` variables, allowing better alternative tooling installation before installing from source. func QualifyGoBinary(binary string) (string, error) { - pterm.Debug.Printfln("searching for binary in all provided PATH locations: %q", binary) qualifiedPath, err := exec.LookPath(binary) if err != nil { diff --git a/vendor/github.com/sheldonhull/magetools/tooling/tooling.go b/vendor/github.com/sheldonhull/magetools/tooling/tooling.go index 4e152db7..d39f02ca 100644 --- a/vendor/github.com/sheldonhull/magetools/tooling/tooling.go +++ b/vendor/github.com/sheldonhull/magetools/tooling/tooling.go @@ -58,6 +58,7 @@ func InstallTools(tools []string) error { // SilentInstallTools reads the stdout and then uses a spinner to show progress. // This is designed to swallow up a lot of the noise with go install commands. // Originally found from: https://www.yellowduck.be/posts/reading-command-output-line-by-line/ and modified. +// //nolint:funlen // This is ok for now. Can refactor into smaller pieces later if needed. func SilentInstallTools(toolList []string) error { var errorCount int @@ -160,6 +161,7 @@ func SilentInstallTools(toolList []string) error { // Example: SpinnerStdOut("go",[]string{"install"},[]string{ "golang.org/x/tools/cmd/goimports@master","github.com/sqs/goreturns@master"}) // This is designed to swallow up a lot of the noise with go install commands. // Originally found from: https://www.yellowduck.be/posts/reading-command-output-line-by-line/ and modified. +// //nolint:funlen // Bypassing. Will need to evaluate later if I want to break this apart. For now it's not important func SpinnerStdOut( binary string, diff --git a/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go b/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go index 2681af35..150f887e 100644 --- a/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go +++ b/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go @@ -13,7 +13,7 @@ import ( "sync" ) -// Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be +// Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be // compiled the first time it is needed. type Regexp struct { str string diff --git a/vendor/golang.org/x/mod/modfile/print.go b/vendor/golang.org/x/mod/modfile/print.go index 524f9302..2a0123d4 100644 --- a/vendor/golang.org/x/mod/modfile/print.go +++ b/vendor/golang.org/x/mod/modfile/print.go @@ -16,7 +16,13 @@ import ( func Format(f *FileSyntax) []byte { pr := &printer{} pr.file(f) - return pr.Bytes() + + // remove trailing blank lines + b := pr.Bytes() + for len(b) > 0 && b[len(b)-1] == '\n' && (len(b) == 1 || b[len(b)-2] == '\n') { + b = b[:len(b)-1] + } + return b } // A printer collects the state during printing of a file or expression. @@ -59,7 +65,11 @@ func (p *printer) newline() { } p.trim() - p.printf("\n") + if b := p.Bytes(); len(b) == 0 || (len(b) >= 2 && b[len(b)-1] == '\n' && b[len(b)-2] == '\n') { + // skip the blank line at top of file or after a blank line + } else { + p.printf("\n") + } for i := 0; i < p.margin; i++ { p.printf("\t") } diff --git a/vendor/golang.org/x/mod/modfile/read.go b/vendor/golang.org/x/mod/modfile/read.go index a503bc21..22056825 100644 --- a/vendor/golang.org/x/mod/modfile/read.go +++ b/vendor/golang.org/x/mod/modfile/read.go @@ -65,7 +65,7 @@ type Comments struct { } // Comment returns the receiver. This isn't useful by itself, but -// a Comments struct is embedded into all the expression +// a [Comments] struct is embedded into all the expression // implementation types, and this gives each of those a Comment // method to satisfy the Expr interface. func (c *Comments) Comment() *Comments { @@ -225,7 +225,7 @@ func (x *FileSyntax) Cleanup() { if ww == 0 { continue } - if ww == 1 { + if ww == 1 && len(stmt.RParen.Comments.Before) == 0 { // Collapse block into single line. line := &Line{ Comments: Comments{ diff --git a/vendor/golang.org/x/mod/modfile/rule.go b/vendor/golang.org/x/mod/modfile/rule.go index 6bcde8fa..0e7b7e26 100644 --- a/vendor/golang.org/x/mod/modfile/rule.go +++ b/vendor/golang.org/x/mod/modfile/rule.go @@ -5,17 +5,17 @@ // Package modfile implements a parser and formatter for go.mod files. // // The go.mod syntax is described in -// https://golang.org/cmd/go/#hdr-The_go_mod_file. +// https://pkg.go.dev/cmd/go/#hdr-The_go_mod_file. // -// The Parse and ParseLax functions both parse a go.mod file and return an +// The [Parse] and [ParseLax] functions both parse a go.mod file and return an // abstract syntax tree. ParseLax ignores unknown statements and may be used to // parse go.mod files that may have been developed with newer versions of Go. // -// The File struct returned by Parse and ParseLax represent an abstract -// go.mod file. File has several methods like AddNewRequire and DropReplace -// that can be used to programmatically edit a file. +// The [File] struct returned by Parse and ParseLax represent an abstract +// go.mod file. File has several methods like [File.AddNewRequire] and +// [File.DropReplace] that can be used to programmatically edit a file. // -// The Format function formats a File back to a byte slice which can be +// The [Format] function formats a File back to a byte slice which can be // written to a file. package modfile @@ -35,12 +35,13 @@ import ( // A File is the parsed, interpreted form of a go.mod file. type File struct { - Module *Module - Go *Go - Require []*Require - Exclude []*Exclude - Replace []*Replace - Retract []*Retract + Module *Module + Go *Go + Toolchain *Toolchain + Require []*Require + Exclude []*Exclude + Replace []*Replace + Retract []*Retract Syntax *FileSyntax } @@ -58,6 +59,12 @@ type Go struct { Syntax *Line } +// A Toolchain is the toolchain statement. +type Toolchain struct { + Name string // "go1.21rc1" + Syntax *Line +} + // An Exclude is a single exclude statement. type Exclude struct { Mod module.Version @@ -219,7 +226,7 @@ var dontFixRetract VersionFixer = func(_, vers string) (string, error) { // data is the content of the file. // // fix is an optional function that canonicalizes module versions. -// If fix is nil, all module versions must be canonical (module.CanonicalVersion +// If fix is nil, all module versions must be canonical ([module.CanonicalVersion] // must return the same string). func Parse(file string, data []byte, fix VersionFixer) (*File, error) { return parseToFile(file, data, fix, true) @@ -296,9 +303,14 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse return f, nil } -var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`) +var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?([a-z]+[0-9]+)?$`) var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`) +// Toolchains must be named beginning with `go1`, +// like "go1.20.3" or "go1.20.3-gccgo". As a special case, "default" is also permitted. +// TODO(samthanawalla): Replace regex with https://pkg.go.dev/go/version#IsValid in 1.23+ +var ToolchainRE = lazyregexp.New(`^default$|^go1($|\.)`) + func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) { // If strict is false, this module is a dependency. // We ignore all unknown directives as well as main-module-only @@ -356,7 +368,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a } } if !fixed { - errorf("invalid go version '%s': must match format 1.23", args[0]) + errorf("invalid go version '%s': must match format 1.23.0", args[0]) return } } @@ -364,6 +376,21 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a f.Go = &Go{Syntax: line} f.Go.Version = args[0] + case "toolchain": + if f.Toolchain != nil { + errorf("repeated toolchain statement") + return + } + if len(args) != 1 { + errorf("toolchain directive expects exactly one argument") + return + } else if strict && !ToolchainRE.MatchString(args[0]) { + errorf("invalid toolchain version '%s': must match format go1.23.0 or default", args[0]) + return + } + f.Toolchain = &Toolchain{Syntax: line} + f.Toolchain.Name = args[0] + case "module": if f.Module != nil { errorf("repeated module statement") @@ -516,7 +543,7 @@ func parseReplace(filename string, line *Line, verb string, args []string, fix V if strings.Contains(ns, "@") { return nil, errorf("replacement module must match format 'path version', not 'path@version'") } - return nil, errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)") + return nil, errorf("replacement module without version must be directory path (rooted or starting with . or ..)") } if filepath.Separator == '/' && strings.Contains(ns, `\`) { return nil, errorf("replacement directory appears to be Windows path (on a non-windows system)") @@ -529,7 +556,6 @@ func parseReplace(filename string, line *Line, verb string, args []string, fix V } if IsDirectoryPath(ns) { return nil, errorf("replacement module directory path %q cannot have version", ns) - } } return &Replace{ @@ -605,13 +631,29 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, errorf("go directive expects exactly one argument") return } else if !GoVersionRE.MatchString(args[0]) { - errorf("invalid go version '%s': must match format 1.23", args[0]) + errorf("invalid go version '%s': must match format 1.23.0", args[0]) return } f.Go = &Go{Syntax: line} f.Go.Version = args[0] + case "toolchain": + if f.Toolchain != nil { + errorf("repeated toolchain statement") + return + } + if len(args) != 1 { + errorf("toolchain directive expects exactly one argument") + return + } else if !ToolchainRE.MatchString(args[0]) { + errorf("invalid toolchain version '%s': must match format go1.23.0 or default", args[0]) + return + } + + f.Toolchain = &Toolchain{Syntax: line} + f.Toolchain.Name = args[0] + case "use": if len(args) != 1 { errorf("usage: %s local/dir", verb) @@ -637,14 +679,15 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, } } -// IsDirectoryPath reports whether the given path should be interpreted -// as a directory path. Just like on the go command line, relative paths +// IsDirectoryPath reports whether the given path should be interpreted as a directory path. +// Just like on the go command line, relative paths starting with a '.' or '..' path component // and rooted paths are directory paths; the rest are module paths. func IsDirectoryPath(ns string) bool { // Because go.mod files can move from one system to another, // we check all known path syntaxes, both Unix and Windows. - return strings.HasPrefix(ns, "./") || strings.HasPrefix(ns, "../") || strings.HasPrefix(ns, "/") || - strings.HasPrefix(ns, `.\`) || strings.HasPrefix(ns, `..\`) || strings.HasPrefix(ns, `\`) || + return ns == "." || strings.HasPrefix(ns, "./") || strings.HasPrefix(ns, `.\`) || + ns == ".." || strings.HasPrefix(ns, "../") || strings.HasPrefix(ns, `..\`) || + strings.HasPrefix(ns, "/") || strings.HasPrefix(ns, `\`) || len(ns) >= 2 && ('A' <= ns[0] && ns[0] <= 'Z' || 'a' <= ns[0] && ns[0] <= 'z') && ns[1] == ':' } @@ -881,7 +924,7 @@ func (f *File) Format() ([]byte, error) { } // Cleanup cleans up the file f after any edit operations. -// To avoid quadratic behavior, modifications like DropRequire +// To avoid quadratic behavior, modifications like [File.DropRequire] // clear the entry but do not remove it from the slice. // Cleanup cleans out all the cleared entries. func (f *File) Cleanup() { @@ -926,12 +969,14 @@ func (f *File) Cleanup() { func (f *File) AddGoStmt(version string) error { if !GoVersionRE.MatchString(version) { - return fmt.Errorf("invalid language version string %q", version) + return fmt.Errorf("invalid language version %q", version) } if f.Go == nil { var hint Expr if f.Module != nil && f.Module.Syntax != nil { hint = f.Module.Syntax + } else if f.Syntax == nil { + f.Syntax = new(FileSyntax) } f.Go = &Go{ Version: version, @@ -944,6 +989,44 @@ func (f *File) AddGoStmt(version string) error { return nil } +// DropGoStmt deletes the go statement from the file. +func (f *File) DropGoStmt() { + if f.Go != nil { + f.Go.Syntax.markRemoved() + f.Go = nil + } +} + +// DropToolchainStmt deletes the toolchain statement from the file. +func (f *File) DropToolchainStmt() { + if f.Toolchain != nil { + f.Toolchain.Syntax.markRemoved() + f.Toolchain = nil + } +} + +func (f *File) AddToolchainStmt(name string) error { + if !ToolchainRE.MatchString(name) { + return fmt.Errorf("invalid toolchain name %q", name) + } + if f.Toolchain == nil { + var hint Expr + if f.Go != nil && f.Go.Syntax != nil { + hint = f.Go.Syntax + } else if f.Module != nil && f.Module.Syntax != nil { + hint = f.Module.Syntax + } + f.Toolchain = &Toolchain{ + Name: name, + Syntax: f.Syntax.addLine(hint, "toolchain", name), + } + } else { + f.Toolchain.Name = name + f.Syntax.updateLine(f.Toolchain.Syntax, "toolchain", name) + } + return nil +} + // AddRequire sets the first require line for path to version vers, // preserving any existing comments for that line and removing all // other lines for path. @@ -995,8 +1078,8 @@ func (f *File) AddNewRequire(path, vers string, indirect bool) { // The requirements in req must specify at most one distinct version for each // module path. // -// If any existing requirements may be removed, the caller should call Cleanup -// after all edits are complete. +// If any existing requirements may be removed, the caller should call +// [File.Cleanup] after all edits are complete. func (f *File) SetRequire(req []*Require) { type elem struct { version string @@ -1387,13 +1470,21 @@ func (f *File) DropRetract(vi VersionInterval) error { func (f *File) SortBlocks() { f.removeDups() // otherwise sorting is unsafe + // semanticSortForExcludeVersionV is the Go version (plus leading "v") at which + // lines in exclude blocks start to use semantic sort instead of lexicographic sort. + // See go.dev/issue/60028. + const semanticSortForExcludeVersionV = "v1.21" + useSemanticSortForExclude := f.Go != nil && semver.Compare("v"+f.Go.Version, semanticSortForExcludeVersionV) >= 0 + for _, stmt := range f.Syntax.Stmt { block, ok := stmt.(*LineBlock) if !ok { continue } less := lineLess - if block.Token[0] == "retract" { + if block.Token[0] == "exclude" && useSemanticSortForExclude { + less = lineExcludeLess + } else if block.Token[0] == "retract" { less = lineRetractLess } sort.SliceStable(block.Line, func(i, j int) bool { @@ -1496,6 +1587,22 @@ func lineLess(li, lj *Line) bool { return len(li.Token) < len(lj.Token) } +// lineExcludeLess reports whether li should be sorted before lj for lines in +// an "exclude" block. +func lineExcludeLess(li, lj *Line) bool { + if len(li.Token) != 2 || len(lj.Token) != 2 { + // Not a known exclude specification. + // Fall back to sorting lexicographically. + return lineLess(li, lj) + } + // An exclude specification has two tokens: ModulePath and Version. + // Compare module path by string order and version by semver rules. + if pi, pj := li.Token[0], lj.Token[0]; pi != pj { + return pi < pj + } + return semver.Compare(li.Token[1], lj.Token[1]) < 0 +} + // lineRetractLess returns whether li should be sorted before lj for lines in // a "retract" block. It treats each line as a version interval. Single versions // are compared as if they were intervals with the same low and high version. diff --git a/vendor/golang.org/x/mod/modfile/work.go b/vendor/golang.org/x/mod/modfile/work.go index 0c0e5215..d7b99376 100644 --- a/vendor/golang.org/x/mod/modfile/work.go +++ b/vendor/golang.org/x/mod/modfile/work.go @@ -12,9 +12,10 @@ import ( // A WorkFile is the parsed, interpreted form of a go.work file. type WorkFile struct { - Go *Go - Use []*Use - Replace []*Replace + Go *Go + Toolchain *Toolchain + Use []*Use + Replace []*Replace Syntax *FileSyntax } @@ -33,7 +34,7 @@ type Use struct { // data is the content of the file. // // fix is an optional function that canonicalizes module versions. -// If fix is nil, all module versions must be canonical (module.CanonicalVersion +// If fix is nil, all module versions must be canonical ([module.CanonicalVersion] // must return the same string). func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) { fs, err := parse(file, data) @@ -82,7 +83,7 @@ func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) { } // Cleanup cleans up the file f after any edit operations. -// To avoid quadratic behavior, modifications like DropRequire +// To avoid quadratic behavior, modifications like [WorkFile.DropRequire] // clear the entry but do not remove it from the slice. // Cleanup cleans out all the cleared entries. func (f *WorkFile) Cleanup() { @@ -109,7 +110,7 @@ func (f *WorkFile) Cleanup() { func (f *WorkFile) AddGoStmt(version string) error { if !GoVersionRE.MatchString(version) { - return fmt.Errorf("invalid language version string %q", version) + return fmt.Errorf("invalid language version %q", version) } if f.Go == nil { stmt := &Line{Token: []string{"go", version}} @@ -117,7 +118,7 @@ func (f *WorkFile) AddGoStmt(version string) error { Version: version, Syntax: stmt, } - // Find the first non-comment-only block that's and add + // Find the first non-comment-only block and add // the go statement before it. That will keep file comments at the top. i := 0 for i = 0; i < len(f.Syntax.Stmt); i++ { @@ -133,6 +134,56 @@ func (f *WorkFile) AddGoStmt(version string) error { return nil } +func (f *WorkFile) AddToolchainStmt(name string) error { + if !ToolchainRE.MatchString(name) { + return fmt.Errorf("invalid toolchain name %q", name) + } + if f.Toolchain == nil { + stmt := &Line{Token: []string{"toolchain", name}} + f.Toolchain = &Toolchain{ + Name: name, + Syntax: stmt, + } + // Find the go line and add the toolchain line after it. + // Or else find the first non-comment-only block and add + // the toolchain line before it. That will keep file comments at the top. + i := 0 + for i = 0; i < len(f.Syntax.Stmt); i++ { + if line, ok := f.Syntax.Stmt[i].(*Line); ok && len(line.Token) > 0 && line.Token[0] == "go" { + i++ + goto Found + } + } + for i = 0; i < len(f.Syntax.Stmt); i++ { + if _, ok := f.Syntax.Stmt[i].(*CommentBlock); !ok { + break + } + } + Found: + f.Syntax.Stmt = append(append(f.Syntax.Stmt[:i:i], stmt), f.Syntax.Stmt[i:]...) + } else { + f.Toolchain.Name = name + f.Syntax.updateLine(f.Toolchain.Syntax, "toolchain", name) + } + return nil +} + +// DropGoStmt deletes the go statement from the file. +func (f *WorkFile) DropGoStmt() { + if f.Go != nil { + f.Go.Syntax.markRemoved() + f.Go = nil + } +} + +// DropToolchainStmt deletes the toolchain statement from the file. +func (f *WorkFile) DropToolchainStmt() { + if f.Toolchain != nil { + f.Toolchain.Syntax.markRemoved() + f.Toolchain = nil + } +} + func (f *WorkFile) AddUse(diskPath, modulePath string) error { need := true for _, d := range f.Use { diff --git a/vendor/golang.org/x/mod/module/module.go b/vendor/golang.org/x/mod/module/module.go index e9dec6e6..2a364b22 100644 --- a/vendor/golang.org/x/mod/module/module.go +++ b/vendor/golang.org/x/mod/module/module.go @@ -4,7 +4,7 @@ // Package module defines the module.Version type along with support code. // -// The module.Version type is a simple Path, Version pair: +// The [module.Version] type is a simple Path, Version pair: // // type Version struct { // Path string @@ -12,7 +12,7 @@ // } // // There are no restrictions imposed directly by use of this structure, -// but additional checking functions, most notably Check, verify that +// but additional checking functions, most notably [Check], verify that // a particular path, version pair is valid. // // # Escaped Paths @@ -140,7 +140,7 @@ type ModuleError struct { Err error } -// VersionError returns a ModuleError derived from a Version and error, +// VersionError returns a [ModuleError] derived from a [Version] and error, // or err itself if it is already such an error. func VersionError(v Version, err error) error { var mErr *ModuleError @@ -169,7 +169,7 @@ func (e *ModuleError) Unwrap() error { return e.Err } // An InvalidVersionError indicates an error specific to a version, with the // module path unknown or specified externally. // -// A ModuleError may wrap an InvalidVersionError, but an InvalidVersionError +// A [ModuleError] may wrap an InvalidVersionError, but an InvalidVersionError // must not wrap a ModuleError. type InvalidVersionError struct { Version string @@ -193,8 +193,8 @@ func (e *InvalidVersionError) Error() string { func (e *InvalidVersionError) Unwrap() error { return e.Err } // An InvalidPathError indicates a module, import, or file path doesn't -// satisfy all naming constraints. See CheckPath, CheckImportPath, -// and CheckFilePath for specific restrictions. +// satisfy all naming constraints. See [CheckPath], [CheckImportPath], +// and [CheckFilePath] for specific restrictions. type InvalidPathError struct { Kind string // "module", "import", or "file" Path string @@ -294,7 +294,7 @@ func fileNameOK(r rune) bool { } // CheckPath checks that a module path is valid. -// A valid module path is a valid import path, as checked by CheckImportPath, +// A valid module path is a valid import path, as checked by [CheckImportPath], // with three additional constraints. // First, the leading path element (up to the first slash, if any), // by convention a domain name, must contain only lower-case ASCII letters, @@ -380,7 +380,7 @@ const ( // checkPath returns an error describing why the path is not valid. // Because these checks apply to module, import, and file paths, // and because other checks may be applied, the caller is expected to wrap -// this error with InvalidPathError. +// this error with [InvalidPathError]. func checkPath(path string, kind pathKind) error { if !utf8.ValidString(path) { return fmt.Errorf("invalid UTF-8") @@ -532,7 +532,7 @@ var badWindowsNames = []string{ // they require ".vN" instead of "/vN", and for all N, not just N >= 2. // SplitPathVersion returns with ok = false when presented with // a path whose last path element does not satisfy the constraints -// applied by CheckPath, such as "example.com/pkg/v1" or "example.com/pkg/v1.2". +// applied by [CheckPath], such as "example.com/pkg/v1" or "example.com/pkg/v1.2". func SplitPathVersion(path string) (prefix, pathMajor string, ok bool) { if strings.HasPrefix(path, "gopkg.in/") { return splitGopkgIn(path) @@ -582,7 +582,7 @@ func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) { // MatchPathMajor reports whether the semantic version v // matches the path major version pathMajor. // -// MatchPathMajor returns true if and only if CheckPathMajor returns nil. +// MatchPathMajor returns true if and only if [CheckPathMajor] returns nil. func MatchPathMajor(v, pathMajor string) bool { return CheckPathMajor(v, pathMajor) == nil } @@ -622,7 +622,7 @@ func CheckPathMajor(v, pathMajor string) error { // PathMajorPrefix returns the major-version tag prefix implied by pathMajor. // An empty PathMajorPrefix allows either v0 or v1. // -// Note that MatchPathMajor may accept some versions that do not actually begin +// Note that [MatchPathMajor] may accept some versions that do not actually begin // with this prefix: namely, it accepts a 'v0.0.0-' prefix for a '.v1' // pathMajor, even though that pathMajor implies 'v1' tagging. func PathMajorPrefix(pathMajor string) string { @@ -643,7 +643,7 @@ func PathMajorPrefix(pathMajor string) string { } // CanonicalVersion returns the canonical form of the version string v. -// It is the same as semver.Canonical(v) except that it preserves the special build suffix "+incompatible". +// It is the same as [semver.Canonical] except that it preserves the special build suffix "+incompatible". func CanonicalVersion(v string) string { cv := semver.Canonical(v) if semver.Build(v) == "+incompatible" { @@ -652,8 +652,8 @@ func CanonicalVersion(v string) string { return cv } -// Sort sorts the list by Path, breaking ties by comparing Version fields. -// The Version fields are interpreted as semantic versions (using semver.Compare) +// Sort sorts the list by Path, breaking ties by comparing [Version] fields. +// The Version fields are interpreted as semantic versions (using [semver.Compare]) // optionally followed by a tie-breaking suffix introduced by a slash character, // like in "v0.0.1/go.mod". func Sort(list []Version) { @@ -793,7 +793,7 @@ func unescapeString(escaped string) (string, bool) { } // MatchPrefixPatterns reports whether any path prefix of target matches one of -// the glob patterns (as defined by path.Match) in the comma-separated globs +// the glob patterns (as defined by [path.Match]) in the comma-separated globs // list. This implements the algorithm used when matching a module path to the // GOPRIVATE environment variable, as described by 'go help module-private'. // diff --git a/vendor/golang.org/x/mod/module/pseudo.go b/vendor/golang.org/x/mod/module/pseudo.go index f04ad378..9cf19d32 100644 --- a/vendor/golang.org/x/mod/module/pseudo.go +++ b/vendor/golang.org/x/mod/module/pseudo.go @@ -125,7 +125,7 @@ func IsPseudoVersion(v string) bool { } // IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base, -// timestamp, and revision, as returned by ZeroPseudoVersion. +// timestamp, and revision, as returned by [ZeroPseudoVersion]. func IsZeroPseudoVersion(v string) bool { return v == ZeroPseudoVersion(semver.Major(v)) } diff --git a/vendor/golang.org/x/mod/semver/semver.go b/vendor/golang.org/x/mod/semver/semver.go index a30a22bf..9a2dfd33 100644 --- a/vendor/golang.org/x/mod/semver/semver.go +++ b/vendor/golang.org/x/mod/semver/semver.go @@ -140,7 +140,7 @@ func Compare(v, w string) int { // Max canonicalizes its arguments and then returns the version string // that compares greater. // -// Deprecated: use Compare instead. In most cases, returning a canonicalized +// Deprecated: use [Compare] instead. In most cases, returning a canonicalized // version is not expected or desired. func Max(v, w string) string { v = Canonical(v) @@ -151,7 +151,7 @@ func Max(v, w string) string { return w } -// ByVersion implements sort.Interface for sorting semantic version strings. +// ByVersion implements [sort.Interface] for sorting semantic version strings. type ByVersion []string func (vs ByVersion) Len() int { return len(vs) } @@ -164,7 +164,7 @@ func (vs ByVersion) Less(i, j int) bool { return vs[i] < vs[j] } -// Sort sorts a list of semantic version strings using ByVersion. +// Sort sorts a list of semantic version strings using [ByVersion]. func Sort(list []string) { sort.Sort(ByVersion(list)) } diff --git a/vendor/modules.txt b/vendor/modules.txt index b40b0244..c1e28154 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -115,8 +115,8 @@ github.com/bgentry/go-netrc/netrc # github.com/bgentry/speakeasy v0.1.0 ## explicit github.com/bgentry/speakeasy -# github.com/bitfield/script v0.22.0 -## explicit; go 1.12 +# github.com/bitfield/script v0.22.1 +## explicit; go 1.18 github.com/bitfield/script # github.com/containerd/console v1.0.3 ## explicit; go 1.13 @@ -251,7 +251,7 @@ github.com/huandu/xstrings # github.com/imdario/mergo v0.3.13 ## explicit; go 1.13 github.com/imdario/mergo -# github.com/itchyny/gojq v0.12.12 +# github.com/itchyny/gojq v0.12.13 ## explicit; go 1.18 github.com/itchyny/gojq # github.com/itchyny/timefmt-go v0.1.5 @@ -279,7 +279,7 @@ github.com/magefile/mage/sh # github.com/mattn/go-colorable v0.1.13 ## explicit; go 1.15 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.17 +# github.com/mattn/go-isatty v0.0.19 ## explicit; go 1.15 github.com/mattn/go-isatty # github.com/mattn/go-runewidth v0.0.15 @@ -321,8 +321,8 @@ github.com/pterm/pterm/internal # github.com/rivo/uniseg v0.4.4 ## explicit; go 1.18 github.com/rivo/uniseg -# github.com/sheldonhull/magetools v1.0.1 -## explicit; go 1.18 +# github.com/sheldonhull/magetools v1.0.2 +## explicit; go 1.21 github.com/sheldonhull/magetools/ci github.com/sheldonhull/magetools/gotools github.com/sheldonhull/magetools/pkg/magetoolsutils @@ -405,8 +405,8 @@ golang.org/x/crypto/openpgp/packet golang.org/x/crypto/openpgp/s2k golang.org/x/crypto/pbkdf2 golang.org/x/crypto/scrypt -# golang.org/x/mod v0.10.0 -## explicit; go 1.17 +# golang.org/x/mod v0.17.0 +## explicit; go 1.18 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module @@ -603,8 +603,8 @@ google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/emptypb google.golang.org/protobuf/types/known/fieldmaskpb google.golang.org/protobuf/types/known/timestamppb -# mvdan.cc/sh/v3 v3.6.0 -## explicit; go 1.18 +# mvdan.cc/sh/v3 v3.7.0 +## explicit; go 1.19 mvdan.cc/sh/v3/expand mvdan.cc/sh/v3/fileutil mvdan.cc/sh/v3/pattern diff --git a/vendor/mvdan.cc/sh/v3/expand/arith.go b/vendor/mvdan.cc/sh/v3/expand/arith.go index 3ce199ec..20a45960 100644 --- a/vendor/mvdan.cc/sh/v3/expand/arith.go +++ b/vendor/mvdan.cc/sh/v3/expand/arith.go @@ -106,7 +106,7 @@ func oneIf(b bool) int { return 0 } -// atoi is like strconv.Atoi, but it ignores errors and trims whitespace. +// atoi is like [strconv.Atoi], but it ignores errors and trims whitespace. func atoi(s string) int { s = strings.TrimSpace(s) n, _ := strconv.Atoi(s) diff --git a/vendor/mvdan.cc/sh/v3/expand/braces.go b/vendor/mvdan.cc/sh/v3/expand/braces.go index e0363aa2..1938a8f0 100644 --- a/vendor/mvdan.cc/sh/v3/expand/braces.go +++ b/vendor/mvdan.cc/sh/v3/expand/braces.go @@ -10,7 +10,7 @@ import ( ) // Braces performs brace expansion on a word, given that it contains any -// syntax.BraceExp parts. For example, the word with a brace expansion +// [syntax.BraceExp] parts. For example, the word with a brace expansion // "foo{bar,baz}" will return two literal words, "foobar" and "foobaz". // // Note that the resulting words may share word parts. diff --git a/vendor/mvdan.cc/sh/v3/expand/environ.go b/vendor/mvdan.cc/sh/v3/expand/environ.go index 68ba384e..49cbf052 100644 --- a/vendor/mvdan.cc/sh/v3/expand/environ.go +++ b/vendor/mvdan.cc/sh/v3/expand/environ.go @@ -60,7 +60,7 @@ const ( // and a value. // // A Variable is unset if its Kind field is Unset, which can be checked via -// Variable.IsSet. The zero value of a Variable is thus a valid unset variable. +// [Variable.IsSet]. The zero value of a Variable is thus a valid unset variable. // // If a variable is set, its Value field will be a []string if it is an indexed // array, a map[string]string if it's an associative array, or a string diff --git a/vendor/mvdan.cc/sh/v3/expand/expand.go b/vendor/mvdan.cc/sh/v3/expand/expand.go index a3152dce..996d496f 100644 --- a/vendor/mvdan.cc/sh/v3/expand/expand.go +++ b/vendor/mvdan.cc/sh/v3/expand/expand.go @@ -83,7 +83,7 @@ type Config struct { } // UnexpectedCommandError is returned if a command substitution is encountered -// when Config.CmdSubst is nil. +// when [Config.CmdSubst] is nil. type UnexpectedCommandError struct { Node *syntax.CmdSubst } @@ -182,9 +182,9 @@ func Document(cfg *Config, word *syntax.Word) (string, error) { const patMode = pattern.Filenames | pattern.Braces -// Pattern expands a single shell word as a pattern, using syntax.QuotePattern +// Pattern expands a single shell word as a pattern, using [syntax.QuotePattern] // on any non-quoted parts of the input word. The result can be used on -// syntax.TranslatePattern directly. +// [syntax.TranslatePattern] directly. // // The config specifies shell expansion options; nil behaves the same as an // empty config. @@ -287,9 +287,10 @@ formatLoop: case 'x', 'u', 'U': i++ max := 2 - if c == 'u' { + switch c { + case 'u': max = 4 - } else if c == 'U' { + case 'U': max = 8 } digits := readDigits(max, true) @@ -342,7 +343,7 @@ formatLoop: if len(args) > 0 { arg, args = args[0], args[1:] } - var farg interface{} + var farg any if c == 'b' { // Passing in nil for args ensures that % format // strings aren't processed; only escape sequences @@ -801,7 +802,7 @@ func findAllIndex(pat, name string, n int) [][]int { var rxGlobStar = regexp.MustCompile(".*") -// pathJoin2 is a simpler version of filepath.Join without cleaning the result, +// pathJoin2 is a simpler version of [filepath.Join] without cleaning the result, // since that's needed for globbing. func pathJoin2(elem1, elem2 string) string { if elem1 == "" { @@ -814,7 +815,7 @@ func pathJoin2(elem1, elem2 string) string { } // pathSplit splits a file path into its elements, retaining empty ones. Before -// splitting, slashes are replaced with filepath.Separator, so that splitting +// splitting, slashes are replaced with [filepath.Separator], so that splitting // Unix paths on Windows works as well. func pathSplit(path string) []string { path = filepath.FromSlash(path) @@ -976,7 +977,8 @@ func (cfg *Config) globDir(base, dir string, rx *regexp.Regexp, matchHidden bool return matches, nil } -// ReadFields TODO write doc. +// ReadFields splits and returns n fields from s, like the "read" shell builtin. +// If raw is set, backslash escape sequences are not interpreted. // // The config specifies shell expansion options; nil behaves the same as an // empty config. diff --git a/vendor/mvdan.cc/sh/v3/expand/param.go b/vendor/mvdan.cc/sh/v3/expand/param.go index bf0d2382..1f1a475f 100644 --- a/vendor/mvdan.cc/sh/v3/expand/param.go +++ b/vendor/mvdan.cc/sh/v3/expand/param.go @@ -199,8 +199,7 @@ func (cfg *Config) paramExp(pe *syntax.ParamExp) (string, error) { if pe.Slice.Length != nil { str = str[:slicePos(sliceLen)] } - } else { // elems are already sliced - } + } // else, elems are already sliced case pe.Repl != nil: orig, err := Pattern(cfg, pe.Repl.Orig) if err != nil { diff --git a/vendor/mvdan.cc/sh/v3/fileutil/file.go b/vendor/mvdan.cc/sh/v3/fileutil/file.go index 1ccf6fef..249ae94c 100644 --- a/vendor/mvdan.cc/sh/v3/fileutil/file.go +++ b/vendor/mvdan.cc/sh/v3/fileutil/file.go @@ -1,8 +1,8 @@ // Copyright (c) 2016, Daniel Martí // See LICENSE for licensing information -// Package fileutil contains code to work with shell files, also known -// as shell scripts. +// Package fileutil allows inspecting shell files, such as detecting whether a +// file may be shell or extracting its shebang. package fileutil import ( diff --git a/vendor/mvdan.cc/sh/v3/pattern/pattern.go b/vendor/mvdan.cc/sh/v3/pattern/pattern.go index bde1ca71..7cd98d14 100644 --- a/vendor/mvdan.cc/sh/v3/pattern/pattern.go +++ b/vendor/mvdan.cc/sh/v3/pattern/pattern.go @@ -39,16 +39,16 @@ const ( var numRange = regexp.MustCompile(`^([+-]?\d+)\.\.([+-]?\d+)}`) // Regexp turns a shell pattern into a regular expression that can be used with -// regexp.Compile. It will return an error if the input pattern was incorrect. -// Otherwise, the returned expression can be passed to regexp.MustCompile. +// [regexp.Compile]. It will return an error if the input pattern was incorrect. +// Otherwise, the returned expression can be passed to [regexp.MustCompile]. // // For example, Regexp(`foo*bar?`, true) returns `foo.*bar.`. // -// Note that this function (and QuoteMeta) should not be directly used with file +// Note that this function (and [QuoteMeta]) should not be directly used with file // paths if Windows is supported, as the path separator on that platform is the // same character as the escaping character for shell patterns. func Regexp(pat string, mode Mode) (string, error) { - any := false + needsEscaping := false noopLoop: for _, r := range pat { switch r { @@ -56,11 +56,11 @@ noopLoop: // regular expression metacharacters case '*', '?', '[', '\\', '.', '+', '(', ')', '|', ']', '{', '}', '^', '$': - any = true + needsEscaping = true break noopLoop } } - if !any && mode&EntireString == 0 { // short-cut without a string copy + if !needsEscaping && mode&EntireString == 0 { // short-cut without a string copy return pat, nil } closingBraces := []int{} @@ -302,7 +302,7 @@ func HasMeta(pat string, mode Mode) bool { // // For example, QuoteMeta(`foo*bar?`) returns `foo\*bar\?`. func QuoteMeta(pat string, mode Mode) string { - any := false + needsEscaping := false loop: for _, r := range pat { switch r { @@ -312,11 +312,11 @@ loop: } fallthrough case '*', '?', '[', '\\': - any = true + needsEscaping = true break loop } } - if !any { // short-cut without a string copy + if !needsEscaping { // short-cut without a string copy return pat } var buf bytes.Buffer diff --git a/vendor/mvdan.cc/sh/v3/syntax/braces.go b/vendor/mvdan.cc/sh/v3/syntax/braces.go index dca854fd..f3452819 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/braces.go +++ b/vendor/mvdan.cc/sh/v3/syntax/braces.go @@ -23,7 +23,7 @@ var ( // It does not return an error; malformed brace expansions are simply skipped. // For example, the literal word "a{b" is left unchanged. func SplitBraces(word *Word) bool { - any := false + toSplit := false top := &Word{} acc := top var cur *BraceExp @@ -90,7 +90,7 @@ func SplitBraces(word *Word) bool { if cur == nil { continue } - any = true + toSplit = true addlitidx() br := pop() if len(br.Elems) == 1 { @@ -154,7 +154,7 @@ func SplitBraces(word *Word) bool { addLit(&left) } } - if !any { + if !toSplit { return false } // open braces that were never closed fall back to non-braces diff --git a/vendor/mvdan.cc/sh/v3/syntax/lexer.go b/vendor/mvdan.cc/sh/v3/syntax/lexer.go index 583abb61..b5dddab7 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/lexer.go +++ b/vendor/mvdan.cc/sh/v3/syntax/lexer.go @@ -270,6 +270,18 @@ skipSpace: case ';', '"', '\'', '(', ')', '$', '|', '&', '>', '<', '`': p.tok = p.regToken(r) case '#': + // If we're parsing $foo#bar, ${foo}#bar, 'foo'#bar, or "foo"#bar, + // #bar is a continuation of the same word, not a comment. + // TODO: support $(foo)#bar and `foo`#bar as well, which is slightly tricky, + // as we can't easily tell them apart from (foo)#bar and `#bar`, + // where #bar should remain a comment. + if !p.spaced { + switch p.tok { + case _LitWord, rightBrace, sglQuote, dblQuote: + p.advanceLitNone(r) + return + } + } r = p.rune() p.newLit(r) runeLoop: @@ -372,10 +384,7 @@ func (p *Parser) extendedGlob() bool { // We do this after peeking for just one byte, so that the input `echo *` // followed by a newline does not hang an interactive shell parser until // another byte is input. - if p.peekBytes("()") { - return false - } - return true + return !p.peekBytes("()") } return false } @@ -420,9 +429,6 @@ func (p *Parser) regToken(r rune) token { p.rune() return andAnd case '>': - if p.lang == LangPOSIX { - break - } if p.rune() == '>' { p.rune() return appAll diff --git a/vendor/mvdan.cc/sh/v3/syntax/nodes.go b/vendor/mvdan.cc/sh/v3/syntax/nodes.go index a43021f7..88eb7fea 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/nodes.go +++ b/vendor/mvdan.cc/sh/v3/syntax/nodes.go @@ -112,14 +112,14 @@ func (p Pos) Offset() uint { return uint(p.offs) } // Line returns the line number of the position, starting at 1. // // Line is protected against overflows; if an input has too many lines, extra -// lines will have a line number of 0, rendered as "?" by Pos.String. +// lines will have a line number of 0, rendered as "?" by [Pos.String]. func (p Pos) Line() uint { return uint(p.lineCol >> colBitSize) } // Col returns the column number of the position, starting at 1. It counts in // bytes. // // Col is protected against overflows; if an input line has too many columns, -// extra columns will have a column number of 0, rendered as "?" by Pos.String. +// extra columns will have a column number of 0, rendered as "?" by [Pos.String]. func (p Pos) Col() uint { return uint(p.lineCol & colBitMask) } func (p Pos) String() string { @@ -139,7 +139,7 @@ func (p Pos) String() string { } // IsValid reports whether the position contains useful position information. -// Some positions returned via Parse may be invalid: for example, Stmt.Semicolon +// Some positions returned via [Parse] may be invalid: for example, [Stmt.Semicolon] // will only be valid if a statement contained a closing token such as ';'. func (p Pos) IsValid() bool { return p != Pos{} } diff --git a/vendor/mvdan.cc/sh/v3/syntax/parser.go b/vendor/mvdan.cc/sh/v3/syntax/parser.go index 86e7274c..99ae17c2 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/parser.go +++ b/vendor/mvdan.cc/sh/v3/syntax/parser.go @@ -230,8 +230,7 @@ func (w *wrappedReader) Read(p []byte) (n int, err error) { // called with said statements. // // If a line ending in an incomplete statement is parsed, the function will be -// called with any fully parsed statements, and Parser.Incomplete will return -// true. +// called with any fully parsed statements, and [Parser.Incomplete] will return true. // // One can imagine a simple interactive shell implementation as follows: // @@ -414,7 +413,7 @@ type Parser struct { // it needs to finish properly parsing a statement. // // It is only safe to call while the parser is blocked on a read. For an example -// use case, see the documentation for Parser.Interactive. +// use case, see [Parser.Interactive]. func (p *Parser) Incomplete() bool { // If we're in a quote state other than noState, we're parsing a node // such as a double-quoted string. @@ -738,7 +737,7 @@ func (p *Parser) quoteErr(lpos Pos, quote token) { p.tok.String(), quote) } -func (p *Parser) matchingErr(lpos Pos, left, right interface{}) { +func (p *Parser) matchingErr(lpos Pos, left, right any) { p.posErr(lpos, "reached %s without matching %s with %s", p.tok.String(), left, right) } @@ -762,7 +761,7 @@ func (p *Parser) errPass(err error) { } // IsIncomplete reports whether a Parser error could have been avoided with -// extra input bytes. For example, if an io.EOF was encountered while there was +// extra input bytes. For example, if an [io.EOF] was encountered while there was // an unclosed quote or parenthesis. func IsIncomplete(err error) bool { perr, ok := err.(ParseError) @@ -804,8 +803,8 @@ func IsKeyword(word string) bool { // the parser cannot recover. type ParseError struct { Filename string - Pos - Text string + Pos Pos + Text string Incomplete bool } @@ -822,9 +821,9 @@ func (e ParseError) Error() string { // in the current language variant, and what languages support it. type LangError struct { Filename string - Pos - Feature string - Langs []LangVariant + Pos Pos + Feature string + Langs []LangVariant } func (e LangError) Error() string { @@ -849,7 +848,7 @@ func (e LangError) Error() string { return buf.String() } -func (p *Parser) posErr(pos Pos, format string, a ...interface{}) { +func (p *Parser) posErr(pos Pos, format string, a ...any) { p.errPass(ParseError{ Filename: p.f.Name, Pos: pos, @@ -858,7 +857,7 @@ func (p *Parser) posErr(pos Pos, format string, a ...interface{}) { }) } -func (p *Parser) curErr(format string, a ...interface{}) { +func (p *Parser) curErr(format string, a ...any) { p.posErr(p.pos, format, a...) } @@ -1628,6 +1627,9 @@ func (p *Parser) doRedirect(s *Stmt) { if !p.lang.isBash() && r.N != nil && r.N.Value[0] == '{' { p.langErr(r.N.Pos(), "{varname} redirects", LangBash) } + if p.lang == LangPOSIX && (p.tok == rdrAll || p.tok == appAll) { + p.langErr(p.pos, "&> redirects", LangBash, LangMirBSDKorn) + } r.Op, r.OpPos = RedirOperator(p.tok), p.pos p.next() switch r.Op { @@ -2078,7 +2080,7 @@ func (p *Parser) caseClause(s *Stmt) { func (p *Parser) caseItems(stop string) (items []*CaseItem) { p.got(_Newl) - for p.tok != _EOF && !(p.tok == _LitWord && p.val == stop) { + for p.tok != _EOF && (p.tok != _LitWord || p.val != stop) { ci := &CaseItem{} ci.Comments, p.accComs = p.accComs, nil p.got(leftParen) diff --git a/vendor/mvdan.cc/sh/v3/syntax/printer.go b/vendor/mvdan.cc/sh/v3/syntax/printer.go index 6626b363..84ad6850 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/printer.go +++ b/vendor/mvdan.cc/sh/v3/syntax/printer.go @@ -216,7 +216,7 @@ func (c *colCounter) Reset(w io.Writer) { // Printer holds the internal state of the printing mechanism of a // program. type Printer struct { - bufWriter + bufWriter // TODO: embedding this makes the methods part of the API, which we did not intend tabWriter *tabwriter.Writer cols colCounter @@ -308,7 +308,7 @@ func (p *Printer) spacePad(pos Pos) { // wantsNewline reports whether we want to print at least one newline before // printing a node at a given position. A zero position can be given to simply // tell if we want a newline following what's just been printed. -func (p *Printer) wantsNewline(pos Pos) bool { +func (p *Printer) wantsNewline(pos Pos, escapingNewline bool) bool { if p.mustNewline { // We must have a newline here. return true @@ -319,7 +319,10 @@ func (p *Printer) wantsNewline(pos Pos) bool { // as that might move them further down to the wrong place. return false } - // THe newline is optional, and we want it via either wantNewline or via + if escapingNewline && p.minify { + return false + } + // The newline is optional, and we want it via either wantNewline or via // the position's line. return p.wantNewline || pos.Line() > p.line } @@ -351,7 +354,7 @@ func (p *Printer) spacedToken(s string, pos Pos) { } func (p *Printer) semiOrNewl(s string, pos Pos) { - if p.wantsNewline(Pos{}) { + if p.wantsNewline(Pos{}, false) { p.newline(pos) p.indent() } else { @@ -509,7 +512,7 @@ func (p *Printer) newlines(pos Pos) { p.firstLine = false return // no empty lines at the top } - if !p.wantsNewline(pos) { + if !p.wantsNewline(pos, false) { return } p.flushHeredocs() @@ -527,7 +530,7 @@ func (p *Printer) newlines(pos Pos) { } func (p *Printer) rightParen(pos Pos) { - if !p.minify { + if len(p.pendingHdocs) > 0 || !p.minify { p.newlines(pos) } p.WriteByte(')') @@ -535,7 +538,7 @@ func (p *Printer) rightParen(pos Pos) { } func (p *Printer) semiRsrv(s string, pos Pos) { - if p.wantsNewline(pos) { + if p.wantsNewline(pos, false) { p.newlines(pos) } else { if !p.wroteSemi { @@ -955,7 +958,7 @@ func (p *Printer) casePatternJoin(pats []*Word) { if i > 0 { p.spacedToken("|", Pos{}) } - if p.wantsNewline(w.Pos()) { + if p.wantsNewline(w.Pos(), true) { if !anyNewline { p.incLevel() anyNewline = true @@ -1015,7 +1018,7 @@ func (p *Printer) stmt(s *Stmt) { } p.incLevel() for _, r := range s.Redirs[startRedirs:] { - if p.wantsNewline(r.OpPos) { + if p.wantsNewline(r.OpPos, true) { p.bslashNewl() } if p.wantSpace == spaceRequired { @@ -1413,7 +1416,7 @@ func (p *Printer) nestedStmts(stmts []*Stmt, last []Comment, closing Pos) { func (p *Printer) assigns(assigns []*Assign) { p.incLevel() for _, a := range assigns { - if p.wantsNewline(a.Pos()) { + if p.wantsNewline(a.Pos(), true) { p.bslashNewl() } else { p.spacePad(a.Pos()) diff --git a/vendor/mvdan.cc/sh/v3/syntax/simplify.go b/vendor/mvdan.cc/sh/v3/syntax/simplify.go index 5a93966e..e82fd55a 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/simplify.go +++ b/vendor/mvdan.cc/sh/v3/syntax/simplify.go @@ -16,7 +16,6 @@ import "bytes" // Remove redundant quotes [[ "$var" == str ]] // Merge negations with unary operators [[ ! -n $var ]] // Use single quotes to shorten literals "\$foo" -// Remove redundant param expansion colons ${foo:-} func Simplify(n Node) bool { s := simplifier{} Walk(n, s.visit) @@ -38,10 +37,6 @@ func (s *simplifier) visit(node Node) bool { x.Index = s.removeParensArithm(x.Index) // don't inline params - same as above. - if x.Exp != nil && x.Exp.Op == DefaultUnsetOrNull && x.Exp.Word == nil { - s.modified = true - x.Exp.Op = DefaultUnset - } if x.Slice == nil { break } diff --git a/vendor/mvdan.cc/sh/v3/syntax/walk.go b/vendor/mvdan.cc/sh/v3/syntax/walk.go index be3f2090..5be8f9c6 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/walk.go +++ b/vendor/mvdan.cc/sh/v3/syntax/walk.go @@ -244,7 +244,7 @@ type debugPrinter struct { err error } -func (p *debugPrinter) printf(format string, args ...interface{}) { +func (p *debugPrinter) printf(format string, args ...any) { _, err := fmt.Fprintf(p.out, format, args...) if err != nil && p.err == nil { p.err = err