blob: ab9108f687973d024ed11f5f0204a01445783e26 [file] [log] [blame]
Jeff Gastonf1fd45e2017-08-09 18:25:28 -07001// Copyright 2017 Google Inc. All rights reserved.
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
15package main
16
17import (
18 "errors"
19 "flag"
20 "fmt"
21 "io"
22 "io/ioutil"
23 "log"
24 "os"
25 "runtime/pprof"
26 "sort"
27 "strings"
28 "time"
29
30 "android/soong/finder"
Colin Cross8d6395c2017-12-21 15:46:01 -080031 "android/soong/finder/fs"
Jeff Gastonf1fd45e2017-08-09 18:25:28 -070032)
33
34var (
35 // configuration of what to find
36 excludeDirs string
37 filenamesToFind string
38 pruneFiles string
39
40 // other configuration
41 cpuprofile string
42 verbose bool
43 dbPath string
44 numIterations int
45)
46
47func init() {
48 flag.StringVar(&cpuprofile, "cpuprofile", "",
49 "filepath of profile file to write (optional)")
50 flag.BoolVar(&verbose, "v", false, "log additional information")
51 flag.StringVar(&dbPath, "db", "", "filepath of cache db")
52
53 flag.StringVar(&excludeDirs, "exclude-dirs", "",
54 "comma-separated list of directory names to exclude from search")
55 flag.StringVar(&filenamesToFind, "names", "",
56 "comma-separated list of filenames to find")
57 flag.StringVar(&pruneFiles, "prune-files", "",
58 "filenames that if discovered will exclude their entire directory "+
59 "(including sibling files and directories)")
60 flag.IntVar(&numIterations, "count", 1,
61 "number of times to run. This is intended for use with --cpuprofile"+
62 " , to increase profile accuracy")
63}
64
65var usage = func() {
66 fmt.Printf("usage: finder -name <fileName> --db <dbPath> <searchDirectory> [<searchDirectory>...]\n")
67 flag.PrintDefaults()
68}
69
70func main() {
71 err := run()
72 if err != nil {
73 fmt.Fprintf(os.Stderr, "%v\n", err.Error())
74 os.Exit(1)
75 }
76}
77
78func stringToList(input string) []string {
79 return strings.Split(input, ",")
80}
81
82func run() error {
83 startTime := time.Now()
84 flag.Parse()
85
86 if cpuprofile != "" {
87 f, err := os.Create(cpuprofile)
88 if err != nil {
89 return fmt.Errorf("Error opening cpuprofile: %s", err)
90 }
91 pprof.StartCPUProfile(f)
92 defer f.Close()
93 defer pprof.StopCPUProfile()
94 }
95
96 var writer io.Writer
97 if verbose {
98 writer = os.Stderr
99 } else {
100 writer = ioutil.Discard
101 }
102
103 // TODO: replace Lshortfile with Llongfile when bug 63821638 is done
104 logger := log.New(writer, "", log.Ldate|log.Lmicroseconds|log.Lshortfile)
105
106 logger.Printf("Finder starting at %v\n", startTime)
107
108 rootPaths := flag.Args()
109 if len(rootPaths) < 1 {
110 usage()
111 return fmt.Errorf(
112 "Must give at least one <searchDirectory>")
113 }
114
115 workingDir, err := os.Getwd()
116 if err != nil {
117 return err
118 }
119 params := finder.CacheParams{
120 WorkingDirectory: workingDir,
121 RootDirs: rootPaths,
122 ExcludeDirs: stringToList(excludeDirs),
123 PruneFiles: stringToList(pruneFiles),
124 IncludeFiles: stringToList(filenamesToFind),
125 }
126 if dbPath == "" {
127 usage()
128 return errors.New("Param 'db' must be nonempty")
129 }
Jeff Gastonb629e182017-08-14 16:49:18 -0700130
Jeff Gastonf1fd45e2017-08-09 18:25:28 -0700131 matches := []string{}
132 for i := 0; i < numIterations; i++ {
Jeff Gastonb629e182017-08-14 16:49:18 -0700133 matches, err = runFind(params, logger)
134 if err != nil {
135 return err
136 }
Jeff Gastonf1fd45e2017-08-09 18:25:28 -0700137 }
138 findDuration := time.Since(startTime)
139 logger.Printf("Found these %v inodes in %v :\n", len(matches), findDuration)
140 sort.Strings(matches)
141 for _, match := range matches {
142 fmt.Println(match)
143 }
144 logger.Printf("End of %v inodes\n", len(matches))
145 logger.Printf("Finder completed in %v\n", time.Since(startTime))
146 return nil
147}
148
Jeff Gastonb629e182017-08-14 16:49:18 -0700149func runFind(params finder.CacheParams, logger *log.Logger) (paths []string, err error) {
150 service, err := finder.New(params, fs.OsFs, logger, dbPath)
151 if err != nil {
152 return []string{}, err
153 }
Jeff Gastonf1fd45e2017-08-09 18:25:28 -0700154 defer service.Shutdown()
Jeff Gastonb629e182017-08-14 16:49:18 -0700155 return service.FindAll(), nil
Jeff Gastonf1fd45e2017-08-09 18:25:28 -0700156}