2 import os, sys, stat, time
3 import options, git, index, drecurse
7 def _simplify_iter(iters):
8 total = sum([len(it) for it in iters])
9 l = list([iter(it) for it in iters])
11 l = list([(next(it),it) for it in l])
12 l = filter(lambda x: x[0], l)
15 if not (count % 1024):
16 progress('bup: merging indexes (%d/%d)\r' % (count, total))
21 #log('merge: %r %r (%d)\n' % (e.ctime, e.name, len(l)))
22 if e.ctime: # skip auto-generated entries
28 log('bup: merging indexes (%d/%d), done.\n' % (count, total))
31 def merge_indexes(out, r1, r2):
32 for e in _simplify_iter([r1, r2]):
33 #if e.flags & index.IX_EXISTS:
38 def __init__(self, l):
45 self.cur = self.i.next()
51 def check_index(reader):
53 log('check: checking forward iteration...\n')
56 for e in reader.forward_iter():
58 log('%08x+%-4d %r\n' % (e.children_ofs, e.children_n, e.name))
59 assert(e.children_ofs)
60 assert(e.name.endswith('/'))
61 assert(not d.get(e.children_ofs))
63 assert(not e or e.name == '/') # last entry is *always* /
64 log('check: checking normal iteration...\n')
71 log('index error! at %r\n' % e)
73 log('check: passed.\n')
76 def update_index(top):
77 ri = index.Reader(indexfile)
78 wi = index.Writer(indexfile)
79 rig = IterHelper(ri.iter(name=top))
80 tstart = int(time.time())
85 return (0, index.FAKE_SHA)
87 #log('doing: %r\n' % paths)
90 for (path,pst) in drecurse.recursive_dirlist([top], xdev=opt.xdev):
91 #log('got: %r\n' % path)
92 if opt.verbose>=2 or (opt.verbose==1 and stat.S_ISDIR(pst.st_mode)):
93 sys.stdout.write('%s\n' % path)
95 progress('Indexing: %d\r' % total)
96 elif not (total % 128):
97 progress('Indexing: %d\r' % total)
99 while rig.cur and rig.cur.name > path: # deleted paths
100 rig.cur.set_deleted()
103 if rig.cur and rig.cur.name == path: # paths that already existed
105 rig.cur.from_stat(pst, tstart)
106 if not (rig.cur.flags & index.IX_HASHVALID):
108 (rig.cur.gitmode, rig.cur.sha) = hashgen(path)
109 rig.cur.flags |= index.IX_HASHVALID
113 #log('adding: %r\n' % path)
114 wi.add(path, pst, hashgen = hashgen)
115 progress('Indexing: %d, done.\n' % total)
123 log('check: before merging: oldfile\n')
125 log('check: before merging: newfile\n')
127 mi = index.Writer(indexfile)
128 merge_indexes(mi, ri, wr)
137 bup index <-p|m|u> [options...] <filenames...>
139 p,print print the index entries for the given names (also works with -u)
140 m,modified print only added/deleted/modified files (implies -p)
141 s,status print each filename with a status char (A/M/D) (implies -p)
142 H,hash print the hash for each object next to its name (implies -p)
143 l,long print more information about each file
144 u,update (recursively) update the index entries for the given filenames
145 x,xdev,one-file-system don't cross filesystem boundaries
146 fake-valid mark all index entries as up-to-date even if they aren't
147 check carefully check index file integrity
148 f,indexfile= the name of the index file (default 'index')
149 v,verbose increase log output (can be used more than once)
151 o = options.Options('bup index', optspec)
152 (opt, flags, extra) = o.parse(sys.argv[1:])
154 if not (opt.modified or opt['print'] or opt.status or opt.update or opt.check):
155 log('bup index: supply one or more of -p, -s, -m, -u, or --check\n')
157 if opt.fake_valid and not opt.update:
158 log('bup index: --fake-valid is meaningless without -u\n')
161 git.check_repo_or_die()
162 indexfile = opt.indexfile or git.repo('bupindex')
165 log('check: starting initial check.\n')
166 check_index(index.Reader(indexfile))
168 paths = index.reduce_paths(extra)
172 log('bup index: update (-u) requested but no paths given\n')
174 for (rp,path) in paths:
177 if opt['print'] or opt.status or opt.modified:
178 for (name, ent) in index.Reader(indexfile).filter(extra or ['']):
180 and (ent.flags & index.IX_HASHVALID
182 or stat.S_ISDIR(ent.mode))):
186 if not ent.flags & index.IX_EXISTS:
188 elif not ent.flags & index.IX_HASHVALID:
189 if ent.sha == index.EMPTY_SHA:
196 line += "%7s " % oct(ent.mode)
198 line += ent.sha.encode('hex') + ' '
199 print line + (name or './')
203 log('check: starting final check.\n')
204 check_index(index.Reader(indexfile))
207 log('WARNING: %d errors encountered.\n' % len(saved_errors))