mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
commands/files: Added PeekFile and StatFile interfaces
squash! commands/files: Added PeekFile and StatFile interfaces commands/http: Updated test
This commit is contained in:
parent
487ef33e67
commit
8ca8d6ef71
@ -64,7 +64,7 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
|
||||
}
|
||||
req.SetArguments(stringArgs)
|
||||
|
||||
file := &files.SliceFile{"", fileArgs}
|
||||
file := files.NewSliceFile("", fileArgs)
|
||||
req.SetFiles(file)
|
||||
|
||||
err = cmd.CheckArguments(req)
|
||||
@ -298,7 +298,7 @@ func appendFile(args []files.File, inputs []string, argDef *cmds.Argument, recur
|
||||
}
|
||||
|
||||
func appendStdinAsFile(args []files.File, stdin *os.File) ([]files.File, *os.File) {
|
||||
arg := &files.ReaderFile{"", stdin}
|
||||
arg := files.NewReaderFile("", stdin, nil)
|
||||
return append(args, arg), nil
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package files
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -29,3 +30,16 @@ type File interface {
|
||||
// If the file is a regular file (not a directory), NextFile will return a non-nil error.
|
||||
NextFile() (File, error)
|
||||
}
|
||||
|
||||
type StatFile interface {
|
||||
File
|
||||
|
||||
Stat() os.FileInfo
|
||||
}
|
||||
|
||||
type PeekFile interface {
|
||||
File
|
||||
|
||||
Peek(n int) File
|
||||
Length() int
|
||||
}
|
||||
|
||||
@ -11,13 +11,13 @@ import (
|
||||
func TestSliceFiles(t *testing.T) {
|
||||
name := "testname"
|
||||
files := []File{
|
||||
&ReaderFile{"file.txt", ioutil.NopCloser(strings.NewReader("Some text!\n"))},
|
||||
&ReaderFile{"beep.txt", ioutil.NopCloser(strings.NewReader("beep"))},
|
||||
&ReaderFile{"boop.txt", ioutil.NopCloser(strings.NewReader("boop"))},
|
||||
NewReaderFile("file.txt", ioutil.NopCloser(strings.NewReader("Some text!\n")), nil),
|
||||
NewReaderFile("beep.txt", ioutil.NopCloser(strings.NewReader("beep")), nil),
|
||||
NewReaderFile("boop.txt", ioutil.NopCloser(strings.NewReader("boop")), nil),
|
||||
}
|
||||
buf := make([]byte, 20)
|
||||
|
||||
sf := &SliceFile{name, files}
|
||||
sf := NewSliceFile(name, files)
|
||||
|
||||
if !sf.IsDirectory() {
|
||||
t.Error("SliceFile should always be a directory")
|
||||
@ -55,7 +55,7 @@ func TestSliceFiles(t *testing.T) {
|
||||
|
||||
func TestReaderFiles(t *testing.T) {
|
||||
message := "beep boop"
|
||||
rf := &ReaderFile{"file.txt", ioutil.NopCloser(strings.NewReader(message))}
|
||||
rf := NewReaderFile("file.txt", ioutil.NopCloser(strings.NewReader(message)), nil)
|
||||
buf := make([]byte, len(message))
|
||||
|
||||
if rf.IsDirectory() {
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
package files
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ReaderFile is a implementation of File created from an `io.Reader`.
|
||||
// ReaderFiles are never directories, and can be read from and closed.
|
||||
type ReaderFile struct {
|
||||
Filename string
|
||||
Reader io.ReadCloser
|
||||
filename string
|
||||
reader io.ReadCloser
|
||||
stat os.FileInfo
|
||||
}
|
||||
|
||||
func NewReaderFile(filename string, reader io.ReadCloser, stat os.FileInfo) *ReaderFile {
|
||||
return &ReaderFile{filename, reader, stat}
|
||||
}
|
||||
|
||||
func (f *ReaderFile) IsDirectory() bool {
|
||||
@ -18,13 +26,17 @@ func (f *ReaderFile) NextFile() (File, error) {
|
||||
}
|
||||
|
||||
func (f *ReaderFile) FileName() string {
|
||||
return f.Filename
|
||||
return f.filename
|
||||
}
|
||||
|
||||
func (f *ReaderFile) Read(p []byte) (int, error) {
|
||||
return f.Reader.Read(p)
|
||||
return f.reader.Read(p)
|
||||
}
|
||||
|
||||
func (f *ReaderFile) Close() error {
|
||||
return f.Reader.Close()
|
||||
return f.reader.Close()
|
||||
}
|
||||
|
||||
func (f *ReaderFile) Stat() os.FileInfo {
|
||||
return f.stat
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ func (es sortFIByName) Less(i, j int) bool { return es[i].Name() < es[j].Name()
|
||||
type serialFile struct {
|
||||
path string
|
||||
files []os.FileInfo
|
||||
stat os.FileInfo
|
||||
current *os.File
|
||||
}
|
||||
|
||||
@ -35,7 +36,7 @@ func NewSerialFile(path string, file *os.File) (File, error) {
|
||||
func newSerialFile(path string, file *os.File, stat os.FileInfo) (File, error) {
|
||||
// for non-directories, return a ReaderFile
|
||||
if !stat.IsDir() {
|
||||
return &ReaderFile{path, file}, nil
|
||||
return &ReaderFile{path, file, stat}, nil
|
||||
}
|
||||
|
||||
// for directories, stat all of the contents first, so we know what files to
|
||||
@ -55,7 +56,7 @@ func newSerialFile(path string, file *os.File, stat os.FileInfo) (File, error) {
|
||||
// make sure contents are sorted so -- repeatably -- we get the same inputs.
|
||||
sort.Sort(sortFIByName(contents))
|
||||
|
||||
return &serialFile{path, contents, nil}, nil
|
||||
return &serialFile{path, contents, stat, nil}, nil
|
||||
}
|
||||
|
||||
func (f *serialFile) IsDirectory() bool {
|
||||
@ -113,3 +114,7 @@ func (f *serialFile) Close() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *serialFile) Stat() os.FileInfo {
|
||||
return f.stat
|
||||
}
|
||||
|
||||
@ -6,8 +6,13 @@ import "io"
|
||||
// It contains children files, and is created from a `[]File`.
|
||||
// SliceFiles are always directories, and can't be read from or closed.
|
||||
type SliceFile struct {
|
||||
Filename string
|
||||
Files []File
|
||||
filename string
|
||||
files []File
|
||||
n int
|
||||
}
|
||||
|
||||
func NewSliceFile(filename string, files []File) *SliceFile {
|
||||
return &SliceFile{filename, files, 0}
|
||||
}
|
||||
|
||||
func (f *SliceFile) IsDirectory() bool {
|
||||
@ -15,16 +20,16 @@ func (f *SliceFile) IsDirectory() bool {
|
||||
}
|
||||
|
||||
func (f *SliceFile) NextFile() (File, error) {
|
||||
if len(f.Files) == 0 {
|
||||
if f.n >= len(f.files) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
file := f.Files[0]
|
||||
f.Files = f.Files[1:]
|
||||
file := f.files[f.n]
|
||||
f.n++
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func (f *SliceFile) FileName() string {
|
||||
return f.Filename
|
||||
return f.filename
|
||||
}
|
||||
|
||||
func (f *SliceFile) Read(p []byte) (int, error) {
|
||||
@ -34,3 +39,11 @@ func (f *SliceFile) Read(p []byte) (int, error) {
|
||||
func (f *SliceFile) Close() error {
|
||||
return ErrNotReader
|
||||
}
|
||||
|
||||
func (f *SliceFile) Peek(n int) File {
|
||||
return f.files[n]
|
||||
}
|
||||
|
||||
func (f *SliceFile) Length() int {
|
||||
return len(f.files)
|
||||
}
|
||||
|
||||
@ -13,14 +13,14 @@ import (
|
||||
func TestOutput(t *testing.T) {
|
||||
text := "Some text! :)"
|
||||
fileset := []files.File{
|
||||
&files.ReaderFile{"file.txt", ioutil.NopCloser(strings.NewReader(text))},
|
||||
&files.SliceFile{"boop", []files.File{
|
||||
&files.ReaderFile{"boop/a.txt", ioutil.NopCloser(strings.NewReader("bleep"))},
|
||||
&files.ReaderFile{"boop/b.txt", ioutil.NopCloser(strings.NewReader("bloop"))},
|
||||
}},
|
||||
&files.ReaderFile{"beep.txt", ioutil.NopCloser(strings.NewReader("beep"))},
|
||||
files.NewReaderFile("file.txt", ioutil.NopCloser(strings.NewReader(text)), nil),
|
||||
files.NewSliceFile("boop", []files.File{
|
||||
files.NewReaderFile("boop/a.txt", ioutil.NopCloser(strings.NewReader("bleep")), nil),
|
||||
files.NewReaderFile("boop/b.txt", ioutil.NopCloser(strings.NewReader("bloop")), nil),
|
||||
}),
|
||||
files.NewReaderFile("beep.txt", ioutil.NopCloser(strings.NewReader("beep")), nil),
|
||||
}
|
||||
sf := &files.SliceFile{"", fileset}
|
||||
sf := files.NewSliceFile("", fileset)
|
||||
buf := make([]byte, 20)
|
||||
|
||||
// testing output by reading it with the go stdlib "mime/multipart" Reader
|
||||
|
||||
Loading…
Reference in New Issue
Block a user