[feature] file exclude
Some checks failed
mkdocs / mkdocs (push) Failing after 15s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 3s
docker / build-docker (inux/arm/v6) (push) Failing after 14s
docker / build-docker (linux/386) (push) Failing after 15s
docker / build-docker (linux/amd64) (push) Failing after 7s
docker / build-docker (linux/arm/v7) (push) Failing after 15s
docker / build-docker (linux/arm64) (push) Failing after 15s
Some checks failed
mkdocs / mkdocs (push) Failing after 15s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 3s
docker / build-docker (inux/arm/v6) (push) Failing after 14s
docker / build-docker (linux/386) (push) Failing after 15s
docker / build-docker (linux/amd64) (push) Failing after 7s
docker / build-docker (linux/arm/v7) (push) Failing after 15s
docker / build-docker (linux/arm64) (push) Failing after 15s
This commit is contained in:
parent
741bae49a4
commit
5f292a0591
7 changed files with 79 additions and 115 deletions
3
.github/workflows/docker.yaml
vendored
3
.github/workflows/docker.yaml
vendored
|
@ -24,9 +24,6 @@ jobs:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v2
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,10 @@ func (s *Service) NewTorrentFs(f vfs.File) (vfs.Filesystem, error) {
|
||||||
}
|
}
|
||||||
<-t.GotInfo()
|
<-t.GotInfo()
|
||||||
t.AllowDataDownload()
|
t.AllowDataDownload()
|
||||||
|
for _, f := range t.Files() {
|
||||||
|
f.SetPriority(torrent.PiecePriorityReadahead)
|
||||||
|
}
|
||||||
|
|
||||||
return vfs.NewTorrentFs(t, s.readTimeout), nil
|
return vfs.NewTorrentFs(t, s.readTimeout), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package vfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
@ -119,28 +120,42 @@ PARTS_LOOP:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (r *resolver) resolveFile(name string, fs Filesystem) (File, error) {
|
var ErrNotExist = fs.ErrNotExist
|
||||||
// fsPath, nestedFs, nestedFsPath, err := r.resolvePath(name, fs)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if nestedFs == nil {
|
func getFile[F File](m map[string]F, name string) (File, error) {
|
||||||
// return fs.Open(fsPath)
|
name = clean(name)
|
||||||
// }
|
if name == Separator {
|
||||||
|
return &Dir{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// return nestedFs.Open(nestedFsPath)
|
f, ok := m[name]
|
||||||
// }
|
if ok {
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
// func (r *resolver) resolveDir(name string, fs Filesystem) (map[string]File, error) {
|
for p := range m {
|
||||||
// fsPath, nestedFs, nestedFsPath, err := r.resolvePath(name, fs)
|
if strings.HasPrefix(p, name) {
|
||||||
// if err != nil {
|
return &Dir{}, nil
|
||||||
// return nil, err
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if nestedFs == nil {
|
return nil, ErrNotExist
|
||||||
// return fs.ReadDir(fsPath)
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// return nestedFs.ReadDir(nestedFsPath)
|
func listFilesInDir[F File](m map[string]F, name string) (map[string]File, error) {
|
||||||
// }
|
name = clean(name)
|
||||||
|
|
||||||
|
out := map[string]File{}
|
||||||
|
for p, f := range m {
|
||||||
|
if strings.HasPrefix(p, name) {
|
||||||
|
parts := strings.Split(trimRelPath(p, name), Separator)
|
||||||
|
if len(parts) == 1 {
|
||||||
|
out[parts[0]] = f
|
||||||
|
} else {
|
||||||
|
out[parts[0]] = &Dir{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
|
@ -144,3 +144,29 @@ func TestArchiveFactories(t *testing.T) {
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
require.NotNil(fs)
|
require.NotNil(fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFiles(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
files := map[string]*Dummy{
|
||||||
|
"/test/file.txt": &Dummy{},
|
||||||
|
}
|
||||||
|
{
|
||||||
|
file, err := getFile(files, "/test")
|
||||||
|
require.Nil(err)
|
||||||
|
require.Equal(&Dir{}, file)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
file, err := getFile(files, "/test/file.txt")
|
||||||
|
require.Nil(err)
|
||||||
|
require.Equal(&Dummy{}, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
out, err := listFilesInDir(files, "/test")
|
||||||
|
require.Nil(err)
|
||||||
|
require.Contains(out, "file.txt")
|
||||||
|
require.Equal(&Dummy{}, out["file.txt"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,10 @@ func (fs *TorrentFs) files() map[string]*torrentFile {
|
||||||
files := make(map[string]*torrentFile)
|
files := make(map[string]*torrentFile)
|
||||||
<-fs.t.GotInfo()
|
<-fs.t.GotInfo()
|
||||||
for _, file := range fs.t.Files() {
|
for _, file := range fs.t.Files() {
|
||||||
|
if file.Priority() == torrent.PiecePriorityNone {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
p := clean(file.Path())
|
p := clean(file.Path())
|
||||||
files[p] = &torrentFile{
|
files[p] = &torrentFile{
|
||||||
readerFunc: file.NewReader,
|
readerFunc: file.NewReader,
|
||||||
|
@ -73,6 +77,12 @@ func (fs *TorrentFs) ReadDir(name string) (map[string]File, error) {
|
||||||
return listFilesInDir(fs.files(), fsPath)
|
return listFilesInDir(fs.files(), fsPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs *TorrentFs) Unlink(name string) error {
|
||||||
|
file := fs.t.Files()[0]
|
||||||
|
file.SetPriority(torrent.PiecePriorityNone)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type reader interface {
|
type reader interface {
|
||||||
iio.Reader
|
iio.Reader
|
||||||
missinggo.ReadContexter
|
missinggo.ReadContexter
|
||||||
|
@ -111,18 +121,11 @@ func readAtLeast(r missinggo.ReadContexter, timeout int, buf []byte, min int) (n
|
||||||
for n < min && err == nil {
|
for n < min && err == nil {
|
||||||
var nn int
|
var nn int
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||||
timer := time.AfterFunc(
|
defer cancel()
|
||||||
time.Duration(timeout)*time.Second,
|
|
||||||
func() {
|
|
||||||
cancel()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
nn, err = r.ReadContext(ctx, buf[n:])
|
nn, err = r.ReadContext(ctx, buf[n:])
|
||||||
n += nn
|
n += nn
|
||||||
|
|
||||||
timer.Stop()
|
|
||||||
}
|
}
|
||||||
if n >= min {
|
if n >= min {
|
||||||
err = nil
|
err = nil
|
||||||
|
@ -175,15 +178,8 @@ func (d *torrentFile) Close() error {
|
||||||
|
|
||||||
func (d *torrentFile) Read(p []byte) (n int, err error) {
|
func (d *torrentFile) Read(p []byte) (n int, err error) {
|
||||||
d.load()
|
d.load()
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(d.timeout)*time.Second)
|
||||||
timer := time.AfterFunc(
|
defer cancel()
|
||||||
time.Duration(d.timeout)*time.Second,
|
|
||||||
func() {
|
|
||||||
cancel()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
defer timer.Stop()
|
|
||||||
|
|
||||||
return d.reader.ReadContext(ctx, p)
|
return d.reader.ReadContext(ctx, p)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,10 @@
|
||||||
package vfs
|
package vfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/fs"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotExist = fs.ErrNotExist
|
|
||||||
|
|
||||||
func getFile[F File](m map[string]F, name string) (File, error) {
|
|
||||||
name = clean(name)
|
|
||||||
if name == Separator {
|
|
||||||
return &Dir{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f, ok := m[name]
|
|
||||||
if ok {
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for p := range m {
|
|
||||||
if strings.HasPrefix(p, name) {
|
|
||||||
return &Dir{}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, ErrNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
func listFilesInDir[F File](m map[string]F, name string) (map[string]File, error) {
|
|
||||||
name = clean(name)
|
|
||||||
|
|
||||||
out := map[string]File{}
|
|
||||||
for p, f := range m {
|
|
||||||
if strings.HasPrefix(p, name) {
|
|
||||||
parts := strings.Split(trimRelPath(p, name), Separator)
|
|
||||||
if len(parts) == 1 {
|
|
||||||
out[parts[0]] = f
|
|
||||||
} else {
|
|
||||||
out[parts[0]] = &Dir{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimRelPath(p, t string) string {
|
func trimRelPath(p, t string) string {
|
||||||
return strings.Trim(strings.TrimPrefix(p, t), "/")
|
return strings.Trim(strings.TrimPrefix(p, t), "/")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
package vfs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFiles(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
files := map[string]*Dummy{
|
|
||||||
"/test/file.txt": &Dummy{},
|
|
||||||
}
|
|
||||||
{
|
|
||||||
file, err := getFile(files, "/test")
|
|
||||||
require.Nil(err)
|
|
||||||
require.Equal(&Dir{}, file)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
file, err := getFile(files, "/test/file.txt")
|
|
||||||
require.Nil(err)
|
|
||||||
require.Equal(&Dummy{}, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
out, err := listFilesInDir(files, "/test")
|
|
||||||
require.Nil(err)
|
|
||||||
require.Contains(out, "file.txt")
|
|
||||||
require.Equal(&Dummy{}, out["file.txt"])
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue