github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/finder/cmd/finder.go (about)

     1  // 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  
    15  package main
    16  
    17  import (
    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"
    31  	"android/soong/finder/fs"
    32  )
    33  
    34  var (
    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  
    47  func 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  
    65  var usage = func() {
    66  	fmt.Printf("usage: finder -name <fileName> --db <dbPath> <searchDirectory> [<searchDirectory>...]\n")
    67  	flag.PrintDefaults()
    68  }
    69  
    70  func main() {
    71  	err := run()
    72  	if err != nil {
    73  		fmt.Fprintf(os.Stderr, "%v\n", err.Error())
    74  		os.Exit(1)
    75  	}
    76  }
    77  
    78  func stringToList(input string) []string {
    79  	return strings.Split(input, ",")
    80  }
    81  
    82  func 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  	}
   130  
   131  	matches := []string{}
   132  	for i := 0; i < numIterations; i++ {
   133  		matches, err = runFind(params, logger)
   134  		if err != nil {
   135  			return err
   136  		}
   137  	}
   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  
   149  func 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  	}
   154  	defer service.Shutdown()
   155  	return service.FindAll(), nil
   156  }