123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- /*
- * Rufs - Remote Union File System
- *
- * Copyright 2017 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- /*
- Package rumble contains Rumble functions which interface with Rufs.
- */
- package rumble
- import (
- "fmt"
- "os"
- "regexp"
- "devt.de/krotik/common/defs/rumble"
- "devt.de/krotik/common/stringutil"
- "devt.de/krotik/rufs/api"
- )
- // Function: dir
- // =============
- /*
- DirFunc queries a directory in a tree.
- */
- type DirFunc struct {
- }
- /*
- Name returns the name of the function.
- */
- func (f *DirFunc) Name() string {
- return "fs.dir"
- }
- /*
- Validate is called for parameter validation and to reset the function state.
- */
- func (f *DirFunc) Validate(argsNum int, rt rumble.Runtime) rumble.RuntimeError {
- var err rumble.RuntimeError
- if argsNum != 3 && argsNum != 4 {
- err = rt.NewRuntimeError(rumble.ErrInvalidConstruct,
- "Function dir requires 3 or 4 parameters: tree, a path, a glob expression and optionally a recursive flag")
- }
- return err
- }
- /*
- Execute executes the rumble function.
- */
- func (f *DirFunc) Execute(argsVal []interface{}, vars rumble.Variables,
- rt rumble.Runtime) (interface{}, rumble.RuntimeError) {
- var res interface{}
- var paths []string
- var fiList [][]os.FileInfo
- treeName := fmt.Sprint(argsVal[0])
- path := fmt.Sprint(argsVal[1])
- pattern := fmt.Sprint(argsVal[2])
- recursive := argsVal[3] == true
- conv := func(re *regexp.Regexp, fis []os.FileInfo) []interface{} {
- r := make([]interface{}, 0, len(fis))
- for _, fi := range fis {
- if !fi.IsDir() && !re.MatchString(fi.Name()) {
- continue
- }
- r = append(r, map[interface{}]interface{}{
- "name": fi.Name(),
- "mode": fmt.Sprint(fi.Mode()),
- "modtime": fmt.Sprint(fi.ModTime()),
- "isdir": fi.IsDir(),
- "size": fi.Size(),
- })
- }
- return r
- }
- tree, ok, err := api.GetTree(treeName)
- if !ok {
- if err == nil {
- err = fmt.Errorf("Unknown tree: %v", treeName)
- }
- }
- if err == nil {
- var globPattern string
- // Create regex for files
- if globPattern, err = stringutil.GlobToRegex(pattern); err == nil {
- var re *regexp.Regexp
- if re, err = regexp.Compile(globPattern); err == nil {
- // Query the file system
- paths, fiList, err = tree.Dir(path, "", recursive, false)
- pathData := make([]interface{}, 0, len(paths))
- fisData := make([]interface{}, 0, len(paths))
- // Convert the result into a Rumble data structure
- for i := range paths {
- fis := conv(re, fiList[i])
- // If we have a regex then only include directories which have files
- pathData = append(pathData, paths[i])
- fisData = append(fisData, fis)
- }
- res = []interface{}{pathData, fisData}
- }
- }
- }
- if err != nil {
- // Wrap error message in RuntimeError
- err = rt.NewRuntimeError(rumble.ErrInvalidState,
- fmt.Sprintf("Cannot list files: %v", err.Error()))
- }
- return res, err
- }
|