]> Sergey Matveev's repositories - glocate.git/blob - main.go
affdffc8d95d0c7179d7cc9359c524cb8f963669053a888a9da1f6d8b3e237e5
[glocate.git] / main.go
1 package main
2
3 import (
4         "flag"
5         "log"
6         "os"
7         "path"
8         "strings"
9         "syscall"
10 )
11
12 type Ent struct {
13         name  []string
14         mtime int64
15         size  int64
16 }
17
18 func (ent *Ent) IsDir() bool {
19         return IsDir(ent.name[len(ent.name)-1])
20 }
21
22 func dbCommit(dbPath string, tmp *os.File) {
23         umask := syscall.Umask(0)
24         syscall.Umask(umask)
25         if err := os.Chmod(tmp.Name(), os.FileMode(0666&^umask)); err != nil {
26                 log.Fatalln(err)
27         }
28         if err := os.Rename(tmp.Name(), dbPath); err != nil {
29                 log.Fatalln(err)
30         }
31 }
32
33 func main() {
34         dbPath := flag.String("db", "glocate.db", "Path to database")
35         doIndex := flag.Bool("index", false, "Perform indexing")
36         doUpdate := flag.String("update", "", "Update database")
37         showMachine := flag.Bool("machine", false, "Show machine friendly")
38         showTree := flag.Bool("tree", false, "Show human-friendly tree")
39         dryRun := flag.Bool("n", false, "Dry run, do not overwrite database")
40         rootPath := flag.String("root", "", "Search only that part of tree")
41         flag.Parse()
42         log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
43
44         if *doIndex {
45                 tmp := index()
46                 tmp.Close()
47                 if !*dryRun {
48                         dbCommit(*dbPath, tmp)
49                 }
50                 return
51         }
52
53         if *doUpdate != "" {
54                 tmp := updateWithDiff(*dbPath, *doUpdate)
55                 tmp.Close()
56                 if !*dryRun {
57                         dbCommit(*dbPath, tmp)
58                 }
59                 return
60         }
61
62         db, err := os.Open(*dbPath)
63         if err != nil {
64                 log.Fatalln(err)
65         }
66         entsReader := make(chan Ent, 1<<10)
67         go reader(db, entsReader)
68
69         entsPrinter := make(chan Ent, 1<<10)
70         printerJob := make(chan struct{})
71         go func() {
72                 if *showMachine {
73                         printerMachine(entsPrinter)
74                 } else if *showTree {
75                         printerTree(entsPrinter)
76                 } else {
77                         printerSimple(entsPrinter)
78                 }
79                 close(printerJob)
80         }()
81
82         var root []string
83         if *rootPath != "" {
84                 root = strings.Split("./"+*rootPath, "/")
85         }
86
87         var pat string
88         if len(flag.Args()) > 0 {
89                 pat = "*" + flag.Arg(0) + "*"
90         }
91
92         rootMet := false
93         var matched bool
94         var namePrev []string
95         var i int
96         for ent := range entsReader {
97                 if hasPrefix(ent.name, root) {
98                         rootMet = true
99                         if pat == "" {
100                                 entsPrinter <- ent
101                                 continue
102                         }
103                         for i = 0; i < len(ent.name); i++ {
104                                 if i == len(namePrev) || ent.name[i] != namePrev[i] {
105                                         break
106                                 }
107                         }
108                         for ; i < len(ent.name); i++ {
109                                 matched, err = path.Match(pat,
110                                         strings.ToLower(strings.TrimSuffix(ent.name[i], "/")))
111                                 if err != nil {
112                                         log.Fatalln(err)
113                                 }
114                         }
115                         if matched {
116                                 entsPrinter <- ent
117                         }
118                         namePrev = ent.name
119                 } else if rootMet {
120                         break
121                 }
122         }
123         close(entsPrinter)
124         <-printerJob
125 }