Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions gocompat_generics_go121.go

This file was deleted.

98 changes: 0 additions & 98 deletions gocompat_generics_unsupported.go

This file was deleted.

10 changes: 10 additions & 0 deletions internal/gocompat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## gocompat ##

This directory contains backports of stdlib functions from later Go versions so
the filepath-securejoin can continue to be used by projects that are stuck with
Go 1.18 support. Note that often filepath-securejoin is added in security
patches for old releases, so avoiding the need to bump Go compiler requirements
is a huge plus to downstreams.

The source code is licensed under the same license as the Go stdlib. See the
source files for the precise license information.
13 changes: 13 additions & 0 deletions internal/gocompat/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause
//go:build linux && go1.20

// Copyright (C) 2025 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gocompat includes compatibility shims (backported from future Go
// stdlib versions) to permit filepath-securejoin to be used with older Go
// versions (often filepath-securejoin is added in security patches for old
// releases, so avoiding the need to bump Go compiler requirements is a huge
// plus to downstreams).
package gocompat
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package securejoin
package gocompat

import (
"fmt"
)

// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
// WrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap)
// is only guaranteed to give you baseErr.
func wrapBaseError(baseErr, extraErr error) error {
func WrapBaseError(baseErr, extraErr error) error {
return fmt.Errorf("%w: %w", extraErr, baseErr)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package securejoin
package gocompat

import (
"errors"
Expand All @@ -20,7 +20,7 @@ func TestGoCompatErrorWrap(t *testing.T) {
baseErr := errors.New("base error")
extraErr := errors.New("extra error")

err := wrapBaseError(baseErr, extraErr)
err := WrapBaseError(baseErr, extraErr)

require.Error(t, err)
assert.ErrorIs(t, err, baseErr, "wrapped error should contain base error") //nolint:testifylint // we are testing error behaviour directly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package securejoin
package gocompat

import (
"fmt"
Expand All @@ -29,10 +29,10 @@ func (err wrappedError) Error() string {
return fmt.Sprintf("%v: %v", err.isError, err.inner)
}

// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
// WrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap)
// is only guaranteed to give you baseErr.
func wrapBaseError(baseErr, extraErr error) error {
func WrapBaseError(baseErr, extraErr error) error {
return wrappedError{
inner: baseErr,
isError: extraErr,
Expand Down
53 changes: 53 additions & 0 deletions internal/gocompat/gocompat_generics_go121.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: BSD-3-Clause

//go:build linux && go1.21

// Copyright (C) 2024-2025 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gocompat

import (
"cmp"
"slices"
"sync"
)

// SlicesDeleteFunc is equivalent to Go 1.21's slices.DeleteFunc.
func SlicesDeleteFunc[S ~[]E, E any](slice S, delFn func(E) bool) S {
return slices.DeleteFunc(slice, delFn)
}

// SlicesContains is equivalent to Go 1.21's slices.Contains.
func SlicesContains[S ~[]E, E comparable](slice S, val E) bool {
return slices.Contains(slice, val)
}

// SlicesClone is equivalent to Go 1.21's slices.Clone.
func SlicesClone[S ~[]E, E any](slice S) S {
return slices.Clone(slice)
}

// SyncOnceValue is equivalent to Go 1.21's sync.OnceValue.
func SyncOnceValue[T any](f func() T) func() T {
return sync.OnceValue(f)
}

// SyncOnceValues is equivalent to Go 1.21's sync.OnceValues.
func SyncOnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
return sync.OnceValues(f)
}

// CmpOrdered is equivalent to Go 1.21's cmp.Ordered generic type definition.
type CmpOrdered = cmp.Ordered

// CmpCompare is equivalent to Go 1.21's cmp.Compare.
func CmpCompare[T CmpOrdered](x, y T) int {
return cmp.Compare(x, y)
}

// Max2 is equivalent to Go 1.21's max builtin (but only for two parameters).
func Max2[T CmpOrdered](x, y T) T {
return max(x, y)
}
Loading
Loading