##// END OF EJS Templates
update: use single quotes in use warning
timeless -
r29964:40f84553 default
parent child Browse files
Show More
@@ -1,437 +1,437 b''
1 1 # destutil.py - Mercurial utility function for command destination
2 2 #
3 3 # Copyright Matt Mackall <mpm@selenic.com> and other
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 from .i18n import _
11 11 from . import (
12 12 bookmarks,
13 13 error,
14 14 obsolete,
15 15 )
16 16
17 17 def _destupdatevalidate(repo, rev, clean, check):
18 18 """validate that the destination comply to various rules
19 19
20 20 This exists as its own function to help wrapping from extensions."""
21 21 wc = repo[None]
22 22 p1 = wc.p1()
23 23 if not clean:
24 24 # Check that the update is linear.
25 25 #
26 26 # Mercurial do not allow update-merge for non linear pattern
27 27 # (that would be technically possible but was considered too confusing
28 28 # for user a long time ago)
29 29 #
30 30 # See mercurial.merge.update for details
31 31 if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
32 32 dirty = wc.dirty(missing=True)
33 33 foreground = obsolete.foreground(repo, [p1.node()])
34 34 if not repo[rev].node() in foreground:
35 35 if dirty:
36 36 msg = _("uncommitted changes")
37 37 hint = _("commit and merge, or update --clean to"
38 38 " discard changes")
39 39 raise error.UpdateAbort(msg, hint=hint)
40 40 elif not check: # destination is not a descendant.
41 41 msg = _("not a linear update")
42 42 hint = _("merge or update --check to force update")
43 43 raise error.UpdateAbort(msg, hint=hint)
44 44
45 45 def _destupdateobs(repo, clean, check):
46 46 """decide of an update destination from obsolescence markers"""
47 47 node = None
48 48 wc = repo[None]
49 49 p1 = wc.p1()
50 50 movemark = None
51 51
52 52 if p1.obsolete() and not p1.children():
53 53 # allow updating to successors
54 54 successors = obsolete.successorssets(repo, p1.node())
55 55
56 56 # behavior of certain cases is as follows,
57 57 #
58 58 # divergent changesets: update to highest rev, similar to what
59 59 # is currently done when there are more than one head
60 60 # (i.e. 'tip')
61 61 #
62 62 # replaced changesets: same as divergent except we know there
63 63 # is no conflict
64 64 #
65 65 # pruned changeset: no update is done; though, we could
66 66 # consider updating to the first non-obsolete parent,
67 67 # similar to what is current done for 'hg prune'
68 68
69 69 if successors:
70 70 # flatten the list here handles both divergent (len > 1)
71 71 # and the usual case (len = 1)
72 72 successors = [n for sub in successors for n in sub]
73 73
74 74 # get the max revision for the given successors set,
75 75 # i.e. the 'tip' of a set
76 76 node = repo.revs('max(%ln)', successors).first()
77 77 if bookmarks.isactivewdirparent(repo):
78 78 movemark = repo['.'].node()
79 79 return node, movemark, None
80 80
81 81 def _destupdatebook(repo, clean, check):
82 82 """decide on an update destination from active bookmark"""
83 83 # we also move the active bookmark, if any
84 84 activemark = None
85 85 node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
86 86 if node is not None:
87 87 activemark = node
88 88 return node, movemark, activemark
89 89
90 90 def _destupdatebranch(repo, clean, check):
91 91 """decide on an update destination from current branch
92 92
93 93 This ignores closed branch heads.
94 94 """
95 95 wc = repo[None]
96 96 movemark = node = None
97 97 currentbranch = wc.branch()
98 98
99 99 if clean:
100 100 currentbranch = repo['.'].branch()
101 101
102 102 if currentbranch in repo.branchmap():
103 103 heads = repo.branchheads(currentbranch)
104 104 if heads:
105 105 node = repo.revs('max(.::(%ln))', heads).first()
106 106 if bookmarks.isactivewdirparent(repo):
107 107 movemark = repo['.'].node()
108 108 elif currentbranch == 'default' and not wc.p1():
109 109 # "null" parent belongs to "default" branch, but it doesn't exist, so
110 110 # update to the tipmost non-closed branch head
111 111 node = repo.revs('max(head() and not closed())').first()
112 112 else:
113 113 node = repo['.'].node()
114 114 return node, movemark, None
115 115
116 116 def _destupdatebranchfallback(repo, clean, check):
117 117 """decide on an update destination from closed heads in current branch"""
118 118 wc = repo[None]
119 119 currentbranch = wc.branch()
120 120 movemark = None
121 121 if currentbranch in repo.branchmap():
122 122 # here, all descendant branch heads are closed
123 123 heads = repo.branchheads(currentbranch, closed=True)
124 124 assert heads, "any branch has at least one head"
125 125 node = repo.revs('max(.::(%ln))', heads).first()
126 126 assert node is not None, ("any revision has at least "
127 127 "one descendant branch head")
128 128 if bookmarks.isactivewdirparent(repo):
129 129 movemark = repo['.'].node()
130 130 else:
131 131 # here, no "default" branch, and all branches are closed
132 132 node = repo.lookup('tip')
133 133 assert node is not None, "'tip' exists even in empty repository"
134 134 return node, movemark, None
135 135
136 136 # order in which each step should be evalutated
137 137 # steps are run until one finds a destination
138 138 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
139 139 # mapping to ease extension overriding steps.
140 140 destupdatestepmap = {'evolution': _destupdateobs,
141 141 'bookmark': _destupdatebook,
142 142 'branch': _destupdatebranch,
143 143 'branchfallback': _destupdatebranchfallback,
144 144 }
145 145
146 146 def destupdate(repo, clean=False, check=False):
147 147 """destination for bare update operation
148 148
149 149 return (rev, movemark, activemark)
150 150
151 151 - rev: the revision to update to,
152 152 - movemark: node to move the active bookmark from
153 153 (cf bookmark.calculate update),
154 154 - activemark: a bookmark to activate at the end of the update.
155 155 """
156 156 node = movemark = activemark = None
157 157
158 158 for step in destupdatesteps:
159 159 node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
160 160 if node is not None:
161 161 break
162 162 rev = repo[node].rev()
163 163
164 164 _destupdatevalidate(repo, rev, clean, check)
165 165
166 166 return rev, movemark, activemark
167 167
168 168 msgdestmerge = {
169 169 # too many matching divergent bookmark
170 170 'toomanybookmarks':
171 171 {'merge':
172 172 (_("multiple matching bookmarks to merge -"
173 173 " please merge with an explicit rev or bookmark"),
174 174 _("run 'hg heads' to see all heads")),
175 175 'rebase':
176 176 (_("multiple matching bookmarks to rebase -"
177 177 " please rebase to an explicit rev or bookmark"),
178 178 _("run 'hg heads' to see all heads")),
179 179 },
180 180 # no other matching divergent bookmark
181 181 'nootherbookmarks':
182 182 {'merge':
183 183 (_("no matching bookmark to merge - "
184 184 "please merge with an explicit rev or bookmark"),
185 185 _("run 'hg heads' to see all heads")),
186 186 'rebase':
187 187 (_("no matching bookmark to rebase - "
188 188 "please rebase to an explicit rev or bookmark"),
189 189 _("run 'hg heads' to see all heads")),
190 190 },
191 191 # branch have too many unbookmarked heads, no obvious destination
192 192 'toomanyheads':
193 193 {'merge':
194 194 (_("branch '%s' has %d heads - please merge with an explicit rev"),
195 195 _("run 'hg heads .' to see heads")),
196 196 'rebase':
197 197 (_("branch '%s' has %d heads - please rebase to an explicit rev"),
198 198 _("run 'hg heads .' to see heads")),
199 199 },
200 200 # branch have no other unbookmarked heads
201 201 'bookmarkedheads':
202 202 {'merge':
203 203 (_("heads are bookmarked - please merge with an explicit rev"),
204 204 _("run 'hg heads' to see all heads")),
205 205 'rebase':
206 206 (_("heads are bookmarked - please rebase to an explicit rev"),
207 207 _("run 'hg heads' to see all heads")),
208 208 },
209 209 # branch have just a single heads, but there is other branches
210 210 'nootherbranchheads':
211 211 {'merge':
212 212 (_("branch '%s' has one head - please merge with an explicit rev"),
213 213 _("run 'hg heads' to see all heads")),
214 214 'rebase':
215 215 (_("branch '%s' has one head - please rebase to an explicit rev"),
216 216 _("run 'hg heads' to see all heads")),
217 217 },
218 218 # repository have a single head
219 219 'nootherheads':
220 220 {'merge':
221 221 (_('nothing to merge'),
222 222 None),
223 223 'rebase':
224 224 (_('nothing to rebase'),
225 225 None),
226 226 },
227 227 # repository have a single head and we are not on it
228 228 'nootherheadsbehind':
229 229 {'merge':
230 230 (_('nothing to merge'),
231 231 _("use 'hg update' instead")),
232 232 'rebase':
233 233 (_('nothing to rebase'),
234 234 _("use 'hg update' instead")),
235 235 },
236 236 # We are not on a head
237 237 'notatheads':
238 238 {'merge':
239 239 (_('working directory not at a head revision'),
240 240 _("use 'hg update' or merge with an explicit revision")),
241 241 'rebase':
242 242 (_('working directory not at a head revision'),
243 243 _("use 'hg update' or rebase to an explicit revision"))
244 244 },
245 245 'emptysourceset':
246 246 {'merge':
247 247 (_('source set is empty'),
248 248 None),
249 249 'rebase':
250 250 (_('source set is empty'),
251 251 None),
252 252 },
253 253 'multiplebranchessourceset':
254 254 {'merge':
255 255 (_('source set is rooted in multiple branches'),
256 256 None),
257 257 'rebase':
258 258 (_('rebaseset is rooted in multiple named branches'),
259 259 _('specify an explicit destination with --dest')),
260 260 },
261 261 }
262 262
263 263 def _destmergebook(repo, action='merge', sourceset=None, destspace=None):
264 264 """find merge destination in the active bookmark case"""
265 265 node = None
266 266 bmheads = repo.bookmarkheads(repo._activebookmark)
267 267 curhead = repo[repo._activebookmark].node()
268 268 if len(bmheads) == 2:
269 269 if curhead == bmheads[0]:
270 270 node = bmheads[1]
271 271 else:
272 272 node = bmheads[0]
273 273 elif len(bmheads) > 2:
274 274 msg, hint = msgdestmerge['toomanybookmarks'][action]
275 275 raise error.ManyMergeDestAbort(msg, hint=hint)
276 276 elif len(bmheads) <= 1:
277 277 msg, hint = msgdestmerge['nootherbookmarks'][action]
278 278 raise error.NoMergeDestAbort(msg, hint=hint)
279 279 assert node is not None
280 280 return node
281 281
282 282 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True,
283 283 destspace=None):
284 284 """find merge destination based on branch heads"""
285 285 node = None
286 286
287 287 if sourceset is None:
288 288 sourceset = [repo[repo.dirstate.p1()].rev()]
289 289 branch = repo.dirstate.branch()
290 290 elif not sourceset:
291 291 msg, hint = msgdestmerge['emptysourceset'][action]
292 292 raise error.NoMergeDestAbort(msg, hint=hint)
293 293 else:
294 294 branch = None
295 295 for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
296 296 if branch is not None and ctx.branch() != branch:
297 297 msg, hint = msgdestmerge['multiplebranchessourceset'][action]
298 298 raise error.ManyMergeDestAbort(msg, hint=hint)
299 299 branch = ctx.branch()
300 300
301 301 bheads = repo.branchheads(branch)
302 302 onhead = repo.revs('%ld and %ln', sourceset, bheads)
303 303 if onheadcheck and not onhead:
304 304 # Case A: working copy if not on a head. (merge only)
305 305 #
306 306 # This is probably a user mistake We bailout pointing at 'hg update'
307 307 if len(repo.heads()) <= 1:
308 308 msg, hint = msgdestmerge['nootherheadsbehind'][action]
309 309 else:
310 310 msg, hint = msgdestmerge['notatheads'][action]
311 311 raise error.Abort(msg, hint=hint)
312 312 # remove heads descendants of source from the set
313 313 bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
314 314 # filters out bookmarked heads
315 315 nbhs = list(repo.revs('%ld - bookmark()', bheads))
316 316
317 317 if destspace is not None:
318 318 # restrict search space
319 319 # used in the 'hg pull --rebase' case, see issue 5214.
320 320 nbhs = list(repo.revs('%ld and %ld', destspace, nbhs))
321 321
322 322 if len(nbhs) > 1:
323 323 # Case B: There is more than 1 other anonymous heads
324 324 #
325 325 # This means that there will be more than 1 candidate. This is
326 326 # ambiguous. We abort asking the user to pick as explicit destination
327 327 # instead.
328 328 msg, hint = msgdestmerge['toomanyheads'][action]
329 329 msg %= (branch, len(bheads) + 1)
330 330 raise error.ManyMergeDestAbort(msg, hint=hint)
331 331 elif not nbhs:
332 332 # Case B: There is no other anonymous heads
333 333 #
334 334 # This means that there is no natural candidate to merge with.
335 335 # We abort, with various messages for various cases.
336 336 if bheads:
337 337 msg, hint = msgdestmerge['bookmarkedheads'][action]
338 338 elif len(repo.heads()) > 1:
339 339 msg, hint = msgdestmerge['nootherbranchheads'][action]
340 340 msg %= branch
341 341 elif not onhead:
342 342 # if 'onheadcheck == False' (rebase case),
343 343 # this was not caught in Case A.
344 344 msg, hint = msgdestmerge['nootherheadsbehind'][action]
345 345 else:
346 346 msg, hint = msgdestmerge['nootherheads'][action]
347 347 raise error.NoMergeDestAbort(msg, hint=hint)
348 348 else:
349 349 node = nbhs[0]
350 350 assert node is not None
351 351 return node
352 352
353 353 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True,
354 354 destspace=None):
355 355 """return the default destination for a merge
356 356
357 357 (or raise exception about why it can't pick one)
358 358
359 359 :action: the action being performed, controls emitted error message
360 360 """
361 361 # destspace is here to work around issues with `hg pull --rebase` see
362 362 # issue5214 for details
363 363 if repo._activebookmark:
364 364 node = _destmergebook(repo, action=action, sourceset=sourceset,
365 365 destspace=destspace)
366 366 else:
367 367 node = _destmergebranch(repo, action=action, sourceset=sourceset,
368 368 onheadcheck=onheadcheck, destspace=destspace)
369 369 return repo[node].rev()
370 370
371 371 histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
372 372
373 373 def desthistedit(ui, repo):
374 374 """Default base revision to edit for `hg histedit`."""
375 375 # Avoid cycle: scmutil -> revset -> destutil
376 376 from . import scmutil
377 377
378 378 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
379 379 if default:
380 380 revs = scmutil.revrange(repo, [default])
381 381 if revs:
382 382 # The revset supplied by the user may not be in ascending order nor
383 383 # take the first revision. So do this manually.
384 384 revs.sort()
385 385 return revs.first()
386 386
387 387 return None
388 388
389 389 def _statusotherbook(ui, repo):
390 390 bmheads = repo.bookmarkheads(repo._activebookmark)
391 391 curhead = repo[repo._activebookmark].node()
392 392 if repo.revs('%n and parents()', curhead):
393 393 # we are on the active bookmark
394 394 bmheads = [b for b in bmheads if curhead != b]
395 395 if bmheads:
396 396 msg = _('%i other divergent bookmarks for "%s"\n')
397 397 ui.status(msg % (len(bmheads), repo._activebookmark))
398 398
399 399 def _statusotherbranchheads(ui, repo):
400 400 currentbranch = repo.dirstate.branch()
401 401 allheads = repo.branchheads(currentbranch, closed=True)
402 402 heads = repo.branchheads(currentbranch)
403 403 if repo.revs('%ln and parents()', allheads):
404 404 # we are on a head, even though it might be closed
405 405 #
406 406 # on closed otherheads
407 407 # ========= ==========
408 408 # o 0 all heads for current branch are closed
409 409 # N only descendant branch heads are closed
410 410 # x 0 there is only one non-closed branch head
411 411 # N there are some non-closed branch heads
412 412 # ========= ==========
413 413 otherheads = repo.revs('%ln - parents()', heads)
414 414 if repo['.'].closesbranch():
415 415 ui.warn(_('no open descendant heads on branch "%s", '
416 416 'updating to a closed head\n') %
417 417 (currentbranch))
418 418 if otherheads:
419 ui.warn(_('(committing will reopen the head, '
420 'use `hg heads .` to see %i other heads)\n') %
419 ui.warn(_("(committing will reopen the head, "
420 "use 'hg heads .' to see %i other heads)\n") %
421 421 (len(otherheads)))
422 422 else:
423 423 ui.warn(_('(committing will reopen branch "%s")\n') %
424 424 (currentbranch))
425 425 elif otherheads:
426 426 ui.status(_('%i other heads for branch "%s"\n') %
427 427 (len(otherheads), currentbranch))
428 428
429 429 def statusotherdests(ui, repo):
430 430 """Print message about other head"""
431 431 # XXX we should probably include a hint:
432 432 # - about what to do
433 433 # - how to see such heads
434 434 if repo._activebookmark:
435 435 _statusotherbook(ui, repo)
436 436 else:
437 437 _statusotherbranchheads(ui, repo)
@@ -1,392 +1,392 b''
1 1 # Construct the following history tree:
2 2 #
3 3 # @ 5:e1bb631146ca b1
4 4 # |
5 5 # o 4:a4fdb3b883c4 0:b608b9236435 b1
6 6 # |
7 7 # | o 3:4b57d2520816 1:44592833ba9f
8 8 # | |
9 9 # | | o 2:063f31070f65
10 10 # | |/
11 11 # | o 1:44592833ba9f
12 12 # |/
13 13 # o 0:b608b9236435
14 14
15 15 $ mkdir b1
16 16 $ cd b1
17 17 $ hg init
18 18 $ echo foo > foo
19 19 $ echo zero > a
20 20 $ hg init sub
21 21 $ echo suba > sub/suba
22 22 $ hg --cwd sub ci -Am addsuba
23 23 adding suba
24 24 $ echo 'sub = sub' > .hgsub
25 25 $ hg ci -qAm0
26 26 $ echo one > a ; hg ci -m1
27 27 $ echo two > a ; hg ci -m2
28 28 $ hg up -q 1
29 29 $ echo three > a ; hg ci -qm3
30 30 $ hg up -q 0
31 31 $ hg branch -q b1
32 32 $ echo four > a ; hg ci -qm4
33 33 $ echo five > a ; hg ci -qm5
34 34
35 35 Initial repo state:
36 36
37 37 $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
38 38 @ 5:ff252e8273df b1
39 39 |
40 40 o 4:d047485b3896 0:60829823a42a b1
41 41 |
42 42 | o 3:6efa171f091b 1:0786582aa4b1
43 43 | |
44 44 | | o 2:bd10386d478c
45 45 | |/
46 46 | o 1:0786582aa4b1
47 47 |/
48 48 o 0:60829823a42a
49 49
50 50
51 51 Make sure update doesn't assume b1 is a repository if invoked from outside:
52 52
53 53 $ cd ..
54 54 $ hg update b1
55 55 abort: no repository found in '$TESTTMP' (.hg not found)!
56 56 [255]
57 57 $ cd b1
58 58
59 59 Test helper functions:
60 60
61 61 $ revtest () {
62 62 > msg=$1
63 63 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
64 64 > startrev=$3
65 65 > targetrev=$4
66 66 > opt=$5
67 67 > hg up -qC $startrev
68 68 > test $dirtyflag = dirty && echo dirty > foo
69 69 > test $dirtyflag = dirtysub && echo dirty > sub/suba
70 70 > hg up $opt $targetrev
71 71 > hg parent --template 'parent={rev}\n'
72 72 > hg stat -S
73 73 > }
74 74
75 75 $ norevtest () {
76 76 > msg=$1
77 77 > dirtyflag=$2 # 'clean', 'dirty' or 'dirtysub'
78 78 > startrev=$3
79 79 > opt=$4
80 80 > hg up -qC $startrev
81 81 > test $dirtyflag = dirty && echo dirty > foo
82 82 > test $dirtyflag = dirtysub && echo dirty > sub/suba
83 83 > hg up $opt
84 84 > hg parent --template 'parent={rev}\n'
85 85 > hg stat -S
86 86 > }
87 87
88 88 Test cases are documented in a table in the update function of merge.py.
89 89 Cases are run as shown in that table, row by row.
90 90
91 91 $ norevtest 'none clean linear' clean 4
92 92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 93 parent=5
94 94
95 95 $ norevtest 'none clean same' clean 2
96 96 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 97 1 other heads for branch "default"
98 98 parent=2
99 99
100 100
101 101 $ revtest 'none clean linear' clean 1 2
102 102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 103 parent=2
104 104
105 105 $ revtest 'none clean same' clean 2 3
106 106 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107 parent=3
108 108
109 109 $ revtest 'none clean cross' clean 3 4
110 110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 111 parent=4
112 112
113 113
114 114 $ revtest 'none dirty linear' dirty 1 2
115 115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 116 parent=2
117 117 M foo
118 118
119 119 $ revtest 'none dirtysub linear' dirtysub 1 2
120 120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 121 parent=2
122 122 M sub/suba
123 123
124 124 $ revtest 'none dirty same' dirty 2 3
125 125 abort: uncommitted changes
126 126 (commit or update --clean to discard changes)
127 127 parent=2
128 128 M foo
129 129
130 130 $ revtest 'none dirtysub same' dirtysub 2 3
131 131 abort: uncommitted changes
132 132 (commit or update --clean to discard changes)
133 133 parent=2
134 134 M sub/suba
135 135
136 136 $ revtest 'none dirty cross' dirty 3 4
137 137 abort: uncommitted changes
138 138 (commit or update --clean to discard changes)
139 139 parent=3
140 140 M foo
141 141
142 142 $ norevtest 'none dirty cross' dirty 2
143 143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
144 144 1 other heads for branch "default"
145 145 parent=2
146 146 M foo
147 147
148 148 $ revtest 'none dirtysub cross' dirtysub 3 4
149 149 abort: uncommitted changes
150 150 (commit or update --clean to discard changes)
151 151 parent=3
152 152 M sub/suba
153 153
154 154 $ revtest '-C dirty linear' dirty 1 2 -C
155 155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 156 parent=2
157 157
158 158 $ revtest '-c dirty linear' dirty 1 2 -c
159 159 abort: uncommitted changes
160 160 parent=1
161 161 M foo
162 162
163 163 $ revtest '-c dirtysub linear' dirtysub 1 2 -c
164 164 abort: uncommitted changes in subrepository 'sub'
165 165 parent=1
166 166 M sub/suba
167 167
168 168 $ norevtest '-c clean same' clean 2 -c
169 169 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 170 1 other heads for branch "default"
171 171 parent=2
172 172
173 173 $ revtest '-cC dirty linear' dirty 1 2 -cC
174 174 abort: cannot specify both -c/--check and -C/--clean
175 175 parent=1
176 176 M foo
177 177
178 178 $ cd ..
179 179
180 180 Test updating with closed head
181 181 ---------------------------------------------------------------------
182 182
183 183 $ hg clone -U -q b1 closed-heads
184 184 $ cd closed-heads
185 185
186 186 Test updating if at least one non-closed branch head exists
187 187
188 188 if on the closed branch head:
189 189 - update to "."
190 190 - "updated to a closed branch head ...." message is displayed
191 191 - "N other heads for ...." message is displayed
192 192
193 193 $ hg update -q -C 3
194 194 $ hg commit --close-branch -m 6
195 195 $ norevtest "on closed branch head" clean 6
196 196 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 197 no open descendant heads on branch "default", updating to a closed head
198 (committing will reopen the head, use `hg heads .` to see 1 other heads)
198 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
199 199 parent=6
200 200
201 201 if descendant non-closed branch head exists, and it is only one branch head:
202 202 - update to it, even if its revision is less than closed one
203 203 - "N other heads for ...." message isn't displayed
204 204
205 205 $ norevtest "non-closed 2 should be chosen" clean 1
206 206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 207 parent=2
208 208
209 209 if all descendant branch heads are closed, but there is another branch head:
210 210 - update to the tipmost descendant head
211 211 - "updated to a closed branch head ...." message is displayed
212 212 - "N other heads for ...." message is displayed
213 213
214 214 $ norevtest "all descendant branch heads are closed" clean 3
215 215 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 216 no open descendant heads on branch "default", updating to a closed head
217 (committing will reopen the head, use `hg heads .` to see 1 other heads)
217 (committing will reopen the head, use 'hg heads .' to see 1 other heads)
218 218 parent=6
219 219
220 220 Test updating if all branch heads are closed
221 221
222 222 if on the closed branch head:
223 223 - update to "."
224 224 - "updated to a closed branch head ...." message is displayed
225 225 - "all heads of branch ...." message is displayed
226 226
227 227 $ hg update -q -C 2
228 228 $ hg commit --close-branch -m 7
229 229 $ norevtest "all heads of branch default are closed" clean 6
230 230 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 231 no open descendant heads on branch "default", updating to a closed head
232 232 (committing will reopen branch "default")
233 233 parent=6
234 234
235 235 if not on the closed branch head:
236 236 - update to the tipmost descendant (closed) head
237 237 - "updated to a closed branch head ...." message is displayed
238 238 - "all heads of branch ...." message is displayed
239 239
240 240 $ norevtest "all heads of branch default are closed" clean 1
241 241 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
242 242 no open descendant heads on branch "default", updating to a closed head
243 243 (committing will reopen branch "default")
244 244 parent=7
245 245
246 246 $ cd ..
247 247
248 248 Test updating if "default" branch doesn't exist and no revision is
249 249 checked out (= "default" is used as current branch)
250 250
251 251 $ hg init no-default-branch
252 252 $ cd no-default-branch
253 253
254 254 $ hg branch foobar
255 255 marked working directory as branch foobar
256 256 (branches are permanent and global, did you want a bookmark?)
257 257 $ echo a > a
258 258 $ hg commit -m "#0" -A
259 259 adding a
260 260 $ echo 1 >> a
261 261 $ hg commit -m "#1"
262 262 $ hg update -q 0
263 263 $ echo 3 >> a
264 264 $ hg commit -m "#2"
265 265 created new head
266 266 $ hg commit --close-branch -m "#3"
267 267
268 268 if there is at least one non-closed branch head:
269 269 - update to the tipmost branch head
270 270
271 271 $ norevtest "non-closed 1 should be chosen" clean null
272 272 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 273 parent=1
274 274
275 275 if all branch heads are closed
276 276 - update to "tip"
277 277 - "updated to a closed branch head ...." message is displayed
278 278 - "all heads for branch "XXXX" are closed" message is displayed
279 279
280 280 $ hg update -q -C 1
281 281 $ hg commit --close-branch -m "#4"
282 282
283 283 $ norevtest "all branches are closed" clean null
284 284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 285 no open descendant heads on branch "foobar", updating to a closed head
286 286 (committing will reopen branch "foobar")
287 287 parent=4
288 288
289 289 $ cd ../b1
290 290
291 291 Test obsolescence behavior
292 292 ---------------------------------------------------------------------
293 293
294 294 successors should be taken in account when checking head destination
295 295
296 296 $ cat << EOF >> $HGRCPATH
297 297 > [ui]
298 298 > logtemplate={rev}:{node|short} {desc|firstline}
299 299 > [experimental]
300 300 > evolution=createmarkers
301 301 > EOF
302 302
303 303 Test no-argument update to a successor of an obsoleted changeset
304 304
305 305 $ hg log -G
306 306 o 5:ff252e8273df 5
307 307 |
308 308 o 4:d047485b3896 4
309 309 |
310 310 | o 3:6efa171f091b 3
311 311 | |
312 312 | | o 2:bd10386d478c 2
313 313 | |/
314 314 | @ 1:0786582aa4b1 1
315 315 |/
316 316 o 0:60829823a42a 0
317 317
318 318 $ hg book bm -r 3
319 319 $ hg status
320 320 M foo
321 321
322 322 We add simple obsolescence marker between 3 and 4 (indirect successors)
323 323
324 324 $ hg id --debug -i -r 3
325 325 6efa171f091b00a3c35edc15d48c52a498929953
326 326 $ hg id --debug -i -r 4
327 327 d047485b3896813b2a624e86201983520f003206
328 328 $ hg debugobsolete 6efa171f091b00a3c35edc15d48c52a498929953 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
329 329 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa d047485b3896813b2a624e86201983520f003206
330 330
331 331 Test that 5 is detected as a valid destination from 3 and also accepts moving
332 332 the bookmark (issue4015)
333 333
334 334 $ hg up --quiet --hidden 3
335 335 $ hg up 5
336 336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 337 $ hg book bm
338 338 moving bookmark 'bm' forward from 6efa171f091b
339 339 $ hg bookmarks
340 340 * bm 5:ff252e8273df
341 341
342 342 Test that 4 is detected as the no-argument destination from 3 and also moves
343 343 the bookmark with it
344 344 $ hg up --quiet 0 # we should be able to update to 3 directly
345 345 $ hg up --quiet --hidden 3 # but not implemented yet.
346 346 $ hg book -f bm
347 347 $ hg up
348 348 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 349 updating bookmark bm
350 350 $ hg book
351 351 * bm 4:d047485b3896
352 352
353 353 Test that 5 is detected as a valid destination from 1
354 354 $ hg up --quiet 0 # we should be able to update to 3 directly
355 355 $ hg up --quiet --hidden 3 # but not implemented yet.
356 356 $ hg up 5
357 357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 358
359 359 Test that 5 is not detected as a valid destination from 2
360 360 $ hg up --quiet 0
361 361 $ hg up --quiet 2
362 362 $ hg up 5
363 363 abort: uncommitted changes
364 364 (commit or update --clean to discard changes)
365 365 [255]
366 366
367 367 Test that we don't crash when updating from a pruned changeset (i.e. has no
368 368 successors). Behavior should probably be that we update to the first
369 369 non-obsolete parent but that will be decided later.
370 370 $ hg id --debug -r 2
371 371 bd10386d478cd5a9faf2e604114c8e6da62d3889
372 372 $ hg up --quiet 0
373 373 $ hg up --quiet 2
374 374 $ hg debugobsolete bd10386d478cd5a9faf2e604114c8e6da62d3889
375 375 $ hg up
376 376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 377
378 378 Test experimental revset support
379 379
380 380 $ hg log -r '_destupdate()'
381 381 2:bd10386d478c 2 (no-eol)
382 382
383 383 Test that boolean flags allow --no-flag specification to override [defaults]
384 384 $ cat >> $HGRCPATH <<EOF
385 385 > [defaults]
386 386 > update = --check
387 387 > EOF
388 388 $ hg co 2
389 389 abort: uncommitted changes
390 390 [255]
391 391 $ hg co --no-check 2
392 392 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
General Comments 0
You need to be logged in to leave comments. Login now