Refactor serialfile
License: MIT Signed-off-by: rht <rhtbot@gmail.com>
rht committed
Sep 4, 2015 at 14:03 UTC
ccc9cd6a6cc0747f10689e22bbd547cfb8ab6600
1 file changed
+25
-70
commands/files/serialfile.go
+25
-70
@@ -3,18 +3,12 @@ package files
3
import (
4
"fmt"
5
"io"
6
+ "io/ioutil"
7
"os"
8
fp "path/filepath"
8
- "sort"
9
"syscall"
10
)
11
12
-type sortFIByName []os.FileInfo
13
-
14
-func (es sortFIByName) Len() int { return len(es) }
15
-func (es sortFIByName) Swap(i, j int) { es[i], es[j] = es[j], es[i] }
16
-func (es sortFIByName) Less(i, j int) bool { return es[i].Name() < es[j].Name() }
17
-
12
// serialFile implements File, and reads from a path on the OS filesystem.
13
// No more than one file will be opened at a time (directories will advance
14
// to the next file when NextFile() is called).
@@ -23,55 +17,34 @@ type serialFile struct {
17
path string
18
files []os.FileInfo
19
stat os.FileInfo
26
- current *os.File
20
+ current *File
21
}
22
23
func NewSerialFile(name, path string, stat os.FileInfo) (File, error) {
24
switch mode := stat.Mode(); {
31
- case mode.IsDir() || mode.IsRegular():
32
- break
25
+ case mode.IsRegular():
26
+ file, err := os.Open(path)
27
+ if err != nil {
28
+ return nil, err
29
+ }
30
+ return NewReaderFile(name, path, file, stat), nil
31
+ case mode.IsDir():
32
+ // for directories, stat all of the contents first, so we know what files to
33
+ // open when NextFile() is called
34
+ contents, err := ioutil.ReadDir(path)
35
+ if err != nil {
36
+ return nil, err
37
+ }
38
+ return &serialFile{name, path, contents, stat, nil}, nil
39
case mode&os.ModeSymlink != 0:
40
target, err := os.Readlink(path)
41
if err != nil {
42
return nil, err
43
}
38
-
39
- return NewLinkFile("", path, target, stat), nil
44
+ return NewLinkFile(name, path, target, stat), nil
45
default:
41
- return nil, fmt.Errorf("Unrecognized file type for %s: %s", stat.Name(), mode.String())
42
- }
43
-
44
- file, err := os.Open(path)
45
- if err != nil {
46
- return nil, err
47
- }
48
-
49
- return newSerialFile(name, path, file, stat)
50
-}
51
-
52
-func newSerialFile(name, path string, file *os.File, stat os.FileInfo) (File, error) {
53
- // for non-directories, return a ReaderFile
54
- if !stat.IsDir() {
55
- return &ReaderFile{name, path, file, stat}, nil
56
- }
57
-
58
- // for directories, stat all of the contents first, so we know what files to
59
- // open when NextFile() is called
60
- contents, err := file.Readdir(0)
61
- if err != nil {
62
- return nil, err
46
+ return nil, fmt.Errorf("Unrecognized file type for %s: %s", name, mode.String())
47
}
64
-
65
- // we no longer need our root directory file (we already statted the contents),
66
- // so close it
67
- if err := file.Close(); err != nil {
68
- return nil, err
69
- }
70
-
71
- // make sure contents are sorted so -- repeatably -- we get the same inputs.
72
- sort.Sort(sortFIByName(contents))
73
-
74
- return &serialFile{name, path, contents, stat, nil}, nil
48
}
49
50
func (f *serialFile) IsDirectory() bool {
@@ -98,36 +71,18 @@ func (f *serialFile) NextFile() (File, error) {
71
// open the next file
72
fileName := fp.Join(f.name, stat.Name())
73
filePath := fp.Join(f.path, stat.Name())
101
- st, err := os.Lstat(filePath)
102
- if err != nil {
103
- return nil, err
104
- }
74
106
- switch mode := st.Mode(); {
107
- case mode.IsDir() || mode.IsRegular():
108
- break
109
- case mode&os.ModeSymlink != 0:
110
- f.current = nil
111
- target, err := os.Readlink(filePath)
112
- if err != nil {
113
- return nil, err
114
- }
115
- return NewLinkFile(fileName, filePath, target, st), nil
116
- default:
117
- return nil, fmt.Errorf("Unrecognized file type for %s: %s", st.Name(), mode.String())
118
- }
119
-
120
- file, err := os.Open(filePath)
75
+ // recursively call the constructor on the next file
76
+ // if it's a regular file, we will open it as a ReaderFile
77
+ // if it's a directory, files in it will be opened serially
78
+ sf, err := NewSerialFile(fileName, filePath, stat)
79
if err != nil {
80
return nil, err
81
}
82
125
- f.current = file
83
+ f.current = &sf
84
127
- // recursively call the constructor on the next file
128
- // if it's a regular file, we will open it as a ReaderFile
129
- // if it's a directory, files in it will be opened serially
130
- return newSerialFile(fileName, filePath, file, stat)
85
+ return sf, nil
86
}
87
88
func (f *serialFile) FileName() string {
@@ -145,7 +100,7 @@ func (f *serialFile) Read(p []byte) (int, error) {
100
func (f *serialFile) Close() error {
101
// close the current file if there is one
102
if f.current != nil {
148
- err := f.current.Close()
103
+ err := (*f.current).Close()
104
// ignore EINVAL error, the file might have already been closed
105
if err != nil && err != syscall.EINVAL {
106
return err