Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Signed-off-by: Paulo Gomes <[email protected]>
  • Loading branch information
pjbgf committed Apr 8, 2024
1 parent 6b66543 commit f2e28e4
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 10 deletions.
2 changes: 1 addition & 1 deletion fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/go-git/go-git-fixtures/v4/internal/tgz"
)

var Filesystem = embedfs.New(&data, "data")
var Filesystem = embedfs.New(&data, "data/")

//go:embed data
var data embed.FS
Expand Down
2 changes: 1 addition & 1 deletion fixtures_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func WithMemFS() Option {
func WithTargetDir(dirName func() string) Option {
return func(o *options) {
o.fsFactory = func() (billy.Filesystem, error) {
return osfs.New(dirName(), osfs.WithBoundOS()), nil
return osfs.New(dirName(), osfs.WithChrootOS()), nil
}
}
}
68 changes: 60 additions & 8 deletions internal/embedfs/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,47 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"sync"

"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/helper/chroot"
"github.com/go-git/go-billy/v5/memfs"
)

type Embed struct {
underlying *embed.FS
base string
}

func New(efs *embed.FS, path string) billy.Filesystem {
func New(efs *embed.FS, base string) billy.Filesystem {
fs := &Embed{
underlying: efs,
base: base,
}

if efs == nil {
fs.underlying = &embed.FS{}
}

return chroot.New(fs, path)
return fs
}

func (fs *Embed) Chroot(path string) (billy.Filesystem, error) {
fs.base = fs.Join(fs.base, path)

return fs, nil
}

func (fs *Embed) Root() string {
return fs.base
}

func (fs *Embed) path(filename string) string {
return fs.Join(fs.base, filename)
}

func (fs *Embed) Stat(filename string) (os.FileInfo, error) {
f, err := fs.underlying.Open(filename)
f, err := fs.underlying.Open(fs.path(filename))
if err != nil {
return nil, err
}
Expand All @@ -49,7 +65,7 @@ func (fs *Embed) OpenFile(filename string, flag int, perm os.FileMode) (billy.Fi
return nil, billy.ErrReadOnly
}

f, err := fs.underlying.Open(filename)
f, err := fs.underlying.Open(fs.path(filename))
if err != nil {
return nil, err
}
Expand All @@ -63,7 +79,7 @@ func (fs *Embed) OpenFile(filename string, flag int, perm os.FileMode) (billy.Fi
return nil, fmt.Errorf("cannot open directory: %s", filename)
}

data, err := fs.underlying.ReadFile(filename)
data, err := fs.underlying.ReadFile(fs.path(filename))
if err != nil {
return nil, err
}
Expand All @@ -74,11 +90,19 @@ func (fs *Embed) OpenFile(filename string, flag int, perm os.FileMode) (billy.Fi
}

func (fs *Embed) Join(elem ...string) string {
return filepath.Join(elem...)
// Function adapted from Go's filepath.Join for unix:
// https://github.com/golang/go/blob/1ed85ee228023d766b37db056311929c00091c9f/src/path/filepath/path_unix.go#L45
for i, el := range elem {
if el != "" {
// reuses filepath.Clean, as it is OS agnostic.
return filepath.Clean(strings.Join(elem[i:], "/"))
}
}
return ""
}

func (fs *Embed) ReadDir(path string) ([]os.FileInfo, error) {
e, err := fs.underlying.ReadDir(path)
e, err := fs.underlying.ReadDir(fs.path(path))
if err != nil {
return nil, err
}
Expand All @@ -94,6 +118,34 @@ func (fs *Embed) ReadDir(path string) ([]os.FileInfo, error) {
return entries, nil
}

// Lstat is not supported.
//
// Calls will always return billy.ErrNotSupported.
func (fs *Embed) Lstat(_ string) (os.FileInfo, error) {
return nil, billy.ErrNotSupported
}

// Readlink is not supported.
//
// Calls will always return billy.ErrNotSupported.
func (fs *Embed) Readlink(_ string) (string, error) {
return "", billy.ErrNotSupported
}

// TempFile is not supported.
//
// Calls will always return billy.ErrNotSupported.
func (fs *Embed) TempFile(_, _ string) (billy.File, error) {
return nil, billy.ErrNotSupported
}

// Symlink is not supported.
//
// Calls will always return billy.ErrReadOnly.
func (fs *Embed) Symlink(_, _ string) error {
return billy.ErrReadOnly
}

// Create is not supported.
//
// Calls will always return billy.ErrReadOnly.
Expand Down
38 changes: 38 additions & 0 deletions internal/embedfs/embed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,41 @@ func TestFileSeek(t *testing.T) {
})
}
}

func TestJoin(t *testing.T) {
tests := []struct {
name string
path []string
want string
}{
{
name: "no leading slash",
path: []string{"data", "foo/bar"},
want: "data/foo/bar",
},
{
name: "w/ leading slash",
path: []string{"/data", "foo/bar"},
want: "/data/foo/bar",
},
{
name: "dot dot",
path: []string{"/data", "../bar"},
want: "/bar",
},
{
name: "dot",
path: []string{"/data", "./bar"},
want: "/data/bar",
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
fs := New(&empty, "")

got := fs.Join(tc.path...)
assert.Equal(t, got, tc.want)
})
}
}

0 comments on commit f2e28e4

Please sign in to comment.