comparison mercurial/repair.py @ 16252:cf17e76be4dd stable

strip: enhance repair.strip to receive a list of nodes (issue3299) Originally, mq.strip called repair.strip a single rev at a time. repair.strip stores in a backup bundle any revision greater than the revision being stripped, strips, then restores the backup with repo.addchangegroup. So, when stripping revisions on more than one topological branch, some could end up being restored from the backup bundle, only to be later removed by a subsequent repair.strip call. But repo.addchangegroup calls hooks for all those restore operations. And 9df9444e96ec changed it to delay all hook calls until the repository lock were released - by mq.strip, after stripping all revisions. Thus, the hooks could be called over revisions already removed from the repository at that point. By generating the revision lists at once inside repo.strip, we avoid calling addchangegroup for temporary restores. Incidentally, this also avoids creating many backup files for a single strip command.
author Wagner Bruna <wbruna@softwareexpress.com.br>
date Mon, 12 Mar 2012 17:02:45 -0300
parents 73c4b3d0c711
children 17f179805297
comparison
equal deleted inserted replaced
16244:3d26d69ef822 16252:cf17e76be4dd
52 for fname in files: 52 for fname in files:
53 collectone(repo.file(fname)) 53 collectone(repo.file(fname))
54 54
55 return s 55 return s
56 56
57 def strip(ui, repo, node, backup="all"): 57 def strip(ui, repo, nodelist, backup="all"):
58 cl = repo.changelog 58 cl = repo.changelog
59 # TODO delete the undo files, and handle undo of merge sets 59 # TODO delete the undo files, and handle undo of merge sets
60 striprev = cl.rev(node) 60 if isinstance(nodelist, str):
61 nodelist = [nodelist]
62 striplist = [cl.rev(node) for node in nodelist]
63 striprev = min(striplist)
61 64
62 keeppartialbundle = backup == 'strip' 65 keeppartialbundle = backup == 'strip'
63 66
64 # Some revisions with rev > striprev may not be descendants of striprev. 67 # Some revisions with rev > striprev may not be descendants of striprev.
65 # We have to find these revisions and put them in a bundle, so that 68 # We have to find these revisions and put them in a bundle, so that
66 # we can restore them after the truncations. 69 # we can restore them after the truncations.
67 # To create the bundle we use repo.changegroupsubset which requires 70 # To create the bundle we use repo.changegroupsubset which requires
68 # the list of heads and bases of the set of interesting revisions. 71 # the list of heads and bases of the set of interesting revisions.
69 # (head = revision in the set that has no descendant in the set; 72 # (head = revision in the set that has no descendant in the set;
70 # base = revision in the set that has no ancestor in the set) 73 # base = revision in the set that has no ancestor in the set)
71 tostrip = set(cl.descendants(striprev)) 74 tostrip = set(striplist)
72 tostrip.add(striprev) 75 for rev in striplist:
76 for desc in cl.descendants(rev):
77 tostrip.add(desc)
73 78
74 files = _collectfiles(repo, striprev) 79 files = _collectfiles(repo, striprev)
75 saverevs = _collectbrokencsets(repo, files, striprev) 80 saverevs = _collectbrokencsets(repo, files, striprev)
76 81
77 # compute heads 82 # compute heads
86 # compute base nodes 91 # compute base nodes
87 if saverevs: 92 if saverevs:
88 descendants = set(cl.descendants(*saverevs)) 93 descendants = set(cl.descendants(*saverevs))
89 saverevs.difference_update(descendants) 94 saverevs.difference_update(descendants)
90 savebases = [cl.node(r) for r in saverevs] 95 savebases = [cl.node(r) for r in saverevs]
96 stripbases = [cl.node(r) for r in tostrip]
91 97
92 bm = repo._bookmarks 98 bm = repo._bookmarks
93 updatebm = [] 99 updatebm = []
94 for m in bm: 100 for m in bm:
95 rev = repo[bm[m]].rev() 101 rev = repo[bm[m]].rev()
97 updatebm.append(m) 103 updatebm.append(m)
98 104
99 # create a changegroup for all the branches we need to keep 105 # create a changegroup for all the branches we need to keep
100 backupfile = None 106 backupfile = None
101 if backup == "all": 107 if backup == "all":
102 backupfile = _bundle(repo, [node], cl.heads(), node, 'backup') 108 backupfile = _bundle(repo, stripbases, cl.heads(), node, 'backup')
103 repo.ui.status(_("saved backup bundle to %s\n") % backupfile) 109 repo.ui.status(_("saved backup bundle to %s\n") % backupfile)
104 if saveheads or savebases: 110 if saveheads or savebases:
105 # do not compress partial bundle if we remove it from disk later 111 # do not compress partial bundle if we remove it from disk later
106 chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp', 112 chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
107 compress=keeppartialbundle) 113 compress=keeppartialbundle)