| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The LUCI Authors. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 package common |
| 16 |
| 17 import ( |
| 18 "fmt" |
| 19 "path/filepath" |
| 20 ) |
| 21 |
| 22 // FilesystemView provides a filtered "view" of a filesystem. |
| 23 // It translates absolute paths to relative paths based on its configured root p
ath. |
| 24 // It also hides any paths which match a blacklist entry. |
| 25 type FilesystemView struct { |
| 26 root string |
| 27 blacklist []string |
| 28 } |
| 29 |
| 30 // NewFilesystemView returns a FilesystemView based on the supplied root and bla
cklist, or |
| 31 // an error if blacklist contains a bad pattern. |
| 32 // root is the the base path used by RelativePath to calulate relative paths. |
| 33 // blacklist is a list of globs of files to ignore. See RelativePath for more i
nformation. |
| 34 func NewFilesystemView(root string, blacklist []string) (FilesystemView, error)
{ |
| 35 for _, b := range blacklist { |
| 36 if _, err := filepath.Match(b, b); err != nil { |
| 37 return FilesystemView{}, fmt.Errorf("bad blacklist patte
rn \"%s\"", b) |
| 38 } |
| 39 } |
| 40 return FilesystemView{root: root, blacklist: blacklist}, nil |
| 41 } |
| 42 |
| 43 // RelativePath returns a version of path which is relative to the FilesystemVie
w root, |
| 44 // or an empty string if path matches a blacklist entry. |
| 45 // |
| 46 // Blacklist globs are matched against the entirety of each of: |
| 47 // * the path relative to the FilesystemView root. |
| 48 // * the basename return by filepath.Base(path). |
| 49 // See filepath.Match for details about the format of blacklist globs. |
| 50 func (ff FilesystemView) RelativePath(path string) (string, error) { |
| 51 relPath, err := filepath.Rel(ff.root, path) |
| 52 if err != nil { |
| 53 return "", fmt.Errorf("calculating relative path(%q): %v", path,
err) |
| 54 } |
| 55 if ff.skipRelPath(relPath) { |
| 56 relPath = "" |
| 57 } |
| 58 return relPath, nil |
| 59 } |
| 60 |
| 61 func (ff FilesystemView) skipRelPath(relPath string) bool { |
| 62 // filepath.Rel is documented to call filepath.Clean on its result befor
e returning it, |
| 63 // which results in "." for an empty relative path. |
| 64 if relPath == "." { // Root directory. |
| 65 return false |
| 66 } |
| 67 |
| 68 for _, glob := range ff.blacklist { |
| 69 if match(glob, relPath) || match(glob, filepath.Base(relPath)) { |
| 70 return true |
| 71 } |
| 72 } |
| 73 |
| 74 return false |
| 75 } |
| 76 |
| 77 // match is equivalent to filepath.Match, but assumes that pattern is valid. |
| 78 func match(pattern, name string) bool { |
| 79 matched, _ := filepath.Match(pattern, name) |
| 80 return matched |
| 81 } |
| OLD | NEW |