##// END OF EJS Templates
bookmarks: disallow bookmarks named 'tip', '.', or 'null'...
Kevin Bullock -
r17816:19388ba7 default
parent child Browse files
Show More
@@ -1,284 +1,286 b''
1 1 # Mercurial bookmark support code
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
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 mercurial.i18n import _
9 9 from mercurial.node import hex
10 10 from mercurial import encoding, error, util, obsolete, phases
11 11 import errno, os
12 12
13 13 def checkvalid(mark):
14 14 for c in (':', '\0', '\n', '\r'):
15 15 if c in mark:
16 16 raise util.Abort(_("bookmark '%s' contains illegal "
17 17 "character" % mark))
18 if mark in ['tip', '.', 'null']:
19 raise util.Abort(_('the name \'%s\' is reserved') % mark)
18 20
19 21 def read(repo):
20 22 '''Parse .hg/bookmarks file and return a dictionary
21 23
22 24 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
23 25 in the .hg/bookmarks file.
24 26 Read the file and return a (name=>nodeid) dictionary
25 27 '''
26 28 bookmarks = {}
27 29 try:
28 30 for line in repo.opener('bookmarks'):
29 31 line = line.strip()
30 32 if not line:
31 33 continue
32 34 if ' ' not in line:
33 35 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
34 36 continue
35 37 sha, refspec = line.split(' ', 1)
36 38 refspec = encoding.tolocal(refspec)
37 39 try:
38 40 bookmarks[refspec] = repo.changelog.lookup(sha)
39 41 except LookupError:
40 42 pass
41 43 except IOError, inst:
42 44 if inst.errno != errno.ENOENT:
43 45 raise
44 46 return bookmarks
45 47
46 48 def readcurrent(repo):
47 49 '''Get the current bookmark
48 50
49 51 If we use gittishsh branches we have a current bookmark that
50 52 we are on. This function returns the name of the bookmark. It
51 53 is stored in .hg/bookmarks.current
52 54 '''
53 55 mark = None
54 56 try:
55 57 file = repo.opener('bookmarks.current')
56 58 except IOError, inst:
57 59 if inst.errno != errno.ENOENT:
58 60 raise
59 61 return None
60 62 try:
61 63 # No readline() in osutil.posixfile, reading everything is cheap
62 64 mark = encoding.tolocal((file.readlines() or [''])[0])
63 65 if mark == '' or mark not in repo._bookmarks:
64 66 mark = None
65 67 finally:
66 68 file.close()
67 69 return mark
68 70
69 71 def write(repo):
70 72 '''Write bookmarks
71 73
72 74 Write the given bookmark => hash dictionary to the .hg/bookmarks file
73 75 in a format equal to those of localtags.
74 76
75 77 We also store a backup of the previous state in undo.bookmarks that
76 78 can be copied back on rollback.
77 79 '''
78 80 refs = repo._bookmarks
79 81
80 82 if repo._bookmarkcurrent not in refs:
81 83 setcurrent(repo, None)
82 84 for mark in refs.keys():
83 85 checkvalid(mark)
84 86
85 87 wlock = repo.wlock()
86 88 try:
87 89
88 90 file = repo.opener('bookmarks', 'w', atomictemp=True)
89 91 for refspec, node in refs.iteritems():
90 92 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
91 93 file.close()
92 94
93 95 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
94 96 try:
95 97 os.utime(repo.sjoin('00changelog.i'), None)
96 98 except OSError:
97 99 pass
98 100
99 101 finally:
100 102 wlock.release()
101 103
102 104 def setcurrent(repo, mark):
103 105 '''Set the name of the bookmark that we are currently on
104 106
105 107 Set the name of the bookmark that we are on (hg update <bookmark>).
106 108 The name is recorded in .hg/bookmarks.current
107 109 '''
108 110 current = repo._bookmarkcurrent
109 111 if current == mark:
110 112 return
111 113
112 114 if mark not in repo._bookmarks:
113 115 mark = ''
114 116 checkvalid(mark)
115 117
116 118 wlock = repo.wlock()
117 119 try:
118 120 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
119 121 file.write(encoding.fromlocal(mark))
120 122 file.close()
121 123 finally:
122 124 wlock.release()
123 125 repo._bookmarkcurrent = mark
124 126
125 127 def unsetcurrent(repo):
126 128 wlock = repo.wlock()
127 129 try:
128 130 try:
129 131 util.unlink(repo.join('bookmarks.current'))
130 132 repo._bookmarkcurrent = None
131 133 except OSError, inst:
132 134 if inst.errno != errno.ENOENT:
133 135 raise
134 136 finally:
135 137 wlock.release()
136 138
137 139 def updatecurrentbookmark(repo, oldnode, curbranch):
138 140 try:
139 141 return update(repo, oldnode, repo.branchtip(curbranch))
140 142 except error.RepoLookupError:
141 143 if curbranch == "default": # no default branch!
142 144 return update(repo, oldnode, repo.lookup("tip"))
143 145 else:
144 146 raise util.Abort(_("branch %s not found") % curbranch)
145 147
146 148 def update(repo, parents, node):
147 149 marks = repo._bookmarks
148 150 update = False
149 151 cur = repo._bookmarkcurrent
150 152 if not cur:
151 153 return False
152 154
153 155 toupdate = [b for b in marks if b.split('@', 1)[0] == cur.split('@', 1)[0]]
154 156 for mark in toupdate:
155 157 if mark and marks[mark] in parents:
156 158 old = repo[marks[mark]]
157 159 new = repo[node]
158 160 if old.descendant(new) and mark == cur:
159 161 marks[cur] = new.node()
160 162 update = True
161 163 if mark != cur:
162 164 del marks[mark]
163 165 if update:
164 166 repo._writebookmarks(marks)
165 167 return update
166 168
167 169 def listbookmarks(repo):
168 170 # We may try to list bookmarks on a repo type that does not
169 171 # support it (e.g., statichttprepository).
170 172 marks = getattr(repo, '_bookmarks', {})
171 173
172 174 d = {}
173 175 for k, v in marks.iteritems():
174 176 # don't expose local divergent bookmarks
175 177 if '@' not in k or k.endswith('@'):
176 178 d[k] = hex(v)
177 179 return d
178 180
179 181 def pushbookmark(repo, key, old, new):
180 182 w = repo.wlock()
181 183 try:
182 184 marks = repo._bookmarks
183 185 if hex(marks.get(key, '')) != old:
184 186 return False
185 187 if new == '':
186 188 del marks[key]
187 189 else:
188 190 if new not in repo:
189 191 return False
190 192 marks[key] = repo[new].node()
191 193 write(repo)
192 194 return True
193 195 finally:
194 196 w.release()
195 197
196 198 def updatefromremote(ui, repo, remote, path):
197 199 ui.debug("checking for updated bookmarks\n")
198 200 rb = remote.listkeys('bookmarks')
199 201 changed = False
200 202 for k in rb.keys():
201 203 if k in repo._bookmarks:
202 204 nr, nl = rb[k], repo._bookmarks[k]
203 205 if nr in repo:
204 206 cr = repo[nr]
205 207 cl = repo[nl]
206 208 if cl.rev() >= cr.rev():
207 209 continue
208 210 if validdest(repo, cl, cr):
209 211 repo._bookmarks[k] = cr.node()
210 212 changed = True
211 213 ui.status(_("updating bookmark %s\n") % k)
212 214 else:
213 215 if k == '@':
214 216 kd = ''
215 217 else:
216 218 kd = k
217 219 # find a unique @ suffix
218 220 for x in range(1, 100):
219 221 n = '%s@%d' % (kd, x)
220 222 if n not in repo._bookmarks:
221 223 break
222 224 # try to use an @pathalias suffix
223 225 # if an @pathalias already exists, we overwrite (update) it
224 226 for p, u in ui.configitems("paths"):
225 227 if path == u:
226 228 n = '%s@%s' % (kd, p)
227 229
228 230 repo._bookmarks[n] = cr.node()
229 231 changed = True
230 232 ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
231 233 elif rb[k] in repo:
232 234 # add remote bookmarks for changes we already have
233 235 repo._bookmarks[k] = repo[rb[k]].node()
234 236 changed = True
235 237 ui.status(_("adding remote bookmark %s\n") % k)
236 238
237 239 if changed:
238 240 write(repo)
239 241
240 242 def diff(ui, dst, src):
241 243 ui.status(_("searching for changed bookmarks\n"))
242 244
243 245 smarks = src.listkeys('bookmarks')
244 246 dmarks = dst.listkeys('bookmarks')
245 247
246 248 diff = sorted(set(smarks) - set(dmarks))
247 249 for k in diff:
248 250 mark = ui.debugflag and smarks[k] or smarks[k][:12]
249 251 ui.write(" %-25s %s\n" % (k, mark))
250 252
251 253 if len(diff) <= 0:
252 254 ui.status(_("no changed bookmarks found\n"))
253 255 return 1
254 256 return 0
255 257
256 258 def validdest(repo, old, new):
257 259 """Is the new bookmark destination a valid update from the old one"""
258 260 if old == new:
259 261 # Old == new -> nothing to update.
260 262 return False
261 263 elif not old:
262 264 # old is nullrev, anything is valid.
263 265 # (new != nullrev has been excluded by the previous check)
264 266 return True
265 267 elif repo.obsstore:
266 268 # We only need this complicated logic if there is obsolescence
267 269 # XXX will probably deserve an optimised revset.
268 270
269 271 validdests = set([old])
270 272 plen = -1
271 273 # compute the whole set of successors or descendants
272 274 while len(validdests) != plen:
273 275 plen = len(validdests)
274 276 succs = set(c.node() for c in validdests)
275 277 for c in validdests:
276 278 if c.phase() > phases.public:
277 279 # obsolescence marker does not apply to public changeset
278 280 succs.update(obsolete.anysuccessors(repo.obsstore,
279 281 c.node()))
280 282 validdests = set(repo.set('%ln::', succs))
281 283 validdests.remove(old)
282 284 return new in validdests
283 285 else:
284 286 return old.descendant(new)
@@ -1,520 +1,535 b''
1 1 $ hg init
2 2
3 3 no bookmarks
4 4
5 5 $ hg bookmarks
6 6 no bookmarks set
7 7
8 8 bookmark rev -1
9 9
10 10 $ hg bookmark X
11 11
12 12 list bookmarks
13 13
14 14 $ hg bookmarks
15 15 * X -1:000000000000
16 16
17 17 list bookmarks with color
18 18
19 19 $ hg --config extensions.color= --config color.mode=ansi \
20 20 > bookmarks --color=always
21 21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22 22
23 23 $ echo a > a
24 24 $ hg add a
25 25 $ hg commit -m 0
26 26
27 27 bookmark X moved to rev 0
28 28
29 29 $ hg bookmarks
30 30 * X 0:f7b1eb17ad24
31 31
32 32 look up bookmark
33 33
34 34 $ hg log -r X
35 35 changeset: 0:f7b1eb17ad24
36 36 bookmark: X
37 37 tag: tip
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: 0
41 41
42 42
43 43 second bookmark for rev 0
44 44
45 45 $ hg bookmark X2
46 46
47 47 bookmark rev -1 again
48 48
49 49 $ hg bookmark -r null Y
50 50
51 51 list bookmarks
52 52
53 53 $ hg bookmarks
54 54 X 0:f7b1eb17ad24
55 55 * X2 0:f7b1eb17ad24
56 56 Y -1:000000000000
57 57
58 58 $ echo b > b
59 59 $ hg add b
60 60 $ hg commit -m 1
61 61
62 62 bookmarks revset
63 63
64 64 $ hg log -r 'bookmark()'
65 65 changeset: 0:f7b1eb17ad24
66 66 bookmark: X
67 67 user: test
68 68 date: Thu Jan 01 00:00:00 1970 +0000
69 69 summary: 0
70 70
71 71 changeset: 1:925d80f479bb
72 72 bookmark: X2
73 73 tag: tip
74 74 user: test
75 75 date: Thu Jan 01 00:00:00 1970 +0000
76 76 summary: 1
77 77
78 78 $ hg log -r 'bookmark(Y)'
79 79 $ hg log -r 'bookmark(X2)'
80 80 changeset: 1:925d80f479bb
81 81 bookmark: X2
82 82 tag: tip
83 83 user: test
84 84 date: Thu Jan 01 00:00:00 1970 +0000
85 85 summary: 1
86 86
87 87 $ hg log -r 'bookmark("re:X")'
88 88 changeset: 0:f7b1eb17ad24
89 89 bookmark: X
90 90 user: test
91 91 date: Thu Jan 01 00:00:00 1970 +0000
92 92 summary: 0
93 93
94 94 changeset: 1:925d80f479bb
95 95 bookmark: X2
96 96 tag: tip
97 97 user: test
98 98 date: Thu Jan 01 00:00:00 1970 +0000
99 99 summary: 1
100 100
101 101 $ hg log -r 'bookmark(unknown)'
102 102 abort: bookmark 'unknown' does not exist
103 103 [255]
104 104
105 105 $ hg help revsets | grep 'bookmark('
106 106 "bookmark([name])"
107 107
108 108 bookmarks X and X2 moved to rev 1, Y at rev -1
109 109
110 110 $ hg bookmarks
111 111 X 0:f7b1eb17ad24
112 112 * X2 1:925d80f479bb
113 113 Y -1:000000000000
114 114
115 115 bookmark rev 0 again
116 116
117 117 $ hg bookmark -r 0 Z
118 118
119 119 $ hg update X
120 120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 121 $ echo c > c
122 122 $ hg add c
123 123 $ hg commit -m 2
124 124 created new head
125 125
126 126 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
127 127
128 128 $ hg bookmarks
129 129 * X 2:db815d6d32e6
130 130 X2 1:925d80f479bb
131 131 Y -1:000000000000
132 132 Z 0:f7b1eb17ad24
133 133
134 134 rename nonexistent bookmark
135 135
136 136 $ hg bookmark -m A B
137 137 abort: bookmark 'A' does not exist
138 138 [255]
139 139
140 140 rename to existent bookmark
141 141
142 142 $ hg bookmark -m X Y
143 143 abort: bookmark 'Y' already exists (use -f to force)
144 144 [255]
145 145
146 146 force rename to existent bookmark
147 147
148 148 $ hg bookmark -f -m X Y
149 149
150 150 list bookmarks
151 151
152 152 $ hg bookmark
153 153 X2 1:925d80f479bb
154 154 * Y 2:db815d6d32e6
155 155 Z 0:f7b1eb17ad24
156 156
157 157 bookmarks from a revset
158 158 $ hg bookmark -r '.^1' REVSET
159 159 $ hg bookmark -r ':tip' TIP
160 160 $ hg bookmarks
161 161 REVSET 0:f7b1eb17ad24
162 162 * TIP 2:db815d6d32e6
163 163 X2 1:925d80f479bb
164 164 Y 2:db815d6d32e6
165 165 Z 0:f7b1eb17ad24
166 166
167 167 $ hg bookmark -d REVSET
168 168 $ hg bookmark -d TIP
169 169
170 170 rename without new name
171 171
172 172 $ hg bookmark -m Y
173 173 abort: new bookmark name required
174 174 [255]
175 175
176 176 delete without name
177 177
178 178 $ hg bookmark -d
179 179 abort: bookmark name required
180 180 [255]
181 181
182 182 delete nonexistent bookmark
183 183
184 184 $ hg bookmark -d A
185 185 abort: bookmark 'A' does not exist
186 186 [255]
187 187
188 188 bookmark name with spaces should be stripped
189 189
190 190 $ hg bookmark ' x y '
191 191
192 192 list bookmarks
193 193
194 194 $ hg bookmarks
195 195 X2 1:925d80f479bb
196 196 Y 2:db815d6d32e6
197 197 Z 0:f7b1eb17ad24
198 198 * x y 2:db815d6d32e6
199 199
200 200 look up stripped bookmark name
201 201
202 202 $ hg log -r '"x y"'
203 203 changeset: 2:db815d6d32e6
204 204 bookmark: Y
205 205 bookmark: x y
206 206 tag: tip
207 207 parent: 0:f7b1eb17ad24
208 208 user: test
209 209 date: Thu Jan 01 00:00:00 1970 +0000
210 210 summary: 2
211 211
212 212
213 213 reject bookmark name with newline
214 214
215 215 $ hg bookmark '
216 216 > '
217 217 abort: bookmark names cannot consist entirely of whitespace
218 218 [255]
219 219
220 220 $ hg bookmark -m Z '
221 221 > '
222 222 abort: bookmark names cannot consist entirely of whitespace
223 223 [255]
224 224
225 bookmark with reserved name
226
227 $ hg bookmark tip
228 abort: the name 'tip' is reserved
229 [255]
230
231 $ hg bookmark .
232 abort: the name '.' is reserved
233 [255]
234
235 $ hg bookmark null
236 abort: the name 'null' is reserved
237 [255]
238
239
225 240 bookmark with existing name
226 241
227 242 $ hg bookmark Z
228 243 abort: bookmark 'Z' already exists (use -f to force)
229 244 [255]
230 245
231 246 $ hg bookmark -m Y Z
232 247 abort: bookmark 'Z' already exists (use -f to force)
233 248 [255]
234 249
235 250 bookmark with name of branch
236 251
237 252 $ hg bookmark default
238 253 abort: a bookmark cannot have the name of an existing branch
239 254 [255]
240 255
241 256 $ hg bookmark -m Y default
242 257 abort: a bookmark cannot have the name of an existing branch
243 258 [255]
244 259
245 260 incompatible options
246 261
247 262 $ hg bookmark -m Y -d Z
248 263 abort: --delete and --rename are incompatible
249 264 [255]
250 265
251 266 $ hg bookmark -r 1 -d Z
252 267 abort: --rev is incompatible with --delete
253 268 [255]
254 269
255 270 $ hg bookmark -r 1 -m Z Y
256 271 abort: --rev is incompatible with --rename
257 272 [255]
258 273
259 274 force bookmark with existing name
260 275
261 276 $ hg bookmark -f Z
262 277
263 278 list bookmarks
264 279
265 280 $ hg bookmark
266 281 X2 1:925d80f479bb
267 282 Y 2:db815d6d32e6
268 283 * Z 2:db815d6d32e6
269 284 x y 2:db815d6d32e6
270 285
271 286 revision but no bookmark name
272 287
273 288 $ hg bookmark -r .
274 289 abort: bookmark name required
275 290 [255]
276 291
277 292 bookmark name with whitespace only
278 293
279 294 $ hg bookmark ' '
280 295 abort: bookmark names cannot consist entirely of whitespace
281 296 [255]
282 297
283 298 $ hg bookmark -m Y ' '
284 299 abort: bookmark names cannot consist entirely of whitespace
285 300 [255]
286 301
287 302 invalid bookmark
288 303
289 304 $ hg bookmark 'foo:bar'
290 305 abort: bookmark 'foo:bar' contains illegal character
291 306 [255]
292 307
293 308 the bookmark extension should be ignored now that it is part of core
294 309
295 310 $ echo "[extensions]" >> $HGRCPATH
296 311 $ echo "bookmarks=" >> $HGRCPATH
297 312 $ hg bookmarks
298 313 X2 1:925d80f479bb
299 314 Y 2:db815d6d32e6
300 315 * Z 2:db815d6d32e6
301 316 x y 2:db815d6d32e6
302 317
303 318 test summary
304 319
305 320 $ hg summary
306 321 parent: 2:db815d6d32e6 tip
307 322 2
308 323 branch: default
309 324 bookmarks: *Z Y x y
310 325 commit: (clean)
311 326 update: 1 new changesets, 2 branch heads (merge)
312 327
313 328 test id
314 329
315 330 $ hg id
316 331 db815d6d32e6 tip Y/Z/x y
317 332
318 333 test rollback
319 334
320 335 $ echo foo > f1
321 336 $ hg ci -Amr
322 337 adding f1
323 338 $ hg bookmark -f Y -r 1
324 339 $ hg bookmark -f Z -r 1
325 340 $ hg rollback
326 341 repository tip rolled back to revision 2 (undo commit)
327 342 working directory now based on revision 2
328 343 $ hg bookmarks
329 344 X2 1:925d80f479bb
330 345 Y 2:db815d6d32e6
331 346 * Z 2:db815d6d32e6
332 347 x y 2:db815d6d32e6
333 348
334 349 test clone
335 350
336 351 $ hg bookmark -r 2 -i @
337 352 $ hg bookmark -r 2 -i a@
338 353 $ hg bookmarks
339 354 @ 2:db815d6d32e6
340 355 X2 1:925d80f479bb
341 356 Y 2:db815d6d32e6
342 357 * Z 2:db815d6d32e6
343 358 a@ 2:db815d6d32e6
344 359 x y 2:db815d6d32e6
345 360 $ hg clone . cloned-bookmarks
346 361 updating to branch default
347 362 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 363 $ hg -R cloned-bookmarks bookmarks
349 364 @ 2:db815d6d32e6
350 365 X2 1:925d80f479bb
351 366 Y 2:db815d6d32e6
352 367 Z 2:db815d6d32e6
353 368 a@ 2:db815d6d32e6
354 369 x y 2:db815d6d32e6
355 370
356 371 test clone with pull protocol
357 372
358 373 $ hg clone --pull . cloned-bookmarks-pull
359 374 requesting all changes
360 375 adding changesets
361 376 adding manifests
362 377 adding file changes
363 378 added 3 changesets with 3 changes to 3 files (+1 heads)
364 379 updating to branch default
365 380 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
366 381 $ hg -R cloned-bookmarks-pull bookmarks
367 382 @ 2:db815d6d32e6
368 383 X2 1:925d80f479bb
369 384 Y 2:db815d6d32e6
370 385 Z 2:db815d6d32e6
371 386 a@ 2:db815d6d32e6
372 387 x y 2:db815d6d32e6
373 388
374 389 $ hg bookmark -d @
375 390 $ hg bookmark -d a@
376 391
377 392 test clone with a specific revision
378 393
379 394 $ hg clone -r 925d80 . cloned-bookmarks-rev
380 395 adding changesets
381 396 adding manifests
382 397 adding file changes
383 398 added 2 changesets with 2 changes to 2 files
384 399 updating to branch default
385 400 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 401 $ hg -R cloned-bookmarks-rev bookmarks
387 402 X2 1:925d80f479bb
388 403
389 404 test clone with update to a bookmark
390 405
391 406 $ hg clone -u Z . cloned-bookmarks-update
392 407 updating to branch default
393 408 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
394 409 $ hg -R cloned-bookmarks-update bookmarks
395 410 X2 1:925d80f479bb
396 411 Y 2:db815d6d32e6
397 412 * Z 2:db815d6d32e6
398 413 x y 2:db815d6d32e6
399 414
400 415 create bundle with two heads
401 416
402 417 $ hg clone . tobundle
403 418 updating to branch default
404 419 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 420 $ echo x > tobundle/x
406 421 $ hg -R tobundle add tobundle/x
407 422 $ hg -R tobundle commit -m'x'
408 423 $ hg -R tobundle update -r -2
409 424 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
410 425 $ echo y > tobundle/y
411 426 $ hg -R tobundle branch test
412 427 marked working directory as branch test
413 428 (branches are permanent and global, did you want a bookmark?)
414 429 $ hg -R tobundle add tobundle/y
415 430 $ hg -R tobundle commit -m'y'
416 431 $ hg -R tobundle bundle tobundle.hg
417 432 searching for changes
418 433 2 changesets found
419 434 $ hg unbundle tobundle.hg
420 435 adding changesets
421 436 adding manifests
422 437 adding file changes
423 438 added 2 changesets with 2 changes to 2 files (+1 heads)
424 439 (run 'hg heads' to see heads, 'hg merge' to merge)
425 440 $ hg update
426 441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 442 $ hg bookmarks
428 443 X2 1:925d80f479bb
429 444 Y 2:db815d6d32e6
430 445 * Z 3:125c9a1d6df6
431 446 x y 2:db815d6d32e6
432 447
433 448 test wrongly formated bookmark
434 449
435 450 $ echo '' >> .hg/bookmarks
436 451 $ hg bookmarks
437 452 X2 1:925d80f479bb
438 453 Y 2:db815d6d32e6
439 454 * Z 3:125c9a1d6df6
440 455 x y 2:db815d6d32e6
441 456 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
442 457 $ hg bookmarks
443 458 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
444 459 X2 1:925d80f479bb
445 460 Y 2:db815d6d32e6
446 461 * Z 3:125c9a1d6df6
447 462 x y 2:db815d6d32e6
448 463
449 464 test missing revisions
450 465
451 466 $ echo "925d80f479bc z" > .hg/bookmarks
452 467 $ hg book
453 468 no bookmarks set
454 469
455 470 test stripping a non-checked-out but bookmarked revision
456 471
457 472 $ hg --config extensions.graphlog= log --graph
458 473 o changeset: 4:9ba5f110a0b3
459 474 | branch: test
460 475 | tag: tip
461 476 | parent: 2:db815d6d32e6
462 477 | user: test
463 478 | date: Thu Jan 01 00:00:00 1970 +0000
464 479 | summary: y
465 480 |
466 481 | @ changeset: 3:125c9a1d6df6
467 482 |/ user: test
468 483 | date: Thu Jan 01 00:00:00 1970 +0000
469 484 | summary: x
470 485 |
471 486 o changeset: 2:db815d6d32e6
472 487 | parent: 0:f7b1eb17ad24
473 488 | user: test
474 489 | date: Thu Jan 01 00:00:00 1970 +0000
475 490 | summary: 2
476 491 |
477 492 | o changeset: 1:925d80f479bb
478 493 |/ user: test
479 494 | date: Thu Jan 01 00:00:00 1970 +0000
480 495 | summary: 1
481 496 |
482 497 o changeset: 0:f7b1eb17ad24
483 498 user: test
484 499 date: Thu Jan 01 00:00:00 1970 +0000
485 500 summary: 0
486 501
487 502 $ hg book should-end-on-two
488 503 $ hg co --clean 4
489 504 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
490 505 $ hg book four
491 506 $ hg --config extensions.mq= strip 3
492 507 saved backup bundle to * (glob)
493 508 should-end-on-two should end up pointing to revision 2, as that's the
494 509 tipmost surviving ancestor of the stripped revision.
495 510 $ hg --config extensions.graphlog= log --graph
496 511 @ changeset: 3:9ba5f110a0b3
497 512 | branch: test
498 513 | bookmark: four
499 514 | tag: tip
500 515 | user: test
501 516 | date: Thu Jan 01 00:00:00 1970 +0000
502 517 | summary: y
503 518 |
504 519 o changeset: 2:db815d6d32e6
505 520 | bookmark: should-end-on-two
506 521 | parent: 0:f7b1eb17ad24
507 522 | user: test
508 523 | date: Thu Jan 01 00:00:00 1970 +0000
509 524 | summary: 2
510 525 |
511 526 | o changeset: 1:925d80f479bb
512 527 |/ user: test
513 528 | date: Thu Jan 01 00:00:00 1970 +0000
514 529 | summary: 1
515 530 |
516 531 o changeset: 0:f7b1eb17ad24
517 532 user: test
518 533 date: Thu Jan 01 00:00:00 1970 +0000
519 534 summary: 0
520 535
General Comments 0
You need to be logged in to leave comments. Login now