| // Copyright 2017 Google Inc. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package main |
| |
| import ( |
| "errors" |
| "flag" |
| "fmt" |
| "io" |
| "io/ioutil" |
| "log" |
| "os" |
| "runtime/pprof" |
| "sort" |
| "strings" |
| "time" |
| |
| "android/soong/finder" |
| "android/soong/finder/fs" |
| ) |
| |
| var ( |
| // configuration of what to find |
| excludeDirs string |
| filenamesToFind string |
| pruneFiles string |
| |
| // other configuration |
| cpuprofile string |
| verbose bool |
| dbPath string |
| numIterations int |
| ) |
| |
| func init() { |
| flag.StringVar(&cpuprofile, "cpuprofile", "", |
| "filepath of profile file to write (optional)") |
| flag.BoolVar(&verbose, "v", false, "log additional information") |
| flag.StringVar(&dbPath, "db", "", "filepath of cache db") |
| |
| flag.StringVar(&excludeDirs, "exclude-dirs", "", |
| "comma-separated list of directory names to exclude from search") |
| flag.StringVar(&filenamesToFind, "names", "", |
| "comma-separated list of filenames to find") |
| flag.StringVar(&pruneFiles, "prune-files", "", |
| "filenames that if discovered will exclude their entire directory "+ |
| "(including sibling files and directories)") |
| flag.IntVar(&numIterations, "count", 1, |
| "number of times to run. This is intended for use with --cpuprofile"+ |
| " , to increase profile accuracy") |
| } |
| |
| var usage = func() { |
| fmt.Printf("usage: finder -name <fileName> --db <dbPath> <searchDirectory> [<searchDirectory>...]\n") |
| flag.PrintDefaults() |
| } |
| |
| func main() { |
| err := run() |
| if err != nil { |
| fmt.Fprintf(os.Stderr, "%v\n", err.Error()) |
| os.Exit(1) |
| } |
| } |
| |
| func stringToList(input string) []string { |
| return strings.Split(input, ",") |
| } |
| |
| func run() error { |
| startTime := time.Now() |
| flag.Parse() |
| |
| if cpuprofile != "" { |
| f, err := os.Create(cpuprofile) |
| if err != nil { |
| return fmt.Errorf("Error opening cpuprofile: %s", err) |
| } |
| pprof.StartCPUProfile(f) |
| defer f.Close() |
| defer pprof.StopCPUProfile() |
| } |
| |
| var writer io.Writer |
| if verbose { |
| writer = os.Stderr |
| } else { |
| writer = ioutil.Discard |
| } |
| |
| // TODO: replace Lshortfile with Llongfile when bug 63821638 is done |
| logger := log.New(writer, "", log.Ldate|log.Lmicroseconds|log.Lshortfile) |
| |
| logger.Printf("Finder starting at %v\n", startTime) |
| |
| rootPaths := flag.Args() |
| if len(rootPaths) < 1 { |
| usage() |
| return fmt.Errorf( |
| "Must give at least one <searchDirectory>") |
| } |
| |
| workingDir, err := os.Getwd() |
| if err != nil { |
| return err |
| } |
| params := finder.CacheParams{ |
| WorkingDirectory: workingDir, |
| RootDirs: rootPaths, |
| ExcludeDirs: stringToList(excludeDirs), |
| PruneFiles: stringToList(pruneFiles), |
| IncludeFiles: stringToList(filenamesToFind), |
| } |
| if dbPath == "" { |
| usage() |
| return errors.New("Param 'db' must be nonempty") |
| } |
| |
| matches := []string{} |
| for i := 0; i < numIterations; i++ { |
| matches, err = runFind(params, logger) |
| if err != nil { |
| return err |
| } |
| } |
| findDuration := time.Since(startTime) |
| logger.Printf("Found these %v inodes in %v :\n", len(matches), findDuration) |
| sort.Strings(matches) |
| for _, match := range matches { |
| fmt.Println(match) |
| } |
| logger.Printf("End of %v inodes\n", len(matches)) |
| logger.Printf("Finder completed in %v\n", time.Since(startTime)) |
| return nil |
| } |
| |
| func runFind(params finder.CacheParams, logger *log.Logger) (paths []string, err error) { |
| service, err := finder.New(params, fs.OsFs, logger, dbPath) |
| if err != nil { |
| return []string{}, err |
| } |
| defer service.Shutdown() |
| return service.FindAll(), nil |
| } |