comparison hgext/uncommit.py @ 35183:9dadcb99cc17

uncommit: unify functions _uncommitdirstate and _unamenddirstate to one The _unamenddirstate() function was inspired by _uncommitdirstate() function as the logic was same but we were unable to use the latter function directly. So previous patch introduced the _unamenddirstate() function and now this patch unifies both the function and we have a _fixdirstate() function. Adding function in previous patch and unifying in a later patch makes the reasoning easier and also leaves the last patch dedicated to what it is meant to be. Differential Revision: https://phab.mercurial-scm.org/D971
author Pulkit Goyal <7895pulkit@gmail.com>
date Fri, 06 Oct 2017 04:17:36 +0530
parents 867990238dc6
children 9e339c97fabb
comparison
equal deleted inserted replaced
35182:867990238dc6 35183:9dadcb99cc17
96 overrides = {('phases', 'new-commit'): commitphase} 96 overrides = {('phases', 'new-commit'): commitphase}
97 with repo.ui.configoverride(overrides, 'uncommit'): 97 with repo.ui.configoverride(overrides, 'uncommit'):
98 newid = repo.commitctx(new) 98 newid = repo.commitctx(new)
99 return newid 99 return newid
100 100
101 def _uncommitdirstate(repo, oldctx, match): 101 def _fixdirstate(repo, oldctx, newctx, status):
102 """Fix the dirstate after switching the working directory from 102 """ fix the dirstate after switching the working directory from oldctx to
103 oldctx to a copy of oldctx not containing changed files matched by 103 newctx which can be result of either unamend or uncommit.
104 match. 104 """
105 """
106 ctx = repo['.']
107 ds = repo.dirstate 105 ds = repo.dirstate
108 copies = dict(ds.copies()) 106 copies = dict(ds.copies())
109 s = repo.status(oldctx.p1(), oldctx, match=match) 107 s = status
110 for f in s.modified: 108 for f in s.modified:
111 if ds[f] == 'r': 109 if ds[f] == 'r':
112 # modified + removed -> removed 110 # modified + removed -> removed
113 continue 111 continue
114 ds.normallookup(f) 112 ds.normallookup(f)
136 oldcopies.update(copies) 134 oldcopies.update(copies)
137 copies = dict((dst, oldcopies.get(src, src)) 135 copies = dict((dst, oldcopies.get(src, src))
138 for dst, src in oldcopies.iteritems()) 136 for dst, src in oldcopies.iteritems())
139 # Adjust the dirstate copies 137 # Adjust the dirstate copies
140 for dst, src in copies.iteritems(): 138 for dst, src in copies.iteritems():
141 if (src not in ctx or dst in ctx or ds[dst] != 'a'): 139 if (src not in newctx or dst in newctx or ds[dst] != 'a'):
142 src = None 140 src = None
143 ds.copy(src, dst) 141 ds.copy(src, dst)
144 142
145 @command('uncommit', 143 @command('uncommit',
146 [('', 'keep', False, _('allow an empty commit after uncommiting')), 144 [('', 'keep', False, _('allow an empty commit after uncommiting')),
192 190
193 scmutil.cleanupnodes(repo, mapping, 'uncommit') 191 scmutil.cleanupnodes(repo, mapping, 'uncommit')
194 192
195 with repo.dirstate.parentchange(): 193 with repo.dirstate.parentchange():
196 repo.dirstate.setparents(newid, node.nullid) 194 repo.dirstate.setparents(newid, node.nullid)
197 _uncommitdirstate(repo, old, match) 195 s = repo.status(old.p1(), old, match=match)
196 _fixdirstate(repo, old, repo[newid], s)
198 197
199 def predecessormarkers(ctx): 198 def predecessormarkers(ctx):
200 """yields the obsolete markers marking the given changeset as a successor""" 199 """yields the obsolete markers marking the given changeset as a successor"""
201 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()): 200 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
202 yield obsutil.marker(ctx.repo(), data) 201 yield obsutil.marker(ctx.repo(), data)
203
204 def _unamenddirstate(repo, predctx, curctx):
205 """"""
206
207 s = repo.status(predctx, curctx)
208 ds = repo.dirstate
209 copies = dict(ds.copies())
210 for f in s.modified:
211 if ds[f] == 'r':
212 # modified + removed -> removed
213 continue
214 ds.normallookup(f)
215
216 for f in s.added:
217 if ds[f] == 'r':
218 # added + removed -> unknown
219 ds.drop(f)
220 elif ds[f] != 'a':
221 ds.add(f)
222
223 for f in s.removed:
224 if ds[f] == 'a':
225 # removed + added -> normal
226 ds.normallookup(f)
227 elif ds[f] != 'r':
228 ds.remove(f)
229
230 # Merge old parent and old working dir copies
231 oldcopies = {}
232 for f in (s.modified + s.added):
233 src = curctx[f].renamed()
234 if src:
235 oldcopies[f] = src[0]
236 oldcopies.update(copies)
237 copies = dict((dst, oldcopies.get(src, src))
238 for dst, src in oldcopies.iteritems())
239 # Adjust the dirstate copies
240 for dst, src in copies.iteritems():
241 if (src not in predctx or dst in predctx or ds[dst] != 'a'):
242 src = None
243 ds.copy(src, dst)
244 202
245 @command('^unamend', []) 203 @command('^unamend', [])
246 def unamend(ui, repo, **opts): 204 def unamend(ui, repo, **opts):
247 """ 205 """
248 undo the most recent amend operation on a current changeset 206 undo the most recent amend operation on a current changeset
310 diff = cm.diff(wm) 268 diff = cm.diff(wm)
311 changedfiles.extend(diff.iterkeys()) 269 changedfiles.extend(diff.iterkeys())
312 270
313 with dirstate.parentchange(): 271 with dirstate.parentchange():
314 dirstate.setparents(newprednode, node.nullid) 272 dirstate.setparents(newprednode, node.nullid)
315 _unamenddirstate(repo, newpredctx, curctx) 273 s = repo.status(predctx, curctx)
274 _fixdirstate(repo, curctx, newpredctx, s)
316 275
317 mapping = {curctx.node(): (newprednode,)} 276 mapping = {curctx.node(): (newprednode,)}
318 scmutil.cleanupnodes(repo, mapping, 'unamend') 277 scmutil.cleanupnodes(repo, mapping, 'unamend')