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 " |
|
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 dir |
|
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: |
|
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("dir |
|
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+1 |
|
190 | e = struct.unpack(">cllll", st[pos:pos+17]) | |
178 |
l = e[ |
|
191 | l = e[4] | |
179 |
pos += 1 |
|
192 | pos += 17 | |
180 | f = st[pos:pos + l] |
|
193 | f = st[pos:pos + l] | |
181 |
self.map[f] = e[: |
|
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 |
|
|
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 |
|
|
211 | try: | |
193 |
|
|
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 |
|
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(" |
|
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("dir |
|
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.dir |
|
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 dir |
|
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.dir |
|
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.dir |
|
405 | self.dirstate.clear() | |
393 |
self.dir |
|
406 | self.dirstate.update(mmap.keys(), "n") | |
394 |
|
407 | |||
395 |
def commit(self, parent, |
|
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 |
|
|
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 |
|
|
436 | commit.sort() | |
417 |
for f in |
|
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 |
|
|
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.dir |
|
468 | self.dirstate.update(new, "n") | |
448 |
self.dir |
|
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.dir |
|
489 | self.dirstate.clear() | |
469 |
self.dir |
|
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.dir |
|
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 |
|
523 | if not c: | |
502 | if fcmp(fn): |
|
524 | if fcmp(fn): | |
503 | changed.append(fn) |
|
525 | changed.append(fn) | |
504 |
|
|
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[ |
|
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 |
|
|
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