MCPcopy
hub / github.com/purpleidea/mgmt / DirectoryReader

Function DirectoryReader

lang/parser/lexparse.go:178–241  ·  view source on GitHub ↗

DirectoryReader takes a filesystem and an absolute directory path, and it returns a combined reader into that directory, and an offset map of the file contents. This is used to build a reader from a directory containing language source files, and as a result, this will skip over files that don't hav

(fs engine.Fs, dir string)

Source from the content-addressed store, hash-verified

176// TODO: Due to an implementation difficulty, offsets are currently in length!
177// NOTE: This was used for an older deprecated form of lex/parse file combining.
178func DirectoryReader(fs engine.Fs, dir string) (io.Reader, map[uint64]string, error) {
179 fis, err := fs.ReadDir(dir) // ([]os.FileInfo, error)
180 if err != nil {
181 return nil, nil, errwrap.Wrapf(err, "can't stat directory contents `%s`", dir)
182 }
183
184 var offset uint64
185 offsets := make(map[uint64]string) // cumulative offset to abs. filename
186 readers := []io.Reader{}
187
188 for _, fi := range fis {
189 if fi.IsDir() {
190 continue // skip directories
191 }
192 name := path.Join(dir, fi.Name()) // relative path made absolute
193 if !strings.HasSuffix(name, interfaces.DotFileNameExtension) {
194 continue
195 }
196
197 f, err := fs.Open(name) // opens read-only
198 if err != nil {
199 return nil, nil, errwrap.Wrapf(err, "can't open file `%s`", name)
200 }
201 defer f.Close()
202 //stat, err := f.Stat() // (os.FileInfo, error)
203 //if err != nil {
204 // return nil, nil, errwrap.Wrapf(err, "can't stat file `%s`", name)
205 //}
206
207 offsets[offset] = name // save cumulative offset (starts at 0)
208 //offset += uint64(stat.Size()) // the earlier stat causes file download
209
210 // TODO: store the offset in size instead of length! we're using
211 // length at the moment since it is not clear how easy it is for
212 // the lexer/parser to return the byte offset as well as line no
213 // NOTE: in addition, this scanning is not the fastest for perf!
214 scanner := bufio.NewScanner(f)
215 lines := 0
216 for scanner.Scan() { // each line
217 lines++
218 }
219 if err := scanner.Err(); err != nil {
220 return nil, nil, errwrap.Wrapf(err, "can't scan file `%s`", name)
221 }
222 offset += uint64(lines)
223 if start, err := f.Seek(0, io.SeekStart); err != nil { // reset
224 return nil, nil, errwrap.Wrapf(err, "can't reset file `%s`", name)
225 } else if start != 0 { // we should be at the start (0)
226 return nil, nil, fmt.Errorf("reset of file `%s` was %d", name, start)
227 }
228
229 readers = append(readers, f)
230 }
231 if len(offsets) == 0 {
232 // TODO: this condition should be validated during the deploy...
233 return nil, nil, fmt.Errorf("no files in main directory")
234 }
235

Callers

nothing calls this directly

Calls 8

WrapfFunction · 0.92
SeekMethod · 0.80
ReadDirMethod · 0.65
IsDirMethod · 0.65
NameMethod · 0.65
ErrMethod · 0.65
OpenMethod · 0.45
CloseMethod · 0.45

Tested by

no test coverage detected