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