From 1a6c70b64984ef2e690f03ac37e182614704a6e6 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 6 May 2025 08:06:49 +0200 Subject: [PATCH] internal: drop `internal/fsnode` package This package has an identical copy in `images` and is also (AFAICT) unused. Hence this commit removes it. --- internal/fsnode/dir.go | 34 ------- internal/fsnode/dir_test.go | 81 ---------------- internal/fsnode/file.go | 36 -------- internal/fsnode/file_test.go | 81 ---------------- internal/fsnode/fsnode.go | 133 --------------------------- internal/fsnode/fsnode_test.go | 163 --------------------------------- 6 files changed, 528 deletions(-) delete mode 100644 internal/fsnode/dir.go delete mode 100644 internal/fsnode/dir_test.go delete mode 100644 internal/fsnode/file.go delete mode 100644 internal/fsnode/file_test.go delete mode 100644 internal/fsnode/fsnode.go delete mode 100644 internal/fsnode/fsnode_test.go diff --git a/internal/fsnode/dir.go b/internal/fsnode/dir.go deleted file mode 100644 index 702165ab0..000000000 --- a/internal/fsnode/dir.go +++ /dev/null @@ -1,34 +0,0 @@ -package fsnode - -import "os" - -type Directory struct { - baseFsNode - ensureParentDirs bool -} - -func (d *Directory) IsDir() bool { - return true -} - -func (d *Directory) EnsureParentDirs() bool { - if d == nil { - return false - } - return d.ensureParentDirs -} - -// NewDirectory creates a new directory with the given path, mode, user and group. -// user and group can be either a string (user name/group name), an int64 (UID/GID) or nil. -func NewDirectory(path string, mode *os.FileMode, user interface{}, group interface{}, ensureParentDirs bool) (*Directory, error) { - baseNode, err := newBaseFsNode(path, mode, user, group) - - if err != nil { - return nil, err - } - - return &Directory{ - baseFsNode: *baseNode, - ensureParentDirs: ensureParentDirs, - }, nil -} diff --git a/internal/fsnode/dir_test.go b/internal/fsnode/dir_test.go deleted file mode 100644 index 303fc447d..000000000 --- a/internal/fsnode/dir_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package fsnode - -import ( - "os" - "testing" - - "github.com/osbuild/osbuild-composer/internal/common" - "github.com/stretchr/testify/assert" -) - -func TestDirectoryIsDir(t *testing.T) { - dir, err := NewDirectory("/etc/dir", nil, nil, nil, false) - assert.NoError(t, err) - assert.True(t, dir.IsDir()) -} - -func TestNewDirectory(t *testing.T) { - testCases := []struct { - name string - path string - mode *os.FileMode - user interface{} - group interface{} - ensureParentDirs bool - expected *Directory - }{ - { - name: "directory-simple", - path: "/etc/dir", - mode: nil, - user: nil, - group: nil, - ensureParentDirs: false, - expected: &Directory{baseFsNode: baseFsNode{path: "/etc/dir", mode: nil, user: nil, group: nil}, ensureParentDirs: false}, - }, - { - name: "directory-with-mode", - path: "/etc/dir", - mode: common.ToPtr(os.FileMode(0644)), - user: nil, - group: nil, - ensureParentDirs: false, - expected: &Directory{baseFsNode: baseFsNode{path: "/etc/dir", mode: common.ToPtr(os.FileMode(0644)), user: nil, group: nil}, ensureParentDirs: false}, - }, - { - name: "directory-with-user-and-group-string", - path: "/etc/dir", - mode: nil, - user: "user", - group: "group", - ensureParentDirs: false, - expected: &Directory{baseFsNode: baseFsNode{path: "/etc/dir", mode: nil, user: "user", group: "group"}, ensureParentDirs: false}, - }, - { - name: "directory-with-user-and-group-int64", - path: "/etc/dir", - mode: nil, - user: int64(1000), - group: int64(1000), - ensureParentDirs: false, - expected: &Directory{baseFsNode: baseFsNode{path: "/etc/dir", mode: nil, user: int64(1000), group: int64(1000)}, ensureParentDirs: false}, - }, - { - name: "directory-with-ensure-parent-dirs", - path: "/etc/dir", - mode: nil, - user: nil, - group: nil, - ensureParentDirs: true, - expected: &Directory{baseFsNode: baseFsNode{path: "/etc/dir", mode: nil, user: nil, group: nil}, ensureParentDirs: true}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - dir, err := NewDirectory(tc.path, tc.mode, tc.user, tc.group, tc.ensureParentDirs) - assert.NoError(t, err) - assert.Equal(t, tc.expected, dir) - }) - } -} diff --git a/internal/fsnode/file.go b/internal/fsnode/file.go deleted file mode 100644 index 3c6813ece..000000000 --- a/internal/fsnode/file.go +++ /dev/null @@ -1,36 +0,0 @@ -package fsnode - -import ( - "os" -) - -type File struct { - baseFsNode - data []byte -} - -func (f *File) IsDir() bool { - return false -} - -func (f *File) Data() []byte { - if f == nil { - return nil - } - return f.data -} - -// NewFile creates a new file with the given path, data, mode, user and group. -// user and group can be either a string (user name/group name), an int64 (UID/GID) or nil. -func NewFile(path string, mode *os.FileMode, user interface{}, group interface{}, data []byte) (*File, error) { - baseNode, err := newBaseFsNode(path, mode, user, group) - - if err != nil { - return nil, err - } - - return &File{ - baseFsNode: *baseNode, - data: data, - }, nil -} diff --git a/internal/fsnode/file_test.go b/internal/fsnode/file_test.go deleted file mode 100644 index 32161841e..000000000 --- a/internal/fsnode/file_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package fsnode - -import ( - "os" - "testing" - - "github.com/osbuild/osbuild-composer/internal/common" - "github.com/stretchr/testify/assert" -) - -func TestFileIsDir(t *testing.T) { - file, err := NewFile("/etc/file", nil, nil, nil, nil) - assert.NoError(t, err) - assert.False(t, file.IsDir()) -} - -func TestNewFile(t *testing.T) { - testCases := []struct { - name string - path string - data []byte - mode *os.FileMode - user interface{} - group interface{} - expected *File - }{ - { - name: "empty-file", - path: "/etc/file", - data: nil, - mode: nil, - user: nil, - group: nil, - expected: &File{baseFsNode: baseFsNode{path: "/etc/file", mode: nil, user: nil, group: nil}, data: nil}, - }, - { - name: "file-with-data", - path: "/etc/file", - data: []byte("data"), - mode: nil, - user: nil, - group: nil, - expected: &File{baseFsNode: baseFsNode{path: "/etc/file", mode: nil, user: nil, group: nil}, data: []byte("data")}, - }, - { - name: "file-with-mode", - path: "/etc/file", - data: nil, - mode: common.ToPtr(os.FileMode(0644)), - user: nil, - group: nil, - expected: &File{baseFsNode: baseFsNode{path: "/etc/file", mode: common.ToPtr(os.FileMode(0644)), user: nil, group: nil}, data: nil}, - }, - { - name: "file-with-user-and-group-string", - path: "/etc/file", - data: nil, - mode: nil, - user: "user", - group: "group", - expected: &File{baseFsNode: baseFsNode{path: "/etc/file", mode: nil, user: "user", group: "group"}, data: nil}, - }, - { - name: "file-with-user-and-group-int64", - path: "/etc/file", - data: nil, - mode: nil, - user: int64(1000), - group: int64(1000), - expected: &File{baseFsNode: baseFsNode{path: "/etc/file", mode: nil, user: int64(1000), group: int64(1000)}, data: nil}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - file, err := NewFile(tc.path, tc.mode, tc.user, tc.group, tc.data) - assert.NoError(t, err) - assert.Equal(t, tc.expected, file) - }) - } -} diff --git a/internal/fsnode/fsnode.go b/internal/fsnode/fsnode.go deleted file mode 100644 index 06e0e2237..000000000 --- a/internal/fsnode/fsnode.go +++ /dev/null @@ -1,133 +0,0 @@ -package fsnode - -import ( - "fmt" - "os" - "path" - "regexp" -) - -const usernameRegex = `^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$` -const groupnameRegex = `^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$` - -type FsNode interface { - Path() string - Mode() *os.FileMode - // User can return either a string (user name/group name), an int64 (UID/GID) or nil - User() interface{} - // Group can return either a string (user name/group name), an int64 (UID/GID) or nil - Group() interface{} - IsDir() bool -} - -type baseFsNode struct { - path string - mode *os.FileMode - user interface{} - group interface{} -} - -func (f *baseFsNode) Path() string { - if f == nil { - return "" - } - return f.path -} - -func (f *baseFsNode) Mode() *os.FileMode { - if f == nil { - return nil - } - return f.mode -} - -// User can return either a string (user name) or an int64 (UID) -func (f *baseFsNode) User() interface{} { - if f == nil { - return nil - } - return f.user -} - -// Group can return either a string (group name) or an int64 (GID) -func (f *baseFsNode) Group() interface{} { - if f == nil { - return nil - } - return f.group -} - -func newBaseFsNode(path string, mode *os.FileMode, user interface{}, group interface{}) (*baseFsNode, error) { - node := &baseFsNode{ - path: path, - mode: mode, - user: user, - group: group, - } - - err := node.validate() - if err != nil { - return nil, err - } - return node, nil -} - -func (f *baseFsNode) validate() error { - // Check that the path is valid - if f.path == "" { - return fmt.Errorf("path must not be empty") - } - if f.path[0] != '/' { - return fmt.Errorf("path must be absolute") - } - if f.path[len(f.path)-1] == '/' { - return fmt.Errorf("path must not end with a slash") - } - if f.path != path.Clean(f.path) { - return fmt.Errorf("path must be canonical") - } - - // Check that the mode is valid - if f.mode != nil && *f.mode&os.ModeType != 0 { - return fmt.Errorf("mode must not contain file type bits") - } - - // Check that the user and group are valid - switch user := f.user.(type) { - case string: - nameRegex := regexp.MustCompile(usernameRegex) - if !nameRegex.MatchString(user) { - return fmt.Errorf("user name %q doesn't conform to validating regex (%s)", user, nameRegex.String()) - } - case int64: - if user < 0 { - return fmt.Errorf("user ID must be non-negative") - } - case nil: - // user is not set - default: - return fmt.Errorf("user must be either a string or an int64, got %T", user) - } - - switch group := f.group.(type) { - case string: - nameRegex := regexp.MustCompile(groupnameRegex) - if !nameRegex.MatchString(group) { - return fmt.Errorf("group name %q doesn't conform to validating regex (%s)", group, nameRegex.String()) - } - case int64: - if group < 0 { - return fmt.Errorf("group ID must be non-negative") - } - case nil: - // group is not set - default: - return fmt.Errorf("group must be either a string or an int64, got %T", group) - } - - return nil -} - -func (f *baseFsNode) IsDir() bool { - panic("IsDir() called on baseFsNode") -} diff --git a/internal/fsnode/fsnode_test.go b/internal/fsnode/fsnode_test.go deleted file mode 100644 index 3862143cd..000000000 --- a/internal/fsnode/fsnode_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package fsnode - -import ( - "fmt" - "os" - "testing" - - "github.com/osbuild/osbuild-composer/internal/common" - "github.com/stretchr/testify/assert" -) - -func TestBaseFsNodeValidate(t *testing.T) { - testCases := []struct { - Node baseFsNode - Error bool - }{ - // PATH - // relative path is not allowed - { - Node: baseFsNode{ - path: "relative/path/file", - }, - Error: true, - }, - // path ending with slash is not allowed - { - Node: baseFsNode{ - path: "/dir/with/trailing/slash/", - }, - Error: true, - }, - // empty path is not allowed - { - Node: baseFsNode{ - path: "", - }, - Error: true, - }, - // path must be canonical - { - Node: baseFsNode{ - path: "/dir/../file", - }, - Error: true, - }, - { - Node: baseFsNode{ - path: "/dir/./file", - }, - Error: true, - }, - // valid paths - { - Node: baseFsNode{ - path: "/etc/file", - }, - }, - { - Node: baseFsNode{ - path: "/etc/dir", - }, - }, - // MODE - // invalid mode - { - Node: baseFsNode{ - path: "/etc/file", - mode: common.ToPtr(os.FileMode(os.ModeDir)), - }, - Error: true, - }, - // valid mode - { - Node: baseFsNode{ - path: "/etc/file", - mode: common.ToPtr(os.FileMode(0o644)), - }, - }, - // USER - // invalid user - { - Node: baseFsNode{ - path: "/etc/file", - user: "", - }, - Error: true, - }, - { - Node: baseFsNode{ - path: "/etc/file", - user: "invalid@@@user", - }, - Error: true, - }, - { - Node: baseFsNode{ - path: "/etc/file", - user: int64(-1), - }, - Error: true, - }, - // valid user - { - Node: baseFsNode{ - path: "/etc/file", - user: "osbuild", - }, - }, - { - Node: baseFsNode{ - path: "/etc/file", - user: int64(0), - }, - }, - // GROUP - // invalid group - { - Node: baseFsNode{ - path: "/etc/file", - group: "", - }, - Error: true, - }, - { - Node: baseFsNode{ - path: "/etc/file", - group: "invalid@@@group", - }, - Error: true, - }, - { - Node: baseFsNode{ - path: "/etc/file", - group: int64(-1), - }, - Error: true, - }, - // valid group - { - Node: baseFsNode{ - path: "/etc/file", - group: "osbuild", - }, - }, - { - Node: baseFsNode{ - path: "/etc/file", - group: int64(0), - }, - }, - } - - for idx, testCase := range testCases { - t.Run(fmt.Sprintf("case #%d", idx), func(t *testing.T) { - err := testCase.Node.validate() - if testCase.Error { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } - }) - } -}