comparison hgext/uncommit.py @ 41937:232d4b9d391a

uncommit: move _movedirstate() to scmutil for reuse The function should be applicable generically when moving from one commit to another. I'll try to add more callers when I find time. I'm not convinced it's handling all the cases correctly, but we should have a generic function for this kind of operation, so I think it belongs somewhere in core (not in the uncommit extension). Differential Revision: https://phab.mercurial-scm.org/D6119
author Martin von Zweigbergk <martinvonz@google.com>
date Mon, 11 Mar 2019 09:42:29 -0700
parents bf72e4c39f0b
children 550a172a603b
comparison
equal deleted inserted replaced
41936:a791623458ef 41937:232d4b9d391a
97 user=ctx.user(), 97 user=ctx.user(),
98 date=ctx.date(), 98 date=ctx.date(),
99 extra=ctx.extra()) 99 extra=ctx.extra())
100 return repo.commitctx(new) 100 return repo.commitctx(new)
101 101
102 def _movedirstate(repo, newctx, match=None):
103 """Move the dirstate to newctx and adjust it as necessary."""
104 oldctx = repo['.']
105 ds = repo.dirstate
106 ds.setparents(newctx.node(), node.nullid)
107 copies = dict(ds.copies())
108 s = newctx.status(oldctx, match=match)
109 for f in s.modified:
110 if ds[f] == 'r':
111 # modified + removed -> removed
112 continue
113 ds.normallookup(f)
114
115 for f in s.added:
116 if ds[f] == 'r':
117 # added + removed -> unknown
118 ds.drop(f)
119 elif ds[f] != 'a':
120 ds.add(f)
121
122 for f in s.removed:
123 if ds[f] == 'a':
124 # removed + added -> normal
125 ds.normallookup(f)
126 elif ds[f] != 'r':
127 ds.remove(f)
128
129 # Merge old parent and old working dir copies
130 oldcopies = copiesmod.pathcopies(newctx, oldctx, match)
131 oldcopies.update(copies)
132 copies = dict((dst, oldcopies.get(src, src))
133 for dst, src in oldcopies.iteritems())
134 # Adjust the dirstate copies
135 for dst, src in copies.iteritems():
136 if (src not in newctx or dst in newctx or ds[dst] != 'a'):
137 src = None
138 ds.copy(src, dst)
139
140 @command('uncommit', 102 @command('uncommit',
141 [('', 'keep', None, _('allow an empty commit after uncommiting')), 103 [('', 'keep', None, _('allow an empty commit after uncommiting')),
142 ('', 'allow-dirty-working-copy', False, 104 ('', 'allow-dirty-working-copy', False,
143 _('allow uncommit with outstanding changes')) 105 _('allow uncommit with outstanding changes'))
144 ] + commands.walkopts, 106 ] + commands.walkopts,
191 else: 153 else:
192 # Fully removed the old commit 154 # Fully removed the old commit
193 mapping[old.node()] = () 155 mapping[old.node()] = ()
194 156
195 with repo.dirstate.parentchange(): 157 with repo.dirstate.parentchange():
196 _movedirstate(repo, repo[newid], match) 158 scmutil.movedirstate(repo, repo[newid], match)
197 159
198 scmutil.cleanupnodes(repo, mapping, 'uncommit', fixphase=True) 160 scmutil.cleanupnodes(repo, mapping, 'uncommit', fixphase=True)
199 161
200 def predecessormarkers(ctx): 162 def predecessormarkers(ctx):
201 """yields the obsolete markers marking the given changeset as a successor""" 163 """yields the obsolete markers marking the given changeset as a successor"""
253 newprednode = repo.commitctx(newctx) 215 newprednode = repo.commitctx(newctx)
254 newpredctx = repo[newprednode] 216 newpredctx = repo[newprednode]
255 dirstate = repo.dirstate 217 dirstate = repo.dirstate
256 218
257 with dirstate.parentchange(): 219 with dirstate.parentchange():
258 _movedirstate(repo, newpredctx) 220 scmutil.movedirstate(repo, newpredctx)
259 221
260 mapping = {curctx.node(): (newprednode,)} 222 mapping = {curctx.node(): (newprednode,)}
261 scmutil.cleanupnodes(repo, mapping, 'unamend', fixphase=True) 223 scmutil.cleanupnodes(repo, mapping, 'unamend', fixphase=True)