##// END OF EJS Templates
unamend: move fb extension unamend to core...
Pulkit Goyal -
r35177:86799023 default
parent child Browse files
Show More
@@ -0,0 +1,366 b''
1 Test for command `hg unamend` which lives in uncommit extension
2 ===============================================================
3
4 $ cat >> $HGRCPATH << EOF
5 > [alias]
6 > glog = log -G -T '{rev}:{node|short} {desc}'
7 > [experimental]
8 > evolution = createmarkers, allowunstable
9 > [extensions]
10 > rebase =
11 > amend =
12 > uncommit =
13 > EOF
14
15 Repo Setup
16
17 $ hg init repo
18 $ cd repo
19 $ for ch in {a..h}; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done
20
21 $ hg glog
22 @ 7:ec2426147f0e Added h
23 |
24 o 6:87d6d6676308 Added g
25 |
26 o 5:825660c69f0c Added f
27 |
28 o 4:aa98ab95a928 Added e
29 |
30 o 3:62615734edd5 Added d
31 |
32 o 2:28ad74487de9 Added c
33 |
34 o 1:29becc82797a Added b
35 |
36 o 0:18d04c59bb5d Added a
37
38 Trying to unamend when there was no amend done
39
40 $ hg unamend
41 abort: changeset must have one predecessor, found 0 predecessors
42 [255]
43
44 Unamend on clean wdir and tip
45
46 $ echo "bar" >> h
47 $ hg amend
48
49 $ hg exp
50 # HG changeset patch
51 # User test
52 # Date 0 0
53 # Thu Jan 01 00:00:00 1970 +0000
54 # Node ID c9fa1a715c1b7661c0fafb362a9f30bd75878d7d
55 # Parent 87d6d66763085b629e6d7ed56778c79827273022
56 Added h
57
58 diff -r 87d6d6676308 -r c9fa1a715c1b h
59 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60 +++ b/h Thu Jan 01 00:00:00 1970 +0000
61 @@ -0,0 +1,2 @@
62 +foo
63 +bar
64
65 $ hg glog --hidden
66 @ 8:c9fa1a715c1b Added h
67 |
68 | x 7:ec2426147f0e Added h
69 |/
70 o 6:87d6d6676308 Added g
71 |
72 o 5:825660c69f0c Added f
73 |
74 o 4:aa98ab95a928 Added e
75 |
76 o 3:62615734edd5 Added d
77 |
78 o 2:28ad74487de9 Added c
79 |
80 o 1:29becc82797a Added b
81 |
82 o 0:18d04c59bb5d Added a
83
84 $ hg unamend
85 $ hg glog --hidden
86 @ 9:8da14a1fd653 Added h
87 |
88 | x 8:c9fa1a715c1b Added h
89 |/
90 | x 7:ec2426147f0e Added h
91 |/
92 o 6:87d6d6676308 Added g
93 |
94 o 5:825660c69f0c Added f
95 |
96 o 4:aa98ab95a928 Added e
97 |
98 o 3:62615734edd5 Added d
99 |
100 o 2:28ad74487de9 Added c
101 |
102 o 1:29becc82797a Added b
103 |
104 o 0:18d04c59bb5d Added a
105
106 $ hg diff
107 diff -r 8da14a1fd653 h
108 --- a/h Thu Jan 01 00:00:00 1970 +0000
109 +++ b/h Thu Jan 01 00:00:00 1970 +0000
110 @@ -1,1 +1,2 @@
111 foo
112 +bar
113
114 $ hg exp
115 # HG changeset patch
116 # User test
117 # Date 0 0
118 # Thu Jan 01 00:00:00 1970 +0000
119 # Node ID 8da14a1fd653c3f07fdad5760511c9e12652a306
120 # Parent 87d6d66763085b629e6d7ed56778c79827273022
121 Added h
122
123 diff -r 87d6d6676308 -r 8da14a1fd653 h
124 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125 +++ b/h Thu Jan 01 00:00:00 1970 +0000
126 @@ -0,0 +1,1 @@
127 +foo
128
129 $ hg status
130 M h
131
132 $ hg log -r . -T '{extras % "{extra}\n"}' --config alias.log=log
133 branch=default
134 unamend_source=\xc9\xfa\x1aq\\\x1bva\xc0\xfa\xfb6*\x9f0\xbdu\x87\x8d}
135
136 Using unamend to undo an unamed (intentional)
137
138 $ hg unamend
139 $ hg exp
140 # HG changeset patch
141 # User test
142 # Date 0 0
143 # Thu Jan 01 00:00:00 1970 +0000
144 # Node ID 1c09887216571a9755fc9d2e7f0e41c2b49e341b
145 # Parent 87d6d66763085b629e6d7ed56778c79827273022
146 Added h
147
148 diff -r 87d6d6676308 -r 1c0988721657 h
149 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150 +++ b/h Thu Jan 01 00:00:00 1970 +0000
151 @@ -0,0 +1,2 @@
152 +foo
153 +bar
154 $ hg diff
155
156 Unamend on a dirty working directory
157
158 $ echo "bar" >> a
159 $ hg amend
160 $ echo "foobar" >> a
161 $ echo "bar" >> b
162 $ hg status
163 M a
164 M b
165
166 $ hg unamend
167
168 $ hg status
169 M a
170 M b
171
172 $ hg diff
173 diff -r 956548224719 a
174 --- a/a Thu Jan 01 00:00:00 1970 +0000
175 +++ b/a Thu Jan 01 00:00:00 1970 +0000
176 @@ -1,1 +1,3 @@
177 foo
178 +bar
179 +foobar
180 diff -r 956548224719 b
181 --- a/b Thu Jan 01 00:00:00 1970 +0000
182 +++ b/b Thu Jan 01 00:00:00 1970 +0000
183 @@ -1,1 +1,2 @@
184 foo
185 +bar
186
187 Unamending an added file
188
189 $ hg ci -m "Added things to a and b"
190 $ echo foo > bar
191 $ hg add bar
192 $ hg amend
193
194 $ hg unamend
195 $ hg status
196 A bar
197
198 $ hg revert --all
199 forgetting bar
200
201 Unamending a removed file
202
203 $ hg remove a
204 $ hg amend
205
206 $ hg unamend
207 $ hg status
208 R a
209 ? bar
210
211 $ hg revert --all
212 undeleting a
213
214 Unamending an added file with dirty wdir status
215
216 $ hg add bar
217 $ hg amend
218 $ echo bar >> bar
219 $ hg status
220 M bar
221
222 $ hg unamend
223 $ hg status
224 A bar
225 $ hg diff
226 diff -r ff917aa01c86 bar
227 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
228 +++ b/bar Thu Jan 01 00:00:00 1970 +0000
229 @@ -0,0 +1,2 @@
230 +foo
231 +bar
232
233 $ hg revert --all
234 forgetting bar
235
236 Unamending in middle of a stack
237
238 $ hg glog
239 @ 19:ff917aa01c86 Added things to a and b
240 |
241 o 12:956548224719 Added h
242 |
243 o 6:87d6d6676308 Added g
244 |
245 o 5:825660c69f0c Added f
246 |
247 o 4:aa98ab95a928 Added e
248 |
249 o 3:62615734edd5 Added d
250 |
251 o 2:28ad74487de9 Added c
252 |
253 o 1:29becc82797a Added b
254 |
255 o 0:18d04c59bb5d Added a
256
257 $ hg up 5
258 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
259 $ echo bar >> f
260 $ hg amend
261 $ hg rebase -s 6 -d . -q
262
263 $ hg glog
264 o 23:2b41b42e192a Added things to a and b
265 |
266 o 22:1860df151f01 Added h
267 |
268 o 21:49635b68477e Added g
269 |
270 @ 20:93f0e8ffab32 Added f
271 |
272 o 4:aa98ab95a928 Added e
273 |
274 o 3:62615734edd5 Added d
275 |
276 o 2:28ad74487de9 Added c
277 |
278 o 1:29becc82797a Added b
279 |
280 o 0:18d04c59bb5d Added a
281
282
283 $ hg unamend
284 abort: cannot unamend a changeset with children
285 [255]
286
287 Trying to unamend a public changeset
288
289 $ hg up
290 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
291 $ hg phase -r . -p
292 $ hg unamend
293 abort: cannot unamend public changesets
294 [255]
295
296 Testing whether unamend retains copies or not
297
298 $ hg status
299 ? bar
300
301 $ hg mv a foo
302
303 $ hg ci -m "Moved a to foo"
304 $ hg exp --git
305 # HG changeset patch
306 # User test
307 # Date 0 0
308 # Thu Jan 01 00:00:00 1970 +0000
309 # Node ID b087c66cada118d6c5487d3d7cb29cac239bd98a
310 # Parent 2b41b42e192adc425b106643c3fc89170d6b8add
311 Moved a to foo
312
313 diff --git a/a b/foo
314 rename from a
315 rename to foo
316
317 $ hg mv b foobar
318 $ hg diff --git
319 diff --git a/b b/foobar
320 rename from b
321 rename to foobar
322 $ hg amend
323
324 $ hg exp --git
325 # HG changeset patch
326 # User test
327 # Date 0 0
328 # Thu Jan 01 00:00:00 1970 +0000
329 # Node ID 9fa06fb09a83a86ec7368d15004dbc52ac1a5d2e
330 # Parent 2b41b42e192adc425b106643c3fc89170d6b8add
331 Moved a to foo
332
333 diff --git a/a b/foo
334 rename from a
335 rename to foo
336 diff --git a/b b/foobar
337 rename from b
338 rename to foobar
339
340 $ hg mv c wat
341 $ hg unamend
342
343 Retained copies in new prdecessor commit
344
345 $ hg exp --git
346 # HG changeset patch
347 # User test
348 # Date 0 0
349 # Thu Jan 01 00:00:00 1970 +0000
350 # Node ID 4cf9987c9b941f615930e7c46307b4dbf35697cf
351 # Parent 2b41b42e192adc425b106643c3fc89170d6b8add
352 Moved a to foo
353
354 diff --git a/a b/foo
355 rename from a
356 rename to foo
357
358 Retained copies in working directoy
359
360 $ hg diff --git
361 diff --git a/b b/foobar
362 rename from b
363 rename to foobar
364 diff --git a/c b/wat
365 rename from c
366 rename to wat
@@ -29,6 +29,7 b' from mercurial import ('
29 error,
29 error,
30 node,
30 node,
31 obsolete,
31 obsolete,
32 obsutil,
32 pycompat,
33 pycompat,
33 registrar,
34 registrar,
34 scmutil,
35 scmutil,
@@ -194,3 +195,124 b' def uncommit(ui, repo, *pats, **opts):'
194 with repo.dirstate.parentchange():
195 with repo.dirstate.parentchange():
195 repo.dirstate.setparents(newid, node.nullid)
196 repo.dirstate.setparents(newid, node.nullid)
196 _uncommitdirstate(repo, old, match)
197 _uncommitdirstate(repo, old, match)
198
199 def predecessormarkers(ctx):
200 """yields the obsolete markers marking the given changeset as a successor"""
201 for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
202 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
245 @command('^unamend', [])
246 def unamend(ui, repo, **opts):
247 """
248 undo the most recent amend operation on a current changeset
249
250 This command will roll back to the previous version of a changeset,
251 leaving working directory in state in which it was before running
252 `hg amend` (e.g. files modified as part of an amend will be
253 marked as modified `hg status`)
254 """
255
256 unfi = repo.unfiltered()
257
258 # identify the commit from which to unamend
259 curctx = repo['.']
260
261 with repo.wlock(), repo.lock(), repo.transaction('unamend'):
262 if not curctx.mutable():
263 raise error.Abort(_('cannot unamend public changesets'))
264
265 # identify the commit to which to unamend
266 markers = list(predecessormarkers(curctx))
267 if len(markers) != 1:
268 e = _("changeset must have one predecessor, found %i predecessors")
269 raise error.Abort(e % len(markers))
270
271 prednode = markers[0].prednode()
272 predctx = unfi[prednode]
273
274 if curctx.children():
275 raise error.Abort(_("cannot unamend a changeset with children"))
276
277 # add an extra so that we get a new hash
278 # note: allowing unamend to undo an unamend is an intentional feature
279 extras = predctx.extra()
280 extras['unamend_source'] = curctx.node()
281
282 def filectxfn(repo, ctx_, path):
283 try:
284 return predctx.filectx(path)
285 except KeyError:
286 return None
287
288 # Make a new commit same as predctx
289 newctx = context.memctx(repo,
290 parents=(predctx.p1(), predctx.p2()),
291 text=predctx.description(),
292 files=predctx.files(),
293 filectxfn=filectxfn,
294 user=predctx.user(),
295 date=predctx.date(),
296 extra=extras)
297 # phase handling
298 commitphase = curctx.phase()
299 overrides = {('phases', 'new-commit'): commitphase}
300 with repo.ui.configoverride(overrides, 'uncommit'):
301 newprednode = repo.commitctx(newctx)
302
303 newpredctx = repo[newprednode]
304
305 changedfiles = []
306 wctx = repo[None]
307 wm = wctx.manifest()
308 cm = newpredctx.manifest()
309 dirstate = repo.dirstate
310 diff = cm.diff(wm)
311 changedfiles.extend(diff.iterkeys())
312
313 with dirstate.parentchange():
314 dirstate.setparents(newprednode, node.nullid)
315 _unamenddirstate(repo, newpredctx, curctx)
316
317 mapping = {curctx.node(): (newprednode,)}
318 scmutil.cleanupnodes(repo, mapping, 'unamend')
General Comments 0
You need to be logged in to leave comments. Login now