...

Source file src/github.com/shurcooL/httpfs/path/vfspath/match.go

Documentation: github.com/shurcooL/httpfs/path/vfspath

     1  // Package vfspath implements utility routines for manipulating virtual file system paths.
     2  package vfspath
     3  
     4  import (
     5  	"net/http"
     6  	"os"
     7  	"path"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/shurcooL/httpfs/vfsutil"
    12  )
    13  
    14  const separator = "/"
    15  
    16  // Glob returns the names of all files matching pattern or nil
    17  // if there is no matching file. The syntax of patterns is the same
    18  // as in path.Match. The pattern may describe hierarchical names such as
    19  // /usr/*/bin/ed.
    20  //
    21  // Glob ignores file system errors such as I/O errors reading directories.
    22  // The only possible returned error is ErrBadPattern, when pattern
    23  // is malformed.
    24  func Glob(fs http.FileSystem, pattern string) (matches []string, err error) {
    25  	if !hasMeta(pattern) {
    26  		if _, err = vfsutil.Stat(fs, pattern); err != nil {
    27  			return nil, nil
    28  		}
    29  		return []string{pattern}, nil
    30  	}
    31  
    32  	dir, file := path.Split(pattern)
    33  	switch dir {
    34  	case "":
    35  		dir = "."
    36  	case string(separator):
    37  		// nothing
    38  	default:
    39  		dir = dir[0 : len(dir)-1] // chop off trailing separator
    40  	}
    41  
    42  	if !hasMeta(dir) {
    43  		return glob(fs, dir, file, nil)
    44  	}
    45  
    46  	var m []string
    47  	m, err = Glob(fs, dir)
    48  	if err != nil {
    49  		return
    50  	}
    51  	for _, d := range m {
    52  		matches, err = glob(fs, d, file, matches)
    53  		if err != nil {
    54  			return
    55  		}
    56  	}
    57  	return
    58  }
    59  
    60  // glob searches for files matching pattern in the directory dir
    61  // and appends them to matches. If the directory cannot be
    62  // opened, it returns the existing matches. New matches are
    63  // added in lexicographical order.
    64  func glob(fs http.FileSystem, dir, pattern string, matches []string) (m []string, e error) {
    65  	m = matches
    66  	fi, err := vfsutil.Stat(fs, dir)
    67  	if err != nil {
    68  		return
    69  	}
    70  	if !fi.IsDir() {
    71  		return
    72  	}
    73  	fis, err := vfsutil.ReadDir(fs, dir)
    74  	if err != nil {
    75  		return
    76  	}
    77  
    78  	sort.Sort(byName(fis))
    79  
    80  	for _, fi := range fis {
    81  		n := fi.Name()
    82  		matched, err := path.Match(path.Clean(pattern), n)
    83  		if err != nil {
    84  			return m, err
    85  		}
    86  		if matched {
    87  			m = append(m, path.Join(dir, n))
    88  		}
    89  	}
    90  	return
    91  }
    92  
    93  // hasMeta reports whether path contains any of the magic characters
    94  // recognized by Match.
    95  func hasMeta(path string) bool {
    96  	// TODO(niemeyer): Should other magic characters be added here?
    97  	return strings.ContainsAny(path, "*?[")
    98  }
    99  
   100  // byName implements sort.Interface.
   101  type byName []os.FileInfo
   102  
   103  func (f byName) Len() int           { return len(f) }
   104  func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
   105  func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
   106  

View as plain text