Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gitea-runner for openSUSE:Factory 
checked in at 2026-10-09 21:46:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gitea-runner (Old)
 and      /work/SRC/openSUSE:Factory/.gitea-runner.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gitea-runner"

Fri Oct  9 21:46:28 2026 rev:3 rq:1383808 version:5.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/gitea-runner/gitea-runner.changes        
2026-10-07 19:36:34.396617690 +0200
+++ /work/SRC/openSUSE:Factory/.gitea-runner.new.3698736/gitea-runner.changes   
2026-10-09 21:47:45.721318700 +0200
@@ -1,0 +2,18 @@
+Fri Oct 09 12:23:53 UTC 2026 - Elisei Roca <[email protected]>
+
+- Update to version 5.0.0:
+  * enhance!: send OTLP metrics under OpenTelemetry semantic conventions, add 
runner state (#1282)
+  * enhance(config): add `container.sweep` option (#1275)
+  * enhance: support client certificates for mutual TLS (#1273)
+  * fix: apply the daemon's mtu to job networks (#1270)
+  * enhance(config): expand environment values (#1274)
+  * enhance(runner): add extra HTTP headers (#1269)
+  * fix: enforce read-only volume restrictions (#1272)
+  * fix!: use the git CLI for action clones and make builtin:checkout match 
actions/checkout (#1277)
+  * fix: reject workflows with jobs lacking `runs-on` (#1271)
+  * fix: strip log-driver and OOM options when privileged is off (#1283)
+  * fix: allow tmpfs mounts in container options (#1289)
+  * fix: extract copied directories at their destination in Kubernetes pods 
(#1286)
+  * fix: recognize Gitea's 401 reply for an unregistered runner (#1287)
+
+-------------------------------------------------------------------

Old:
----
  runner-4.1.0.tar.gz

New:
----
  runner-5.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gitea-runner.spec ++++++
--- /var/tmp/diff_new_pack.HL0Rxm/_old  2026-10-09 21:47:46.916368818 +0200
+++ /var/tmp/diff_new_pack.HL0Rxm/_new  2026-10-09 21:47:46.918368902 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           gitea-runner
-Version:        4.1.0
+Version:        5.0.0
 Release:        0
 Summary:        Gitea Runner for Gitea Actions
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.HL0Rxm/_old  2026-10-09 21:47:46.959370622 +0200
+++ /var/tmp/diff_new_pack.HL0Rxm/_new  2026-10-09 21:47:46.963370789 +0200
@@ -5,7 +5,7 @@
     <param name="exclude">.git</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
-    <param name="revision">v4.1.0</param>
+    <param name="revision">v5.0.0</param>
     <param name="changesgenerate">enable</param>
   </service>
   <service name="recompress" mode="manual">

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.HL0Rxm/_old  2026-10-09 21:47:46.987371796 +0200
+++ /var/tmp/diff_new_pack.HL0Rxm/_new  2026-10-09 21:47:46.991371964 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://gitea.com/gitea/runner.git</param>
-              <param 
name="changesrevision">ddee2e054ae5b590b01b557807b8a53403cc50f3</param></service></servicedata>
+              <param 
name="changesrevision">8b14a38d4ad6a1cb40dabb953a8a65656de70301</param></service></servicedata>
 (No newline at EOF)
 

++++++ runner-4.1.0.tar.gz -> runner-5.0.0.tar.gz ++++++
++++ 4958 lines of diff (skipped)

++++++ vendor.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/gitea.dev/actionslib/pkg/expreval/subexpr.go 
new/vendor/gitea.dev/actionslib/pkg/expreval/subexpr.go
--- old/vendor/gitea.dev/actionslib/pkg/expreval/subexpr.go     2026-10-01 
21:45:13.000000000 +0200
+++ new/vendor/gitea.dev/actionslib/pkg/expreval/subexpr.go     2026-10-08 
20:01:36.000000000 +0200
@@ -61,6 +61,19 @@
        return partsMatch(parts, match)
 }
 
+// Literal returns the text of a value that is plain text or a lone string 
literal expression.
+func Literal(value string) (string, bool) {
+       parts, err := splitSubExpressions(value)
+       switch {
+       case err != nil || len(parts) != 1:
+               return "", false
+       case parts[0].isLiteral:
+               return parts[0].literal, true
+       default:
+               return parts[0].text, !parts[0].isExpr
+       }
+}
+
 // ReadsContext reports whether value reads the named context, without 
exposing the AST.
 func ReadsContext(value, contextName string) bool {
        return Match(value, func(node exprparser.ExprNode) bool {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/gitea.dev/actionslib/pkg/model/matrix.go 
new/vendor/gitea.dev/actionslib/pkg/model/matrix.go
--- old/vendor/gitea.dev/actionslib/pkg/model/matrix.go 2026-10-01 
21:45:13.000000000 +0200
+++ new/vendor/gitea.dev/actionslib/pkg/model/matrix.go 2026-10-08 
20:01:36.000000000 +0200
@@ -8,8 +8,10 @@
        "errors"
        "fmt"
        "maps"
-       "reflect"
+       "math"
        "slices"
+       "strconv"
+       "strings"
 
        "go.yaml.in/yaml/v4"
 )
@@ -21,13 +23,21 @@
 type matrixAxis struct {
        name   string
        values []any
+       node   *yaml.Node
 }
 
 // matrix keeps axes in YAML declaration order for GitHub's first-axis-slowest 
expansion.
 type matrix struct {
-       axes    []matrixAxis
-       include []map[string]any
-       exclude []map[string]any
+       axes         []matrixAxis
+       include      []map[string]any
+       includeNodes []*yaml.Node
+       exclude      []map[string]any
+}
+
+// MatrixCombination is an expanded combination with the scalars its default 
job name lists, in order.
+type MatrixCombination struct {
+       Values     map[string]any
+       NameValues []any
 }
 
 func (j *Job) matrixOf() (*matrix, error) {
@@ -60,14 +70,12 @@
                                return nil, err
                        }
                        if name == "include" {
-                               parsed.include = entries
+                               parsed.include, parsed.includeNodes = entries, 
value.Content
                        } else {
                                parsed.exclude = entries
                        }
                default:
-                       if value.Kind == yaml.AliasNode {
-                               value = value.Alias
-                       }
+                       value = resolveAlias(value)
                        if value.Kind != yaml.SequenceNode {
                                return nil, fmt.Errorf("the workflow is not 
valid. Matrix vector %q is not a list of values", name)
                        }
@@ -75,7 +83,7 @@
                        if err := value.Decode(&values); err != nil {
                                return nil, fmt.Errorf("the workflow is not 
valid. Matrix key %q: %w", name, err)
                        }
-                       parsed.axes = append(parsed.axes, matrixAxis{name: 
name, values: values})
+                       parsed.axes = append(parsed.axes, matrixAxis{name: 
name, values: values, node: value})
                }
        }
        if len(parsed.axes) == 0 && len(parsed.include) == 0 {
@@ -128,12 +136,25 @@
 
 // GetMatrixes expands evaluated matrix sequences in declaration order, 
rejecting excludes with undeclared keys.
 func (j *Job) GetMatrixes() ([]map[string]any, error) {
+       combinations, err := j.MatrixCombinations()
+       if err != nil {
+               return nil, err
+       }
+       matrixes := make([]map[string]any, len(combinations))
+       for i, combination := range combinations {
+               matrixes[i] = combination.Values
+       }
+       return matrixes, nil
+}
+
+// MatrixCombinations is GetMatrixes with each combination's NameValues.
+func (j *Job) MatrixCombinations() ([]MatrixCombination, error) {
        parsed, err := j.matrixOf()
        if err != nil {
                return nil, err
        }
        if parsed == nil {
-               return []map[string]any{{}}, nil
+               return []MatrixCombination{{Values: map[string]any{}}}, nil
        }
 
        product := 1
@@ -142,7 +163,7 @@
                if len(axis.values) == 0 {
                        return nil, fmt.Errorf("the workflow is not valid. 
Matrix vector %q does not contain any values", axis.name)
                }
-               declaredKeys[axis.name] = true
+               declaredKeys[strings.ToLower(axis.name)] = true
                product *= len(axis.values)
                if product > MaxMatrixCombinations {
                        return nil, errTooManyCombinations(product)
@@ -151,43 +172,106 @@
 
        for _, exclude := range parsed.exclude {
                for key := range exclude {
-                       if !declaredKeys[key] {
+                       if !declaredKeys[strings.ToLower(key)] {
                                return nil, fmt.Errorf("the workflow is not 
valid. Matrix exclude key %q does not match any key within the matrix", key)
                        }
                }
        }
 
-       matrixes := make([]map[string]any, 0, product)
+       combinations := make([]MatrixCombination, 0, product)
        for _, combination := range cartesianProduct(parsed.axes, product) {
                if !slices.ContainsFunc(parsed.exclude, func(exclude 
map[string]any) bool {
-                       return matchesMatrixKeys(combination, exclude, 
declaredKeys)
+                       return matchesMatrixKeys(combination.Values, exclude, 
declaredKeys)
                }) {
-                       matrixes = append(matrixes, combination)
+                       combinations = append(combinations, combination)
                }
        }
 
-       var extra []map[string]any
-       for _, include := range parsed.include {
+       var extra []MatrixCombination
+       for i, include := range parsed.include {
                matched := false
-               for _, combination := range matrixes {
-                       if matchesMatrixKeys(combination, include, 
declaredKeys) {
-                               maps.Copy(combination, include)
+               for _, combination := range combinations {
+                       if matchesMatrixKeys(combination.Values, include, 
declaredKeys) {
+                               for key, value := range include {
+                                       if !declaredKeys[strings.ToLower(key)] {
+                                               combination.Values[key] = value
+                                       }
+                               }
                                matched = true
                        }
                }
                if !matched {
-                       extra = append(extra, include)
+                       extra = append(extra, MatrixCombination{Values: 
include, NameValues: includeNameValues(include, parsed.includeNodes[i], 
declaredKeys)})
                }
        }
-       matrixes = append(matrixes, extra...)
+       combinations = append(combinations, extra...)
 
-       if len(matrixes) == 0 {
-               return []map[string]any{{}}, nil
+       if len(combinations) == 0 {
+               return []MatrixCombination{{Values: map[string]any{}}}, nil
        }
-       if len(matrixes) > MaxMatrixCombinations {
-               return nil, errTooManyCombinations(len(matrixes))
+       if len(combinations) > MaxMatrixCombinations {
+               return nil, errTooManyCombinations(len(combinations))
        }
-       return matrixes, nil
+       return combinations, nil
+}
+
+func includeNameValues(include map[string]any, node *yaml.Node, declaredKeys 
map[string]bool) []any {
+       axes, others := map[string]any{}, map[string]any{}
+       for key, value := range include {
+               if declaredKeys[strings.ToLower(key)] {
+                       axes[key] = value
+               } else {
+                       others[key] = value
+               }
+       }
+       return appendScalars(appendScalars(nil, axes, node), others, node)
+}
+
+// appendScalars appends the scalars of value, ordering mapping keys like 
node, which value was decoded from.
+func appendScalars(scalars []any, value any, node *yaml.Node) []any {
+       node = resolveAlias(node)
+       switch value := value.(type) {
+       case map[string]any:
+               remaining := maps.Clone(value)
+               for i := 0; node != nil && node.Kind == yaml.MappingNode && i+1 
< len(node.Content); i += 2 {
+                       key := resolveAlias(node.Content[i]).Value
+                       if item, ok := remaining[key]; ok {
+                               delete(remaining, key)
+                               scalars = appendScalars(scalars, item, 
node.Content[i+1])
+                       }
+               }
+               for _, key := range slices.Sorted(maps.Keys(remaining)) {
+                       scalars = appendScalars(scalars, remaining[key], nil)
+               }
+       case map[any]any:
+               keyed := make(map[string]any, len(value))
+               for key, item := range value {
+                       keyed[fmt.Sprint(key)] = item
+               }
+               scalars = appendScalars(scalars, keyed, node)
+       case []any:
+               for i, item := range value {
+                       scalars = appendScalars(scalars, item, itemNode(node, 
i, len(value)))
+               }
+       default:
+               scalars = append(scalars, value)
+       }
+       return scalars
+}
+
+// itemNode returns the i-th item of the sequence node, or nil when the 
decoder dropped items like `<<`.
+func itemNode(node *yaml.Node, i, count int) *yaml.Node {
+       if node == nil || node.Kind != yaml.SequenceNode || len(node.Content) 
!= count {
+               return nil
+       }
+       return node.Content[i]
+}
+
+func resolveAlias(node *yaml.Node) *yaml.Node {
+       if node != nil && node.Kind == yaml.AliasNode {
+               return node.Alias
+       }
+       return node
 }
 
 func errTooManyCombinations(count int) error {
@@ -195,26 +279,105 @@
 }
 
 func matchesMatrixKeys(combination, entry map[string]any, declaredKeys 
map[string]bool) bool {
-       for key, value := range entry {
-               if declaredKeys[key] && !reflect.DeepEqual(combination[key], 
value) {
+       for key, filter := range entry {
+               if declaredKeys[strings.ToLower(key)] && 
!matchesFilter(propertyFold(combination, key), filter) {
                        return false
                }
        }
        return true
 }
 
+// matchesFilter compares each scalar of filter with the value at its path 
using expression equality.
+func matchesFilter(value, filter any) bool {
+       switch filter := filter.(type) {
+       case map[string]any:
+               object, _ := value.(map[string]any)
+               for key, item := range filter {
+                       if !matchesFilter(propertyFold(object, key), item) {
+                               return false
+                       }
+               }
+               return true
+       case []any:
+               array, _ := value.([]any)
+               for i, item := range filter {
+                       var element any
+                       if i < len(array) {
+                               element = array[i]
+                       }
+                       if !matchesFilter(element, item) {
+                               return false
+                       }
+               }
+               return true
+       }
+       return looseEqual(value, filter)
+}
+
+func propertyFold(object map[string]any, key string) any {
+       if value, ok := object[key]; ok {
+               return value
+       }
+       for name, value := range object {
+               if strings.EqualFold(name, key) {
+                       return value
+               }
+       }
+       return nil
+}
+
+// looseEqual is the expression `==` of exprparser, which model cannot import, 
for a matrix value and a filter scalar.
+func looseEqual(value, scalar any) bool {
+       if valueText, ok := value.(string); ok {
+               if scalarText, ok := scalar.(string); ok {
+                       return strings.EqualFold(valueText, scalarText)
+               }
+       }
+       return toNumber(value) == toNumber(scalar)
+}
+
+func toNumber(value any) float64 {
+       switch value := value.(type) {
+       case nil:
+               return 0
+       case bool:
+               if value {
+                       return 1
+               }
+               return 0
+       case int:
+               return float64(value)
+       case uint64:
+               return float64(value)
+       case float64:
+               return value
+       case string:
+               text := strings.TrimSpace(value)
+               if text == "" {
+                       return 0
+               }
+               if number, err := strconv.ParseFloat(text, 64); err == nil {
+                       return number
+               }
+       }
+       return math.NaN()
+}
+
 // cartesianProduct expands the axes into combinations with the first axis 
varying slowest, which
 // is the order GitHub documents and lists the resulting jobs in.
-func cartesianProduct(axes []matrixAxis, product int) []map[string]any {
+func cartesianProduct(axes []matrixAxis, product int) []MatrixCombination {
        if len(axes) == 0 {
                return nil
        }
-       combinations := make([]map[string]any, 0, product)
+       combinations := make([]MatrixCombination, 0, product)
        for ordinal := range product {
-               combination := make(map[string]any, len(axes))
-               for _, axis := range slices.Backward(axes) {
-                       combination[axis.name] = 
axis.values[ordinal%len(axis.values)]
-                       ordinal /= len(axis.values)
+               combination := MatrixCombination{Values: make(map[string]any, 
len(axes))}
+               stride := product
+               for _, axis := range axes {
+                       stride /= len(axis.values)
+                       index := ordinal / stride % len(axis.values)
+                       combination.Values[axis.name] = axis.values[index]
+                       combination.NameValues = 
appendScalars(combination.NameValues, axis.values[index], itemNode(axis.node, 
index, len(axis.values)))
                }
                combinations = append(combinations, combination)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/golang.org/x/net/http/httpguts/guts.go 
new/vendor/golang.org/x/net/http/httpguts/guts.go
--- old/vendor/golang.org/x/net/http/httpguts/guts.go   1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/golang.org/x/net/http/httpguts/guts.go   2026-10-08 
20:01:36.000000000 +0200
@@ -0,0 +1,50 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httpguts provides functions implementing various details
+// of the HTTP specification.
+//
+// This package is shared by the standard library (which vendors it)
+// and x/net/http2. It comes with no API stability promise.
+package httpguts
+
+import (
+       "net/textproto"
+       "strings"
+)
+
+// ValidTrailerHeader reports whether name is a valid header field name to 
appear
+// in trailers.
+// See RFC 7230, Section 4.1.2
+func ValidTrailerHeader(name string) bool {
+       name = textproto.CanonicalMIMEHeaderKey(name)
+       if strings.HasPrefix(name, "If-") || badTrailer[name] {
+               return false
+       }
+       return true
+}
+
+var badTrailer = map[string]bool{
+       "Authorization":       true,
+       "Cache-Control":       true,
+       "Connection":          true,
+       "Content-Encoding":    true,
+       "Content-Length":      true,
+       "Content-Range":       true,
+       "Content-Type":        true,
+       "Expect":              true,
+       "Host":                true,
+       "Keep-Alive":          true,
+       "Max-Forwards":        true,
+       "Pragma":              true,
+       "Proxy-Authenticate":  true,
+       "Proxy-Authorization": true,
+       "Proxy-Connection":    true,
+       "Range":               true,
+       "Realm":               true,
+       "Te":                  true,
+       "Trailer":             true,
+       "Transfer-Encoding":   true,
+       "Www-Authenticate":    true,
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/golang.org/x/net/http/httpguts/httplex.go 
new/vendor/golang.org/x/net/http/httpguts/httplex.go
--- old/vendor/golang.org/x/net/http/httpguts/httplex.go        1970-01-01 
01:00:00.000000000 +0100
+++ new/vendor/golang.org/x/net/http/httpguts/httplex.go        2026-10-08 
20:01:36.000000000 +0200
@@ -0,0 +1,347 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httpguts
+
+import (
+       "net"
+       "strings"
+       "unicode/utf8"
+
+       "golang.org/x/net/idna"
+)
+
+var isTokenTable = [256]bool{
+       '!':  true,
+       '#':  true,
+       '$':  true,
+       '%':  true,
+       '&':  true,
+       '\'': true,
+       '*':  true,
+       '+':  true,
+       '-':  true,
+       '.':  true,
+       '0':  true,
+       '1':  true,
+       '2':  true,
+       '3':  true,
+       '4':  true,
+       '5':  true,
+       '6':  true,
+       '7':  true,
+       '8':  true,
+       '9':  true,
+       'A':  true,
+       'B':  true,
+       'C':  true,
+       'D':  true,
+       'E':  true,
+       'F':  true,
+       'G':  true,
+       'H':  true,
+       'I':  true,
+       'J':  true,
+       'K':  true,
+       'L':  true,
+       'M':  true,
+       'N':  true,
+       'O':  true,
+       'P':  true,
+       'Q':  true,
+       'R':  true,
+       'S':  true,
+       'T':  true,
+       'U':  true,
+       'W':  true,
+       'V':  true,
+       'X':  true,
+       'Y':  true,
+       'Z':  true,
+       '^':  true,
+       '_':  true,
+       '`':  true,
+       'a':  true,
+       'b':  true,
+       'c':  true,
+       'd':  true,
+       'e':  true,
+       'f':  true,
+       'g':  true,
+       'h':  true,
+       'i':  true,
+       'j':  true,
+       'k':  true,
+       'l':  true,
+       'm':  true,
+       'n':  true,
+       'o':  true,
+       'p':  true,
+       'q':  true,
+       'r':  true,
+       's':  true,
+       't':  true,
+       'u':  true,
+       'v':  true,
+       'w':  true,
+       'x':  true,
+       'y':  true,
+       'z':  true,
+       '|':  true,
+       '~':  true,
+}
+
+func IsTokenRune(r rune) bool {
+       return r < utf8.RuneSelf && isTokenTable[byte(r)]
+}
+
+// HeaderValuesContainsToken reports whether any string in values
+// contains the provided token, ASCII case-insensitively.
+func HeaderValuesContainsToken(values []string, token string) bool {
+       for _, v := range values {
+               if headerValueContainsToken(v, token) {
+                       return true
+               }
+       }
+       return false
+}
+
+// isOWS reports whether b is an optional whitespace byte, as defined
+// by RFC 7230 section 3.2.3.
+func isOWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// trimOWS returns x with all optional whitespace removes from the
+// beginning and end.
+func trimOWS(x string) string {
+       // TODO: consider using strings.Trim(x, " \t") instead,
+       // if and when it's fast enough. See issue 10292.
+       // But this ASCII-only code will probably always beat UTF-8
+       // aware code.
+       for len(x) > 0 && isOWS(x[0]) {
+               x = x[1:]
+       }
+       for len(x) > 0 && isOWS(x[len(x)-1]) {
+               x = x[:len(x)-1]
+       }
+       return x
+}
+
+// headerValueContainsToken reports whether v (assumed to be a
+// 0#element, in the ABNF extension described in RFC 7230 section 7)
+// contains token amongst its comma-separated tokens, ASCII
+// case-insensitively.
+func headerValueContainsToken(v string, token string) bool {
+       for comma := strings.IndexByte(v, ','); comma != -1; comma = 
strings.IndexByte(v, ',') {
+               if tokenEqual(trimOWS(v[:comma]), token) {
+                       return true
+               }
+               v = v[comma+1:]
+       }
+       return tokenEqual(trimOWS(v), token)
+}
+
+// lowerASCII returns the ASCII lowercase version of b.
+func lowerASCII(b byte) byte {
+       if 'A' <= b && b <= 'Z' {
+               return b + ('a' - 'A')
+       }
+       return b
+}
+
+// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
+func tokenEqual(t1, t2 string) bool {
+       if len(t1) != len(t2) {
+               return false
+       }
+       for i, b := range t1 {
+               if b >= utf8.RuneSelf {
+                       // No UTF-8 or non-ASCII allowed in tokens.
+                       return false
+               }
+               if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
+                       return false
+               }
+       }
+       return true
+}
+
+// isLWS reports whether b is linear white space, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+//
+//     LWS            = [CRLF] 1*( SP | HT )
+func isLWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// isCTL reports whether b is a control byte, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+//
+//     CTL            = <any US-ASCII control character
+//                      (octets 0 - 31) and DEL (127)>
+func isCTL(b byte) bool {
+       const del = 0x7f // a CTL
+       return b < ' ' || b == del
+}
+
+// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
+// HTTP/2 imposes the additional restriction that uppercase ASCII
+// letters are not allowed.
+//
+// RFC 7230 says:
+//
+//     header-field   = field-name ":" OWS field-value OWS
+//     field-name     = token
+//     token          = 1*tchar
+//     tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+//             "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+func ValidHeaderFieldName(v string) bool {
+       if len(v) == 0 {
+               return false
+       }
+       for i := 0; i < len(v); i++ {
+               if !isTokenTable[v[i]] {
+                       return false
+               }
+       }
+       return true
+}
+
+// ValidHostHeader reports whether h is a valid host header.
+func ValidHostHeader(h string) bool {
+       // The latest spec is actually this:
+       //
+       // http://tools.ietf.org/html/rfc7230#section-5.4
+       //     Host = uri-host [ ":" port ]
+       //
+       // Where uri-host is:
+       //     http://tools.ietf.org/html/rfc3986#section-3.2.2
+       //
+       // But we're going to be much more lenient for now and just
+       // search for any byte that's not a valid byte in any of those
+       // expressions.
+       for i := 0; i < len(h); i++ {
+               if !validHostByte[h[i]] {
+                       return false
+               }
+       }
+       return true
+}
+
+// See the validHostHeader comment.
+var validHostByte = [256]bool{
+       '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': 
true, '7': true,
+       '8': true, '9': true,
+
+       'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': 
true, 'h': true,
+       'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': 
true, 'p': true,
+       'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': 
true, 'x': true,
+       'y': true, 'z': true,
+
+       'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': 
true, 'H': true,
+       'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': 
true, 'P': true,
+       'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': 
true, 'X': true,
+       'Y': true, 'Z': true,
+
+       '!':  true, // sub-delims
+       '$':  true, // sub-delims
+       '%':  true, // pct-encoded (and used in IPv6 zones)
+       '&':  true, // sub-delims
+       '(':  true, // sub-delims
+       ')':  true, // sub-delims
+       '*':  true, // sub-delims
+       '+':  true, // sub-delims
+       ',':  true, // sub-delims
+       '-':  true, // unreserved
+       '.':  true, // unreserved
+       ':':  true, // IPv6address + Host expression's optional port
+       ';':  true, // sub-delims
+       '=':  true, // sub-delims
+       '[':  true,
+       '\'': true, // sub-delims
+       ']':  true,
+       '_':  true, // unreserved
+       '~':  true, // unreserved
+}
+
+// ValidHeaderFieldValue reports whether v is a valid "field-value" according 
to
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
+//
+//     message-header = field-name ":" [ field-value ]
+//     field-value    = *( field-content | LWS )
+//     field-content  = <the OCTETs making up the field-value
+//                      and consisting of either *TEXT or combinations
+//                      of token, separators, and quoted-string>
+//
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
+//
+//     TEXT           = <any OCTET except CTLs,
+//                       but including LWS>
+//     LWS            = [CRLF] 1*( SP | HT )
+//     CTL            = <any US-ASCII control character
+//                      (octets 0 - 31) and DEL (127)>
+//
+// RFC 7230 says:
+//
+//     field-value    = *( field-content / obs-fold )
+//     obj-fold       =  N/A to http2, and deprecated
+//     field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+//     field-vchar    = VCHAR / obs-text
+//     obs-text       = %x80-FF
+//     VCHAR          = "any visible [USASCII] character"
+//
+// http2 further says: "Similarly, HTTP/2 allows header field values
+// that are not valid. While most of the values that can be encoded
+// will not alter header field parsing, carriage return (CR, ASCII
+// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
+// 0x0) might be exploited by an attacker if they are translated
+// verbatim. Any request or response that contains a character not
+// permitted in a header field value MUST be treated as malformed
+// (Section 8.1.2.6). Valid characters are defined by the
+// field-content ABNF rule in Section 3.2 of [RFC7230]."
+//
+// This function does not (yet?) properly handle the rejection of
+// strings that begin or end with SP or HTAB.
+func ValidHeaderFieldValue(v string) bool {
+       for i := 0; i < len(v); i++ {
+               b := v[i]
+               if isCTL(b) && !isLWS(b) {
+                       return false
+               }
+       }
+       return true
+}
+
+func isASCII(s string) bool {
+       for i := 0; i < len(s); i++ {
+               if s[i] >= utf8.RuneSelf {
+                       return false
+               }
+       }
+       return true
+}
+
+// PunycodeHostPort returns the IDNA Punycode version
+// of the provided "host" or "host:port" string.
+func PunycodeHostPort(v string) (string, error) {
+       if isASCII(v) {
+               return v, nil
+       }
+
+       host, port, err := net.SplitHostPort(v)
+       if err != nil {
+               // The input 'v' argument was just a "host" argument,
+               // without a port. This error should not be returned
+               // to the caller.
+               host = v
+               port = ""
+       }
+       host, err = idna.ToASCII(host)
+       if err != nil {
+               // Non-UTF-8? Not representable in Punycode, in any
+               // case.
+               return "", err
+       }
+       if port == "" {
+               return host, nil
+       }
+       return net.JoinHostPort(host, port), nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt
--- old/vendor/modules.txt      2026-10-01 21:45:13.000000000 +0200
+++ new/vendor/modules.txt      2026-10-08 20:01:36.000000000 +0200
@@ -11,7 +11,7 @@
 # dario.cat/mergo v1.0.2
 ## explicit; go 1.13
 dario.cat/mergo
-# gitea.dev/actionslib v1.2.1
+# gitea.dev/actionslib v1.3.0
 ## explicit; go 1.26.0
 gitea.dev/actionslib/ping/v1
 gitea.dev/actionslib/ping/v1/pingv1connect
@@ -116,7 +116,7 @@
 # github.com/distribution/reference v0.6.0
 ## explicit; go 1.20
 github.com/distribution/reference
-# github.com/docker/cli v29.8.1+incompatible
+# github.com/docker/cli v29.8.2+incompatible
 ## explicit
 github.com/docker/cli/cli/compose/interpolation
 github.com/docker/cli/cli/compose/loader
@@ -166,7 +166,7 @@
 github.com/go-git/gcfg/scanner
 github.com/go-git/gcfg/token
 github.com/go-git/gcfg/types
-# github.com/go-git/go-billy/v5 v5.9.1
+# github.com/go-git/go-billy/v5 v5.9.2
 ## explicit; go 1.25.0
 github.com/go-git/go-billy/v5
 github.com/go-git/go-billy/v5/helper/chroot
@@ -517,6 +517,7 @@
 # golang.org/x/net v0.59.0
 ## explicit; go 1.26.0
 golang.org/x/net/context
+golang.org/x/net/http/httpguts
 golang.org/x/net/http/httpproxy
 golang.org/x/net/idna
 golang.org/x/net/internal/socks

Reply via email to