github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/tools/filelistgen/main.go (about) 1 // Copyright 2015 The rkt 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 main 16 17 import ( 18 "flag" 19 "fmt" 20 "io/ioutil" 21 "os" 22 "path/filepath" 23 "strings" 24 25 "github.com/coreos/rkt/tools/common" 26 "github.com/coreos/rkt/tools/common/filelist" 27 ) 28 29 type fsWalker struct { 30 dir string 31 list *filelist.Lists 32 } 33 34 func main() { 35 dir := "" 36 suffix := "" 37 empty := false 38 flag.StringVar(&dir, "directory", "", "Directory path") 39 flag.StringVar(&suffix, "suffix", "", "Suffix for files in directory, when passed it basically does ${--dir}/*${suffix} (dotfiles are ignored)") 40 flag.BoolVar(&empty, "empty", false, "Generate empty filelist") 41 42 flag.Parse() 43 if !empty && dir == "" { 44 common.Die("No --directory parameter passed") 45 } 46 47 list := getListing(empty, dir, suffix) 48 if err := list.GenerateFilelist(os.Stdout); err != nil { 49 common.Die("Failed to generate a filelist: %v", err) 50 } 51 } 52 53 func getListing(empty bool, dir, suffix string) *filelist.Lists { 54 if empty { 55 return &filelist.Lists{} 56 } 57 if suffix == "" { 58 return getDeepListing(dir) 59 } 60 return getShallowListing(dir, suffix) 61 } 62 63 func getDeepListing(dir string) *filelist.Lists { 64 walker := newFsWalker(common.MustAbs(dir)) 65 list, err := walker.getListing() 66 if err != nil { 67 common.Die("Error during getting listing from directory %q: %v", dir, err) 68 } 69 return list 70 } 71 72 func getShallowListing(dir, suffix string) *filelist.Lists { 73 list := &filelist.Lists{} 74 fiList, err := ioutil.ReadDir(dir) 75 if err != nil { 76 common.Die("Failed to read directory %q: %v", dir, err) 77 } 78 for _, fi := range fiList { 79 name := fi.Name() 80 if !strings.HasSuffix(name, suffix) { 81 continue 82 } 83 if strings.HasPrefix(name, ".") { 84 continue 85 } 86 if err := categorizeEntry(name, fi.Mode(), list); err != nil { 87 common.Die("%v", err) 88 } 89 } 90 return list 91 } 92 93 func newFsWalker(dir string) *fsWalker { 94 return &fsWalker{ 95 dir: dir, 96 list: &filelist.Lists{}, 97 } 98 } 99 100 func (w *fsWalker) getListing() (*filelist.Lists, error) { 101 src := w.dir 102 if err := filepath.Walk(src, w.getWalkFunc(src)); err != nil { 103 return nil, err 104 } 105 return w.list, nil 106 } 107 108 func (w *fsWalker) getWalkFunc(src string) filepath.WalkFunc { 109 return func(path string, info os.FileInfo, err error) error { 110 if err != nil { 111 return err 112 } 113 rootLess := filepath.Clean(path[len(src):]) 114 // filepath.Clean guarantees that rootLess is never empty. 115 if rootLess[0] == filepath.Separator { 116 rootLess = rootLess[1:] 117 } 118 if rootLess == "." { 119 // skip the toplevel directory 120 return nil 121 } 122 if err := categorizeEntry(rootLess, info.Mode(), w.list); err != nil { 123 return err 124 } 125 return nil 126 } 127 } 128 129 func categorizeEntry(path string, mode os.FileMode, list *filelist.Lists) error { 130 switch { 131 case mode.IsDir(): 132 list.Dirs = append(list.Dirs, path) 133 case mode.IsRegular(): 134 list.Files = append(list.Files, path) 135 case isSymlink(mode): 136 list.Symlinks = append(list.Symlinks, path) 137 default: 138 return fmt.Errorf("unsupported file mode: %d (not a file, directory or symlink)", mode&os.ModeType) 139 } 140 return nil 141 } 142 143 func isSymlink(mode os.FileMode) bool { 144 return mode&os.ModeSymlink == os.ModeSymlink 145 }