##// END OF EJS Templates
bookmarks: abort 'push -B .' when no active bookmark
liscju -
r29354:af849596 default
parent child Browse files
Show More
@@ -1,606 +1,610 b''
1 # Mercurial bookmark support code
1 # Mercurial bookmark support code
2 #
2 #
3 # Copyright 2008 David Soria Parra <dsp@php.net>
3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import os
11 import os
12
12
13 from .i18n import _
13 from .i18n import _
14 from .node import (
14 from .node import (
15 bin,
15 bin,
16 hex,
16 hex,
17 )
17 )
18 from . import (
18 from . import (
19 encoding,
19 encoding,
20 error,
20 lock as lockmod,
21 lock as lockmod,
21 obsolete,
22 obsolete,
22 util,
23 util,
23 )
24 )
24
25
25 def _getbkfile(repo):
26 def _getbkfile(repo):
26 """Hook so that extensions that mess with the store can hook bm storage.
27 """Hook so that extensions that mess with the store can hook bm storage.
27
28
28 For core, this just handles wether we should see pending
29 For core, this just handles wether we should see pending
29 bookmarks or the committed ones. Other extensions (like share)
30 bookmarks or the committed ones. Other extensions (like share)
30 may need to tweak this behavior further.
31 may need to tweak this behavior further.
31 """
32 """
32 bkfile = None
33 bkfile = None
33 if 'HG_PENDING' in os.environ:
34 if 'HG_PENDING' in os.environ:
34 try:
35 try:
35 bkfile = repo.vfs('bookmarks.pending')
36 bkfile = repo.vfs('bookmarks.pending')
36 except IOError as inst:
37 except IOError as inst:
37 if inst.errno != errno.ENOENT:
38 if inst.errno != errno.ENOENT:
38 raise
39 raise
39 if bkfile is None:
40 if bkfile is None:
40 bkfile = repo.vfs('bookmarks')
41 bkfile = repo.vfs('bookmarks')
41 return bkfile
42 return bkfile
42
43
43
44
44 class bmstore(dict):
45 class bmstore(dict):
45 """Storage for bookmarks.
46 """Storage for bookmarks.
46
47
47 This object should do all bookmark-related reads and writes, so
48 This object should do all bookmark-related reads and writes, so
48 that it's fairly simple to replace the storage underlying
49 that it's fairly simple to replace the storage underlying
49 bookmarks without having to clone the logic surrounding
50 bookmarks without having to clone the logic surrounding
50 bookmarks. This type also should manage the active bookmark, if
51 bookmarks. This type also should manage the active bookmark, if
51 any.
52 any.
52
53
53 This particular bmstore implementation stores bookmarks as
54 This particular bmstore implementation stores bookmarks as
54 {hash}\s{name}\n (the same format as localtags) in
55 {hash}\s{name}\n (the same format as localtags) in
55 .hg/bookmarks. The mapping is stored as {name: nodeid}.
56 .hg/bookmarks. The mapping is stored as {name: nodeid}.
56 """
57 """
57
58
58 def __init__(self, repo):
59 def __init__(self, repo):
59 dict.__init__(self)
60 dict.__init__(self)
60 self._repo = repo
61 self._repo = repo
61 try:
62 try:
62 bkfile = _getbkfile(repo)
63 bkfile = _getbkfile(repo)
63 for line in bkfile:
64 for line in bkfile:
64 line = line.strip()
65 line = line.strip()
65 if not line:
66 if not line:
66 continue
67 continue
67 if ' ' not in line:
68 if ' ' not in line:
68 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
69 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
69 % line)
70 % line)
70 continue
71 continue
71 sha, refspec = line.split(' ', 1)
72 sha, refspec = line.split(' ', 1)
72 refspec = encoding.tolocal(refspec)
73 refspec = encoding.tolocal(refspec)
73 try:
74 try:
74 self[refspec] = repo.changelog.lookup(sha)
75 self[refspec] = repo.changelog.lookup(sha)
75 except LookupError:
76 except LookupError:
76 pass
77 pass
77 except IOError as inst:
78 except IOError as inst:
78 if inst.errno != errno.ENOENT:
79 if inst.errno != errno.ENOENT:
79 raise
80 raise
80 self._clean = True
81 self._clean = True
81 self._active = _readactive(repo, self)
82 self._active = _readactive(repo, self)
82 self._aclean = True
83 self._aclean = True
83
84
84 @property
85 @property
85 def active(self):
86 def active(self):
86 return self._active
87 return self._active
87
88
88 @active.setter
89 @active.setter
89 def active(self, mark):
90 def active(self, mark):
90 if mark is not None and mark not in self:
91 if mark is not None and mark not in self:
91 raise AssertionError('bookmark %s does not exist!' % mark)
92 raise AssertionError('bookmark %s does not exist!' % mark)
92
93
93 self._active = mark
94 self._active = mark
94 self._aclean = False
95 self._aclean = False
95
96
96 def __setitem__(self, *args, **kwargs):
97 def __setitem__(self, *args, **kwargs):
97 self._clean = False
98 self._clean = False
98 return dict.__setitem__(self, *args, **kwargs)
99 return dict.__setitem__(self, *args, **kwargs)
99
100
100 def __delitem__(self, key):
101 def __delitem__(self, key):
101 self._clean = False
102 self._clean = False
102 return dict.__delitem__(self, key)
103 return dict.__delitem__(self, key)
103
104
104 def recordchange(self, tr):
105 def recordchange(self, tr):
105 """record that bookmarks have been changed in a transaction
106 """record that bookmarks have been changed in a transaction
106
107
107 The transaction is then responsible for updating the file content."""
108 The transaction is then responsible for updating the file content."""
108 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
109 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
109 location='plain')
110 location='plain')
110 tr.hookargs['bookmark_moved'] = '1'
111 tr.hookargs['bookmark_moved'] = '1'
111
112
112 def _writerepo(self, repo):
113 def _writerepo(self, repo):
113 """Factored out for extensibility"""
114 """Factored out for extensibility"""
114 rbm = repo._bookmarks
115 rbm = repo._bookmarks
115 if rbm.active not in self:
116 if rbm.active not in self:
116 rbm.active = None
117 rbm.active = None
117 rbm._writeactive()
118 rbm._writeactive()
118
119
119 with repo.wlock():
120 with repo.wlock():
120 file_ = repo.vfs('bookmarks', 'w', atomictemp=True,
121 file_ = repo.vfs('bookmarks', 'w', atomictemp=True,
121 checkambig=True)
122 checkambig=True)
122 try:
123 try:
123 self._write(file_)
124 self._write(file_)
124 except: # re-raises
125 except: # re-raises
125 file_.discard()
126 file_.discard()
126 raise
127 raise
127 finally:
128 finally:
128 file_.close()
129 file_.close()
129
130
130 def _writeactive(self):
131 def _writeactive(self):
131 if self._aclean:
132 if self._aclean:
132 return
133 return
133 with self._repo.wlock():
134 with self._repo.wlock():
134 if self._active is not None:
135 if self._active is not None:
135 f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
136 f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
136 checkambig=True)
137 checkambig=True)
137 try:
138 try:
138 f.write(encoding.fromlocal(self._active))
139 f.write(encoding.fromlocal(self._active))
139 finally:
140 finally:
140 f.close()
141 f.close()
141 else:
142 else:
142 try:
143 try:
143 self._repo.vfs.unlink('bookmarks.current')
144 self._repo.vfs.unlink('bookmarks.current')
144 except OSError as inst:
145 except OSError as inst:
145 if inst.errno != errno.ENOENT:
146 if inst.errno != errno.ENOENT:
146 raise
147 raise
147 self._aclean = True
148 self._aclean = True
148
149
149 def _write(self, fp):
150 def _write(self, fp):
150 for name, node in self.iteritems():
151 for name, node in self.iteritems():
151 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
152 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
152 self._clean = True
153 self._clean = True
153 self._repo.invalidatevolatilesets()
154 self._repo.invalidatevolatilesets()
154
155
155 def expandname(self, bname):
156 def expandname(self, bname):
156 if bname == '.':
157 if bname == '.':
158 if self.active:
157 return self.active
159 return self.active
160 else:
161 raise error.Abort(_("no active bookmark"))
158 return bname
162 return bname
159
163
160 def _readactive(repo, marks):
164 def _readactive(repo, marks):
161 """
165 """
162 Get the active bookmark. We can have an active bookmark that updates
166 Get the active bookmark. We can have an active bookmark that updates
163 itself as we commit. This function returns the name of that bookmark.
167 itself as we commit. This function returns the name of that bookmark.
164 It is stored in .hg/bookmarks.current
168 It is stored in .hg/bookmarks.current
165 """
169 """
166 mark = None
170 mark = None
167 try:
171 try:
168 file = repo.vfs('bookmarks.current')
172 file = repo.vfs('bookmarks.current')
169 except IOError as inst:
173 except IOError as inst:
170 if inst.errno != errno.ENOENT:
174 if inst.errno != errno.ENOENT:
171 raise
175 raise
172 return None
176 return None
173 try:
177 try:
174 # No readline() in osutil.posixfile, reading everything is
178 # No readline() in osutil.posixfile, reading everything is
175 # cheap.
179 # cheap.
176 # Note that it's possible for readlines() here to raise
180 # Note that it's possible for readlines() here to raise
177 # IOError, since we might be reading the active mark over
181 # IOError, since we might be reading the active mark over
178 # static-http which only tries to load the file when we try
182 # static-http which only tries to load the file when we try
179 # to read from it.
183 # to read from it.
180 mark = encoding.tolocal((file.readlines() or [''])[0])
184 mark = encoding.tolocal((file.readlines() or [''])[0])
181 if mark == '' or mark not in marks:
185 if mark == '' or mark not in marks:
182 mark = None
186 mark = None
183 except IOError as inst:
187 except IOError as inst:
184 if inst.errno != errno.ENOENT:
188 if inst.errno != errno.ENOENT:
185 raise
189 raise
186 return None
190 return None
187 finally:
191 finally:
188 file.close()
192 file.close()
189 return mark
193 return mark
190
194
191 def activate(repo, mark):
195 def activate(repo, mark):
192 """
196 """
193 Set the given bookmark to be 'active', meaning that this bookmark will
197 Set the given bookmark to be 'active', meaning that this bookmark will
194 follow new commits that are made.
198 follow new commits that are made.
195 The name is recorded in .hg/bookmarks.current
199 The name is recorded in .hg/bookmarks.current
196 """
200 """
197 repo._bookmarks.active = mark
201 repo._bookmarks.active = mark
198 repo._bookmarks._writeactive()
202 repo._bookmarks._writeactive()
199
203
200 def deactivate(repo):
204 def deactivate(repo):
201 """
205 """
202 Unset the active bookmark in this repository.
206 Unset the active bookmark in this repository.
203 """
207 """
204 repo._bookmarks.active = None
208 repo._bookmarks.active = None
205 repo._bookmarks._writeactive()
209 repo._bookmarks._writeactive()
206
210
207 def isactivewdirparent(repo):
211 def isactivewdirparent(repo):
208 """
212 """
209 Tell whether the 'active' bookmark (the one that follows new commits)
213 Tell whether the 'active' bookmark (the one that follows new commits)
210 points to one of the parents of the current working directory (wdir).
214 points to one of the parents of the current working directory (wdir).
211
215
212 While this is normally the case, it can on occasion be false; for example,
216 While this is normally the case, it can on occasion be false; for example,
213 immediately after a pull, the active bookmark can be moved to point
217 immediately after a pull, the active bookmark can be moved to point
214 to a place different than the wdir. This is solved by running `hg update`.
218 to a place different than the wdir. This is solved by running `hg update`.
215 """
219 """
216 mark = repo._activebookmark
220 mark = repo._activebookmark
217 marks = repo._bookmarks
221 marks = repo._bookmarks
218 parents = [p.node() for p in repo[None].parents()]
222 parents = [p.node() for p in repo[None].parents()]
219 return (mark in marks and marks[mark] in parents)
223 return (mark in marks and marks[mark] in parents)
220
224
221 def deletedivergent(repo, deletefrom, bm):
225 def deletedivergent(repo, deletefrom, bm):
222 '''Delete divergent versions of bm on nodes in deletefrom.
226 '''Delete divergent versions of bm on nodes in deletefrom.
223
227
224 Return True if at least one bookmark was deleted, False otherwise.'''
228 Return True if at least one bookmark was deleted, False otherwise.'''
225 deleted = False
229 deleted = False
226 marks = repo._bookmarks
230 marks = repo._bookmarks
227 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
231 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
228 for mark in divergent:
232 for mark in divergent:
229 if mark == '@' or '@' not in mark:
233 if mark == '@' or '@' not in mark:
230 # can't be divergent by definition
234 # can't be divergent by definition
231 continue
235 continue
232 if mark and marks[mark] in deletefrom:
236 if mark and marks[mark] in deletefrom:
233 if mark != bm:
237 if mark != bm:
234 del marks[mark]
238 del marks[mark]
235 deleted = True
239 deleted = True
236 return deleted
240 return deleted
237
241
238 def calculateupdate(ui, repo, checkout):
242 def calculateupdate(ui, repo, checkout):
239 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
243 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
240 check out and where to move the active bookmark from, if needed.'''
244 check out and where to move the active bookmark from, if needed.'''
241 movemarkfrom = None
245 movemarkfrom = None
242 if checkout is None:
246 if checkout is None:
243 activemark = repo._activebookmark
247 activemark = repo._activebookmark
244 if isactivewdirparent(repo):
248 if isactivewdirparent(repo):
245 movemarkfrom = repo['.'].node()
249 movemarkfrom = repo['.'].node()
246 elif activemark:
250 elif activemark:
247 ui.status(_("updating to active bookmark %s\n") % activemark)
251 ui.status(_("updating to active bookmark %s\n") % activemark)
248 checkout = activemark
252 checkout = activemark
249 return (checkout, movemarkfrom)
253 return (checkout, movemarkfrom)
250
254
251 def update(repo, parents, node):
255 def update(repo, parents, node):
252 deletefrom = parents
256 deletefrom = parents
253 marks = repo._bookmarks
257 marks = repo._bookmarks
254 update = False
258 update = False
255 active = marks.active
259 active = marks.active
256 if not active:
260 if not active:
257 return False
261 return False
258
262
259 if marks[active] in parents:
263 if marks[active] in parents:
260 new = repo[node]
264 new = repo[node]
261 divs = [repo[b] for b in marks
265 divs = [repo[b] for b in marks
262 if b.split('@', 1)[0] == active.split('@', 1)[0]]
266 if b.split('@', 1)[0] == active.split('@', 1)[0]]
263 anc = repo.changelog.ancestors([new.rev()])
267 anc = repo.changelog.ancestors([new.rev()])
264 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
268 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
265 if validdest(repo, repo[marks[active]], new):
269 if validdest(repo, repo[marks[active]], new):
266 marks[active] = new.node()
270 marks[active] = new.node()
267 update = True
271 update = True
268
272
269 if deletedivergent(repo, deletefrom, active):
273 if deletedivergent(repo, deletefrom, active):
270 update = True
274 update = True
271
275
272 if update:
276 if update:
273 lock = tr = None
277 lock = tr = None
274 try:
278 try:
275 lock = repo.lock()
279 lock = repo.lock()
276 tr = repo.transaction('bookmark')
280 tr = repo.transaction('bookmark')
277 marks.recordchange(tr)
281 marks.recordchange(tr)
278 tr.close()
282 tr.close()
279 finally:
283 finally:
280 lockmod.release(tr, lock)
284 lockmod.release(tr, lock)
281 return update
285 return update
282
286
283 def listbookmarks(repo):
287 def listbookmarks(repo):
284 # We may try to list bookmarks on a repo type that does not
288 # We may try to list bookmarks on a repo type that does not
285 # support it (e.g., statichttprepository).
289 # support it (e.g., statichttprepository).
286 marks = getattr(repo, '_bookmarks', {})
290 marks = getattr(repo, '_bookmarks', {})
287
291
288 d = {}
292 d = {}
289 hasnode = repo.changelog.hasnode
293 hasnode = repo.changelog.hasnode
290 for k, v in marks.iteritems():
294 for k, v in marks.iteritems():
291 # don't expose local divergent bookmarks
295 # don't expose local divergent bookmarks
292 if hasnode(v) and ('@' not in k or k.endswith('@')):
296 if hasnode(v) and ('@' not in k or k.endswith('@')):
293 d[k] = hex(v)
297 d[k] = hex(v)
294 return d
298 return d
295
299
296 def pushbookmark(repo, key, old, new):
300 def pushbookmark(repo, key, old, new):
297 w = l = tr = None
301 w = l = tr = None
298 try:
302 try:
299 w = repo.wlock()
303 w = repo.wlock()
300 l = repo.lock()
304 l = repo.lock()
301 tr = repo.transaction('bookmarks')
305 tr = repo.transaction('bookmarks')
302 marks = repo._bookmarks
306 marks = repo._bookmarks
303 existing = hex(marks.get(key, ''))
307 existing = hex(marks.get(key, ''))
304 if existing != old and existing != new:
308 if existing != old and existing != new:
305 return False
309 return False
306 if new == '':
310 if new == '':
307 del marks[key]
311 del marks[key]
308 else:
312 else:
309 if new not in repo:
313 if new not in repo:
310 return False
314 return False
311 marks[key] = repo[new].node()
315 marks[key] = repo[new].node()
312 marks.recordchange(tr)
316 marks.recordchange(tr)
313 tr.close()
317 tr.close()
314 return True
318 return True
315 finally:
319 finally:
316 lockmod.release(tr, l, w)
320 lockmod.release(tr, l, w)
317
321
318 def compare(repo, srcmarks, dstmarks,
322 def compare(repo, srcmarks, dstmarks,
319 srchex=None, dsthex=None, targets=None):
323 srchex=None, dsthex=None, targets=None):
320 '''Compare bookmarks between srcmarks and dstmarks
324 '''Compare bookmarks between srcmarks and dstmarks
321
325
322 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
326 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
323 differ, invalid)", each are list of bookmarks below:
327 differ, invalid)", each are list of bookmarks below:
324
328
325 :addsrc: added on src side (removed on dst side, perhaps)
329 :addsrc: added on src side (removed on dst side, perhaps)
326 :adddst: added on dst side (removed on src side, perhaps)
330 :adddst: added on dst side (removed on src side, perhaps)
327 :advsrc: advanced on src side
331 :advsrc: advanced on src side
328 :advdst: advanced on dst side
332 :advdst: advanced on dst side
329 :diverge: diverge
333 :diverge: diverge
330 :differ: changed, but changeset referred on src is unknown on dst
334 :differ: changed, but changeset referred on src is unknown on dst
331 :invalid: unknown on both side
335 :invalid: unknown on both side
332 :same: same on both side
336 :same: same on both side
333
337
334 Each elements of lists in result tuple is tuple "(bookmark name,
338 Each elements of lists in result tuple is tuple "(bookmark name,
335 changeset ID on source side, changeset ID on destination
339 changeset ID on source side, changeset ID on destination
336 side)". Each changeset IDs are 40 hexadecimal digit string or
340 side)". Each changeset IDs are 40 hexadecimal digit string or
337 None.
341 None.
338
342
339 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
343 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
340 "invalid" list may be unknown for repo.
344 "invalid" list may be unknown for repo.
341
345
342 This function expects that "srcmarks" and "dstmarks" return
346 This function expects that "srcmarks" and "dstmarks" return
343 changeset ID in 40 hexadecimal digit string for specified
347 changeset ID in 40 hexadecimal digit string for specified
344 bookmark. If not so (e.g. bmstore "repo._bookmarks" returning
348 bookmark. If not so (e.g. bmstore "repo._bookmarks" returning
345 binary value), "srchex" or "dsthex" should be specified to convert
349 binary value), "srchex" or "dsthex" should be specified to convert
346 into such form.
350 into such form.
347
351
348 If "targets" is specified, only bookmarks listed in it are
352 If "targets" is specified, only bookmarks listed in it are
349 examined.
353 examined.
350 '''
354 '''
351 if not srchex:
355 if not srchex:
352 srchex = lambda x: x
356 srchex = lambda x: x
353 if not dsthex:
357 if not dsthex:
354 dsthex = lambda x: x
358 dsthex = lambda x: x
355
359
356 if targets:
360 if targets:
357 bset = set(targets)
361 bset = set(targets)
358 else:
362 else:
359 srcmarkset = set(srcmarks)
363 srcmarkset = set(srcmarks)
360 dstmarkset = set(dstmarks)
364 dstmarkset = set(dstmarks)
361 bset = srcmarkset | dstmarkset
365 bset = srcmarkset | dstmarkset
362
366
363 results = ([], [], [], [], [], [], [], [])
367 results = ([], [], [], [], [], [], [], [])
364 addsrc = results[0].append
368 addsrc = results[0].append
365 adddst = results[1].append
369 adddst = results[1].append
366 advsrc = results[2].append
370 advsrc = results[2].append
367 advdst = results[3].append
371 advdst = results[3].append
368 diverge = results[4].append
372 diverge = results[4].append
369 differ = results[5].append
373 differ = results[5].append
370 invalid = results[6].append
374 invalid = results[6].append
371 same = results[7].append
375 same = results[7].append
372
376
373 for b in sorted(bset):
377 for b in sorted(bset):
374 if b not in srcmarks:
378 if b not in srcmarks:
375 if b in dstmarks:
379 if b in dstmarks:
376 adddst((b, None, dsthex(dstmarks[b])))
380 adddst((b, None, dsthex(dstmarks[b])))
377 else:
381 else:
378 invalid((b, None, None))
382 invalid((b, None, None))
379 elif b not in dstmarks:
383 elif b not in dstmarks:
380 addsrc((b, srchex(srcmarks[b]), None))
384 addsrc((b, srchex(srcmarks[b]), None))
381 else:
385 else:
382 scid = srchex(srcmarks[b])
386 scid = srchex(srcmarks[b])
383 dcid = dsthex(dstmarks[b])
387 dcid = dsthex(dstmarks[b])
384 if scid == dcid:
388 if scid == dcid:
385 same((b, scid, dcid))
389 same((b, scid, dcid))
386 elif scid in repo and dcid in repo:
390 elif scid in repo and dcid in repo:
387 sctx = repo[scid]
391 sctx = repo[scid]
388 dctx = repo[dcid]
392 dctx = repo[dcid]
389 if sctx.rev() < dctx.rev():
393 if sctx.rev() < dctx.rev():
390 if validdest(repo, sctx, dctx):
394 if validdest(repo, sctx, dctx):
391 advdst((b, scid, dcid))
395 advdst((b, scid, dcid))
392 else:
396 else:
393 diverge((b, scid, dcid))
397 diverge((b, scid, dcid))
394 else:
398 else:
395 if validdest(repo, dctx, sctx):
399 if validdest(repo, dctx, sctx):
396 advsrc((b, scid, dcid))
400 advsrc((b, scid, dcid))
397 else:
401 else:
398 diverge((b, scid, dcid))
402 diverge((b, scid, dcid))
399 else:
403 else:
400 # it is too expensive to examine in detail, in this case
404 # it is too expensive to examine in detail, in this case
401 differ((b, scid, dcid))
405 differ((b, scid, dcid))
402
406
403 return results
407 return results
404
408
405 def _diverge(ui, b, path, localmarks, remotenode):
409 def _diverge(ui, b, path, localmarks, remotenode):
406 '''Return appropriate diverged bookmark for specified ``path``
410 '''Return appropriate diverged bookmark for specified ``path``
407
411
408 This returns None, if it is failed to assign any divergent
412 This returns None, if it is failed to assign any divergent
409 bookmark name.
413 bookmark name.
410
414
411 This reuses already existing one with "@number" suffix, if it
415 This reuses already existing one with "@number" suffix, if it
412 refers ``remotenode``.
416 refers ``remotenode``.
413 '''
417 '''
414 if b == '@':
418 if b == '@':
415 b = ''
419 b = ''
416 # try to use an @pathalias suffix
420 # try to use an @pathalias suffix
417 # if an @pathalias already exists, we overwrite (update) it
421 # if an @pathalias already exists, we overwrite (update) it
418 if path.startswith("file:"):
422 if path.startswith("file:"):
419 path = util.url(path).path
423 path = util.url(path).path
420 for p, u in ui.configitems("paths"):
424 for p, u in ui.configitems("paths"):
421 if u.startswith("file:"):
425 if u.startswith("file:"):
422 u = util.url(u).path
426 u = util.url(u).path
423 if path == u:
427 if path == u:
424 return '%s@%s' % (b, p)
428 return '%s@%s' % (b, p)
425
429
426 # assign a unique "@number" suffix newly
430 # assign a unique "@number" suffix newly
427 for x in range(1, 100):
431 for x in range(1, 100):
428 n = '%s@%d' % (b, x)
432 n = '%s@%d' % (b, x)
429 if n not in localmarks or localmarks[n] == remotenode:
433 if n not in localmarks or localmarks[n] == remotenode:
430 return n
434 return n
431
435
432 return None
436 return None
433
437
434 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
438 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
435 ui.debug("checking for updated bookmarks\n")
439 ui.debug("checking for updated bookmarks\n")
436 localmarks = repo._bookmarks
440 localmarks = repo._bookmarks
437 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
441 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
438 ) = compare(repo, remotemarks, localmarks, dsthex=hex)
442 ) = compare(repo, remotemarks, localmarks, dsthex=hex)
439
443
440 status = ui.status
444 status = ui.status
441 warn = ui.warn
445 warn = ui.warn
442 if ui.configbool('ui', 'quietbookmarkmove', False):
446 if ui.configbool('ui', 'quietbookmarkmove', False):
443 status = warn = ui.debug
447 status = warn = ui.debug
444
448
445 explicit = set(explicit)
449 explicit = set(explicit)
446 changed = []
450 changed = []
447 for b, scid, dcid in addsrc:
451 for b, scid, dcid in addsrc:
448 if scid in repo: # add remote bookmarks for changes we already have
452 if scid in repo: # add remote bookmarks for changes we already have
449 changed.append((b, bin(scid), status,
453 changed.append((b, bin(scid), status,
450 _("adding remote bookmark %s\n") % (b)))
454 _("adding remote bookmark %s\n") % (b)))
451 elif b in explicit:
455 elif b in explicit:
452 explicit.remove(b)
456 explicit.remove(b)
453 ui.warn(_("remote bookmark %s points to locally missing %s\n")
457 ui.warn(_("remote bookmark %s points to locally missing %s\n")
454 % (b, scid[:12]))
458 % (b, scid[:12]))
455
459
456 for b, scid, dcid in advsrc:
460 for b, scid, dcid in advsrc:
457 changed.append((b, bin(scid), status,
461 changed.append((b, bin(scid), status,
458 _("updating bookmark %s\n") % (b)))
462 _("updating bookmark %s\n") % (b)))
459 # remove normal movement from explicit set
463 # remove normal movement from explicit set
460 explicit.difference_update(d[0] for d in changed)
464 explicit.difference_update(d[0] for d in changed)
461
465
462 for b, scid, dcid in diverge:
466 for b, scid, dcid in diverge:
463 if b in explicit:
467 if b in explicit:
464 explicit.discard(b)
468 explicit.discard(b)
465 changed.append((b, bin(scid), status,
469 changed.append((b, bin(scid), status,
466 _("importing bookmark %s\n") % (b)))
470 _("importing bookmark %s\n") % (b)))
467 else:
471 else:
468 snode = bin(scid)
472 snode = bin(scid)
469 db = _diverge(ui, b, path, localmarks, snode)
473 db = _diverge(ui, b, path, localmarks, snode)
470 if db:
474 if db:
471 changed.append((db, snode, warn,
475 changed.append((db, snode, warn,
472 _("divergent bookmark %s stored as %s\n") %
476 _("divergent bookmark %s stored as %s\n") %
473 (b, db)))
477 (b, db)))
474 else:
478 else:
475 warn(_("warning: failed to assign numbered name "
479 warn(_("warning: failed to assign numbered name "
476 "to divergent bookmark %s\n") % (b))
480 "to divergent bookmark %s\n") % (b))
477 for b, scid, dcid in adddst + advdst:
481 for b, scid, dcid in adddst + advdst:
478 if b in explicit:
482 if b in explicit:
479 explicit.discard(b)
483 explicit.discard(b)
480 changed.append((b, bin(scid), status,
484 changed.append((b, bin(scid), status,
481 _("importing bookmark %s\n") % (b)))
485 _("importing bookmark %s\n") % (b)))
482 for b, scid, dcid in differ:
486 for b, scid, dcid in differ:
483 if b in explicit:
487 if b in explicit:
484 explicit.remove(b)
488 explicit.remove(b)
485 ui.warn(_("remote bookmark %s points to locally missing %s\n")
489 ui.warn(_("remote bookmark %s points to locally missing %s\n")
486 % (b, scid[:12]))
490 % (b, scid[:12]))
487
491
488 if changed:
492 if changed:
489 tr = trfunc()
493 tr = trfunc()
490 for b, node, writer, msg in sorted(changed):
494 for b, node, writer, msg in sorted(changed):
491 localmarks[b] = node
495 localmarks[b] = node
492 writer(msg)
496 writer(msg)
493 localmarks.recordchange(tr)
497 localmarks.recordchange(tr)
494
498
495 def incoming(ui, repo, other):
499 def incoming(ui, repo, other):
496 '''Show bookmarks incoming from other to repo
500 '''Show bookmarks incoming from other to repo
497 '''
501 '''
498 ui.status(_("searching for changed bookmarks\n"))
502 ui.status(_("searching for changed bookmarks\n"))
499
503
500 r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
504 r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
501 dsthex=hex)
505 dsthex=hex)
502 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
506 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
503
507
504 incomings = []
508 incomings = []
505 if ui.debugflag:
509 if ui.debugflag:
506 getid = lambda id: id
510 getid = lambda id: id
507 else:
511 else:
508 getid = lambda id: id[:12]
512 getid = lambda id: id[:12]
509 if ui.verbose:
513 if ui.verbose:
510 def add(b, id, st):
514 def add(b, id, st):
511 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
515 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
512 else:
516 else:
513 def add(b, id, st):
517 def add(b, id, st):
514 incomings.append(" %-25s %s\n" % (b, getid(id)))
518 incomings.append(" %-25s %s\n" % (b, getid(id)))
515 for b, scid, dcid in addsrc:
519 for b, scid, dcid in addsrc:
516 # i18n: "added" refers to a bookmark
520 # i18n: "added" refers to a bookmark
517 add(b, scid, _('added'))
521 add(b, scid, _('added'))
518 for b, scid, dcid in advsrc:
522 for b, scid, dcid in advsrc:
519 # i18n: "advanced" refers to a bookmark
523 # i18n: "advanced" refers to a bookmark
520 add(b, scid, _('advanced'))
524 add(b, scid, _('advanced'))
521 for b, scid, dcid in diverge:
525 for b, scid, dcid in diverge:
522 # i18n: "diverged" refers to a bookmark
526 # i18n: "diverged" refers to a bookmark
523 add(b, scid, _('diverged'))
527 add(b, scid, _('diverged'))
524 for b, scid, dcid in differ:
528 for b, scid, dcid in differ:
525 # i18n: "changed" refers to a bookmark
529 # i18n: "changed" refers to a bookmark
526 add(b, scid, _('changed'))
530 add(b, scid, _('changed'))
527
531
528 if not incomings:
532 if not incomings:
529 ui.status(_("no changed bookmarks found\n"))
533 ui.status(_("no changed bookmarks found\n"))
530 return 1
534 return 1
531
535
532 for s in sorted(incomings):
536 for s in sorted(incomings):
533 ui.write(s)
537 ui.write(s)
534
538
535 return 0
539 return 0
536
540
537 def outgoing(ui, repo, other):
541 def outgoing(ui, repo, other):
538 '''Show bookmarks outgoing from repo to other
542 '''Show bookmarks outgoing from repo to other
539 '''
543 '''
540 ui.status(_("searching for changed bookmarks\n"))
544 ui.status(_("searching for changed bookmarks\n"))
541
545
542 r = compare(repo, repo._bookmarks, other.listkeys('bookmarks'),
546 r = compare(repo, repo._bookmarks, other.listkeys('bookmarks'),
543 srchex=hex)
547 srchex=hex)
544 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
548 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
545
549
546 outgoings = []
550 outgoings = []
547 if ui.debugflag:
551 if ui.debugflag:
548 getid = lambda id: id
552 getid = lambda id: id
549 else:
553 else:
550 getid = lambda id: id[:12]
554 getid = lambda id: id[:12]
551 if ui.verbose:
555 if ui.verbose:
552 def add(b, id, st):
556 def add(b, id, st):
553 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
557 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
554 else:
558 else:
555 def add(b, id, st):
559 def add(b, id, st):
556 outgoings.append(" %-25s %s\n" % (b, getid(id)))
560 outgoings.append(" %-25s %s\n" % (b, getid(id)))
557 for b, scid, dcid in addsrc:
561 for b, scid, dcid in addsrc:
558 # i18n: "added refers to a bookmark
562 # i18n: "added refers to a bookmark
559 add(b, scid, _('added'))
563 add(b, scid, _('added'))
560 for b, scid, dcid in adddst:
564 for b, scid, dcid in adddst:
561 # i18n: "deleted" refers to a bookmark
565 # i18n: "deleted" refers to a bookmark
562 add(b, ' ' * 40, _('deleted'))
566 add(b, ' ' * 40, _('deleted'))
563 for b, scid, dcid in advsrc:
567 for b, scid, dcid in advsrc:
564 # i18n: "advanced" refers to a bookmark
568 # i18n: "advanced" refers to a bookmark
565 add(b, scid, _('advanced'))
569 add(b, scid, _('advanced'))
566 for b, scid, dcid in diverge:
570 for b, scid, dcid in diverge:
567 # i18n: "diverged" refers to a bookmark
571 # i18n: "diverged" refers to a bookmark
568 add(b, scid, _('diverged'))
572 add(b, scid, _('diverged'))
569 for b, scid, dcid in differ:
573 for b, scid, dcid in differ:
570 # i18n: "changed" refers to a bookmark
574 # i18n: "changed" refers to a bookmark
571 add(b, scid, _('changed'))
575 add(b, scid, _('changed'))
572
576
573 if not outgoings:
577 if not outgoings:
574 ui.status(_("no changed bookmarks found\n"))
578 ui.status(_("no changed bookmarks found\n"))
575 return 1
579 return 1
576
580
577 for s in sorted(outgoings):
581 for s in sorted(outgoings):
578 ui.write(s)
582 ui.write(s)
579
583
580 return 0
584 return 0
581
585
582 def summary(repo, other):
586 def summary(repo, other):
583 '''Compare bookmarks between repo and other for "hg summary" output
587 '''Compare bookmarks between repo and other for "hg summary" output
584
588
585 This returns "(# of incoming, # of outgoing)" tuple.
589 This returns "(# of incoming, # of outgoing)" tuple.
586 '''
590 '''
587 r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
591 r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
588 dsthex=hex)
592 dsthex=hex)
589 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
593 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
590 return (len(addsrc), len(adddst))
594 return (len(addsrc), len(adddst))
591
595
592 def validdest(repo, old, new):
596 def validdest(repo, old, new):
593 """Is the new bookmark destination a valid update from the old one"""
597 """Is the new bookmark destination a valid update from the old one"""
594 repo = repo.unfiltered()
598 repo = repo.unfiltered()
595 if old == new:
599 if old == new:
596 # Old == new -> nothing to update.
600 # Old == new -> nothing to update.
597 return False
601 return False
598 elif not old:
602 elif not old:
599 # old is nullrev, anything is valid.
603 # old is nullrev, anything is valid.
600 # (new != nullrev has been excluded by the previous check)
604 # (new != nullrev has been excluded by the previous check)
601 return True
605 return True
602 elif repo.obsstore:
606 elif repo.obsstore:
603 return new.node() in obsolete.foreground(repo, [old.node()])
607 return new.node() in obsolete.foreground(repo, [old.node()])
604 else:
608 else:
605 # still an independent clause as it is lazier (and therefore faster)
609 # still an independent clause as it is lazier (and therefore faster)
606 return old.descendant(new)
610 return old.descendant(new)
@@ -1,850 +1,863 b''
1 #require serve
1 #require serve
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [ui]
4 > [ui]
5 > logtemplate={rev}:{node|short} {desc|firstline}
5 > logtemplate={rev}:{node|short} {desc|firstline}
6 > [phases]
6 > [phases]
7 > publish=False
7 > publish=False
8 > [experimental]
8 > [experimental]
9 > evolution=createmarkers,exchange
9 > evolution=createmarkers,exchange
10 > # drop me once bundle2 is the default,
10 > # drop me once bundle2 is the default,
11 > # added to get test change early.
11 > # added to get test change early.
12 > bundle2-exp = True
12 > bundle2-exp = True
13 > EOF
13 > EOF
14
14
15 initialize
15 initialize
16
16
17 $ hg init a
17 $ hg init a
18 $ cd a
18 $ cd a
19 $ echo 'test' > test
19 $ echo 'test' > test
20 $ hg commit -Am'test'
20 $ hg commit -Am'test'
21 adding test
21 adding test
22
22
23 set bookmarks
23 set bookmarks
24
24
25 $ hg bookmark X
25 $ hg bookmark X
26 $ hg bookmark Y
26 $ hg bookmark Y
27 $ hg bookmark Z
27 $ hg bookmark Z
28
28
29 import bookmark by name
29 import bookmark by name
30
30
31 $ hg init ../b
31 $ hg init ../b
32 $ cd ../b
32 $ cd ../b
33 $ hg book Y
33 $ hg book Y
34 $ hg book
34 $ hg book
35 * Y -1:000000000000
35 * Y -1:000000000000
36 $ hg pull ../a
36 $ hg pull ../a
37 pulling from ../a
37 pulling from ../a
38 requesting all changes
38 requesting all changes
39 adding changesets
39 adding changesets
40 adding manifests
40 adding manifests
41 adding file changes
41 adding file changes
42 added 1 changesets with 1 changes to 1 files
42 added 1 changesets with 1 changes to 1 files
43 adding remote bookmark X
43 adding remote bookmark X
44 updating bookmark Y
44 updating bookmark Y
45 adding remote bookmark Z
45 adding remote bookmark Z
46 (run 'hg update' to get a working copy)
46 (run 'hg update' to get a working copy)
47 $ hg bookmarks
47 $ hg bookmarks
48 X 0:4e3505fd9583
48 X 0:4e3505fd9583
49 * Y 0:4e3505fd9583
49 * Y 0:4e3505fd9583
50 Z 0:4e3505fd9583
50 Z 0:4e3505fd9583
51 $ hg debugpushkey ../a namespaces
51 $ hg debugpushkey ../a namespaces
52 bookmarks
52 bookmarks
53 namespaces
53 namespaces
54 obsolete
54 obsolete
55 phases
55 phases
56 $ hg debugpushkey ../a bookmarks
56 $ hg debugpushkey ../a bookmarks
57 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
57 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
60
60
61 delete the bookmark to re-pull it
61 delete the bookmark to re-pull it
62
62
63 $ hg book -d X
63 $ hg book -d X
64 $ hg pull -B X ../a
64 $ hg pull -B X ../a
65 pulling from ../a
65 pulling from ../a
66 no changes found
66 no changes found
67 adding remote bookmark X
67 adding remote bookmark X
68
68
69 finally no-op pull
69 finally no-op pull
70
70
71 $ hg pull -B X ../a
71 $ hg pull -B X ../a
72 pulling from ../a
72 pulling from ../a
73 no changes found
73 no changes found
74 $ hg bookmark
74 $ hg bookmark
75 X 0:4e3505fd9583
75 X 0:4e3505fd9583
76 * Y 0:4e3505fd9583
76 * Y 0:4e3505fd9583
77 Z 0:4e3505fd9583
77 Z 0:4e3505fd9583
78
78
79 export bookmark by name
79 export bookmark by name
80
80
81 $ hg bookmark W
81 $ hg bookmark W
82 $ hg bookmark foo
82 $ hg bookmark foo
83 $ hg bookmark foobar
83 $ hg bookmark foobar
84 $ hg push -B W ../a
84 $ hg push -B W ../a
85 pushing to ../a
85 pushing to ../a
86 searching for changes
86 searching for changes
87 no changes found
87 no changes found
88 exporting bookmark W
88 exporting bookmark W
89 [1]
89 [1]
90 $ hg -R ../a bookmarks
90 $ hg -R ../a bookmarks
91 W -1:000000000000
91 W -1:000000000000
92 X 0:4e3505fd9583
92 X 0:4e3505fd9583
93 Y 0:4e3505fd9583
93 Y 0:4e3505fd9583
94 * Z 0:4e3505fd9583
94 * Z 0:4e3505fd9583
95
95
96 delete a remote bookmark
96 delete a remote bookmark
97
97
98 $ hg book -d W
98 $ hg book -d W
99 $ hg push -B W ../a
99 $ hg push -B W ../a
100 pushing to ../a
100 pushing to ../a
101 searching for changes
101 searching for changes
102 no changes found
102 no changes found
103 deleting remote bookmark W
103 deleting remote bookmark W
104 [1]
104 [1]
105
105
106 export the active bookmark
106 export the active bookmark
107
107
108 $ hg bookmark V
108 $ hg bookmark V
109 $ hg push -B . ../a
109 $ hg push -B . ../a
110 pushing to ../a
110 pushing to ../a
111 searching for changes
111 searching for changes
112 no changes found
112 no changes found
113 exporting bookmark V
113 exporting bookmark V
114 [1]
114 [1]
115
115
116 exporting the active bookmark with 'push -B .'
117 demand that one of the bookmarks is activated
118
119 $ hg update -r default
120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 (leaving bookmark V)
122 $ hg push -B . ../a
123 abort: no active bookmark
124 [255]
125 $ hg update -r V
126 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
127 (activating bookmark V)
128
116 delete the bookmark
129 delete the bookmark
117
130
118 $ hg book -d V
131 $ hg book -d V
119 $ hg push -B V ../a
132 $ hg push -B V ../a
120 pushing to ../a
133 pushing to ../a
121 searching for changes
134 searching for changes
122 no changes found
135 no changes found
123 deleting remote bookmark V
136 deleting remote bookmark V
124 [1]
137 [1]
125 $ hg up foobar
138 $ hg up foobar
126 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
139 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 (activating bookmark foobar)
140 (activating bookmark foobar)
128
141
129 push/pull name that doesn't exist
142 push/pull name that doesn't exist
130
143
131 $ hg push -B badname ../a
144 $ hg push -B badname ../a
132 pushing to ../a
145 pushing to ../a
133 searching for changes
146 searching for changes
134 bookmark badname does not exist on the local or remote repository!
147 bookmark badname does not exist on the local or remote repository!
135 no changes found
148 no changes found
136 [2]
149 [2]
137 $ hg pull -B anotherbadname ../a
150 $ hg pull -B anotherbadname ../a
138 pulling from ../a
151 pulling from ../a
139 abort: remote bookmark anotherbadname not found!
152 abort: remote bookmark anotherbadname not found!
140 [255]
153 [255]
141
154
142 divergent bookmarks
155 divergent bookmarks
143
156
144 $ cd ../a
157 $ cd ../a
145 $ echo c1 > f1
158 $ echo c1 > f1
146 $ hg ci -Am1
159 $ hg ci -Am1
147 adding f1
160 adding f1
148 $ hg book -f @
161 $ hg book -f @
149 $ hg book -f X
162 $ hg book -f X
150 $ hg book
163 $ hg book
151 @ 1:0d2164f0ce0d
164 @ 1:0d2164f0ce0d
152 * X 1:0d2164f0ce0d
165 * X 1:0d2164f0ce0d
153 Y 0:4e3505fd9583
166 Y 0:4e3505fd9583
154 Z 1:0d2164f0ce0d
167 Z 1:0d2164f0ce0d
155
168
156 $ cd ../b
169 $ cd ../b
157 $ hg up
170 $ hg up
158 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 updating bookmark foobar
172 updating bookmark foobar
160 $ echo c2 > f2
173 $ echo c2 > f2
161 $ hg ci -Am2
174 $ hg ci -Am2
162 adding f2
175 adding f2
163 $ hg book -if @
176 $ hg book -if @
164 $ hg book -if X
177 $ hg book -if X
165 $ hg book
178 $ hg book
166 @ 1:9b140be10808
179 @ 1:9b140be10808
167 X 1:9b140be10808
180 X 1:9b140be10808
168 Y 0:4e3505fd9583
181 Y 0:4e3505fd9583
169 Z 0:4e3505fd9583
182 Z 0:4e3505fd9583
170 foo -1:000000000000
183 foo -1:000000000000
171 * foobar 1:9b140be10808
184 * foobar 1:9b140be10808
172
185
173 $ hg pull --config paths.foo=../a foo
186 $ hg pull --config paths.foo=../a foo
174 pulling from $TESTTMP/a (glob)
187 pulling from $TESTTMP/a (glob)
175 searching for changes
188 searching for changes
176 adding changesets
189 adding changesets
177 adding manifests
190 adding manifests
178 adding file changes
191 adding file changes
179 added 1 changesets with 1 changes to 1 files (+1 heads)
192 added 1 changesets with 1 changes to 1 files (+1 heads)
180 divergent bookmark @ stored as @foo
193 divergent bookmark @ stored as @foo
181 divergent bookmark X stored as X@foo
194 divergent bookmark X stored as X@foo
182 updating bookmark Z
195 updating bookmark Z
183 (run 'hg heads' to see heads, 'hg merge' to merge)
196 (run 'hg heads' to see heads, 'hg merge' to merge)
184 $ hg book
197 $ hg book
185 @ 1:9b140be10808
198 @ 1:9b140be10808
186 @foo 2:0d2164f0ce0d
199 @foo 2:0d2164f0ce0d
187 X 1:9b140be10808
200 X 1:9b140be10808
188 X@foo 2:0d2164f0ce0d
201 X@foo 2:0d2164f0ce0d
189 Y 0:4e3505fd9583
202 Y 0:4e3505fd9583
190 Z 2:0d2164f0ce0d
203 Z 2:0d2164f0ce0d
191 foo -1:000000000000
204 foo -1:000000000000
192 * foobar 1:9b140be10808
205 * foobar 1:9b140be10808
193
206
194 (test that too many divergence of bookmark)
207 (test that too many divergence of bookmark)
195
208
196 $ python $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
209 $ python $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
197 $ hg pull ../a
210 $ hg pull ../a
198 pulling from ../a
211 pulling from ../a
199 searching for changes
212 searching for changes
200 no changes found
213 no changes found
201 warning: failed to assign numbered name to divergent bookmark X
214 warning: failed to assign numbered name to divergent bookmark X
202 divergent bookmark @ stored as @1
215 divergent bookmark @ stored as @1
203 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
216 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
204 X 1:9b140be10808
217 X 1:9b140be10808
205 X@foo 2:0d2164f0ce0d
218 X@foo 2:0d2164f0ce0d
206
219
207 (test that remotely diverged bookmarks are reused if they aren't changed)
220 (test that remotely diverged bookmarks are reused if they aren't changed)
208
221
209 $ hg bookmarks | grep '^ @'
222 $ hg bookmarks | grep '^ @'
210 @ 1:9b140be10808
223 @ 1:9b140be10808
211 @1 2:0d2164f0ce0d
224 @1 2:0d2164f0ce0d
212 @foo 2:0d2164f0ce0d
225 @foo 2:0d2164f0ce0d
213 $ hg pull ../a
226 $ hg pull ../a
214 pulling from ../a
227 pulling from ../a
215 searching for changes
228 searching for changes
216 no changes found
229 no changes found
217 warning: failed to assign numbered name to divergent bookmark X
230 warning: failed to assign numbered name to divergent bookmark X
218 divergent bookmark @ stored as @1
231 divergent bookmark @ stored as @1
219 $ hg bookmarks | grep '^ @'
232 $ hg bookmarks | grep '^ @'
220 @ 1:9b140be10808
233 @ 1:9b140be10808
221 @1 2:0d2164f0ce0d
234 @1 2:0d2164f0ce0d
222 @foo 2:0d2164f0ce0d
235 @foo 2:0d2164f0ce0d
223
236
224 $ python $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
237 $ python $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
225 $ hg bookmarks -d "@1"
238 $ hg bookmarks -d "@1"
226
239
227 $ hg push -f ../a
240 $ hg push -f ../a
228 pushing to ../a
241 pushing to ../a
229 searching for changes
242 searching for changes
230 adding changesets
243 adding changesets
231 adding manifests
244 adding manifests
232 adding file changes
245 adding file changes
233 added 1 changesets with 1 changes to 1 files (+1 heads)
246 added 1 changesets with 1 changes to 1 files (+1 heads)
234 $ hg -R ../a book
247 $ hg -R ../a book
235 @ 1:0d2164f0ce0d
248 @ 1:0d2164f0ce0d
236 * X 1:0d2164f0ce0d
249 * X 1:0d2164f0ce0d
237 Y 0:4e3505fd9583
250 Y 0:4e3505fd9583
238 Z 1:0d2164f0ce0d
251 Z 1:0d2164f0ce0d
239
252
240 explicit pull should overwrite the local version (issue4439)
253 explicit pull should overwrite the local version (issue4439)
241
254
242 $ hg pull --config paths.foo=../a foo -B X
255 $ hg pull --config paths.foo=../a foo -B X
243 pulling from $TESTTMP/a (glob)
256 pulling from $TESTTMP/a (glob)
244 no changes found
257 no changes found
245 divergent bookmark @ stored as @foo
258 divergent bookmark @ stored as @foo
246 importing bookmark X
259 importing bookmark X
247
260
248 reinstall state for further testing:
261 reinstall state for further testing:
249
262
250 $ hg book -fr 9b140be10808 X
263 $ hg book -fr 9b140be10808 X
251
264
252 revsets should not ignore divergent bookmarks
265 revsets should not ignore divergent bookmarks
253
266
254 $ hg bookmark -fr 1 Z
267 $ hg bookmark -fr 1 Z
255 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
268 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
256 0:4e3505fd9583 Y
269 0:4e3505fd9583 Y
257 1:9b140be10808 @ X Z foobar
270 1:9b140be10808 @ X Z foobar
258 2:0d2164f0ce0d @foo X@foo
271 2:0d2164f0ce0d @foo X@foo
259 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
272 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
260 2:0d2164f0ce0d @foo X@foo
273 2:0d2164f0ce0d @foo X@foo
261 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
274 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
262 2:0d2164f0ce0d @foo X@foo
275 2:0d2164f0ce0d @foo X@foo
263
276
264 update a remote bookmark from a non-head to a head
277 update a remote bookmark from a non-head to a head
265
278
266 $ hg up -q Y
279 $ hg up -q Y
267 $ echo c3 > f2
280 $ echo c3 > f2
268 $ hg ci -Am3
281 $ hg ci -Am3
269 adding f2
282 adding f2
270 created new head
283 created new head
271 $ hg push ../a
284 $ hg push ../a
272 pushing to ../a
285 pushing to ../a
273 searching for changes
286 searching for changes
274 adding changesets
287 adding changesets
275 adding manifests
288 adding manifests
276 adding file changes
289 adding file changes
277 added 1 changesets with 1 changes to 1 files (+1 heads)
290 added 1 changesets with 1 changes to 1 files (+1 heads)
278 updating bookmark Y
291 updating bookmark Y
279 $ hg -R ../a book
292 $ hg -R ../a book
280 @ 1:0d2164f0ce0d
293 @ 1:0d2164f0ce0d
281 * X 1:0d2164f0ce0d
294 * X 1:0d2164f0ce0d
282 Y 3:f6fc62dde3c0
295 Y 3:f6fc62dde3c0
283 Z 1:0d2164f0ce0d
296 Z 1:0d2164f0ce0d
284
297
285 update a bookmark in the middle of a client pulling changes
298 update a bookmark in the middle of a client pulling changes
286
299
287 $ cd ..
300 $ cd ..
288 $ hg clone -q a pull-race
301 $ hg clone -q a pull-race
289
302
290 We want to use http because it is stateless and therefore more susceptible to
303 We want to use http because it is stateless and therefore more susceptible to
291 race conditions
304 race conditions
292
305
293 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
306 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
294 $ cat pull-race.pid >> $DAEMON_PIDS
307 $ cat pull-race.pid >> $DAEMON_PIDS
295
308
296 $ hg clone -q http://localhost:$HGPORT/ pull-race2
309 $ hg clone -q http://localhost:$HGPORT/ pull-race2
297 $ cd pull-race
310 $ cd pull-race
298 $ hg up -q Y
311 $ hg up -q Y
299 $ echo c4 > f2
312 $ echo c4 > f2
300 $ hg ci -Am4
313 $ hg ci -Am4
301 $ echo c5 > f3
314 $ echo c5 > f3
302 $ cat <<EOF > .hg/hgrc
315 $ cat <<EOF > .hg/hgrc
303 > [hooks]
316 > [hooks]
304 > outgoing.makecommit = hg ci -Am5; echo committed in pull-race
317 > outgoing.makecommit = hg ci -Am5; echo committed in pull-race
305 > EOF
318 > EOF
306
319
307 (new config needs a server restart)
320 (new config needs a server restart)
308
321
309 $ cd ..
322 $ cd ..
310 $ killdaemons.py
323 $ killdaemons.py
311 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
324 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
312 $ cat pull-race.pid >> $DAEMON_PIDS
325 $ cat pull-race.pid >> $DAEMON_PIDS
313 $ cd pull-race2
326 $ cd pull-race2
314 $ hg -R $TESTTMP/pull-race book
327 $ hg -R $TESTTMP/pull-race book
315 @ 1:0d2164f0ce0d
328 @ 1:0d2164f0ce0d
316 X 1:0d2164f0ce0d
329 X 1:0d2164f0ce0d
317 * Y 4:b0a5eff05604
330 * Y 4:b0a5eff05604
318 Z 1:0d2164f0ce0d
331 Z 1:0d2164f0ce0d
319 $ hg pull
332 $ hg pull
320 pulling from http://localhost:$HGPORT/
333 pulling from http://localhost:$HGPORT/
321 searching for changes
334 searching for changes
322 adding changesets
335 adding changesets
323 adding manifests
336 adding manifests
324 adding file changes
337 adding file changes
325 added 1 changesets with 1 changes to 1 files
338 added 1 changesets with 1 changes to 1 files
326 updating bookmark Y
339 updating bookmark Y
327 (run 'hg update' to get a working copy)
340 (run 'hg update' to get a working copy)
328 $ hg book
341 $ hg book
329 * @ 1:0d2164f0ce0d
342 * @ 1:0d2164f0ce0d
330 X 1:0d2164f0ce0d
343 X 1:0d2164f0ce0d
331 Y 4:b0a5eff05604
344 Y 4:b0a5eff05604
332 Z 1:0d2164f0ce0d
345 Z 1:0d2164f0ce0d
333
346
334 Update a bookmark right after the initial lookup -B (issue4689)
347 Update a bookmark right after the initial lookup -B (issue4689)
335
348
336 $ echo c6 > ../pull-race/f3 # to be committed during the race
349 $ echo c6 > ../pull-race/f3 # to be committed during the race
337 $ cat <<EOF > ../pull-race/.hg/hgrc
350 $ cat <<EOF > ../pull-race/.hg/hgrc
338 > [hooks]
351 > [hooks]
339 > # If anything to commit, commit it right after the first key listing used
352 > # If anything to commit, commit it right after the first key listing used
340 > # during lookup. This makes the commit appear before the actual getbundle
353 > # during lookup. This makes the commit appear before the actual getbundle
341 > # call.
354 > # call.
342 > listkeys.makecommit= ((hg st | grep -q M) && (hg commit -m race; echo commited in pull-race)) || exit 0
355 > listkeys.makecommit= ((hg st | grep -q M) && (hg commit -m race; echo commited in pull-race)) || exit 0
343 > EOF
356 > EOF
344
357
345 (new config need server restart)
358 (new config need server restart)
346
359
347 $ killdaemons.py
360 $ killdaemons.py
348 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
361 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
349 $ cat ../pull-race.pid >> $DAEMON_PIDS
362 $ cat ../pull-race.pid >> $DAEMON_PIDS
350
363
351 $ hg -R $TESTTMP/pull-race book
364 $ hg -R $TESTTMP/pull-race book
352 @ 1:0d2164f0ce0d
365 @ 1:0d2164f0ce0d
353 X 1:0d2164f0ce0d
366 X 1:0d2164f0ce0d
354 * Y 5:35d1ef0a8d1b
367 * Y 5:35d1ef0a8d1b
355 Z 1:0d2164f0ce0d
368 Z 1:0d2164f0ce0d
356 $ hg pull -B Y
369 $ hg pull -B Y
357 pulling from http://localhost:$HGPORT/
370 pulling from http://localhost:$HGPORT/
358 searching for changes
371 searching for changes
359 adding changesets
372 adding changesets
360 adding manifests
373 adding manifests
361 adding file changes
374 adding file changes
362 added 1 changesets with 1 changes to 1 files
375 added 1 changesets with 1 changes to 1 files
363 updating bookmark Y
376 updating bookmark Y
364 (run 'hg update' to get a working copy)
377 (run 'hg update' to get a working copy)
365 $ hg book
378 $ hg book
366 * @ 1:0d2164f0ce0d
379 * @ 1:0d2164f0ce0d
367 X 1:0d2164f0ce0d
380 X 1:0d2164f0ce0d
368 Y 5:35d1ef0a8d1b
381 Y 5:35d1ef0a8d1b
369 Z 1:0d2164f0ce0d
382 Z 1:0d2164f0ce0d
370
383
371 (done with this section of the test)
384 (done with this section of the test)
372
385
373 $ killdaemons.py
386 $ killdaemons.py
374 $ cd ../b
387 $ cd ../b
375
388
376 diverging a remote bookmark fails
389 diverging a remote bookmark fails
377
390
378 $ hg up -q 4e3505fd9583
391 $ hg up -q 4e3505fd9583
379 $ echo c4 > f2
392 $ echo c4 > f2
380 $ hg ci -Am4
393 $ hg ci -Am4
381 adding f2
394 adding f2
382 created new head
395 created new head
383 $ echo c5 > f2
396 $ echo c5 > f2
384 $ hg ci -Am5
397 $ hg ci -Am5
385 $ hg log -G
398 $ hg log -G
386 @ 5:c922c0139ca0 5
399 @ 5:c922c0139ca0 5
387 |
400 |
388 o 4:4efff6d98829 4
401 o 4:4efff6d98829 4
389 |
402 |
390 | o 3:f6fc62dde3c0 3
403 | o 3:f6fc62dde3c0 3
391 |/
404 |/
392 | o 2:0d2164f0ce0d 1
405 | o 2:0d2164f0ce0d 1
393 |/
406 |/
394 | o 1:9b140be10808 2
407 | o 1:9b140be10808 2
395 |/
408 |/
396 o 0:4e3505fd9583 test
409 o 0:4e3505fd9583 test
397
410
398
411
399 $ hg book -f Y
412 $ hg book -f Y
400
413
401 $ cat <<EOF > ../a/.hg/hgrc
414 $ cat <<EOF > ../a/.hg/hgrc
402 > [web]
415 > [web]
403 > push_ssl = false
416 > push_ssl = false
404 > allow_push = *
417 > allow_push = *
405 > EOF
418 > EOF
406
419
407 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
420 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
408 $ cat ../hg2.pid >> $DAEMON_PIDS
421 $ cat ../hg2.pid >> $DAEMON_PIDS
409
422
410 $ hg push http://localhost:$HGPORT2/
423 $ hg push http://localhost:$HGPORT2/
411 pushing to http://localhost:$HGPORT2/
424 pushing to http://localhost:$HGPORT2/
412 searching for changes
425 searching for changes
413 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
426 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
414 (merge or see "hg help push" for details about pushing new heads)
427 (merge or see "hg help push" for details about pushing new heads)
415 [255]
428 [255]
416 $ hg -R ../a book
429 $ hg -R ../a book
417 @ 1:0d2164f0ce0d
430 @ 1:0d2164f0ce0d
418 * X 1:0d2164f0ce0d
431 * X 1:0d2164f0ce0d
419 Y 3:f6fc62dde3c0
432 Y 3:f6fc62dde3c0
420 Z 1:0d2164f0ce0d
433 Z 1:0d2164f0ce0d
421
434
422
435
423 Unrelated marker does not alter the decision
436 Unrelated marker does not alter the decision
424
437
425 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
438 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
426 $ hg push http://localhost:$HGPORT2/
439 $ hg push http://localhost:$HGPORT2/
427 pushing to http://localhost:$HGPORT2/
440 pushing to http://localhost:$HGPORT2/
428 searching for changes
441 searching for changes
429 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
442 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
430 (merge or see "hg help push" for details about pushing new heads)
443 (merge or see "hg help push" for details about pushing new heads)
431 [255]
444 [255]
432 $ hg -R ../a book
445 $ hg -R ../a book
433 @ 1:0d2164f0ce0d
446 @ 1:0d2164f0ce0d
434 * X 1:0d2164f0ce0d
447 * X 1:0d2164f0ce0d
435 Y 3:f6fc62dde3c0
448 Y 3:f6fc62dde3c0
436 Z 1:0d2164f0ce0d
449 Z 1:0d2164f0ce0d
437
450
438 Update to a successor works
451 Update to a successor works
439
452
440 $ hg id --debug -r 3
453 $ hg id --debug -r 3
441 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
454 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
442 $ hg id --debug -r 4
455 $ hg id --debug -r 4
443 4efff6d98829d9c824c621afd6e3f01865f5439f
456 4efff6d98829d9c824c621afd6e3f01865f5439f
444 $ hg id --debug -r 5
457 $ hg id --debug -r 5
445 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
458 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
446 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
459 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
447 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
460 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
448 $ hg push http://localhost:$HGPORT2/
461 $ hg push http://localhost:$HGPORT2/
449 pushing to http://localhost:$HGPORT2/
462 pushing to http://localhost:$HGPORT2/
450 searching for changes
463 searching for changes
451 remote: adding changesets
464 remote: adding changesets
452 remote: adding manifests
465 remote: adding manifests
453 remote: adding file changes
466 remote: adding file changes
454 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
467 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
455 remote: 2 new obsolescence markers
468 remote: 2 new obsolescence markers
456 updating bookmark Y
469 updating bookmark Y
457 $ hg -R ../a book
470 $ hg -R ../a book
458 @ 1:0d2164f0ce0d
471 @ 1:0d2164f0ce0d
459 * X 1:0d2164f0ce0d
472 * X 1:0d2164f0ce0d
460 Y 5:c922c0139ca0
473 Y 5:c922c0139ca0
461 Z 1:0d2164f0ce0d
474 Z 1:0d2164f0ce0d
462
475
463 hgweb
476 hgweb
464
477
465 $ cat <<EOF > .hg/hgrc
478 $ cat <<EOF > .hg/hgrc
466 > [web]
479 > [web]
467 > push_ssl = false
480 > push_ssl = false
468 > allow_push = *
481 > allow_push = *
469 > EOF
482 > EOF
470
483
471 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
484 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
472 $ cat ../hg.pid >> $DAEMON_PIDS
485 $ cat ../hg.pid >> $DAEMON_PIDS
473 $ cd ../a
486 $ cd ../a
474
487
475 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
488 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
476 bookmarks
489 bookmarks
477 namespaces
490 namespaces
478 obsolete
491 obsolete
479 phases
492 phases
480 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
493 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
481 @ 9b140be1080824d768c5a4691a564088eede71f9
494 @ 9b140be1080824d768c5a4691a564088eede71f9
482 X 9b140be1080824d768c5a4691a564088eede71f9
495 X 9b140be1080824d768c5a4691a564088eede71f9
483 Y c922c0139ca03858f655e4a2af4dd02796a63969
496 Y c922c0139ca03858f655e4a2af4dd02796a63969
484 Z 9b140be1080824d768c5a4691a564088eede71f9
497 Z 9b140be1080824d768c5a4691a564088eede71f9
485 foo 0000000000000000000000000000000000000000
498 foo 0000000000000000000000000000000000000000
486 foobar 9b140be1080824d768c5a4691a564088eede71f9
499 foobar 9b140be1080824d768c5a4691a564088eede71f9
487 $ hg out -B http://localhost:$HGPORT/
500 $ hg out -B http://localhost:$HGPORT/
488 comparing with http://localhost:$HGPORT/
501 comparing with http://localhost:$HGPORT/
489 searching for changed bookmarks
502 searching for changed bookmarks
490 @ 0d2164f0ce0d
503 @ 0d2164f0ce0d
491 X 0d2164f0ce0d
504 X 0d2164f0ce0d
492 Z 0d2164f0ce0d
505 Z 0d2164f0ce0d
493 foo
506 foo
494 foobar
507 foobar
495 $ hg push -B Z http://localhost:$HGPORT/
508 $ hg push -B Z http://localhost:$HGPORT/
496 pushing to http://localhost:$HGPORT/
509 pushing to http://localhost:$HGPORT/
497 searching for changes
510 searching for changes
498 no changes found
511 no changes found
499 updating bookmark Z
512 updating bookmark Z
500 [1]
513 [1]
501 $ hg book -d Z
514 $ hg book -d Z
502 $ hg in -B http://localhost:$HGPORT/
515 $ hg in -B http://localhost:$HGPORT/
503 comparing with http://localhost:$HGPORT/
516 comparing with http://localhost:$HGPORT/
504 searching for changed bookmarks
517 searching for changed bookmarks
505 @ 9b140be10808
518 @ 9b140be10808
506 X 9b140be10808
519 X 9b140be10808
507 Z 0d2164f0ce0d
520 Z 0d2164f0ce0d
508 foo 000000000000
521 foo 000000000000
509 foobar 9b140be10808
522 foobar 9b140be10808
510 $ hg pull -B Z http://localhost:$HGPORT/
523 $ hg pull -B Z http://localhost:$HGPORT/
511 pulling from http://localhost:$HGPORT/
524 pulling from http://localhost:$HGPORT/
512 no changes found
525 no changes found
513 divergent bookmark @ stored as @1
526 divergent bookmark @ stored as @1
514 divergent bookmark X stored as X@1
527 divergent bookmark X stored as X@1
515 adding remote bookmark Z
528 adding remote bookmark Z
516 adding remote bookmark foo
529 adding remote bookmark foo
517 adding remote bookmark foobar
530 adding remote bookmark foobar
518 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
531 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
519 requesting all changes
532 requesting all changes
520 adding changesets
533 adding changesets
521 adding manifests
534 adding manifests
522 adding file changes
535 adding file changes
523 added 5 changesets with 5 changes to 3 files (+2 heads)
536 added 5 changesets with 5 changes to 3 files (+2 heads)
524 2 new obsolescence markers
537 2 new obsolescence markers
525 updating to bookmark @
538 updating to bookmark @
526 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
527 $ hg -R cloned-bookmarks bookmarks
540 $ hg -R cloned-bookmarks bookmarks
528 * @ 1:9b140be10808
541 * @ 1:9b140be10808
529 X 1:9b140be10808
542 X 1:9b140be10808
530 Y 4:c922c0139ca0
543 Y 4:c922c0139ca0
531 Z 2:0d2164f0ce0d
544 Z 2:0d2164f0ce0d
532 foo -1:000000000000
545 foo -1:000000000000
533 foobar 1:9b140be10808
546 foobar 1:9b140be10808
534
547
535 $ cd ..
548 $ cd ..
536
549
537 Test to show result of bookmarks comparision
550 Test to show result of bookmarks comparision
538
551
539 $ mkdir bmcomparison
552 $ mkdir bmcomparison
540 $ cd bmcomparison
553 $ cd bmcomparison
541
554
542 $ hg init source
555 $ hg init source
543 $ hg -R source debugbuilddag '+2*2*3*4'
556 $ hg -R source debugbuilddag '+2*2*3*4'
544 $ hg -R source log -G --template '{rev}:{node|short}'
557 $ hg -R source log -G --template '{rev}:{node|short}'
545 o 4:e7bd5218ca15
558 o 4:e7bd5218ca15
546 |
559 |
547 | o 3:6100d3090acf
560 | o 3:6100d3090acf
548 |/
561 |/
549 | o 2:fa942426a6fd
562 | o 2:fa942426a6fd
550 |/
563 |/
551 | o 1:66f7d451a68b
564 | o 1:66f7d451a68b
552 |/
565 |/
553 o 0:1ea73414a91b
566 o 0:1ea73414a91b
554
567
555 $ hg -R source bookmarks -r 0 SAME
568 $ hg -R source bookmarks -r 0 SAME
556 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
569 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
557 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
570 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
558 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
571 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
559 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
572 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
560 $ hg -R source bookmarks -r 1 DIVERGED
573 $ hg -R source bookmarks -r 1 DIVERGED
561
574
562 $ hg clone -U source repo1
575 $ hg clone -U source repo1
563
576
564 (test that incoming/outgoing exit with 1, if there is no bookmark to
577 (test that incoming/outgoing exit with 1, if there is no bookmark to
565 be exchanged)
578 be exchanged)
566
579
567 $ hg -R repo1 incoming -B
580 $ hg -R repo1 incoming -B
568 comparing with $TESTTMP/bmcomparison/source
581 comparing with $TESTTMP/bmcomparison/source
569 searching for changed bookmarks
582 searching for changed bookmarks
570 no changed bookmarks found
583 no changed bookmarks found
571 [1]
584 [1]
572 $ hg -R repo1 outgoing -B
585 $ hg -R repo1 outgoing -B
573 comparing with $TESTTMP/bmcomparison/source
586 comparing with $TESTTMP/bmcomparison/source
574 searching for changed bookmarks
587 searching for changed bookmarks
575 no changed bookmarks found
588 no changed bookmarks found
576 [1]
589 [1]
577
590
578 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
591 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
579 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
592 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
580 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
593 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
581 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
594 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
582 $ hg -R repo1 -q --config extensions.mq= strip 4
595 $ hg -R repo1 -q --config extensions.mq= strip 4
583 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
596 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
584 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
597 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
585 |
598 |
586 | o fa942426a6fd (ADV_ON_REPO1)
599 | o fa942426a6fd (ADV_ON_REPO1)
587 |/
600 |/
588 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
601 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
589 |/
602 |/
590 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
603 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
591
604
592
605
593 $ hg clone -U source repo2
606 $ hg clone -U source repo2
594 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
607 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
595 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
608 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
596 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
609 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
597 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
610 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
598 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
611 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
599 $ hg -R repo2 -q --config extensions.mq= strip 3
612 $ hg -R repo2 -q --config extensions.mq= strip 3
600 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
613 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
601 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
614 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
602 |
615 |
603 | o fa942426a6fd (DIVERGED)
616 | o fa942426a6fd (DIVERGED)
604 |/
617 |/
605 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
618 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
606 |/
619 |/
607 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
620 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
608
621
609
622
610 (test that difference of bookmarks between repositories are fully shown)
623 (test that difference of bookmarks between repositories are fully shown)
611
624
612 $ hg -R repo1 incoming -B repo2 -v
625 $ hg -R repo1 incoming -B repo2 -v
613 comparing with repo2
626 comparing with repo2
614 searching for changed bookmarks
627 searching for changed bookmarks
615 ADD_ON_REPO2 66f7d451a68b added
628 ADD_ON_REPO2 66f7d451a68b added
616 ADV_ON_REPO2 66f7d451a68b advanced
629 ADV_ON_REPO2 66f7d451a68b advanced
617 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
630 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
618 DIFF_DIVERGED e7bd5218ca15 changed
631 DIFF_DIVERGED e7bd5218ca15 changed
619 DIVERGED fa942426a6fd diverged
632 DIVERGED fa942426a6fd diverged
620 $ hg -R repo1 outgoing -B repo2 -v
633 $ hg -R repo1 outgoing -B repo2 -v
621 comparing with repo2
634 comparing with repo2
622 searching for changed bookmarks
635 searching for changed bookmarks
623 ADD_ON_REPO1 66f7d451a68b added
636 ADD_ON_REPO1 66f7d451a68b added
624 ADD_ON_REPO2 deleted
637 ADD_ON_REPO2 deleted
625 ADV_ON_REPO1 fa942426a6fd advanced
638 ADV_ON_REPO1 fa942426a6fd advanced
626 DIFF_ADV_ON_REPO1 6100d3090acf advanced
639 DIFF_ADV_ON_REPO1 6100d3090acf advanced
627 DIFF_ADV_ON_REPO2 1ea73414a91b changed
640 DIFF_ADV_ON_REPO2 1ea73414a91b changed
628 DIFF_DIVERGED 6100d3090acf changed
641 DIFF_DIVERGED 6100d3090acf changed
629 DIVERGED 66f7d451a68b diverged
642 DIVERGED 66f7d451a68b diverged
630
643
631 $ hg -R repo2 incoming -B repo1 -v
644 $ hg -R repo2 incoming -B repo1 -v
632 comparing with repo1
645 comparing with repo1
633 searching for changed bookmarks
646 searching for changed bookmarks
634 ADD_ON_REPO1 66f7d451a68b added
647 ADD_ON_REPO1 66f7d451a68b added
635 ADV_ON_REPO1 fa942426a6fd advanced
648 ADV_ON_REPO1 fa942426a6fd advanced
636 DIFF_ADV_ON_REPO1 6100d3090acf changed
649 DIFF_ADV_ON_REPO1 6100d3090acf changed
637 DIFF_DIVERGED 6100d3090acf changed
650 DIFF_DIVERGED 6100d3090acf changed
638 DIVERGED 66f7d451a68b diverged
651 DIVERGED 66f7d451a68b diverged
639 $ hg -R repo2 outgoing -B repo1 -v
652 $ hg -R repo2 outgoing -B repo1 -v
640 comparing with repo1
653 comparing with repo1
641 searching for changed bookmarks
654 searching for changed bookmarks
642 ADD_ON_REPO1 deleted
655 ADD_ON_REPO1 deleted
643 ADD_ON_REPO2 66f7d451a68b added
656 ADD_ON_REPO2 66f7d451a68b added
644 ADV_ON_REPO2 66f7d451a68b advanced
657 ADV_ON_REPO2 66f7d451a68b advanced
645 DIFF_ADV_ON_REPO1 1ea73414a91b changed
658 DIFF_ADV_ON_REPO1 1ea73414a91b changed
646 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
659 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
647 DIFF_DIVERGED e7bd5218ca15 changed
660 DIFF_DIVERGED e7bd5218ca15 changed
648 DIVERGED fa942426a6fd diverged
661 DIVERGED fa942426a6fd diverged
649
662
650 $ cd ..
663 $ cd ..
651
664
652 Pushing a bookmark should only push the changes required by that
665 Pushing a bookmark should only push the changes required by that
653 bookmark, not all outgoing changes:
666 bookmark, not all outgoing changes:
654 $ hg clone http://localhost:$HGPORT/ addmarks
667 $ hg clone http://localhost:$HGPORT/ addmarks
655 requesting all changes
668 requesting all changes
656 adding changesets
669 adding changesets
657 adding manifests
670 adding manifests
658 adding file changes
671 adding file changes
659 added 5 changesets with 5 changes to 3 files (+2 heads)
672 added 5 changesets with 5 changes to 3 files (+2 heads)
660 2 new obsolescence markers
673 2 new obsolescence markers
661 updating to bookmark @
674 updating to bookmark @
662 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
675 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
663 $ cd addmarks
676 $ cd addmarks
664 $ echo foo > foo
677 $ echo foo > foo
665 $ hg add foo
678 $ hg add foo
666 $ hg commit -m 'add foo'
679 $ hg commit -m 'add foo'
667 $ echo bar > bar
680 $ echo bar > bar
668 $ hg add bar
681 $ hg add bar
669 $ hg commit -m 'add bar'
682 $ hg commit -m 'add bar'
670 $ hg co "tip^"
683 $ hg co "tip^"
671 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
684 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
672 (leaving bookmark @)
685 (leaving bookmark @)
673 $ hg book add-foo
686 $ hg book add-foo
674 $ hg book -r tip add-bar
687 $ hg book -r tip add-bar
675 Note: this push *must* push only a single changeset, as that's the point
688 Note: this push *must* push only a single changeset, as that's the point
676 of this test.
689 of this test.
677 $ hg push -B add-foo --traceback
690 $ hg push -B add-foo --traceback
678 pushing to http://localhost:$HGPORT/
691 pushing to http://localhost:$HGPORT/
679 searching for changes
692 searching for changes
680 remote: adding changesets
693 remote: adding changesets
681 remote: adding manifests
694 remote: adding manifests
682 remote: adding file changes
695 remote: adding file changes
683 remote: added 1 changesets with 1 changes to 1 files
696 remote: added 1 changesets with 1 changes to 1 files
684 exporting bookmark add-foo
697 exporting bookmark add-foo
685
698
686 pushing a new bookmark on a new head does not require -f if -B is specified
699 pushing a new bookmark on a new head does not require -f if -B is specified
687
700
688 $ hg up -q X
701 $ hg up -q X
689 $ hg book W
702 $ hg book W
690 $ echo c5 > f2
703 $ echo c5 > f2
691 $ hg ci -Am5
704 $ hg ci -Am5
692 created new head
705 created new head
693 $ hg push -B .
706 $ hg push -B .
694 pushing to http://localhost:$HGPORT/
707 pushing to http://localhost:$HGPORT/
695 searching for changes
708 searching for changes
696 remote: adding changesets
709 remote: adding changesets
697 remote: adding manifests
710 remote: adding manifests
698 remote: adding file changes
711 remote: adding file changes
699 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
712 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
700 exporting bookmark W
713 exporting bookmark W
701 $ hg -R ../b id -r W
714 $ hg -R ../b id -r W
702 cc978a373a53 tip W
715 cc978a373a53 tip W
703
716
704 pushing an existing but divergent bookmark with -B still requires -f
717 pushing an existing but divergent bookmark with -B still requires -f
705
718
706 $ hg clone -q . ../r
719 $ hg clone -q . ../r
707 $ hg up -q X
720 $ hg up -q X
708 $ echo 1 > f2
721 $ echo 1 > f2
709 $ hg ci -qAml
722 $ hg ci -qAml
710
723
711 $ cd ../r
724 $ cd ../r
712 $ hg up -q X
725 $ hg up -q X
713 $ echo 2 > f2
726 $ echo 2 > f2
714 $ hg ci -qAmr
727 $ hg ci -qAmr
715 $ hg push -B X
728 $ hg push -B X
716 pushing to $TESTTMP/addmarks (glob)
729 pushing to $TESTTMP/addmarks (glob)
717 searching for changes
730 searching for changes
718 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
731 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
719 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
732 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
720 (pull and merge or see "hg help push" for details about pushing new heads)
733 (pull and merge or see "hg help push" for details about pushing new heads)
721 [255]
734 [255]
722 $ cd ../addmarks
735 $ cd ../addmarks
723
736
724 Check summary output for incoming/outgoing bookmarks
737 Check summary output for incoming/outgoing bookmarks
725
738
726 $ hg bookmarks -d X
739 $ hg bookmarks -d X
727 $ hg bookmarks -d Y
740 $ hg bookmarks -d Y
728 $ hg summary --remote | grep '^remote:'
741 $ hg summary --remote | grep '^remote:'
729 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
742 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
730
743
731 $ cd ..
744 $ cd ..
732
745
733 pushing an unchanged bookmark should result in no changes
746 pushing an unchanged bookmark should result in no changes
734
747
735 $ hg init unchanged-a
748 $ hg init unchanged-a
736 $ hg init unchanged-b
749 $ hg init unchanged-b
737 $ cd unchanged-a
750 $ cd unchanged-a
738 $ echo initial > foo
751 $ echo initial > foo
739 $ hg commit -A -m initial
752 $ hg commit -A -m initial
740 adding foo
753 adding foo
741 $ hg bookmark @
754 $ hg bookmark @
742 $ hg push -B @ ../unchanged-b
755 $ hg push -B @ ../unchanged-b
743 pushing to ../unchanged-b
756 pushing to ../unchanged-b
744 searching for changes
757 searching for changes
745 adding changesets
758 adding changesets
746 adding manifests
759 adding manifests
747 adding file changes
760 adding file changes
748 added 1 changesets with 1 changes to 1 files
761 added 1 changesets with 1 changes to 1 files
749 exporting bookmark @
762 exporting bookmark @
750
763
751 $ hg push -B @ ../unchanged-b
764 $ hg push -B @ ../unchanged-b
752 pushing to ../unchanged-b
765 pushing to ../unchanged-b
753 searching for changes
766 searching for changes
754 no changes found
767 no changes found
755 [1]
768 [1]
756
769
757
770
758 Check hook preventing push (issue4455)
771 Check hook preventing push (issue4455)
759 ======================================
772 ======================================
760
773
761 $ hg bookmarks
774 $ hg bookmarks
762 * @ 0:55482a6fb4b1
775 * @ 0:55482a6fb4b1
763 $ hg log -G
776 $ hg log -G
764 @ 0:55482a6fb4b1 initial
777 @ 0:55482a6fb4b1 initial
765
778
766 $ hg init ../issue4455-dest
779 $ hg init ../issue4455-dest
767 $ hg push ../issue4455-dest # changesets only
780 $ hg push ../issue4455-dest # changesets only
768 pushing to ../issue4455-dest
781 pushing to ../issue4455-dest
769 searching for changes
782 searching for changes
770 adding changesets
783 adding changesets
771 adding manifests
784 adding manifests
772 adding file changes
785 adding file changes
773 added 1 changesets with 1 changes to 1 files
786 added 1 changesets with 1 changes to 1 files
774 $ cat >> .hg/hgrc << EOF
787 $ cat >> .hg/hgrc << EOF
775 > [paths]
788 > [paths]
776 > local=../issue4455-dest/
789 > local=../issue4455-dest/
777 > ssh=ssh://user@dummy/issue4455-dest
790 > ssh=ssh://user@dummy/issue4455-dest
778 > http=http://localhost:$HGPORT/
791 > http=http://localhost:$HGPORT/
779 > [ui]
792 > [ui]
780 > ssh=python "$TESTDIR/dummyssh"
793 > ssh=python "$TESTDIR/dummyssh"
781 > EOF
794 > EOF
782 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
795 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
783 > [hooks]
796 > [hooks]
784 > prepushkey=false
797 > prepushkey=false
785 > [web]
798 > [web]
786 > push_ssl = false
799 > push_ssl = false
787 > allow_push = *
800 > allow_push = *
788 > EOF
801 > EOF
789 $ killdaemons.py
802 $ killdaemons.py
790 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
803 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
791 $ cat ../issue4455.pid >> $DAEMON_PIDS
804 $ cat ../issue4455.pid >> $DAEMON_PIDS
792
805
793 Local push
806 Local push
794 ----------
807 ----------
795
808
796 $ hg push -B @ local
809 $ hg push -B @ local
797 pushing to $TESTTMP/issue4455-dest (glob)
810 pushing to $TESTTMP/issue4455-dest (glob)
798 searching for changes
811 searching for changes
799 no changes found
812 no changes found
800 pushkey-abort: prepushkey hook exited with status 1
813 pushkey-abort: prepushkey hook exited with status 1
801 abort: exporting bookmark @ failed!
814 abort: exporting bookmark @ failed!
802 [255]
815 [255]
803 $ hg -R ../issue4455-dest/ bookmarks
816 $ hg -R ../issue4455-dest/ bookmarks
804 no bookmarks set
817 no bookmarks set
805
818
806 Using ssh
819 Using ssh
807 ---------
820 ---------
808
821
809 $ hg push -B @ ssh --config experimental.bundle2-exp=True
822 $ hg push -B @ ssh --config experimental.bundle2-exp=True
810 pushing to ssh://user@dummy/issue4455-dest
823 pushing to ssh://user@dummy/issue4455-dest
811 searching for changes
824 searching for changes
812 no changes found
825 no changes found
813 remote: pushkey-abort: prepushkey hook exited with status 1
826 remote: pushkey-abort: prepushkey hook exited with status 1
814 abort: exporting bookmark @ failed!
827 abort: exporting bookmark @ failed!
815 [255]
828 [255]
816 $ hg -R ../issue4455-dest/ bookmarks
829 $ hg -R ../issue4455-dest/ bookmarks
817 no bookmarks set
830 no bookmarks set
818
831
819 $ hg push -B @ ssh --config experimental.bundle2-exp=False
832 $ hg push -B @ ssh --config experimental.bundle2-exp=False
820 pushing to ssh://user@dummy/issue4455-dest
833 pushing to ssh://user@dummy/issue4455-dest
821 searching for changes
834 searching for changes
822 no changes found
835 no changes found
823 remote: pushkey-abort: prepushkey hook exited with status 1
836 remote: pushkey-abort: prepushkey hook exited with status 1
824 exporting bookmark @ failed!
837 exporting bookmark @ failed!
825 [1]
838 [1]
826 $ hg -R ../issue4455-dest/ bookmarks
839 $ hg -R ../issue4455-dest/ bookmarks
827 no bookmarks set
840 no bookmarks set
828
841
829 Using http
842 Using http
830 ----------
843 ----------
831
844
832 $ hg push -B @ http --config experimental.bundle2-exp=True
845 $ hg push -B @ http --config experimental.bundle2-exp=True
833 pushing to http://localhost:$HGPORT/
846 pushing to http://localhost:$HGPORT/
834 searching for changes
847 searching for changes
835 no changes found
848 no changes found
836 remote: pushkey-abort: prepushkey hook exited with status 1
849 remote: pushkey-abort: prepushkey hook exited with status 1
837 abort: exporting bookmark @ failed!
850 abort: exporting bookmark @ failed!
838 [255]
851 [255]
839 $ hg -R ../issue4455-dest/ bookmarks
852 $ hg -R ../issue4455-dest/ bookmarks
840 no bookmarks set
853 no bookmarks set
841
854
842 $ hg push -B @ http --config experimental.bundle2-exp=False
855 $ hg push -B @ http --config experimental.bundle2-exp=False
843 pushing to http://localhost:$HGPORT/
856 pushing to http://localhost:$HGPORT/
844 searching for changes
857 searching for changes
845 no changes found
858 no changes found
846 remote: pushkey-abort: prepushkey hook exited with status 1
859 remote: pushkey-abort: prepushkey hook exited with status 1
847 exporting bookmark @ failed!
860 exporting bookmark @ failed!
848 [1]
861 [1]
849 $ hg -R ../issue4455-dest/ bookmarks
862 $ hg -R ../issue4455-dest/ bookmarks
850 no bookmarks set
863 no bookmarks set
General Comments 0
You need to be logged in to leave comments. Login now