##// END OF EJS Templates
change dircache into dirstate...
mpm@selenic.com -
r220:3113a94c default
parent child Browse files
Show More
@@ -67,7 +67,7 b' def diff(files = None, node1 = None, nod'
67 date2 = time.asctime()
67 date2 = time.asctime()
68 if not node1:
68 if not node1:
69 node1 = repo.current
69 node1 = repo.current
70 (c, a, d) = repo.diffdir(repo.root, node1)
70 (c, a, d, u) = repo.diffdir(repo.root, node1)
71 a = [] # ignore unknown files in repo, by popular request
71 a = [] # ignore unknown files in repo, by popular request
72 def read(f): return file(os.path.join(repo.root, f)).read()
72 def read(f): return file(os.path.join(repo.root, f)).read()
73
73
@@ -79,9 +79,7 b' def diff(files = None, node1 = None, nod'
79 c, a, d = map(lambda x: filterfiles(x, files), (c, a, d))
79 c, a, d = map(lambda x: filterfiles(x, files), (c, a, d))
80
80
81 for f in c:
81 for f in c:
82 to = ""
82 to = repo.file(f).read(mmap[f])
83 if mmap.has_key(f):
84 to = repo.file(f).read(mmap[f])
85 tn = read(f)
83 tn = read(f)
86 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
84 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
87 for f in a:
85 for f in a:
@@ -132,6 +130,9 b' if os.getcwd() != repo.root:'
132 elif cmd == "add":
130 elif cmd == "add":
133 repo.add(args)
131 repo.add(args)
134
132
133 elif cmd == "forget":
134 repo.forget(args)
135
135 elif cmd == "remove" or cmd == "rm" or cmd == "del" or cmd == "delete":
136 elif cmd == "remove" or cmd == "rm" or cmd == "del" or cmd == "delete":
136 repo.remove(args)
137 repo.remove(args)
137
138
@@ -250,7 +251,7 b' elif cmd == "debugaddchangegroup":'
250 repo.addchangegroup(data)
251 repo.addchangegroup(data)
251
252
252 elif cmd == "addremove":
253 elif cmd == "addremove":
253 (c, a, d) = repo.diffdir(repo.root, repo.current)
254 (c, a, d, u) = repo.diffdir(repo.root, repo.current)
254 repo.add(a)
255 repo.add(a)
255 repo.remove(d)
256 repo.remove(d)
256
257
@@ -355,8 +356,8 b' elif cmd == "debugindexdot":'
355 print "}"
356 print "}"
356
357
357 elif cmd == "merge":
358 elif cmd == "merge":
358 (c, a, d) = repo.diffdir(repo.root, repo.current)
359 (c, a, d, u) = repo.diffdir(repo.root, repo.current)
359 if c:
360 if c or a or d:
360 ui.warn("aborting (outstanding changes in working directory)\n")
361 ui.warn("aborting (outstanding changes in working directory)\n")
361 sys.exit(1)
362 sys.exit(1)
362
363
@@ -70,8 +70,8 b' def branch(ui, path):'
70
70
71 def checkout(ui, repo, changeset=None):
71 def checkout(ui, repo, changeset=None):
72 '''checkout a given changeset or the current tip'''
72 '''checkout a given changeset or the current tip'''
73 (c, a, d) = repo.diffdir(repo.root, repo.current)
73 (c, a, d, u) = repo.diffdir(repo.root, repo.current)
74 if c:
74 if c or a or d:
75 ui.warn("aborting (outstanding changes in working directory)\n")
75 ui.warn("aborting (outstanding changes in working directory)\n")
76 sys.exit(1)
76 sys.exit(1)
77
77
@@ -129,12 +129,13 b' C = changed'
129 A = added
129 A = added
130 R = removed
130 R = removed
131 ? = not tracked'''
131 ? = not tracked'''
132 (c, a, d) = repo.diffdir(repo.root, repo.current)
132 (c, a, d, u) = repo.diffdir(repo.root, repo.current)
133 (c, a, d) = map(lambda x: relfilter(repo, x), (c, a, d))
133 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
134
134
135 for f in c: print "C", f
135 for f in c: print "C", f
136 for f in a: print "?", f
136 for f in a: print "A", f
137 for f in d: print "R", f
137 for f in d: print "R", f
138 for f in u: print "?", f
138
139
139 def undo(ui, repo):
140 def undo(ui, repo):
140 repo.undo()
141 repo.undo()
@@ -149,57 +149,73 b' class changelog(revlog):'
149 text = "\n".join(l)
149 text = "\n".join(l)
150 return self.addrevision(text, transaction, self.count(), p1, p2)
150 return self.addrevision(text, transaction, self.count(), p1, p2)
151
151
152 class dircache:
152 class dirstate:
153 def __init__(self, opener, ui):
153 def __init__(self, opener, ui):
154 self.opener = opener
154 self.opener = opener
155 self.dirty = 0
155 self.dirty = 0
156 self.ui = ui
156 self.ui = ui
157 self.map = None
157 self.map = None
158
158 def __del__(self):
159 def __del__(self):
159 if self.dirty: self.write()
160 if self.dirty:
161 self.write()
162
160 def __getitem__(self, key):
163 def __getitem__(self, key):
161 try:
164 try:
162 return self.map[key]
165 return self.map[key]
163 except TypeError:
166 except TypeError:
164 self.read()
167 self.read()
165 return self[key]
168 return self[key]
166
169
170 def __contains__(self, key):
171 if not self.map: self.read()
172 return key in self.map
173
174 def state(self, key):
175 try:
176 return self[key][0]
177 except KeyError:
178 return "?"
179
167 def read(self):
180 def read(self):
168 if self.map is not None: return self.map
181 if self.map is not None: return self.map
169
182
170 self.map = {}
183 self.map = {}
171 try:
184 try:
172 st = self.opener("dircache").read()
185 st = self.opener("dirstate").read()
173 except: return
186 except: return
174
187
175 pos = 0
188 pos = 0
176 while pos < len(st):
189 while pos < len(st):
177 e = struct.unpack(">llll", st[pos:pos+16])
190 e = struct.unpack(">cllll", st[pos:pos+17])
178 l = e[3]
191 l = e[4]
179 pos += 16
192 pos += 17
180 f = st[pos:pos + l]
193 f = st[pos:pos + l]
181 self.map[f] = e[:3]
194 self.map[f] = e[:4]
182 pos += l
195 pos += l
183
196
184 def update(self, files):
197 def update(self, files, state):
198 ''' current states:
199 n normal
200 i invalid
201 r marked for removal
202 a marked for addition'''
203
185 if not files: return
204 if not files: return
186 self.read()
205 self.read()
187 self.dirty = 1
206 self.dirty = 1
188 for f in files:
207 for f in files:
189 try:
208 if state == "r":
190 s = os.stat(f)
209 self.map[f] = ('r', 0, 0, 0)
191 self.map[f] = (s.st_mode, s.st_size, s.st_mtime)
210 else:
192 except IOError:
211 try:
193 self.remove(f)
212 s = os.stat(f)
213 self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime)
214 except OSError:
215 if state != "i": raise
216 self.map[f] = ('r', 0, 0, 0)
194
217
195 def taint(self, files):
218 def forget(self, files):
196 if not files: return
197 self.read()
198 self.dirty = 1
199 for f in files:
200 self.map[f] = (0, -1, 0)
201
202 def remove(self, files):
203 if not files: return
219 if not files: return
204 self.read()
220 self.read()
205 self.dirty = 1
221 self.dirty = 1
@@ -207,7 +223,7 b' class dircache:'
207 try:
223 try:
208 del self.map[f]
224 del self.map[f]
209 except KeyError:
225 except KeyError:
210 self.ui.warn("Not in dircache: %s\n" % f)
226 self.ui.warn("not in dirstate: %s!\n" % f)
211 pass
227 pass
212
228
213 def clear(self):
229 def clear(self):
@@ -215,9 +231,9 b' class dircache:'
215 self.dirty = 1
231 self.dirty = 1
216
232
217 def write(self):
233 def write(self):
218 st = self.opener("dircache", "w")
234 st = self.opener("dirstate", "w")
219 for f, e in self.map.items():
235 for f, e in self.map.items():
220 e = struct.pack(">llll", e[0], e[1], e[2], len(f))
236 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
221 st.write(e + f)
237 st.write(e + f)
222 self.dirty = 0
238 self.dirty = 0
223
239
@@ -280,7 +296,7 b' class localrepository:'
280 self.tags = None
296 self.tags = None
281
297
282 if not self.remote:
298 if not self.remote:
283 self.dircache = dircache(self.opener, ui)
299 self.dirstate = dirstate(self.opener, ui)
284 try:
300 try:
285 self.current = bin(self.opener("current").read())
301 self.current = bin(self.opener("current").read())
286 except IOError:
302 except IOError:
@@ -340,21 +356,18 b' class localrepository:'
340 def undo(self):
356 def undo(self):
341 self.lock()
357 self.lock()
342 if os.path.exists(self.join("undo")):
358 if os.path.exists(self.join("undo")):
359 f = self.changelog.read(self.changelog.tip())[3]
343 self.ui.status("attempting to rollback last transaction\n")
360 self.ui.status("attempting to rollback last transaction\n")
344 rollback(self.opener, self.join("undo"))
361 rollback(self.opener, self.join("undo"))
345 self.manifest = manifest(self.opener)
362 self.manifest = manifest(self.opener)
346 self.changelog = changelog(self.opener)
363 self.changelog = changelog(self.opener)
347
364
348 self.ui.status("discarding dircache\n")
365 self.ui.status("discarding dirstate\n")
349 node = self.changelog.tip()
366 node = self.changelog.tip()
350 mf = self.changelog.read(node)[0]
351 mm = self.manifest.read(mf)
352 f = mm.keys()
353 f.sort()
367 f.sort()
354
368
355 self.setcurrent(node)
369 self.setcurrent(node)
356 self.dircache.clear()
370 self.dirstate.update(f, 'i')
357 self.dircache.taint(f)
358
371
359 else:
372 else:
360 self.ui.warn("no undo information available\n")
373 self.ui.warn("no undo information available\n")
@@ -389,22 +402,29 b' class localrepository:'
389 n = self.changelog.add(mnode, files, text, tr, p1, p2, user ,date, )
402 n = self.changelog.add(mnode, files, text, tr, p1, p2, user ,date, )
390 tr.close()
403 tr.close()
391 self.setcurrent(n)
404 self.setcurrent(n)
392 self.dircache.clear()
405 self.dirstate.clear()
393 self.dircache.update(mmap)
406 self.dirstate.update(mmap.keys(), "n")
394
407
395 def commit(self, parent, update = None, text = ""):
408 def commit(self, parent, files = None, text = ""):
396 self.lock()
409 self.lock()
397 try:
398 remove = [ l[:-1] for l in self.opener("to-remove") ]
399 os.unlink(self.join("to-remove"))
400
410
401 except IOError:
411 commit = []
402 remove = []
412 remove = []
413 if files:
414 for f in files:
415 s = self.dirstate.state(f)
416 if s in 'cai':
417 commit.append(f)
418 elif s == 'r':
419 remove.append(f)
420 else:
421 self.warn("%s not tracked!\n")
422 else:
423 (c, a, d, u) = self.diffdir(self.root, parent)
424 commit = c + a
425 remove = d
403
426
404 if update == None:
427 if not commit and not remove:
405 update = self.diffdir(self.root, parent)[0]
406
407 if not update:
408 self.ui.status("nothing changed\n")
428 self.ui.status("nothing changed\n")
409 return
429 return
410
430
@@ -413,14 +433,15 b' class localrepository:'
413 # check in files
433 # check in files
414 new = {}
434 new = {}
415 linkrev = self.changelog.count()
435 linkrev = self.changelog.count()
416 update.sort()
436 commit.sort()
417 for f in update:
437 for f in commit:
418 self.ui.note(f + "\n")
438 self.ui.note(f + "\n")
419 try:
439 try:
420 t = file(f).read()
440 t = file(f).read()
421 except IOError:
441 except IOError:
422 remove.append(f)
442 self.warn("trouble committing %s!\n" % f)
423 continue
443 raise
444
424 r = self.file(f)
445 r = self.file(f)
425 new[f] = r.add(t, tr, linkrev)
446 new[f] = r.add(t, tr, linkrev)
426
447
@@ -444,8 +465,8 b' class localrepository:'
444 tr.close()
465 tr.close()
445
466
446 self.setcurrent(n)
467 self.setcurrent(n)
447 self.dircache.update(new)
468 self.dirstate.update(new, "n")
448 self.dircache.remove(remove)
469 self.dirstate.forget(remove)
449
470
450 def checkout(self, node):
471 def checkout(self, node):
451 # checkout is really dumb at the moment
472 # checkout is really dumb at the moment
@@ -465,20 +486,21 b' class localrepository:'
465 file(f, "w").write(t)
486 file(f, "w").write(t)
466
487
467 self.setcurrent(node)
488 self.setcurrent(node)
468 self.dircache.clear()
489 self.dirstate.clear()
469 self.dircache.update([f for f,n in l])
490 self.dirstate.update([f for f,n in l], "n")
470
491
471 def diffdir(self, path, changeset):
492 def diffdir(self, path, changeset):
472 changed = []
493 changed = []
494 added = []
495 unknown = []
473 mf = {}
496 mf = {}
474 added = []
475
497
476 if changeset:
498 if changeset:
477 change = self.changelog.read(changeset)
499 change = self.changelog.read(changeset)
478 mf = self.manifest.read(change[0])
500 mf = self.manifest.read(change[0])
479
501
480 if changeset == self.current:
502 if changeset == self.current:
481 dc = self.dircache.copy()
503 dc = self.dirstate.copy()
482 else:
504 else:
483 dc = dict.fromkeys(mf)
505 dc = dict.fromkeys(mf)
484
506
@@ -498,22 +520,31 b' class localrepository:'
498 if fn in dc:
520 if fn in dc:
499 c = dc[fn]
521 c = dc[fn]
500 del dc[fn]
522 del dc[fn]
501 if not c or c[1] < 0:
523 if not c:
502 if fcmp(fn):
524 if fcmp(fn):
503 changed.append(fn)
525 changed.append(fn)
504 elif c[1] != s.st_size:
526 if c[0] == 'i':
527 if fn not in mf:
528 added.append(fn)
529 elif fcmp(fn):
530 changed.append(fn)
531 elif c[0] == 'a':
532 added.append(fn)
533 elif c[0] == 'r':
534 unknown.append(fn)
535 elif c[2] != s.st_size:
505 changed.append(fn)
536 changed.append(fn)
506 elif c[0] != s.st_mode or c[2] != s.st_mtime:
537 elif c[1] != s.st_mode or c[3] != s.st_mtime:
507 if fcmp(fn):
538 if fcmp(fn):
508 changed.append(fn)
539 changed.append(fn)
509 else:
540 else:
510 if self.ignore(fn): continue
541 if self.ignore(fn): continue
511 added.append(fn)
542 unknown.append(fn)
512
543
513 deleted = dc.keys()
544 deleted = dc.keys()
514 deleted.sort()
545 deleted.sort()
515
546
516 return (changed, added, deleted)
547 return (changed, added, deleted, unknown)
517
548
518 def diffrevs(self, node1, node2):
549 def diffrevs(self, node1, node2):
519 changed, added = [], []
550 changed, added = [], []
@@ -537,12 +568,31 b' class localrepository:'
537 return (changed, added, deleted)
568 return (changed, added, deleted)
538
569
539 def add(self, list):
570 def add(self, list):
540 self.dircache.taint(list)
571 for f in list:
572 p = os.path.join(self.root, f)
573 if not os.path.isfile(p):
574 self.ui.warn("%s does not exist!\n" % f)
575 elif self.dirstate.state(f) == 'n':
576 self.ui.warn("%s already tracked!\n" % f)
577 else:
578 self.dirstate.update([f], "a")
579
580 def forget(self, list):
581 for f in list:
582 if self.dirstate.state(f) not in 'ai':
583 self.ui.warn("%s not added!\n" % f)
584 else:
585 self.dirstate.forget([f])
541
586
542 def remove(self, list):
587 def remove(self, list):
543 dl = self.opener("to-remove", "a")
544 for f in list:
588 for f in list:
545 dl.write(f + "\n")
589 p = os.path.join(self.root, f)
590 if os.path.isfile(p):
591 self.ui.warn("%s still exists!\n" % f)
592 elif f not in self.dirstate:
593 self.ui.warn("%s not tracked!\n" % f)
594 else:
595 self.dirstate.update([f], "r")
546
596
547 def branches(self, nodes):
597 def branches(self, nodes):
548 if not nodes: nodes = [self.changelog.tip()]
598 if not nodes: nodes = [self.changelog.tip()]
General Comments 0
You need to be logged in to leave comments. Login now