19 func (a BySrc) Len() int {
23 func (a BySrc) Swap(i, j int) {
24 a[i], a[j] = a[j], a[i]
27 func (a BySrc) Less(i, j int) bool {
28 return namesCmp(a[i].src, a[j].src) < 0
33 func (a EntByName) Len() int {
37 func (a EntByName) Swap(i, j int) {
38 a[i], a[j] = a[j], a[i]
41 func (a EntByName) Less(i, j int) bool {
42 return namesCmp(a[i].name, a[j].name) < 0
45 func updateWithDiff(dbPath, strip string) *os.File {
46 scanner := bufio.NewScanner(os.Stdin)
48 var delsNames []string
49 var addsNames []string
50 var modsNames []string
58 cols := strings.Split(t, "\t")
60 log.Fatalln("bad zfs-diff format")
62 isDir = cols[1] == "/"
63 name := deoctalize(strings.TrimPrefix(cols[2], strip))
64 name = strings.TrimRight(name, "/")
74 delsNames = append(delsNames, name)
76 addsNames = append(addsNames, name)
78 modsNames = append(modsNames, name)
81 log.Fatalln("bad zfs-diff format for R")
83 dst := "./" + deoctalize(strings.TrimPrefix(cols[3], strip))
86 rens = append(rens, Ren{
91 delsNames = append(delsNames, name)
92 addsNames = append(addsNames, dst)
95 log.Fatalln("bad zfs-diff format")
99 entsReader := make(chan Ent, 1<<10)
100 db, err := os.Open(dbPath)
104 dels := make([][]string, 0, len(delsNames)+len(rens))
105 adds := make([][]string, 0, len(addsNames)+len(rens))
106 mods := make([]*Ent, 0, len(modsNames)+len(rens))
108 sort.Sort(BySrc(rens))
109 go reader(db, entsReader)
113 ent, ok = <-entsReader
119 if hasPrefix(ent.name, rens[0].src) {
120 dels = append(dels, ent.name)
122 append([]string{}, rens[0].dst...),
123 ent.name[len(rens[0].src):]...,
125 adds = append(adds, dst)
126 mods = append(mods, &Ent{name: dst})
128 // strip "/" from prefix directory
130 last := dst[len(dst)-1]
131 dst[len(dst)-1] = last[:len(last)-1]
144 for _, name := range delsNames {
145 dels = append(dels, nameSplit(name))
148 sort.Sort(ByName(dels))
150 for _, name := range addsNames {
151 adds = append(adds, nameSplit(name))
152 modsNames = append(modsNames, name)
155 sort.Sort(ByName(adds))
157 for _, name := range modsNames {
158 mods = append(mods, &Ent{name: nameSplit(name)})
161 sort.Sort(EntByName(mods))
163 for _, ent := range mods {
164 info, err = os.Stat(nameJoin(ent.name))
166 log.Println("can not stat:", nameJoin(ent.name), ":", err)
169 if info.Mode().IsRegular() {
170 ent.size = info.Size()
172 ent.mtime = info.ModTime().Unix()
175 _, err = db.Seek(0, io.SeekStart)
179 tmp0, err := os.CreateTemp(TmpDir, "glocate-idx")
183 defer os.Remove(tmp0.Name())
184 entsReader = make(chan Ent, 1<<10)
185 entsDirSizer := make(chan Ent, 1<<10)
186 entsWriter := make(chan Ent, 1<<10)
187 go reader(db, entsReader)
189 dirSizerJob := make(chan struct{})
191 sinkBack := make(chan Ent, 1)
193 dirSizer(&dirSizes, 1, sinkBack, entsDirSizer, entsWriter)
197 writerJob := make(chan struct{})
199 writer(tmp0, entsWriter)
203 for ent := range entsReader {
204 if len(dels) > 0 && namesCmp(ent.name, dels[0]) == 0 {
208 for len(adds) > 0 && namesCmp(adds[0], ent.name) < 0 {
209 if namesCmp(mods[0].name, adds[0]) != 0 {
210 panic("+ and M lists are out of sync")
214 mtime: mods[0].mtime,
217 entsDirSizer <- newEnt
221 if len(mods) > 0 && namesCmp(ent.name, mods[0].name) == 0 {
222 ent.mtime = mods[0].mtime
223 ent.size = mods[0].size
232 if namesCmp(mods[0].name, adds[0]) != 0 {
233 panic("+ and M lists are out of sync")
237 mtime: mods[0].mtime,
240 entsDirSizer <- newEnt
250 tmp1 := applyDirSizes(tmp0, dirSizes)
252 os.Remove(tmp0.Name())