##// END OF EJS Templates
rewrite revert command. fix issues 93, 123, 147....
Vadim Gelfer -
r2029:d436b21b default
parent child Browse files
Show More
@@ -43,16 +43,17 b' def matchpats(repo, pats=[], opts={}, he'
43 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
43 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
44 opts.get('exclude'), head)
44 opts.get('exclude'), head)
45
45
46 def makewalk(repo, pats, opts, node=None, head=''):
46 def makewalk(repo, pats, opts, node=None, head='', badmatch=None):
47 files, matchfn, anypats = matchpats(repo, pats, opts, head)
47 files, matchfn, anypats = matchpats(repo, pats, opts, head)
48 exact = dict(zip(files, files))
48 exact = dict(zip(files, files))
49 def walk():
49 def walk():
50 for src, fn in repo.walk(node=node, files=files, match=matchfn):
50 for src, fn in repo.walk(node=node, files=files, match=matchfn,
51 badmatch=None):
51 yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
52 yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
52 return files, matchfn, walk()
53 return files, matchfn, walk()
53
54
54 def walk(repo, pats, opts, node=None, head=''):
55 def walk(repo, pats, opts, node=None, head='', badmatch=None):
55 files, matchfn, results = makewalk(repo, pats, opts, node, head)
56 files, matchfn, results = makewalk(repo, pats, opts, node, head, badmatch)
56 for r in results:
57 for r in results:
57 yield r
58 yield r
58
59
@@ -2003,7 +2004,7 b' def merge(ui, repo, node=None, **opts):'
2003 performed before any further updates are allowed.
2004 performed before any further updates are allowed.
2004 """
2005 """
2005 return update(ui, repo, node=node, merge=True, **opts)
2006 return update(ui, repo, node=node, merge=True, **opts)
2006
2007
2007 def outgoing(ui, repo, dest="default-push", **opts):
2008 def outgoing(ui, repo, dest="default-push", **opts):
2008 """show changesets not found in destination
2009 """show changesets not found in destination
2009
2010
@@ -2088,7 +2089,7 b' def postincoming(ui, repo, modheads, opt'
2088 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2089 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2089 else:
2090 else:
2090 ui.status(_("(run 'hg update' to get a working copy)\n"))
2091 ui.status(_("(run 'hg update' to get a working copy)\n"))
2091
2092
2092 def pull(ui, repo, source="default", **opts):
2093 def pull(ui, repo, source="default", **opts):
2093 """pull changes from the specified source
2094 """pull changes from the specified source
2094
2095
@@ -2286,6 +2287,10 b' def revert(ui, repo, *pats, **opts):'
2286 to the named files or directories. This restores the contents of
2287 to the named files or directories. This restores the contents of
2287 the affected files to an unmodified state.
2288 the affected files to an unmodified state.
2288
2289
2290 Modified files have backup copies saved before revert. To disable
2291 backups, use --no-backup. To change the name of backup files, use
2292 --backup to give a format string.
2293
2289 Using the -r option, it reverts the given files or directories to
2294 Using the -r option, it reverts the given files or directories to
2290 their state as of an earlier revision. This can be helpful to "roll
2295 their state as of an earlier revision. This can be helpful to "roll
2291 back" some or all of a change that should not have been committed.
2296 back" some or all of a change that should not have been committed.
@@ -2300,15 +2305,92 b' def revert(ui, repo, *pats, **opts):'
2300
2305
2301 If no arguments are given, all files in the repository are reverted.
2306 If no arguments are given, all files in the repository are reverted.
2302 """
2307 """
2303 node = opts['rev'] and repo.lookup(opts['rev']) or \
2308 parent = repo.dirstate.parents()[0]
2304 repo.dirstate.parents()[0]
2309 node = opts['rev'] and repo.lookup(opts['rev']) or parent
2305
2310 mf = repo.manifest.read(repo.changelog.read(node)[0])
2306 files, choose, anypats = matchpats(repo, pats, opts)
2311
2307 modified, added, removed, deleted, unknown = repo.changes(match=choose)
2312 def backup(name, exact):
2308 repo.forget(added)
2313 bakname = make_filename(repo, repo.changelog,
2309 repo.undelete(removed)
2314 opts['backup_name'] or '%p.orig',
2310
2315 node=parent, pathname=name)
2311 return repo.update(node, False, True, choose, False)
2316 if os.path.exists(name):
2317 # if backup already exists and is same as backup we want
2318 # to make, do nothing
2319 if os.path.exists(bakname):
2320 if repo.wread(name) == repo.wread(bakname):
2321 return
2322 raise util.Abort(_('cannot save current version of %s - '
2323 '%s exists and differs') %
2324 (name, bakname))
2325 ui.status(('saving current version of %s as %s\n') %
2326 (name, bakname))
2327 shutil.copyfile(name, bakname)
2328 shutil.copymode(name, bakname)
2329
2330 wlock = repo.wlock()
2331
2332 entries = []
2333 names = {}
2334 for src, abs, rel, exact in walk(repo, pats, opts, badmatch=mf.has_key):
2335 names[abs] = True
2336 entries.append((abs, rel, exact))
2337
2338 changes = repo.changes(match=names.has_key, wlock=wlock)
2339 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
2340
2341 revert = ([], _('reverting %s\n'))
2342 add = ([], _('adding %s\n'))
2343 remove = ([], _('removing %s\n'))
2344 forget = ([], _('forgetting %s\n'))
2345 undelete = ([], _('undeleting %s\n'))
2346 update = {}
2347
2348 disptable = (
2349 # dispatch table:
2350 # file state
2351 # action if in target manifest
2352 # action if not in target manifest
2353 # make backup if in target manifest
2354 # make backup if not in target manifest
2355 (modified, revert, remove, True, True),
2356 (added, revert, forget, True, True),
2357 (removed, undelete, None, False, False),
2358 (deleted, revert, remove, False, False),
2359 (unknown, add, None, True, False),
2360 )
2361
2362 for abs, rel, exact in entries:
2363 def handle(xlist, dobackup):
2364 xlist[0].append(abs)
2365 if dobackup and not opts['no_backup']:
2366 backup(rel, exact)
2367 if ui.verbose or not exact:
2368 ui.status(xlist[1] % rel)
2369 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2370 if abs not in table: continue
2371 # file has changed in dirstate
2372 if abs in mf:
2373 handle(hitlist, backuphit)
2374 elif misslist is not None:
2375 handle(misslist, backupmiss)
2376 else:
2377 if exact: ui.warn(_('file not managed: %s\n' % rel))
2378 break
2379 else:
2380 # file has not changed in dirstate
2381 if node == parent:
2382 if exact: ui.warn(_('no changes needed to %s\n' % rel))
2383 continue
2384 if abs not in mf:
2385 remove[0].append(abs)
2386 update[abs] = True
2387
2388 repo.dirstate.forget(forget[0])
2389 r = repo.update(node, False, True, update.has_key, False, wlock=wlock)
2390 repo.dirstate.update(add[0], 'a')
2391 repo.dirstate.update(undelete[0], 'n')
2392 repo.dirstate.update(remove[0], 'r')
2393 return r
2312
2394
2313 def root(ui, repo):
2395 def root(ui, repo):
2314 """print the root (top) of the current working dir
2396 """print the root (top) of the current working dir
@@ -2929,8 +3011,10 b' table = {'
2929 "^revert":
3011 "^revert":
2930 (revert,
3012 (revert,
2931 [('r', 'rev', '', _('revision to revert to')),
3013 [('r', 'rev', '', _('revision to revert to')),
2932 ('I', 'include', [], _('include names matching the given patterns')),
3014 ('', 'backup-name', '', _('save backup with formatted name')),
2933 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3015 ('', 'no-backup', None, _('do not save backup copies of files')),
3016 ('I', 'include', [], _('include names matching given patterns')),
3017 ('X', 'exclude', [], _('exclude names matching given patterns'))],
2934 _('hg revert [-r REV] [NAME]...')),
3018 _('hg revert [-r REV] [NAME]...')),
2935 "root": (root, [], _('hg root')),
3019 "root": (root, [], _('hg root')),
2936 "^serve":
3020 "^serve":
@@ -483,7 +483,7 b' class localrepository(object):'
483 self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
483 self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
484 return n
484 return n
485
485
486 def walk(self, node=None, files=[], match=util.always):
486 def walk(self, node=None, files=[], match=util.always, badmatch=None):
487 if node:
487 if node:
488 fdict = dict.fromkeys(files)
488 fdict = dict.fromkeys(files)
489 for fn in self.manifest.read(self.changelog.read(node)[0]):
489 for fn in self.manifest.read(self.changelog.read(node)[0]):
@@ -491,8 +491,12 b' class localrepository(object):'
491 if match(fn):
491 if match(fn):
492 yield 'm', fn
492 yield 'm', fn
493 for fn in fdict:
493 for fn in fdict:
494 self.ui.warn(_('%s: No such file in rev %s\n') % (
494 if badmatch and badmatch(fn):
495 util.pathto(self.getcwd(), fn), short(node)))
495 if match(fn):
496 yield 'b', fn
497 else:
498 self.ui.warn(_('%s: No such file in rev %s\n') % (
499 util.pathto(self.getcwd(), fn), short(node)))
496 else:
500 else:
497 for src, fn in self.dirstate.walk(files, match):
501 for src, fn in self.dirstate.walk(files, match):
498 yield src, fn
502 yield src, fn
@@ -2,16 +2,24 b''
2 A b
2 A b
3 R a
3 R a
4 reverting...
4 reverting...
5 saving current version of b as b.bak
6 forgetting b
7 undeleting a
5 %%% should show b unknown and a back to normal
8 %%% should show b unknown and a back to normal
6 ? b
9 ? b
10 ? b.bak
7 merging a
11 merging a
8 %%% should show foo-b
12 %%% should show foo-b
9 foo-b
13 foo-b
10 %%% should show a removed and b added
14 %%% should show a removed and b added
11 A b
15 A b
12 R a
16 R a
17 ? b.bak
13 reverting...
18 reverting...
19 forgetting b
20 undeleting a
14 %%% should show b unknown and a marked modified (merged)
21 %%% should show b unknown and a marked modified (merged)
15 ? b
22 ? b
23 ? b.bak
16 %%% should show foo-b
24 %%% should show foo-b
17 foo-b
25 foo-b
@@ -3,10 +3,18 b' 0:eb43f19ff115'
3 016807e6fdaf tip
3 016807e6fdaf tip
4 eb43f19ff115
4 eb43f19ff115
5 eb43f19ff115+
5 eb43f19ff115+
6 saving current version of file1 as file1.bak
7 reverting file1
8 ? file1.bak
6 eb43f19ff115
9 eb43f19ff115
10 ? file1.bak
7 016807e6fdaf tip
11 016807e6fdaf tip
8 merging file1
12 merging file1
13 ? file1.bak
9 016807e6fdaf tip
14 016807e6fdaf tip
15 ? file1.bak
10 016807e6fdaf tip
16 016807e6fdaf tip
17 ? file1.bak
11 016807e6fdaf tip
18 016807e6fdaf tip
19 ? file1.bak
12 016807e6fdaf tip
20 016807e6fdaf tip
@@ -16,7 +16,7 b' hg update -C 0'
16 hg id
16 hg id
17 echo "changed file1" >> file1
17 echo "changed file1" >> file1
18 hg id
18 hg id
19 hg revert
19 hg revert --no-backup
20 hg diff
20 hg diff
21 hg status
21 hg status
22 hg id
22 hg id
@@ -31,11 +31,11 b' hg diff | sed -e "s/\\(+++ [a-zA-Z0-9_/.-'
31 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
31 -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
32 hg status
32 hg status
33 hg id
33 hg id
34 hg revert
34 hg revert --no-backup
35 hg diff
35 hg diff
36 hg status
36 hg status
37 hg id
37 hg id
38 hg revert -r tip
38 hg revert -r tip --no-backup
39 hg diff
39 hg diff
40 hg status
40 hg status
41 hg id
41 hg id
@@ -3,6 +3,7 b' 0:9eca13a34789'
3 f248da0d4c3e tip
3 f248da0d4c3e tip
4 9eca13a34789
4 9eca13a34789
5 9eca13a34789+
5 9eca13a34789+
6 reverting file1
6 9eca13a34789
7 9eca13a34789
7 f248da0d4c3e tip
8 f248da0d4c3e tip
8 merge: warning: conflicts during merge
9 merge: warning: conflicts during merge
@@ -21,6 +22,7 b' diff -r f248da0d4c3e file1'
21 +>>>>>>>
22 +>>>>>>>
22 M file1
23 M file1
23 f248da0d4c3e+ tip
24 f248da0d4c3e+ tip
25 reverting file1
24 f248da0d4c3e tip
26 f248da0d4c3e tip
25 f248da0d4c3e tip
27 f248da0d4c3e tip
26 f248da0d4c3e tip
28 f248da0d4c3e tip
@@ -3,8 +3,9 b''
3 hg init
3 hg init
4 echo 123 > a
4 echo 123 > a
5 echo 123 > c
5 echo 123 > c
6 hg add a c
6 echo 123 > e
7 hg commit -m "first" -d "1000000 0" a c
7 hg add a c e
8 hg commit -m "first" -d "1000000 0" a c e
8 echo 123 > b
9 echo 123 > b
9 echo %% should show b unknown
10 echo %% should show b unknown
10 hg status
11 hg status
@@ -18,15 +19,25 b' hg rm a'
18 echo %% should show a removed, b added and c modified
19 echo %% should show a removed, b added and c modified
19 hg status
20 hg status
20 hg revert a
21 hg revert a
21 echo %% should show b added and c modified
22 echo %% should show b added, copy saved, and c modified
22 hg status
23 hg status
23 hg revert b
24 hg revert b
24 echo %% should show b unknown and c modified
25 echo %% should show b unknown, b.bak unknown, and c modified
26 hg status
27 hg revert --no-backup c
28 echo %% should show unknown: b b.bak
25 hg status
29 hg status
26 hg revert c
30 echo %% should show a b b.bak c e
27 echo %% should show b unknown
28 hg status
29 echo %% should show a b and c
30 ls
31 ls
32 echo %% should save backup to e.0
33 echo z > e
34 hg revert --backup='%p.%R'
35 echo %% should say no changes needed
36 hg revert a
37 echo %% should say file not managed
38 echo q > q
39 hg revert q
40 echo %% should say file not found
41 hg revert notfound
31
42
32 true
43 true
@@ -1,7 +1,7 b''
1 %% Should show unknown
1 %% Should show unknown
2 ? unknown
2 ? unknown
3 %% Should show unknown and b removed
3 %% Should show unknown and b removed
4 ! b
4 R b
5 ? unknown
5 ? unknown
6 %% Should show a and unknown
6 %% Should show a and unknown
7 a
7 a
@@ -10,15 +10,29 b' A b'
10 M c
10 M c
11 A b
11 A b
12 R a
12 R a
13 %% should show b added and c modified
13 %% should show b added, copy saved, and c modified
14 M c
14 M c
15 A b
15 A b
16 %% should show b unknown and c modified
16 saving current version of b as b.bak
17 %% should show b unknown, b.bak unknown, and c modified
17 M c
18 M c
18 ? b
19 ? b
19 %% should show b unknown
20 ? b.bak
21 %% should show unknown: b b.bak
20 ? b
22 ? b
21 %% should show a b and c
23 ? b.bak
24 %% should show a b b.bak c e
22 a
25 a
23 b
26 b
27 b.bak
24 c
28 c
29 e
30 %% should save backup to e.0
31 saving current version of e as e.0
32 reverting e
33 %% should say no changes needed
34 no changes needed to a
35 %% should say file not managed
36 file not managed: q
37 %% should say file not found
38 notfound: No such file or directory
@@ -21,6 +21,7 b' failed'
21 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
21 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
22 abort: use only one form to specify the revision
22 abort: use only one form to specify the revision
23 failed
23 failed
24 saving current version of .hgtags as .hgtags.bak
24 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
25 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
25 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
26 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
26 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
27 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
General Comments 0
You need to be logged in to leave comments. Login now