Last active
July 8, 2023 21:06
-
-
Save pjbgf/c0ee84bdf54fa18a736c2e185f1465f0 to your computer and use it in GitHub Desktop.
Filtered billy.Filesystem PoC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package filtered | |
import ( | |
"io" | |
"os" | |
"time" | |
"github.com/go-git/go-billy/v5" | |
) | |
type discardFile struct { | |
name string | |
content *discardContent | |
position int64 | |
flag int | |
mode os.FileMode | |
} | |
func newDiscardFile(name string) *discardFile { | |
return &discardFile{ | |
name: name, | |
} | |
} | |
func (f *discardFile) Name() string { | |
return f.name | |
} | |
func (f *discardFile) Read(b []byte) (int, error) { | |
return 0, io.EOF | |
} | |
func (f *discardFile) ReadAt(b []byte, off int64) (int, error) { | |
return 0, io.EOF | |
} | |
func (f *discardFile) Seek(offset int64, whence int) (int64, error) { | |
switch whence { | |
case io.SeekCurrent: | |
f.position += offset | |
case io.SeekStart: | |
f.position = offset | |
} | |
return f.position, nil | |
} | |
func (f *discardFile) Write(p []byte) (int, error) { | |
return len(p), nil | |
} | |
func (f *discardFile) Close() error { | |
return nil | |
} | |
func (f *discardFile) Truncate(size int64) error { | |
return nil | |
} | |
func (f *discardFile) Duplicate(filename string, mode os.FileMode, flag int) billy.File { | |
return f | |
} | |
func (f *discardFile) Stat() (os.FileInfo, error) { | |
return &discardFileInfo{ | |
name: f.Name(), | |
mode: f.mode, | |
}, nil | |
} | |
// Lock is a no-op in memfs. | |
func (f *discardFile) Lock() error { | |
return nil | |
} | |
// Unlock is a no-op in memfs. | |
func (f *discardFile) Unlock() error { | |
return nil | |
} | |
type discardFileInfo struct { | |
name string | |
size int | |
mode os.FileMode | |
} | |
func (fi *discardFileInfo) Name() string { | |
return fi.name | |
} | |
func (fi *discardFileInfo) Size() int64 { | |
return int64(fi.size) | |
} | |
func (fi *discardFileInfo) Mode() os.FileMode { | |
return fi.mode | |
} | |
func (*discardFileInfo) ModTime() time.Time { | |
return time.Now() | |
} | |
func (fi *discardFileInfo) IsDir() bool { | |
return fi.mode.IsDir() | |
} | |
func (*discardFileInfo) Sys() interface{} { | |
return nil | |
} | |
type discardContent struct { | |
} | |
func (c *discardContent) WriteAt(p []byte, off int64) (int, error) { | |
return len(p), nil | |
} | |
func (c *discardContent) ReadAt(b []byte, off int64) (n int, err error) { | |
return len(b) - int(off), nil | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"os" | |
"runtime" | |
"strconv" | |
"strings" | |
"time" | |
"github.com/go-git/go-git/v5" | |
"github.com/go-git/go-git/v5/plumbing/cache" | |
"github.com/go-git/go-git/v5/storage/filesystem" | |
"github.com/go-git/go-billy/v5" | |
"github.com/go-git/go-billy/v5/osfs" | |
) | |
func main() { | |
CheckArgs("<url>", "<directory>", "<filtered>") | |
url := os.Args[1] | |
directory := os.Args[2] | |
filter, _ := strconv.ParseBool(os.Args[3]) | |
// Clone the given repository to the given directory | |
Info("git clone %s %s", url, directory) | |
fs := osfs.New(directory) | |
dotgit, err := fs.Chroot(git.GitDirName) | |
CheckIfError(err) | |
storer := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()) | |
var wt billy.Filesystem | |
if filter { | |
fmt.Println("filter ON") | |
wt, _ = NewFilteredStorage(fs, `^(Makefile|.git.*)`) | |
} else { | |
fmt.Println("filter OFF") | |
wt = fs | |
} | |
CheckIfError(err) | |
fmt.Println("cloning...") | |
t := time.Now() | |
_, err = git.Clone(storer, wt, &git.CloneOptions{ | |
URL: url, | |
Depth: 1, | |
Tags: git.NoTags, | |
SingleBranch: true, | |
}) | |
CheckIfError(err) | |
d := time.Now().Sub(t) | |
fmt.Printf("total time: %.fm %.fs %dn\n", d.Minutes(), d.Seconds(), d.Nanoseconds()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package filtered | |
import ( | |
"os" | |
"path/filepath" | |
"regexp" | |
"github.com/go-git/go-billy/v5" | |
) | |
type FilteredStorage struct { | |
pattern *regexp.Regexp | |
fs billy.Filesystem | |
fake billy.File | |
fakeInfo os.FileInfo | |
} | |
func NewFilteredStorage(fs billy.Filesystem, pattern string) (billy.Filesystem, error) { | |
re, err := regexp.Compile(pattern) | |
if err != nil { | |
return nil, err | |
} | |
return &FilteredStorage{ | |
pattern: re, | |
fs: fs, | |
fake: &discardFile{}, | |
fakeInfo: &discardFileInfo{}, | |
}, nil | |
} | |
func (s *FilteredStorage) Create(filename string) (billy.File, error) { | |
if s.pattern.MatchString(filename) { | |
return s.fs.Create(filename) | |
} | |
return newDiscardFile(filename), nil | |
} | |
func (s *FilteredStorage) Open(filename string) (billy.File, error) { | |
return s.OpenFile(filename, os.O_RDONLY, 0o000) | |
} | |
func (s *FilteredStorage) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) { | |
if s.pattern.MatchString(filename) { | |
return s.fs.OpenFile(filename, flag, perm) | |
} | |
return s.fake, nil | |
} | |
func (s *FilteredStorage) Stat(filename string) (os.FileInfo, error) { | |
if s.pattern.MatchString(filename) { | |
return s.fs.Stat(filename) | |
} | |
return s.fakeInfo, nil | |
} | |
func (s *FilteredStorage) Lstat(filename string) (os.FileInfo, error) { | |
if s.pattern.MatchString(filename) { | |
return s.fs.Lstat(filename) | |
} | |
return s.fakeInfo, nil | |
} | |
func (s *FilteredStorage) ReadDir(path string) ([]os.FileInfo, error) { | |
if path == "" || s.pattern.MatchString(path) { | |
return s.fs.ReadDir(path) | |
} | |
return nil, nil | |
} | |
func (s *FilteredStorage) MkdirAll(path string, perm os.FileMode) error { | |
if s.pattern.MatchString(path) { | |
return s.fs.MkdirAll(path, perm) | |
} | |
return nil | |
} | |
func (s *FilteredStorage) Rename(from, to string) error { | |
if s.pattern.MatchString(from) { | |
return s.fs.Rename(from, to) | |
} | |
return nil | |
} | |
func (s *FilteredStorage) Remove(filename string) error { | |
if s.pattern.MatchString(filename) { | |
return s.fs.Remove(filename) | |
} | |
return nil | |
} | |
func (s *FilteredStorage) Symlink(target, link string) error { | |
if s.pattern.MatchString(link) { | |
return s.fs.Symlink(target, link) | |
} | |
return nil | |
} | |
func (s *FilteredStorage) Readlink(link string) (string, error) { | |
if s.pattern.MatchString(link) { | |
return s.fs.Readlink(link) | |
} | |
return "", nil | |
} | |
// Funcs not filtered: | |
func (s *FilteredStorage) TempFile(dir, prefix string) (billy.File, error) { | |
return s.fs.TempFile(dir, prefix) | |
} | |
func (s *FilteredStorage) Chroot(path string) (billy.Filesystem, error) { | |
fs, err := s.fs.Chroot(path) | |
if err != nil { | |
return nil, err | |
} | |
return New(fs, s.pattern.String()) | |
} | |
func (s *FilteredStorage) Root() string { | |
return s.fs.Root() | |
} | |
func (s *FilteredStorage) Join(elem ...string) string { | |
return filepath.Join(elem...) | |
} | |
// Capabilities implements the Capable interface. | |
func (s *FilteredStorage) Capabilities() billy.Capability { | |
return billy.WriteCapability | | |
billy.ReadCapability | | |
billy.ReadAndWriteCapability | | |
billy.SeekCapability | | |
billy.TruncateCapability | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment