Mercurial > hg-stable
comparison hgext/uncommit.py @ 41942: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
41941:a791623458ef | 41942: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) |