func main() { flag.Usage = usage flag.Parse() args := flag.Args() if *indexPath != "" { if err := os.Setenv("CSEARCHINDEX", *indexPath); err != nil { log.Fatal(err) } } if *listFlag { master := index.File() if stat, err := os.Stat(master); err != nil || stat == nil { log.Fatal("Index " + master + " is not accessible") } else if stat.IsDir() || !stat.Mode().IsRegular() { log.Fatal("Index " + master + " must point to an index file") } ix := index.Open(master) for _, arg := range ix.Paths() { fmt.Printf("%s\n", arg) } return } if *cpuProfile != "" { f, err := os.Create(*cpuProfile) if err != nil { log.Fatal(err) } defer f.Close() pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if *resetFlag && len(args) == 0 { master := index.File() stat, err := os.Stat(master) if err != nil { // does not exist so nothing to do return } if stat != nil && !stat.IsDir() && stat.Mode().IsRegular() { os.Remove(master) return } else { log.Fatal("Invalid index path " + master) } } if len(args) == 0 { ix := index.Open(index.File()) for _, arg := range ix.Paths() { args = append(args, arg) } ix.Close() } // Translate paths to absolute paths so that we can // generate the file list in sorted order. for i, arg := range args { a, err := filepath.Abs(arg) if err != nil { log.Printf("%s: %s", arg, err) args[i] = "" continue } args[i] = a } sort.Strings(args) for len(args) > 0 && args[0] == "" { args = args[1:] } master := index.File() if stat, err := os.Stat(master); err != nil { // Does not exist. *resetFlag = true } else { if stat != nil && (stat.IsDir() || !stat.Mode().IsRegular()) { log.Fatal("Invalid index path " + master) } } file := master if !*resetFlag { file += "~" } ix := index.Create(file) ix.Verbose = *verboseFlag ix.LogSkip = *logSkipFlag ix.MaxFileLen = *maxFileLen ix.MaxLineLen = *maxLineLen ix.MaxTextTrigrams = *maxTextTrigrams ix.MaxInvalidUTF8Ratio = *maxInvalidUTF8Ratio ix.AddPaths(args) walkChan := make(chan string) doneChan := make(chan bool) go func() { seen := make(map[string]bool) for { select { case path := <-walkChan: if !seen[path] { seen[path] = true ix.AddFile(path) } case <-doneChan: return } } }() for _, arg := range args { log.Printf("index %s", arg) walk(arg, "", walkChan, *logSkipFlag) } doneChan <- true log.Printf("flush index") ix.Flush() if !*resetFlag { log.Printf("merge %s %s", master, file) index.Merge(file+"~", master, file) os.Remove(file) os.Rename(file+"~", master) } log.Printf("done") return }
func Main() { g := regexp.Grep{ Stdout: os.Stdout, Stderr: os.Stderr, } g.AddFlags() flag.Usage = usage flag.Parse() args := flag.Args() if len(args) != 1 { usage() } if *cpuProfile != "" { f, err := os.Create(*cpuProfile) if err != nil { log.Fatal(err) } defer f.Close() pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if *indexPath != "" { err := os.Setenv("CSEARCHINDEX", *indexPath) if err != nil { log.Fatal(err) } } pat := "(?m)" + args[0] if *iFlag { pat = "(?i)" + pat } re, err := regexp.Compile(pat) if err != nil { log.Fatal(err) } g.Regexp = re var fre *regexp.Regexp if *fFlag != "" { fre, err = regexp.Compile(*fFlag) if err != nil { log.Fatal(err) } } q := index.RegexpQuery(re.Syntax) if *verboseFlag { log.Printf("query: %s\n", q) } ix := index.Open(index.File()) ix.Verbose = *verboseFlag var post []uint32 if *bruteFlag { post = ix.PostingQuery(&index.Query{Op: index.QAll}) } else { post = ix.PostingQuery(q) } if *verboseFlag { log.Printf("post query identified %d possible files\n", len(post)) } if fre != nil { fnames := make([]uint32, 0, len(post)) for _, fileid := range post { name := ix.Name(fileid) if fre.MatchString(name, true, true) < 0 { continue } fnames = append(fnames, fileid) } if *verboseFlag { log.Printf("filename regexp matched %d files\n", len(fnames)) } post = fnames } g.Limit(*maxCount) for _, fileid := range post { name := ix.Name(fileid) g.File(name) // short circuit here too if g.Done { break } } matches = g.Match }