Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gojq for openSUSE:Factory checked in at 2024-12-02 16:59:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gojq (Old) and /work/SRC/openSUSE:Factory/.gojq.new.28523 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gojq" Mon Dec 2 16:59:01 2024 rev:7 rq:1227621 version:0.12.17 Changes: -------- --- /work/SRC/openSUSE:Factory/gojq/gojq.changes 2024-06-03 17:42:55.561845875 +0200 +++ /work/SRC/openSUSE:Factory/.gojq.new.28523/gojq.changes 2024-12-02 16:59:18.669646263 +0100 @@ -1,0 +2,14 @@ +Sun Dec 1 17:17:33 UTC 2024 - Arnav Singh <opens...@arnavion.dev> + +- Update to v0.12.17 + * Implement `add/1`, `skip/2` functions. + * Implement `--library-path` option as the alias of `-L` option. + * Fix `reduce` syntax to emit results for each initial value. + * Fix `last/1` to yield no values when the argument yields no values. + * Fix `limit/2` to emit an error on negative count. + * Fix `@uri` and `@urid` formats not to convert space between plus sign. + * Fix resolving search paths of import statements in the query. + * Improve time functions to accept fewer element arrays. + + +------------------------------------------------------------------- Old: ---- gojq-0.12.16.tar.gz New: ---- gojq-0.12.17.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gojq.spec ++++++ --- /var/tmp/diff_new_pack.EvxjmE/_old 2024-12-02 16:59:19.265671271 +0100 +++ /var/tmp/diff_new_pack.EvxjmE/_new 2024-12-02 16:59:19.269671439 +0100 @@ -17,7 +17,7 @@ Name: gojq -Version: 0.12.16 +Version: 0.12.17 Release: 0 Summary: Pure Go implementation of jq License: MIT @@ -25,7 +25,7 @@ Source0: %{url}/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz Source1: vendor.tar.zst Source2: gojq.rpmlintrc -BuildRequires: go >= 1.20 +BuildRequires: go >= 1.21 BuildRequires: golang-packaging BuildRequires: zstd ++++++ gojq-0.12.16.tar.gz -> gojq-0.12.17.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/.github/workflows/ci.yaml new/gojq-0.12.17/.github/workflows/ci.yaml --- old/gojq-0.12.16/.github/workflows/ci.yaml 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/.github/workflows/ci.yaml 2024-12-01 13:30:01.000000000 +0100 @@ -21,7 +21,7 @@ - name: Setup Go uses: actions/setup-go@v5 with: - go-version: 1.22.x + go-version: 1.23.x - name: Build run: make build - name: Check command examples @@ -54,7 +54,7 @@ strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - go: [1.22.x, 1.21.x, 1.20.x] + go: [1.23.x, 1.22.x, 1.21.x] fail-fast: false steps: - name: Checkout code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/CHANGELOG.md new/gojq-0.12.17/CHANGELOG.md --- old/gojq-0.12.16/CHANGELOG.md 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/CHANGELOG.md 2024-12-01 13:30:01.000000000 +0100 @@ -1,4 +1,14 @@ # Changelog +## [v0.12.17](https://github.com/itchyny/gojq/compare/v0.12.16..v0.12.17) (2024-12-01) +* implement `add/1`, `skip/2` functions +* implement `--library-path` option as the alias of `-L` option +* fix `reduce` syntax to emit results for each initial value +* fix `last/1` to yield no values when the argument yields no values +* fix `limit/2` to emit an error on negative count +* fix `@uri` and `@urid` formats not to convert space between plus sign +* fix resolving search paths of import statements in the query +* improve time functions to accept fewer element arrays + ## [v0.12.16](https://github.com/itchyny/gojq/compare/v0.12.15..v0.12.16) (2024-06-01) * fix offset of query parsing error on multi-byte characters * fix tests of `exp10` and `atan2` failing on some platforms diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/Dockerfile new/gojq-0.12.17/Dockerfile --- old/gojq-0.12.16/Dockerfile 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/Dockerfile 2024-12-01 13:30:01.000000000 +0100 @@ -1,10 +1,10 @@ -FROM golang:1.22 AS builder +FROM golang:1.23 AS builder WORKDIR /app COPY go.* ./ RUN go mod download COPY . . -ENV CGO_ENABLED 0 +ENV CGO_ENABLED=0 RUN make build FROM gcr.io/distroless/static:debug diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/Makefile new/gojq-0.12.17/Makefile --- old/gojq-0.12.16/Makefile 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/Makefile 2024-12-01 13:30:01.000000000 +0100 @@ -89,9 +89,9 @@ .PHONY: update update: export GOPROXY=direct update: - go get -u -d ./... && go mod tidy + go get -u ./... && go mod tidy go mod edit -modfile=go.dev.mod -droprequire=github.com/itchyny/{astgen,timefmt}-go - go get -u -d -modfile=go.dev.mod github.com/itchyny/{astgen,timefmt}-go && go generate + go get -u -modfile=go.dev.mod github.com/itchyny/{astgen,timefmt}-go && go generate .PHONY: bump bump: $(GOBIN)/gobump diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/_gojq new/gojq-0.12.17/_gojq --- old/gojq-0.12.16/_gojq 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/_gojq 2024-12-01 13:30:01.000000000 +0100 @@ -7,7 +7,7 @@ '(-r --raw-output -j --join-output)--raw-output0[implies -r with NUL character delimiter]' \ '(-r --raw-output --raw-output0 -j --join-output)'{-j,--join-output}'[implies -r with no newline delimiter]' \ '(-c --compact-output --indent --tab --yaml-output)'{-c,--compact-output}'[output without pretty-printing]' \ - '(-c --compact-output --tab --yaml-output)--indent=[number of spaces for indentation]:indentation count:(2 4 8)' \ + '(-c --compact-output --tab --yaml-output)--indent[number of spaces for indentation]:indentation count:(2 4 8)' \ '(-c --compact-output --indent --yaml-output)--tab[use tabs for indentation]' \ '(-c --compact-output --indent --tab )--yaml-output[output in YAML format]' \ '(-C --color-output -M --monochrome-output)'{-C,--color-output}'[output with colors even if piped]' \ @@ -18,7 +18,7 @@ '(-R --raw-input --stream )--yaml-input[read input as YAML format]' \ '(-s --slurp)'{-s,--slurp}'[read all inputs into an array]' \ '(-f --from-file 1)'{-f,--from-file}'[load query from file]:filename of jq query:_files' \ - '*-L=[directory to search modules from]:module directory:_directories' \ + '*'{-L,--library-path}'[directory to search modules from]:module directory:_directories' \ '*--arg[set a string value to a variable]:variable name: :string value' \ '*--argjson[set a JSON value to a variable]:variable name: :JSON value' \ '*--slurpfile[set the JSON contents of a file to a variable]:variable name: :JSON file:_files' \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/builtin.go new/gojq-0.12.17/builtin.go --- old/gojq-0.12.16/builtin.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/builtin.go 2024-12-01 13:30:01.000000000 +0100 @@ -9,6 +9,7 @@ "JOIN": {{Name: "JOIN", Args: []string{"$idx", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}}}}, {Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}, {Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr", "join_expr"}, Body: &Query{Left: &Query{Func: "s tream"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "join_expr"}}}}}, "_assign": {}, "_modify": {}, + "add": {{Name: "add", Args: []string{"f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}, Op: OpPipe, Right: &Query{Func: "add"}}}}, "all": {{Name: "all", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{{Func: "."}}}}}}, {Name: "all", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}}}, {Func: "y"}}}}}}, {Name: "all", Args: []string{"g", "y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "y"}, Op: OpPipe, Right: &Query{Func: "not"}}}}}}}}}}}}}, "any": {{Name: "any", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{{Func: "."}}}}}}, {Name: "any", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}}}, {Func: "y"}}}}}}, {Name: "any", Args: []string{"g", "y"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Func: "y"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "not"}}}}, "arrays": {{Name: "arrays", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}}}}}}}, @@ -20,7 +21,7 @@ "first": {{Name: "first", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}, {Name: "first", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}, "fromdate": {{Name: "fromdate", Body: &Query{Func: "fromdateiso8601"}}}, "fromdateiso8601": {{Name: "fromdateiso8601", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strptime", Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%S%z"}}}}}}}, Op: OpPipe, Right: &Query{Func: "mktime"}}}}, - "fromstream": {{Name: "fromstream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{{Key: "x", Val: &Query{Func: "null"}}, {Key: "e", Val: &Query{Func: "false"}}}}, SuffixList: []*Suffix{{Bind: &Bind{Patterns: []*Pattern{{Name: "$init"}}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Query: &Query{Func: "f"}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Func: "$init"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Func: "$init"}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "2"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, {Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "x"}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, {Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, {Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "x"}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}, + "fromstream": {{Name: "fromstream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Query: &Query{Func: "f"}, Pattern: &Pattern{Name: "$pv"}, Start: &Query{Func: "null"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Func: "null"}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$pv"}, SuffixList: []*Suffix{{Bind: &Bind{Patterns: []*Pattern{{Array: []*Pattern{{Name: "$p"}, {Name: "$v"}}}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$pv"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "2"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTyp eString, Str: &String{Str: "v"}}}}}}, Op: OpAdd, Right: &Query{Func: "$p"}}, {Func: "$v"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, {Left: &Query{Func: "$p"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, {Left: &Query{Func: "$p"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}}}}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "v"}}}, Else: &Query{Func: "empty"}}}}}}}}}, "group_by": {{Name: "group_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_group_by", Args: []*Query{{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, "gsub": {{Name: "gsub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{{Func: "$re"}, {Func: "str"}, {Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, {Name: "gsub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{{Func: "$re"}, {Func: "str"}, {Left: &Query{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}}}, "in": {{Name: "in", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Bind: &Bind{Patterns: []*Pattern{{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "has", Args: []*Query{{Func: "$x"}}}}}}}}}}}}}, @@ -28,8 +29,8 @@ "inside": {{Name: "inside", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Bind: &Bind{Patterns: []*Pattern{{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "contains", Args: []*Query{{Func: "$x"}}}}}}}}}}}}}, "isempty": {{Name: "isempty", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "false"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}, Op: OpComma, Right: &Query{Func: "true"}}}}}}}, "iterables": {{Name: "iterables", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, - "last": {{Name: "last", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}, {Name: "last", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Query: &Query{Func: "g"}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "null"}, Update: &Query{Func: "$item"}}}}}}, - "limit": {{Name: "limit", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Query: &Query{Func: "g"}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}, Else: &Query{Func: "empty"}}}}}}}}}}}, Elif: []*IfElif{{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumbe r, Number: "0"}}}, Then: &Query{Func: "empty"}}}, Else: &Query{Func: "g"}}}}}}, + "last": {{Name: "last", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}, + "limit": {{Name: "limit", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Query: &Query{Func: "g"}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}, Else: &Query{Func: "empty"}}}}}}}}}}}, Elif: []*IfElif{{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumbe r, Number: "0"}}}, Then: &Query{Func: "empty"}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: "limit doesn't support negative count"}}}}}}}}}}}}, "map": {{Name: "map", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}, "map_values": {{Name: "map_values", Args: []string{"f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}}}, Op: OpModify, Right: &Query{Func: "f"}}}}, "match": {{Name: "match", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{{Func: "$re"}, {Func: "null"}}}}}}, {Name: "match", Args: []string{"$re", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{{Func: "$re"}, {Func: "$flags"}, {Func: "false"}}}, SuffixList: []*Suffix{{Iter: true}}}}}}, @@ -37,7 +38,7 @@ "min_by": {{Name: "min_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_min_by", Args: []*Query{{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, "normals": {{Name: "normals", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Func: "isnormal"}}}}}}}, "not": {{Name: "not", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "."}, Then: &Query{Func: "false"}, Else: &Query{Func: "true"}}}}}}, - "nth": {{Name: "nth", Args: []string{"$n"}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$n"}}}}}, {Name: "nth", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: "nth doesn't support negative indices"}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Query: &Query{Func: "g"}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Left: &Query{Func: "$n"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Term: &Term{Type: Ter mTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}}, + "nth": {{Name: "nth", Args: []string{"$n"}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$n"}}}}}, {Name: "nth", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "first", Args: []*Query{{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "skip", Args: []*Query{{Func: "$n"}, {Func: "g"}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: "nth doesn't support negative index"}}}}}}}}}}}}, "nulls": {{Name: "nulls", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Func: "null"}}}}}}}}, "numbers": {{Name: "numbers", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}}}}}}, "objects": {{Name: "objects", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}, @@ -49,6 +50,7 @@ "scalars": {{Name: "scalars", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, "scan": {{Name: "scan", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "scan", Args: []*Query{{Func: "$re"}, {Func: "null"}}}}}}, {Name: "scan", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{{Func: "$re"}, {Left: &Query{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}, Else: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}, SuffixList: []*Suffix{{Iter: true}, {Index: &Index{Name: "string"}}}}}}}}}}}}}}, "select": {{Name: "select", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "f"}, Then: &Query{Func: "."}, Else: &Query{Func: "empty"}}}}}}, + "skip": {{Name: "skip", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Query: &Query{Func: "g"}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Func: "$item"}, Else: &Query{Func: "empty"}}}}}}}, Elif: []*IfElif{{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Func: "g"}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{{Term: &Term{Type: TermTypeString, Str : &String{Str: "skip doesn't support negative count"}}}}}}}}}}}}, "sort_by": {{Name: "sort_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_sort_by", Args: []*Query{{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, "splits": {{Name: "splits", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "splits", Args: []*Query{{Func: "$re"}, {Func: "null"}}}}}}, {Name: "splits", Args: []string{"$re", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "split", Args: []*Query{{Func: "$re"}, {Func: "$flags"}}}, SuffixList: []*Suffix{{Iter: true}}}}}}, "strings": {{Name: "strings", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}}}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/builtin.jq new/gojq-0.12.17/builtin.jq --- old/gojq-0.12.16/builtin.jq 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/builtin.jq 2024-12-01 13:30:01.000000000 +0100 @@ -20,6 +20,7 @@ def range($start; $end): _range($start; $end; 1); def range($start; $end; $step): _range($start; $end; $step); +def add(f): [f] | add; def min_by(f): _min_by(map([f])); def max_by(f): _max_by(map([f])); def sort_by(f): _sort_by(map([f])); @@ -58,7 +59,6 @@ def first: .[0]; def first(g): label $out | g | ., break $out; def last: .[-1]; -def last(g): reduce g as $item (null; $item); def isempty(g): label $out | (g | false, break $out), true; def all: all(.); def all(y): all(.[]; y); @@ -77,36 +77,43 @@ elif $n == 0 then empty else + error("limit doesn't support negative count") + end; +def skip($n; g): + if $n > 0 then + foreach g as $item ( + $n; + . - 1; + if . < 0 then $item else empty end + ) + elif $n == 0 then g + else + error("skip doesn't support negative count") end; def nth($n): .[$n]; def nth($n; g): - if $n < 0 then - error("nth doesn't support negative indices") + if $n >= 0 then + first(skip($n; g)) else - label $out | - foreach g as $item ( - $n + 1; - . - 1; - if . <= 0 then $item, break $out else empty end - ) + error("nth doesn't support negative index") end; def truncate_stream(f): . as $n | null | f | if .[0] | length > $n then .[0] |= .[$n:] else empty end; def fromstream(f): - { x: null, e: false } as $init | - foreach f as $i ( - $init; - if .e then $init end | - if $i | length == 2 then - setpath(["e"]; $i[0] | length == 0) | - setpath(["x"] + $i[0]; $i[1]) + foreach f as $pv ( + null; + if .e then null end | + $pv as [$p, $v] | + if $pv | length == 2 then + setpath(["v"] + $p; $v) | + setpath(["e"]; $p | length == 0) else - setpath(["e"]; $i[0] | length == 1) + setpath(["e"]; $p | length == 1) end; - if .e then .x else empty end + if .e then .v else empty end ); def tostream: path(def r: (.[]? | r), .; r) as $p | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/cli.go new/gojq-0.12.17/cli/cli.go --- old/gojq-0.12.16/cli/cli.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/cli.go 2024-12-01 13:30:01.000000000 +0100 @@ -16,7 +16,7 @@ const name = "gojq" -const version = "0.12.16" +const version = "0.12.17" var revision = "HEAD" @@ -58,7 +58,7 @@ OutputRaw0 bool `long:"raw-output0" description:"implies -r with NUL character delimiter"` OutputJoin bool `short:"j" long:"join-output" description:"implies -r with no newline delimiter"` OutputCompact bool `short:"c" long:"compact-output" description:"output without pretty-printing"` - OutputIndent *int `long:"indent" description:"number of spaces for indentation"` + OutputIndent *int `long:"indent" args:"number" description:"number of spaces for indentation"` OutputTab bool `long:"tab" description:"use tabs for indentation"` OutputYAML bool `long:"yaml-output" description:"output in YAML format"` OutputColor bool `short:"C" long:"color-output" description:"output with colors even if piped"` @@ -69,11 +69,11 @@ InputYAML bool `long:"yaml-input" description:"read input as YAML format"` InputSlurp bool `short:"s" long:"slurp" description:"read all inputs into an array"` FromFile bool `short:"f" long:"from-file" description:"load query from file"` - ModulePaths []string `short:"L" description:"directory to search modules from"` - Arg map[string]string `long:"arg" description:"set a string value to a variable"` - ArgJSON map[string]string `long:"argjson" description:"set a JSON value to a variable"` - SlurpFile map[string]string `long:"slurpfile" description:"set the JSON contents of a file to a variable"` - RawFile map[string]string `long:"rawfile" description:"set the contents of a file to a variable"` + ModulePaths []string `short:"L" long:"library-path" args:"dir" description:"directory to search modules from"` + Arg map[string]string `long:"arg" args:"name value" description:"set a string value to a variable"` + ArgJSON map[string]string `long:"argjson" args:"name value" description:"set a JSON value to a variable"` + SlurpFile map[string]string `long:"slurpfile" args:"name file" description:"set the JSON contents of a file to a variable"` + RawFile map[string]string `long:"rawfile" args:"name file" description:"set the contents of a file to a variable"` Args []any `long:"args" positional:"" description:"consume remaining arguments as positional string values"` JSONArgs []any `long:"jsonargs" positional:"" description:"consume remaining arguments as positional JSON values"` ExitStatus bool `short:"e" long:"exit-status" description:"exit 1 when the last value is false or null"` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/cli_test.go new/gojq-0.12.17/cli/cli_test.go --- old/gojq-0.12.16/cli/cli_test.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/cli_test.go 2024-12-01 13:30:01.000000000 +0100 @@ -12,8 +12,6 @@ func init() { addDefaultModulePaths = false - os.Setenv("NO_COLOR", "") - os.Setenv("GOJQ_COLORS", "") } func setLocation(loc *time.Location) func() { @@ -23,6 +21,12 @@ } func TestCliRun(t *testing.T) { + if err := os.Setenv("NO_COLOR", ""); err != nil { + t.Fatal(err) + } + if err := os.Setenv("GOJQ_COLORS", ""); err != nil { + t.Fatal(err) + } f, err := os.Open("test.yaml") if err != nil { t.Fatal(err) @@ -64,7 +68,11 @@ for _, env := range tc.Env { xs := strings.SplitN(env, "=", 2) k, v := xs[0], xs[1] - defer func(v string) { os.Setenv(k, v) }(os.Getenv(k)) + defer func(v string) { + if err := os.Setenv(k, v); err != nil { + t.Fatal(err) + } + }(os.Getenv(k)) if k == "GOJQ_COLORS" { defer func(colors [][]byte) { nullColor, falseColor, trueColor, numberColor, @@ -76,7 +84,9 @@ stringColor, objectKeyColor, arrayColor, objectColor, }) } - os.Setenv(k, v) + if err := os.Setenv(k, v); err != nil { + t.Fatal(err) + } } code := cli.run(tc.Args) if tc.Error == "" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/color.go new/gojq-0.12.17/cli/color.go --- old/gojq-0.12.16/cli/color.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/color.go 2024-12-01 13:30:01.000000000 +0100 @@ -41,32 +41,21 @@ return false } } - return num || x == "" + return num } func setColors(colors string) error { - var i int var color string for _, target := range []*[]byte{ &nullColor, &falseColor, &trueColor, &numberColor, &stringColor, &objectKeyColor, &arrayColor, &objectColor, } { - if i < len(colors) { - if j := strings.IndexByte(colors[i:], ':'); j >= 0 { - color = colors[i : i+j] - i += j + 1 - } else { - color = colors[i:] - i = len(colors) - } + color, colors, _ = strings.Cut(colors, ":") + if color != "" { if !validColor(color) { return fmt.Errorf("invalid color: %q", color) } - if color == "" { - *target = nil - } else { - *target = newColor(color) - } + *target = newColor(color) } else { *target = nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/encoder.go new/gojq-0.12.17/cli/encoder.go --- old/gojq-0.12.16/cli/encoder.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/encoder.go 2024-12-01 13:30:01.000000000 +0100 @@ -81,11 +81,7 @@ e.write([]byte("null"), nullColor) return } - if f >= math.MaxFloat64 { - f = math.MaxFloat64 - } else if f <= -math.MaxFloat64 { - f = -math.MaxFloat64 - } + f = min(max(f, -math.MaxFloat64), math.MaxFloat64) format := byte('f') if x := math.Abs(f); x != 0 && x < 1e-6 || x >= 1e21 { format = 'e' @@ -260,7 +256,7 @@ } } -func (e *encoder) write(bs []byte, color []byte) { +func (e *encoder) write(bs, color []byte) { if color == nil { e.w.Write(bs) } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/error.go new/gojq-0.12.17/cli/error.go --- old/gojq-0.12.16/cli/error.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/error.go 2024-12-01 13:30:01.000000000 +0100 @@ -125,13 +125,11 @@ msg := strings.TrimPrefix( strings.TrimPrefix(err.err.Error(), "yaml: "), "unmarshal errors:\n ") - if fmt.Sscanf(msg, "line %d: ", &line); line == 0 { + if _, e := fmt.Sscanf(msg, "line %d: ", &line); e != nil { return "invalid yaml: " + err.fname } - msg = msg[strings.Index(msg, ": ")+2:] - if i := strings.IndexByte(msg, '\n'); i >= 0 { - msg = msg[:i] - } + _, msg, _ = strings.Cut(msg, ": ") + msg, _, _ = strings.Cut(msg, "\n") linestr := getLineByLine(err.contents, line) return fmt.Sprintf("invalid yaml: %s:%d\n%s %s", err.fname, line, formatLineInfo(linestr, line, 0), msg) @@ -152,26 +150,17 @@ break } } - if offset > len(linestr) { - offset = len(linestr) - } else if offset > 0 { - offset-- - } else { - offset = 0 - } + offset = min(max(offset-1, 0), len(linestr)) if offset > 48 { skip := len(trimLastInvalidRune(linestr[:offset-48])) linestr = linestr[skip:] offset -= skip } - if len(linestr) > 64 { - linestr = linestr[:64] - } - linestr = trimLastInvalidRune(linestr) - if offset >= len(linestr) { - offset = len(linestr) - } else { + linestr = trimLastInvalidRune(linestr[:min(64, len(linestr))]) + if offset < len(linestr) { offset = len(trimLastInvalidRune(linestr[:offset])) + } else { + offset = len(linestr) } column = runewidth.StringWidth(linestr[:offset]) return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/flags.go new/gojq-0.12.17/cli/flags.go --- old/gojq-0.12.16/cli/flags.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/flags.go 2024-12-01 13:30:01.000000000 +0100 @@ -186,24 +186,12 @@ } sb.WriteString("--") sb.WriteString(flag) - switch val.Field(i).Kind() { - case reflect.Bool: - sb.WriteString(" ") - case reflect.Map: - if strings.HasSuffix(flag, "file") { - sb.WriteString(" name file") - } else { - sb.WriteString(" name value") - } - default: - if _, ok = tag.Lookup("positional"); !ok { - sb.WriteString("=") - } - } - } else { - sb.WriteString("=") } - sb.WriteString(" "[:24-sb.Len()+m]) + if args, ok := tag.Lookup("args"); ok { + sb.WriteString(" ") + sb.WriteString(args) + } + sb.WriteString(strings.Repeat(" ", 24-(sb.Len()-m))) sb.WriteString(tag.Get("description")) sb.WriteString("\n") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/inputs.go new/gojq-0.12.17/cli/inputs.go --- old/gojq-0.12.16/cli/inputs.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/inputs.go 2024-12-01 13:30:01.000000000 +0100 @@ -68,7 +68,7 @@ } type jsonInputIter struct { - dec *json.Decoder + next func() (any, error) ir *inputReader fname string offset int64 @@ -80,15 +80,16 @@ ir := newInputReader(r) dec := json.NewDecoder(ir) dec.UseNumber() - return &jsonInputIter{dec: dec, ir: ir, fname: fname} + next := func() (v any, err error) { err = dec.Decode(&v); return } + return &jsonInputIter{next: next, ir: ir, fname: fname} } func (i *jsonInputIter) Next() (any, bool) { if i.err != nil { return nil, false } - var v any - if err := i.dec.Decode(&v); err != nil { + v, err := i.next() + if err != nil { if err == io.EOF { i.err = err return nil, false @@ -119,6 +120,13 @@ return i.fname } +func newStreamInputIter(r io.Reader, fname string) inputIter { + ir := newInputReader(r) + dec := json.NewDecoder(ir) + dec.UseNumber() + return &jsonInputIter{next: newJSONStream(dec).next, ir: ir, fname: fname} +} + type nullInputIter struct { err error } @@ -253,58 +261,6 @@ return i.fname } -type streamInputIter struct { - stream *jsonStream - ir *inputReader - fname string - offset int64 - line int - err error -} - -func newStreamInputIter(r io.Reader, fname string) inputIter { - ir := newInputReader(r) - dec := json.NewDecoder(ir) - dec.UseNumber() - return &streamInputIter{stream: newJSONStream(dec), ir: ir, fname: fname} -} - -func (i *streamInputIter) Next() (any, bool) { - if i.err != nil { - return nil, false - } - v, err := i.stream.next() - if err != nil { - if err == io.EOF { - i.err = err - return nil, false - } - var offset *int64 - var line *int - if err, ok := err.(*json.SyntaxError); ok { - err.Offset -= i.offset - offset, line = &err.Offset, &i.line - } - i.err = &jsonParseError{i.fname, i.ir.getContents(offset, line), i.line, err} - return i.err, true - } - if buf := i.ir.buf; buf != nil && buf.Len() >= 16*1024 { - i.offset += int64(buf.Len()) - i.line += bytes.Count(buf.Bytes(), []byte{'\n'}) - buf.Reset() - } - return v, true -} - -func (i *streamInputIter) Close() error { - i.err = io.EOF - return nil -} - -func (i *streamInputIter) Name() string { - return i.fname -} - type yamlInputIter struct { dec *yaml.Decoder ir *inputReader diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/cli/test.yaml new/gojq-0.12.17/cli/test.yaml --- old/gojq-0.12.16/cli/test.yaml 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/cli/test.yaml 2024-12-01 13:30:01.000000000 +0100 @@ -1453,7 +1453,7 @@ expected: | {"xa":2,"xb":3} -- name: add function +- name: add/0 function args: - -c - 'add' @@ -1478,7 +1478,7 @@ "abc" [1,2,3,4] -- name: add function with a variable +- name: add/0 function with a variable args: - '. as $x | [$x, {y:1}] | add, $x' input: '{"x":0}' @@ -1491,7 +1491,7 @@ "x": 0 } -- name: add function with slicing +- name: add/0 function with slicing args: - -c - '[.[:2], [0], .[1:]] | add' @@ -1499,20 +1499,51 @@ expected: | [1,2,0,2,3] -- name: add function error +- name: add/0 function error args: - 'add' input: '[{}, [], {}]' error: | cannot add: object ({}) and array ([]) -- name: add function error +- name: add/0 function error args: - 'add' input: '["x", null, "y", {}, "z"]' error: | cannot add: string ("xy") and object ({}) +- name: add/1 function + args: + - 'add(.), add(empty), add(1,2,3), add(range(10))' + input: 'null' + expected: | + null + null + 6 + 45 + +- name: add/1 function with iterator + args: + - 'add(.[])' + input: | + [1,2,3] + ["a","b","c"] + expected: | + 6 + "abc" + +- name: add/1 function with update operator + args: + - -c + - '.y = add(.x[])' + input: | + {"x":[1,2,3]} + {"x":["a","b","c"]} + expected: | + {"x":[1,2,3],"y":6} + {"x":["a","b","c"],"y":"abc"} + - name: flatten/0 function args: - -c @@ -3348,6 +3379,22 @@ expected: | 4.5 +- name: reduce with select in update + args: + - 'reduce range(5) as $x (0; . + $x | select($x != 2))' + input: 'null' + expected: | + 8 + +- name: reduce with query in start + args: + - 'reduce range(5) as $x (range(3); . + $x)' + input: 'null' + expected: | + 10 + 11 + 12 + - name: reduce with variable binding args: - 'reduce .[] as $x (0; . + $x) as $x | $x' @@ -3407,6 +3454,33 @@ 0 1 +- name: foreach with select in update + args: + - -c + - 'foreach range(5) as $i (0; . + $i | select($i != 2); [$i, .])' + input: 'null' + expected: | + [0,0] + [1,1] + [3,4] + [4,8] + +- name: foreach with query in start + args: + - -c + - 'foreach range(3) as $i (range(3); . + $i; [$i, .])' + input: 'null' + expected: | + [0,0] + [1,1] + [2,3] + [0,1] + [1,2] + [2,4] + [0,2] + [1,3] + [2,5] + - name: foreach with unary operator args: - '[-foreach -.[] as $i (0; . + $i)]' @@ -3974,21 +4048,29 @@ function not defined: f/0 exit_code: 3 -- name: first/0, last/0 functions +- name: first/0, last/0, nth/1 functions args: - -c - - '[first, last]' + - '[first, last, nth(-6,-5,-1,0,2,5)]' input: '[1,2,3,4,5]' expected: | - [1,5] + [1,5,null,1,5,1,3,null] -- name: first/1, last/1, nth functions +- name: first/1, last/1, nth/2 functions args: - -c - - '[first(.[]), last(.[]), nth(0,3,5), nth(0,3,5;.[]), nth(9; range(infinite))]' + - '[first(.[]), last(.[]), nth(0,3,5;.[]), nth(9;range(infinite))]' input: '[1,2,3,4,5]' expected: | - [1,5,1,4,null,1,4,9] + [1,5,1,4,9] + +- name: first/1, last/1, nth/2 functions on empty + args: + - -c + - '[first(.[]), last(.[]), nth(0;.[])]' + input: '[]' + expected: | + [] - name: first/1 function with optional operator args: @@ -4009,6 +4091,29 @@ expected: | null +- name: nth/2 function with negative index + args: + - 'nth(-1;.[])' + input: '[]' + error: | + error: nth doesn't support negative index + +- name: nth/2 function with infinite range + args: + - 'nth(range(3); range(infinite))' + input: 'null' + expected: | + 0 + 1 + 2 + +- name: nth/2 function with error + args: + - 'nth(1; 0,1,error)' + input: 'null' + expected: | + 1 + - name: all/2 function in first/1 argument args: - 'first(range(1; 200) | . as $x | select(all(range(1; 7); $x % . == 0)))' @@ -4024,6 +4129,28 @@ expected: | [0,1,2,0,1,2,3,4,5,6,7,8,9,10,11,12] +- name: limit/2 function with negative count + args: + - 'limit(-1; range(3))' + input: 'null' + error: | + limit doesn't support negative count + +- name: skip/2 function + args: + - -c + - '[skip(0,3,5,7; range(5))]' + input: 'null' + expected: | + [0,1,2,3,4,3,4] + +- name: skip/2 function with negative count + args: + - 'skip(-1; range(3))' + input: 'null' + error: | + skip doesn't support negative count + - name: all/0, any/0 functions args: - -c @@ -4433,13 +4560,16 @@ - name: fromstream function args: - -c - - 'fromstream(0,1,2|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]]))' + - 'fromstream(range(5) | truncate_stream({x:[1,{y:[2]},3],z:[4]} | tostream))' input: 'null' expected: | - [1,[2]] + {"x":[1,{"y":[2]},3],"z":[4]} + [1,{"y":[2]},3] + [4] + {"y":[2]} [2] -- name: stream function +- name: tostream function args: - -c - 'tostream' @@ -5419,6 +5549,8 @@ [2017,6,14,2,40,0,5,194] [2019,8,7,21,2,3.4560000889999998,6,249] [2020,8,13,12,26,40.111000061,0,256] + [2024,7,20] + [2025] expected: | 1500000000 "2017-07-14T02:40:00Z" @@ -5438,6 +5570,18 @@ "2020-09-13T12:26:40-0700" "2020-09-13T05:26:40-0700" "2020-09-13T12:26:40Z" + 1724112000 + "2024-08-20T00:00:00Z" + "2024-08-20T00:00:00Z" + "2024-08-20T00:00:00-0700" + "2024-08-19T17:00:00-0700" + "2024-08-20T00:00:00Z" + 1735603200 + "2024-12-31T00:00:00Z" + "2024-12-31T00:00:00Z" + "2024-12-31T00:00:00-0700" + "2024-12-30T17:00:00-0700" + "2024-12-31T00:00:00Z" - name: strptime, fromdate functions args: @@ -5915,17 +6059,28 @@ [["a",2]] [["a"]] -- name: inputs function with stream option and truncate_stream function +- name: inputs function with stream option and fromstream function args: - -n + - -c - --stream - - 'fromstream(1 | truncate_stream(inputs) | select(length > 1) | .[0] |= .[1:])' - input: '{"a":[1,true,null,"x"]}' + - 'fromstream(inputs)' + input: 'null [false] {"x":[null]}' expected: | - 1 - true null - "x" + [false] + {"x":[null]} + +- name: inputs function with stream option and truncate_stream function + args: + - -n + - -c + - --stream + - 'fromstream(1 | truncate_stream(inputs))' + input: '{"x":[1,{"y":[2]},3],"z":[4]}' + expected: | + [1,{"y":[2]},3] + [4] - name: inputs function with stream option args: @@ -6240,9 +6395,9 @@ args: - '@uri' input: | - [1, {"foo": "<div>&'\"()</div>"}] + [1, {"foo": "<div>&'\"()+</div>"}] expected: | - "%5B1%2C%7B%22foo%22%3A%22%3Cdiv%3E%26%27%5C%22%28%29%3C%2Fdiv%3E%22%7D%5D" + "%5B1%2C%7B%22foo%22%3A%22%3Cdiv%3E%26%27%5C%22%28%29%2B%3C%2Fdiv%3E%22%7D%5D" - name: format strings @uri with string interpolation args: @@ -6256,9 +6411,9 @@ args: - '@urid' input: | - "%5B1%2C%7B%22foo%22%3A%22%3Cdiv%3E%26%27%5C%22%28%29%3C%2Fdiv%3E%22%7D%5D" + "%5B1%2C%7B%22foo%22%3A%22%3Cdiv%3E%26%27%5C%22%28%29%2B%3C%2Fdiv%3E%22%7D%5D" expected: | - "[1,{\"foo\":\"<div>&'\\\"()</div>\"}]" + "[1,{\"foo\":\"<div>&'\\\"()+</div>\"}]" - name: format strings @urid error args: @@ -7747,7 +7902,7 @@ - name: module directory option args: - -c - - -L + - --library-path - 'testdata' - 'import "7" as $foo; $foo, $foo::foo' input: '0' @@ -7758,7 +7913,7 @@ - name: module directory option args: - -c - - -L + - --library-path - 'testdata' - 'import "m1" as $x; $x, $x::x, $x[1].m1*100000000000000000000' input: '0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/compare.go new/gojq-0.12.17/compare.go --- old/gojq-0.12.16/compare.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/compare.go 2024-12-01 13:30:01.000000000 +0100 @@ -35,11 +35,7 @@ } }, func(l, r []any) any { - n := len(l) - if len(r) < n { - n = len(r) - } - for i := 0; i < n; i++ { + for i, n := 0, min(len(l), len(r)); i < n; i++ { if cmp := Compare(l[i], r[i]); cmp != 0 { return cmp } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/compiler.go new/gojq-0.12.17/compiler.go --- old/gojq-0.12.16/compiler.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/compiler.go 2024-12-01 13:30:01.000000000 +0100 @@ -726,9 +726,6 @@ func (c *compiler) compileReduce(e *Reduce) error { c.appendCodeInfo(e) defer c.newScopeDepth()() - setfork := c.lazy(func() *code { - return &code{op: opfork, v: len(c.codes)} - }) c.append(&code{op: opdup}) v := c.newVariable() f := c.newScopeDepth() @@ -737,6 +734,9 @@ } f() c.append(&code{op: opstore, v: v}) + setfork := c.lazy(func() *code { + return &code{op: opfork, v: len(c.codes)} + }) if err := c.compileQuery(e.Query); err != nil { return err } @@ -913,8 +913,8 @@ env := make(map[string]any) if c.environLoader != nil { for _, kv := range c.environLoader() { - if i := strings.IndexByte(kv, '='); i > 0 { - env[kv[:i]] = kv[i+1:] + if k, v, ok := strings.Cut(kv, "="); ok && k != "" { + env[k] = v } } } @@ -937,20 +937,24 @@ return c.compileCallPc(f, e.Args) } if fds, ok := builtinFuncDefs[e.Name]; ok { + var compiled bool for _, fd := range fds { if len(fd.Args) == len(e.Args) { if err := c.compileFuncDef(fd, true); err != nil { return err } + compiled = true break } } - if len(fds) == 0 { + if !compiled { switch e.Name { case "_assign": c.compileAssign() case "_modify": c.compileModify() + case "last": + c.compileLast() } } if f := c.lookupBuiltin(e.Name, len(e.Args)); f != nil { @@ -1062,13 +1066,13 @@ &code{op: opfork, v: len(c.codes) + 30}, // reduce [L1] &code{op: opdup}, &code{op: opstore, v: w}, - &code{op: oppathbegin}, // path(p) + &code{op: oppathbegin}, // path(p) &code{op: opload, v: p}, &code{op: opcallpc}, &code{op: opload, v: w}, &code{op: oppathend}, &code{op: opstore, v: q}, // as $q (.; - &code{op: opload, v: a}, // setpath($q; $x) + &code{op: opload, v: a}, // setpath($q; $x) &code{op: opload, v: x}, &code{op: opload, v: q}, &code{op: opload, v: w}, @@ -1137,6 +1141,35 @@ &code{op: opret}, ) } + +// Appends the compiled code for the `last/1` function to +// maximize performance avoiding unnecessary boxing. +func (c *compiler) compileLast() { + defer c.appendBuiltin("last", 1)() + scope := c.newScope() + v, g, x := [2]int{scope.id, 0}, [2]int{scope.id, 1}, [2]int{scope.id, 2} + c.appends( + &code{op: opscope, v: [3]int{scope.id, 3, 1}}, + &code{op: opstore, v: v}, + &code{op: opstore, v: g}, + &code{op: oppush, v: true}, // $x = true + &code{op: opstore, v: x}, + &code{op: opload, v: v}, + &code{op: opfork, v: len(c.codes) + 13}, // reduce [L1] + &code{op: opload, v: g}, // g + &code{op: opcallpc}, + &code{op: opstore, v: v}, // as $v ( + &code{op: oppush, v: false}, // $x = false + &code{op: opstore, v: x}, + &code{op: opbacktrack}, // ); + &code{op: oppop}, // [L1] + &code{op: opload, v: x}, // if $x then $v else empty end + &code{op: opjumpifnot, v: len(c.codes) + 17}, + &code{op: opbacktrack}, + &code{op: opload, v: v}, + &code{op: opret}, + ) +} func (c *compiler) funcBuiltins(any, []any) any { type funcNameArity struct { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/debug.go new/gojq-0.12.17/debug.go --- old/gojq-0.12.16/debug.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/debug.go 2024-12-01 13:30:01.000000000 +0100 @@ -1,5 +1,4 @@ //go:build gojq_debug -// +build gojq_debug package gojq diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/encoder.go new/gojq-0.12.17/encoder.go --- old/gojq-0.12.16/encoder.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/encoder.go 2024-12-01 13:30:01.000000000 +0100 @@ -79,11 +79,7 @@ e.w.WriteString("null") return } - if f >= math.MaxFloat64 { - f = math.MaxFloat64 - } else if f <= -math.MaxFloat64 { - f = -math.MaxFloat64 - } + f = min(max(f, -math.MaxFloat64), math.MaxFloat64) format := byte('f') if x := math.Abs(f); x != 0 && x < 1e-6 || x >= 1e21 { format = 'e' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/func.go new/gojq-0.12.17/func.go --- old/gojq-0.12.16/func.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/func.go 2024-12-01 13:30:01.000000000 +0100 @@ -884,7 +884,7 @@ func funcToURI(v any) any { switch x := funcToString(v).(type) { case string: - return url.QueryEscape(x) + return strings.ReplaceAll(url.QueryEscape(x), "+", "%20") default: return x } @@ -893,7 +893,7 @@ func funcToURId(v any) any { switch x := funcToString(v).(type) { case string: - x, err := url.QueryUnescape(x) + x, err := url.QueryUnescape(strings.ReplaceAll(x, "+", "%2B")) if err != nil { return &func0WrapError{"@urid", v, err} } @@ -1504,10 +1504,7 @@ } func (a allocator) makeArray(l, c int) []any { - if c < l { - c = l - } - v := make([]any, l, c) + v := make([]any, l, max(l, c)) if a != nil { a[reflect.ValueOf(v).Pointer()] = struct{}{} } @@ -1939,41 +1936,30 @@ func arrayToTime(a []any, loc *time.Location) (time.Time, error) { var t time.Time - if len(a) != 8 { - return t, &timeArrayError{} - } - var y, m, d, h, min, sec, nsec int - var ok bool - if y, ok = toInt(a[0]); !ok { - return t, &timeArrayError{} - } - if m, ok = toInt(a[1]); ok { - m++ - } else { - return t, &timeArrayError{} - } - if d, ok = toInt(a[2]); !ok { - return t, &timeArrayError{} - } - if h, ok = toInt(a[3]); !ok { - return t, &timeArrayError{} - } - 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, &timeArrayError{} - } - if _, ok = toFloat(a[6]); !ok { - return t, &timeArrayError{} - } - if _, ok = toFloat(a[7]); !ok { - return t, &timeArrayError{} + var year, month, day, hour, minute, + second, nanosecond, weekday, yearday int + for i, p := range []*int{ + &year, &month, &day, &hour, &minute, + &second, &weekday, &yearday, + } { + if i >= len(a) { + break + } + if i == 5 { + if v, ok := toFloat(a[i]); ok { + *p = int(v) + nanosecond = int((v - math.Floor(v)) * 1e9) + } else { + return t, &timeArrayError{} + } + } else if v, ok := toInt(a[i]); ok { + *p = v + } else { + return t, &timeArrayError{} + } } - return time.Date(y, time.Month(m), d, h, min, sec, nsec, loc), nil + return time.Date(year, time.Month(month+1), day, + hour, minute, second, nanosecond, loc), nil } func funcNow(any) any { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/go.dev.mod new/gojq-0.12.17/go.dev.mod --- old/gojq-0.12.16/go.dev.mod 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/go.dev.mod 2024-12-01 13:30:01.000000000 +0100 @@ -1,6 +1,6 @@ module github.com/itchyny/gojq -go 1.20 +go 1.21 require ( github.com/itchyny/astgen-go v0.0.0-20231113225122-e1c22b9aaf7b // indirect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/go.mod new/gojq-0.12.17/go.mod --- old/gojq-0.12.16/go.mod 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/go.mod 2024-12-01 13:30:01.000000000 +0100 @@ -1,6 +1,6 @@ module github.com/itchyny/gojq -go 1.20 +go 1.21 require ( github.com/google/go-cmp v0.5.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/module_loader.go new/gojq-0.12.17/module_loader.go --- old/gojq-0.12.16/module_loader.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/module_loader.go 2024-12-01 13:30:01.000000000 +0100 @@ -118,7 +118,9 @@ func (l *moduleLoader) lookupModule(name, extension string, meta map[string]any) (string, error) { paths := l.paths if path, ok := meta["search"].(string); ok { - paths = append([]string{path}, paths...) + if path = resolvePath(path, ""); path != "" { + paths = append([]string{path}, paths...) + } } for _, base := range paths { path := filepath.Join(base, name+extension) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/release.go new/gojq-0.12.17/release.go --- old/gojq-0.12.16/release.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/release.go 2024-12-01 13:30:01.000000000 +0100 @@ -1,5 +1,4 @@ //go:build !gojq_debug -// +build !gojq_debug package gojq diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/scope_stack.go new/gojq-0.12.17/scope_stack.go --- old/gojq-0.12.16/scope_stack.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/scope_stack.go 2024-12-01 13:30:01.000000000 +0100 @@ -17,13 +17,9 @@ func (s *scopeStack) push(v scope) { b := scopeBlock{v, s.index} - i := s.index + 1 - if i <= s.limit { - i = s.limit + 1 - } - s.index = i - if i < len(s.data) { - s.data[i] = b + s.index = max(s.index, s.limit) + 1 + if s.index < len(s.data) { + s.data[s.index] = b } else { s.data = append(s.data, b) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gojq-0.12.16/stack.go new/gojq-0.12.17/stack.go --- old/gojq-0.12.16/stack.go 2024-06-01 16:43:23.000000000 +0200 +++ new/gojq-0.12.17/stack.go 2024-12-01 13:30:01.000000000 +0100 @@ -17,13 +17,9 @@ func (s *stack) push(v any) { b := block{v, s.index} - i := s.index + 1 - if i <= s.limit { - i = s.limit + 1 - } - s.index = i - if i < len(s.data) { - s.data[i] = b + s.index = max(s.index, s.limit) + 1 + if s.index < len(s.data) { + s.data[s.index] = b } else { s.data = append(s.data, b) } ++++++ vendor.tar.zst ++++++