Commit 8ca8d6ef authored by Matt Bell's avatar Matt Bell

commands/files: Added PeekFile and StatFile interfaces

squash! commands/files: Added PeekFile and StatFile interfaces

commands/http: Updated test
parent 487ef33e
......@@ -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() {
......
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"))},
}
sf := &files.SliceFile{"", fileset}
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.NewSliceFile("", fileset)
buf := make([]byte, 20)
// testing output by reading it with the go stdlib "mime/multipart" Reader
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment