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))
73 delsNames = append(delsNames, name)
75 addsNames = append(addsNames, name)
77 modsNames = append(modsNames, name)
80 log.Fatalln("bad zfs-diff format for R")
82 dst := "./" + deoctalize(strings.TrimPrefix(cols[3], strip))
85 rens = append(rens, Ren{
90 delsNames = append(delsNames, name)
91 addsNames = append(addsNames, dst)
94 log.Fatalln("bad zfs-diff format")
98 entsReader := make(chan Ent, 1<<10)
99 db, err := os.Open(dbPath)
103 dels := make([][]string, 0, len(delsNames)+len(rens))
104 adds := make([][]string, 0, len(addsNames)+len(rens))
105 mods := make([]*Ent, 0, len(modsNames)+len(rens))
107 sort.Sort(BySrc(rens))
108 go reader(db, entsReader)
112 ent, ok = <-entsReader
118 if hasPrefix(ent.name, rens[0].src) {
119 dels = append(dels, ent.name)
121 append([]string{}, rens[0].dst...),
122 ent.name[len(rens[0].src):]...,
124 adds = append(adds, dst)
125 mods = append(mods, &Ent{name: dst})
127 // strip "/" from prefix directory
129 last := dst[len(dst)-1]
130 dst[len(dst)-1] = last[:len(last)-1]
143 for _, name := range delsNames {
144 dels = append(dels, nameSplit(name))
147 sort.Sort(ByName(dels))
149 for _, name := range addsNames {
150 adds = append(adds, nameSplit(name))
151 modsNames = append(modsNames, name)
154 sort.Sort(ByName(adds))
156 for _, name := range modsNames {
157 mods = append(mods, &Ent{name: nameSplit(name)})
160 sort.Sort(EntByName(mods))
162 for _, ent := range mods {
163 info, err = os.Stat(nameJoin(ent.name))
165 log.Println("can not stat:", nameJoin(ent.name), ":", err)
168 if info.Mode().IsRegular() {
169 ent.size = info.Size()
171 ent.mtime = info.ModTime().Unix()
174 _, err = db.Seek(0, io.SeekStart)
178 tmp0, err := os.CreateTemp("", "glocate-idx")
182 defer os.Remove(tmp0.Name())
183 entsReader = make(chan Ent, 1<<10)
184 entsDirSizer := make(chan Ent, 1<<10)
185 entsWriter := make(chan Ent, 1<<10)
186 go reader(db, entsReader)
188 dirSizerJob := make(chan struct{})
190 sinkBack := make(chan Ent, 1)
192 dirSizer(&dirSizes, 1, sinkBack, entsDirSizer, entsWriter)
196 writerJob := make(chan struct{})
198 writer(tmp0, entsWriter)
202 for ent := range entsReader {
203 if len(dels) > 0 && namesCmp(ent.name, dels[0]) == 0 {
207 for len(adds) > 0 && namesCmp(adds[0], ent.name) < 0 {
208 if namesCmp(mods[0].name, adds[0]) != 0 {
209 panic("+ and M lists are out of sync")
213 mtime: mods[0].mtime,
216 entsDirSizer <- newEnt
220 if len(mods) > 0 && namesCmp(ent.name, mods[0].name) == 0 {
221 ent.mtime = mods[0].mtime
222 ent.size = mods[0].size
228 if namesCmp(mods[0].name, adds[0]) != 0 {
229 panic("+ and M lists are out of sync")
233 mtime: mods[0].mtime,
236 entsDirSizer <- newEnt
246 tmp1 := applyDirSizes(tmp0, dirSizes)
248 os.Remove(tmp0.Name())