xref: /aosp_15_r20/build/soong/finder/cmd/finder.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage main
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"errors"
19*333d2b36SAndroid Build Coastguard Worker	"flag"
20*333d2b36SAndroid Build Coastguard Worker	"fmt"
21*333d2b36SAndroid Build Coastguard Worker	"io"
22*333d2b36SAndroid Build Coastguard Worker	"io/ioutil"
23*333d2b36SAndroid Build Coastguard Worker	"log"
24*333d2b36SAndroid Build Coastguard Worker	"os"
25*333d2b36SAndroid Build Coastguard Worker	"runtime/pprof"
26*333d2b36SAndroid Build Coastguard Worker	"sort"
27*333d2b36SAndroid Build Coastguard Worker	"strings"
28*333d2b36SAndroid Build Coastguard Worker	"time"
29*333d2b36SAndroid Build Coastguard Worker
30*333d2b36SAndroid Build Coastguard Worker	"android/soong/finder"
31*333d2b36SAndroid Build Coastguard Worker	"android/soong/finder/fs"
32*333d2b36SAndroid Build Coastguard Worker)
33*333d2b36SAndroid Build Coastguard Worker
34*333d2b36SAndroid Build Coastguard Workervar (
35*333d2b36SAndroid Build Coastguard Worker	// configuration of what to find
36*333d2b36SAndroid Build Coastguard Worker	excludeDirs     string
37*333d2b36SAndroid Build Coastguard Worker	filenamesToFind string
38*333d2b36SAndroid Build Coastguard Worker	pruneFiles      string
39*333d2b36SAndroid Build Coastguard Worker
40*333d2b36SAndroid Build Coastguard Worker	// other configuration
41*333d2b36SAndroid Build Coastguard Worker	cpuprofile    string
42*333d2b36SAndroid Build Coastguard Worker	verbose       bool
43*333d2b36SAndroid Build Coastguard Worker	dbPath        string
44*333d2b36SAndroid Build Coastguard Worker	numIterations int
45*333d2b36SAndroid Build Coastguard Worker)
46*333d2b36SAndroid Build Coastguard Worker
47*333d2b36SAndroid Build Coastguard Workerfunc init() {
48*333d2b36SAndroid Build Coastguard Worker	flag.StringVar(&cpuprofile, "cpuprofile", "",
49*333d2b36SAndroid Build Coastguard Worker		"filepath of profile file to write (optional)")
50*333d2b36SAndroid Build Coastguard Worker	flag.BoolVar(&verbose, "v", false, "log additional information")
51*333d2b36SAndroid Build Coastguard Worker	flag.StringVar(&dbPath, "db", "", "filepath of cache db")
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker	flag.StringVar(&excludeDirs, "exclude-dirs", "",
54*333d2b36SAndroid Build Coastguard Worker		"comma-separated list of directory names to exclude from search")
55*333d2b36SAndroid Build Coastguard Worker	flag.StringVar(&filenamesToFind, "names", "",
56*333d2b36SAndroid Build Coastguard Worker		"comma-separated list of filenames to find")
57*333d2b36SAndroid Build Coastguard Worker	flag.StringVar(&pruneFiles, "prune-files", "",
58*333d2b36SAndroid Build Coastguard Worker		"filenames that if discovered will exclude their entire directory "+
59*333d2b36SAndroid Build Coastguard Worker			"(including sibling files and directories)")
60*333d2b36SAndroid Build Coastguard Worker	flag.IntVar(&numIterations, "count", 1,
61*333d2b36SAndroid Build Coastguard Worker		"number of times to run. This is intended for use with --cpuprofile"+
62*333d2b36SAndroid Build Coastguard Worker			" , to increase profile accuracy")
63*333d2b36SAndroid Build Coastguard Worker}
64*333d2b36SAndroid Build Coastguard Worker
65*333d2b36SAndroid Build Coastguard Workervar usage = func() {
66*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("usage: finder -name <fileName> --db <dbPath> <searchDirectory> [<searchDirectory>...]\n")
67*333d2b36SAndroid Build Coastguard Worker	flag.PrintDefaults()
68*333d2b36SAndroid Build Coastguard Worker}
69*333d2b36SAndroid Build Coastguard Worker
70*333d2b36SAndroid Build Coastguard Workerfunc main() {
71*333d2b36SAndroid Build Coastguard Worker	err := run()
72*333d2b36SAndroid Build Coastguard Worker	if err != nil {
73*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, "%v\n", err.Error())
74*333d2b36SAndroid Build Coastguard Worker		os.Exit(1)
75*333d2b36SAndroid Build Coastguard Worker	}
76*333d2b36SAndroid Build Coastguard Worker}
77*333d2b36SAndroid Build Coastguard Worker
78*333d2b36SAndroid Build Coastguard Workerfunc stringToList(input string) []string {
79*333d2b36SAndroid Build Coastguard Worker	return strings.Split(input, ",")
80*333d2b36SAndroid Build Coastguard Worker}
81*333d2b36SAndroid Build Coastguard Worker
82*333d2b36SAndroid Build Coastguard Workerfunc run() error {
83*333d2b36SAndroid Build Coastguard Worker	startTime := time.Now()
84*333d2b36SAndroid Build Coastguard Worker	flag.Parse()
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker	if cpuprofile != "" {
87*333d2b36SAndroid Build Coastguard Worker		f, err := os.Create(cpuprofile)
88*333d2b36SAndroid Build Coastguard Worker		if err != nil {
89*333d2b36SAndroid Build Coastguard Worker			return fmt.Errorf("Error opening cpuprofile: %s", err)
90*333d2b36SAndroid Build Coastguard Worker		}
91*333d2b36SAndroid Build Coastguard Worker		pprof.StartCPUProfile(f)
92*333d2b36SAndroid Build Coastguard Worker		defer f.Close()
93*333d2b36SAndroid Build Coastguard Worker		defer pprof.StopCPUProfile()
94*333d2b36SAndroid Build Coastguard Worker	}
95*333d2b36SAndroid Build Coastguard Worker
96*333d2b36SAndroid Build Coastguard Worker	var writer io.Writer
97*333d2b36SAndroid Build Coastguard Worker	if verbose {
98*333d2b36SAndroid Build Coastguard Worker		writer = os.Stderr
99*333d2b36SAndroid Build Coastguard Worker	} else {
100*333d2b36SAndroid Build Coastguard Worker		writer = ioutil.Discard
101*333d2b36SAndroid Build Coastguard Worker	}
102*333d2b36SAndroid Build Coastguard Worker
103*333d2b36SAndroid Build Coastguard Worker	// TODO: replace Lshortfile with Llongfile when bug 63821638 is done
104*333d2b36SAndroid Build Coastguard Worker	logger := log.New(writer, "", log.Ldate|log.Lmicroseconds|log.Lshortfile)
105*333d2b36SAndroid Build Coastguard Worker
106*333d2b36SAndroid Build Coastguard Worker	logger.Printf("Finder starting at %v\n", startTime)
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Worker	rootPaths := flag.Args()
109*333d2b36SAndroid Build Coastguard Worker	if len(rootPaths) < 1 {
110*333d2b36SAndroid Build Coastguard Worker		usage()
111*333d2b36SAndroid Build Coastguard Worker		return fmt.Errorf(
112*333d2b36SAndroid Build Coastguard Worker			"Must give at least one <searchDirectory>")
113*333d2b36SAndroid Build Coastguard Worker	}
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Worker	workingDir, err := os.Getwd()
116*333d2b36SAndroid Build Coastguard Worker	if err != nil {
117*333d2b36SAndroid Build Coastguard Worker		return err
118*333d2b36SAndroid Build Coastguard Worker	}
119*333d2b36SAndroid Build Coastguard Worker	params := finder.CacheParams{
120*333d2b36SAndroid Build Coastguard Worker		WorkingDirectory: workingDir,
121*333d2b36SAndroid Build Coastguard Worker		RootDirs:         rootPaths,
122*333d2b36SAndroid Build Coastguard Worker		ExcludeDirs:      stringToList(excludeDirs),
123*333d2b36SAndroid Build Coastguard Worker		PruneFiles:       stringToList(pruneFiles),
124*333d2b36SAndroid Build Coastguard Worker		IncludeFiles:     stringToList(filenamesToFind),
125*333d2b36SAndroid Build Coastguard Worker	}
126*333d2b36SAndroid Build Coastguard Worker	if dbPath == "" {
127*333d2b36SAndroid Build Coastguard Worker		usage()
128*333d2b36SAndroid Build Coastguard Worker		return errors.New("Param 'db' must be nonempty")
129*333d2b36SAndroid Build Coastguard Worker	}
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Worker	matches := []string{}
132*333d2b36SAndroid Build Coastguard Worker	for i := 0; i < numIterations; i++ {
133*333d2b36SAndroid Build Coastguard Worker		matches, err = runFind(params, logger)
134*333d2b36SAndroid Build Coastguard Worker		if err != nil {
135*333d2b36SAndroid Build Coastguard Worker			return err
136*333d2b36SAndroid Build Coastguard Worker		}
137*333d2b36SAndroid Build Coastguard Worker	}
138*333d2b36SAndroid Build Coastguard Worker	findDuration := time.Since(startTime)
139*333d2b36SAndroid Build Coastguard Worker	logger.Printf("Found these %v inodes in %v :\n", len(matches), findDuration)
140*333d2b36SAndroid Build Coastguard Worker	sort.Strings(matches)
141*333d2b36SAndroid Build Coastguard Worker	for _, match := range matches {
142*333d2b36SAndroid Build Coastguard Worker		fmt.Println(match)
143*333d2b36SAndroid Build Coastguard Worker	}
144*333d2b36SAndroid Build Coastguard Worker	logger.Printf("End of %v inodes\n", len(matches))
145*333d2b36SAndroid Build Coastguard Worker	logger.Printf("Finder completed in %v\n", time.Since(startTime))
146*333d2b36SAndroid Build Coastguard Worker	return nil
147*333d2b36SAndroid Build Coastguard Worker}
148*333d2b36SAndroid Build Coastguard Worker
149*333d2b36SAndroid Build Coastguard Workerfunc runFind(params finder.CacheParams, logger *log.Logger) (paths []string, err error) {
150*333d2b36SAndroid Build Coastguard Worker	service, err := finder.New(params, fs.OsFs, logger, dbPath)
151*333d2b36SAndroid Build Coastguard Worker	if err != nil {
152*333d2b36SAndroid Build Coastguard Worker		return []string{}, err
153*333d2b36SAndroid Build Coastguard Worker	}
154*333d2b36SAndroid Build Coastguard Worker	defer service.Shutdown()
155*333d2b36SAndroid Build Coastguard Worker	return service.FindAll(), nil
156*333d2b36SAndroid Build Coastguard Worker}
157