mirror of
https://github.com/containers/podman.git
synced 2025-10-18 19:53:58 +08:00
Potentially breaking: Make hooks sort order locale-independent
Don't sort OCI hooks using the locale collation order; it does not make sense for the same system-wide directory to be interpreted differently depending on the user's LC_COLLATE setting, and the language-specific collation order can even change over time. Besides, the current collation order determination code has never worked with the most common LC_COLLATE values like en_US.UTF-8. Ideally, we would like to just order based on Unicode code points to be reliably stable, but the existing implementation is case-insensitive, so we are forced to rely on the unicode case mapping tables at least. (This gives up on canonicalization and width-insensitivity, potentially breaking users who rely on these previously documented properties.) Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
@ -5,14 +5,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
current "github.com/containers/libpod/pkg/hooks/1.0.0"
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/text/collate"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Version is the current hook configuration version.
|
||||
@ -31,7 +31,6 @@ type Manager struct {
|
||||
hooks map[string]*current.Hook
|
||||
directories []string
|
||||
extensionStages []string
|
||||
language language.Tag
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
@ -40,8 +39,6 @@ type namedHook struct {
|
||||
hook *current.Hook
|
||||
}
|
||||
|
||||
type namedHooks []*namedHook
|
||||
|
||||
// New creates a new hook manager. Directories are ordered by
|
||||
// increasing preference (hook configurations in later directories
|
||||
// override configurations with the same filename from earlier
|
||||
@ -51,12 +48,11 @@ type namedHooks []*namedHook
|
||||
// those specified in the OCI Runtime Specification and to control
|
||||
// OCI-defined stages instead of delagating to the OCI runtime. See
|
||||
// Hooks() for more information.
|
||||
func New(ctx context.Context, directories []string, extensionStages []string, lang language.Tag) (manager *Manager, err error) {
|
||||
func New(ctx context.Context, directories []string, extensionStages []string) (manager *Manager, err error) {
|
||||
manager = &Manager{
|
||||
hooks: map[string]*current.Hook{},
|
||||
directories: directories,
|
||||
extensionStages: extensionStages,
|
||||
language: lang,
|
||||
}
|
||||
|
||||
for _, dir := range directories {
|
||||
@ -94,15 +90,14 @@ func (m *Manager) namedHooks() (hooks []*namedHook) {
|
||||
// extensionStageHooks. This takes precedence over their inclusion in
|
||||
// the OCI configuration. For example:
|
||||
//
|
||||
// manager, err := New(ctx, []string{DefaultDir}, []string{"poststop"}, lang)
|
||||
// manager, err := New(ctx, []string{DefaultDir}, []string{"poststop"})
|
||||
// extensionStageHooks, err := manager.Hooks(config, annotations, hasBindMounts)
|
||||
//
|
||||
// will have any matching post-stop hooks in extensionStageHooks and
|
||||
// will not insert them into config.Hooks.Poststop.
|
||||
func (m *Manager) Hooks(config *rspec.Spec, annotations map[string]string, hasBindMounts bool) (extensionStageHooks map[string][]rspec.Hook, err error) {
|
||||
hooks := m.namedHooks()
|
||||
collator := collate.New(m.language, collate.IgnoreCase, collate.IgnoreWidth)
|
||||
collator.Sort(namedHooks(hooks))
|
||||
sort.Slice(hooks, func(i, j int) bool { return strings.ToLower(hooks[i].name) < strings.ToLower(hooks[j].name) })
|
||||
localStages := map[string]bool{} // stages destined for extensionStageHooks
|
||||
for _, stage := range m.extensionStages {
|
||||
localStages[stage] = true
|
||||
@ -166,18 +161,3 @@ func (m *Manager) add(path string) (err error) {
|
||||
m.hooks[filepath.Base(path)] = hook
|
||||
return nil
|
||||
}
|
||||
|
||||
// Len is part of the collate.Lister interface.
|
||||
func (hooks namedHooks) Len() int {
|
||||
return len(hooks)
|
||||
}
|
||||
|
||||
// Swap is part of the collate.Lister interface.
|
||||
func (hooks namedHooks) Swap(i, j int) {
|
||||
hooks[i], hooks[j] = hooks[j], hooks[i]
|
||||
}
|
||||
|
||||
// Bytes is part of the collate.Lister interface.
|
||||
func (hooks namedHooks) Bytes(i int) []byte {
|
||||
return []byte(hooks[i].name)
|
||||
}
|
||||
|
Reference in New Issue
Block a user