2017-08-10 09:25:28 +08:00
|
|
|
// 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"
|
2017-12-22 07:46:01 +08:00
|
|
|
"android/soong/finder/fs"
|
2017-08-10 09:25:28 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
2017-08-15 07:49:18 +08:00
|
|
|
|
2017-08-10 09:25:28 +08:00
|
|
|
matches := []string{}
|
|
|
|
for i := 0; i < numIterations; i++ {
|
2017-08-15 07:49:18 +08:00
|
|
|
matches, err = runFind(params, logger)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-08-10 09:25:28 +08:00
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2017-08-15 07:49:18 +08:00
|
|
|
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
|
|
|
|
}
|
2017-08-10 09:25:28 +08:00
|
|
|
defer service.Shutdown()
|
2017-08-15 07:49:18 +08:00
|
|
|
return service.FindAll(), nil
|
2017-08-10 09:25:28 +08:00
|
|
|
}
|