##// END OF EJS Templates
strip: use bookmarks.unsetcurrent instead of setcurrent with None
Siddharth Agarwal -
r20099:6284b0b1 default
parent child Browse files
Show More
@@ -1,219 +1,219
1 1 """strip changesets and their descendents from history
2 2
3 3 This extension allows you to strip changesets and all their descendants from the
4 4 repository. See the command help for details.
5 5 """
6 6 from mercurial.i18n import _
7 7 from mercurial.node import nullid
8 8 from mercurial.lock import release
9 9 from mercurial import cmdutil, hg, scmutil, util
10 10 from mercurial import repair, bookmarks
11 11
12 12 cmdtable = {}
13 13 command = cmdutil.command(cmdtable)
14 14 testedwith = 'internal'
15 15
16 16 def checksubstate(repo, baserev=None):
17 17 '''return list of subrepos at a different revision than substate.
18 18 Abort if any subrepos have uncommitted changes.'''
19 19 inclsubs = []
20 20 wctx = repo[None]
21 21 if baserev:
22 22 bctx = repo[baserev]
23 23 else:
24 24 bctx = wctx.parents()[0]
25 25 for s in sorted(wctx.substate):
26 26 if wctx.sub(s).dirty(True):
27 27 raise util.Abort(
28 28 _("uncommitted changes in subrepository %s") % s)
29 29 elif s not in bctx.substate or bctx.sub(s).dirty():
30 30 inclsubs.append(s)
31 31 return inclsubs
32 32
33 33 def checklocalchanges(repo, force=False, excsuffix=''):
34 34 cmdutil.checkunfinished(repo)
35 35 m, a, r, d = repo.status()[:4]
36 36 if not force:
37 37 if (m or a or r or d):
38 38 _("local changes found") # i18n tool detection
39 39 raise util.Abort(_("local changes found" + excsuffix))
40 40 if checksubstate(repo):
41 41 _("local changed subrepos found") # i18n tool detection
42 42 raise util.Abort(_("local changed subrepos found" + excsuffix))
43 43 return m, a, r, d
44 44
45 45 def strip(ui, repo, revs, update=True, backup="all", force=None):
46 46 wlock = lock = None
47 47 try:
48 48 wlock = repo.wlock()
49 49 lock = repo.lock()
50 50
51 51 if update:
52 52 checklocalchanges(repo, force=force)
53 53 urev, p2 = repo.changelog.parents(revs[0])
54 54 if (util.safehasattr(repo, 'mq') and
55 55 p2 != nullid
56 56 and p2 in [x.node for x in repo.mq.applied]):
57 57 urev = p2
58 58 hg.clean(repo, urev)
59 59 repo.dirstate.write()
60 60
61 61 repair.strip(ui, repo, revs, backup)
62 62 finally:
63 63 release(lock, wlock)
64 64
65 65
66 66 @command("strip",
67 67 [
68 68 ('r', 'rev', [], _('strip specified revision (optional, '
69 69 'can specify revisions without this '
70 70 'option)'), _('REV')),
71 71 ('f', 'force', None, _('force removal of changesets, discard '
72 72 'uncommitted changes (no backup)')),
73 73 ('b', 'backup', None, _('bundle only changesets with local revision'
74 74 ' number greater than REV which are not'
75 75 ' descendants of REV (DEPRECATED)')),
76 76 ('', 'no-backup', None, _('no backups')),
77 77 ('', 'nobackup', None, _('no backups (DEPRECATED)')),
78 78 ('n', '', None, _('ignored (DEPRECATED)')),
79 79 ('k', 'keep', None, _("do not modify working copy during strip")),
80 80 ('B', 'bookmark', '', _("remove revs only reachable from given"
81 81 " bookmark"))],
82 82 _('hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...'))
83 83 def stripcmd(ui, repo, *revs, **opts):
84 84 """strip changesets and all their descendants from the repository
85 85
86 86 The strip command removes the specified changesets and all their
87 87 descendants. If the working directory has uncommitted changes, the
88 88 operation is aborted unless the --force flag is supplied, in which
89 89 case changes will be discarded.
90 90
91 91 If a parent of the working directory is stripped, then the working
92 92 directory will automatically be updated to the most recent
93 93 available ancestor of the stripped parent after the operation
94 94 completes.
95 95
96 96 Any stripped changesets are stored in ``.hg/strip-backup`` as a
97 97 bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can
98 98 be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`,
99 99 where BUNDLE is the bundle file created by the strip. Note that
100 100 the local revision numbers will in general be different after the
101 101 restore.
102 102
103 103 Use the --no-backup option to discard the backup bundle once the
104 104 operation completes.
105 105
106 106 Strip is not a history-rewriting operation and can be used on
107 107 changesets in the public phase. But if the stripped changesets have
108 108 been pushed to a remote repository you will likely pull them again.
109 109
110 110 Return 0 on success.
111 111 """
112 112 backup = 'all'
113 113 if opts.get('backup'):
114 114 backup = 'strip'
115 115 elif opts.get('no_backup') or opts.get('nobackup'):
116 116 backup = 'none'
117 117
118 118 cl = repo.changelog
119 119 revs = list(revs) + opts.get('rev')
120 120 revs = set(scmutil.revrange(repo, revs))
121 121
122 122 if opts.get('bookmark'):
123 123 mark = opts.get('bookmark')
124 124 marks = repo._bookmarks
125 125 if mark not in marks:
126 126 raise util.Abort(_("bookmark '%s' not found") % mark)
127 127
128 128 # If the requested bookmark is not the only one pointing to a
129 129 # a revision we have to only delete the bookmark and not strip
130 130 # anything. revsets cannot detect that case.
131 131 uniquebm = True
132 132 for m, n in marks.iteritems():
133 133 if m != mark and n == repo[mark].node():
134 134 uniquebm = False
135 135 break
136 136 if uniquebm:
137 137 rsrevs = repo.revs("ancestors(bookmark(%s)) - "
138 138 "ancestors(head() and not bookmark(%s)) - "
139 139 "ancestors(bookmark() and not bookmark(%s))",
140 140 mark, mark, mark)
141 141 revs.update(set(rsrevs))
142 142 if not revs:
143 143 del marks[mark]
144 144 marks.write()
145 145 ui.write(_("bookmark '%s' deleted\n") % mark)
146 146
147 147 if not revs:
148 148 raise util.Abort(_('empty revision set'))
149 149
150 150 descendants = set(cl.descendants(revs))
151 151 strippedrevs = revs.union(descendants)
152 152 roots = revs.difference(descendants)
153 153
154 154 update = False
155 155 # if one of the wdir parent is stripped we'll need
156 156 # to update away to an earlier revision
157 157 for p in repo.dirstate.parents():
158 158 if p != nullid and cl.rev(p) in strippedrevs:
159 159 update = True
160 160 break
161 161
162 162 rootnodes = set(cl.node(r) for r in roots)
163 163
164 164 q = getattr(repo, 'mq', None)
165 165 if q is not None and q.applied:
166 166 # refresh queue state if we're about to strip
167 167 # applied patches
168 168 if cl.rev(repo.lookup('qtip')) in strippedrevs:
169 169 q.applieddirty = True
170 170 start = 0
171 171 end = len(q.applied)
172 172 for i, statusentry in enumerate(q.applied):
173 173 if statusentry.node in rootnodes:
174 174 # if one of the stripped roots is an applied
175 175 # patch, only part of the queue is stripped
176 176 start = i
177 177 break
178 178 del q.applied[start:end]
179 179 q.savedirty()
180 180
181 181 revs = sorted(rootnodes)
182 182 if update and opts.get('keep'):
183 183 wlock = repo.wlock()
184 184 try:
185 185 urev, p2 = repo.changelog.parents(revs[0])
186 186 if (util.safehasattr(repo, 'mq') and p2 != nullid
187 187 and p2 in [x.node for x in repo.mq.applied]):
188 188 urev = p2
189 189 uctx = repo[urev]
190 190
191 191 # only reset the dirstate for files that would actually change
192 192 # between the working context and uctx
193 193 descendantrevs = repo.revs("%s::." % uctx.rev())
194 194 changedfiles = []
195 195 for rev in descendantrevs:
196 196 # blindly reset the files, regardless of what actually changed
197 197 changedfiles.extend(repo[rev].files())
198 198
199 199 # reset files that only changed in the dirstate too
200 200 dirstate = repo.dirstate
201 201 dirchanges = [f for f in dirstate if dirstate[f] != 'n']
202 202 changedfiles.extend(dirchanges)
203 203
204 204 repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
205 205 repo.dirstate.write()
206 206 update = False
207 207 finally:
208 208 wlock.release()
209 209
210 210 if opts.get('bookmark'):
211 211 if mark == repo._bookmarkcurrent:
212 bookmarks.setcurrent(repo, None)
212 bookmarks.unsetcurrent(repo)
213 213 del marks[mark]
214 214 marks.write()
215 215 ui.write(_("bookmark '%s' deleted\n") % mark)
216 216
217 217 strip(ui, repo, revs, backup=backup, update=update, force=opts.get('force'))
218 218
219 219 return 0
General Comments 0
You need to be logged in to leave comments. Login now