##// END OF EJS Templates
bookmarks: when @ bookmark diverges, don't double the @ sign (BC)...
David M. Carr -
r17770:6c81b8eb default
parent child Browse files
Show More
@@ -1,284 +1,288
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 mercurial.i18n import _
8 from mercurial.i18n import _
9 from mercurial.node import hex
9 from mercurial.node import hex
10 from mercurial import encoding, error, util, obsolete, phases
10 from mercurial import encoding, error, util, obsolete, phases
11 import errno, os
11 import errno, os
12
12
13 def valid(mark):
13 def valid(mark):
14 for c in (':', '\0', '\n', '\r'):
14 for c in (':', '\0', '\n', '\r'):
15 if c in mark:
15 if c in mark:
16 return False
16 return False
17 return True
17 return True
18
18
19 def read(repo):
19 def read(repo):
20 '''Parse .hg/bookmarks file and return a dictionary
20 '''Parse .hg/bookmarks file and return a dictionary
21
21
22 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
22 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
23 in the .hg/bookmarks file.
23 in the .hg/bookmarks file.
24 Read the file and return a (name=>nodeid) dictionary
24 Read the file and return a (name=>nodeid) dictionary
25 '''
25 '''
26 bookmarks = {}
26 bookmarks = {}
27 try:
27 try:
28 for line in repo.opener('bookmarks'):
28 for line in repo.opener('bookmarks'):
29 line = line.strip()
29 line = line.strip()
30 if not line:
30 if not line:
31 continue
31 continue
32 if ' ' not in line:
32 if ' ' not in line:
33 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
33 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
34 continue
34 continue
35 sha, refspec = line.split(' ', 1)
35 sha, refspec = line.split(' ', 1)
36 refspec = encoding.tolocal(refspec)
36 refspec = encoding.tolocal(refspec)
37 try:
37 try:
38 bookmarks[refspec] = repo.changelog.lookup(sha)
38 bookmarks[refspec] = repo.changelog.lookup(sha)
39 except LookupError:
39 except LookupError:
40 pass
40 pass
41 except IOError, inst:
41 except IOError, inst:
42 if inst.errno != errno.ENOENT:
42 if inst.errno != errno.ENOENT:
43 raise
43 raise
44 return bookmarks
44 return bookmarks
45
45
46 def readcurrent(repo):
46 def readcurrent(repo):
47 '''Get the current bookmark
47 '''Get the current bookmark
48
48
49 If we use gittishsh branches we have a current bookmark that
49 If we use gittishsh branches we have a current bookmark that
50 we are on. This function returns the name of the bookmark. It
50 we are on. This function returns the name of the bookmark. It
51 is stored in .hg/bookmarks.current
51 is stored in .hg/bookmarks.current
52 '''
52 '''
53 mark = None
53 mark = None
54 try:
54 try:
55 file = repo.opener('bookmarks.current')
55 file = repo.opener('bookmarks.current')
56 except IOError, inst:
56 except IOError, inst:
57 if inst.errno != errno.ENOENT:
57 if inst.errno != errno.ENOENT:
58 raise
58 raise
59 return None
59 return None
60 try:
60 try:
61 # No readline() in osutil.posixfile, reading everything is cheap
61 # No readline() in osutil.posixfile, reading everything is cheap
62 mark = encoding.tolocal((file.readlines() or [''])[0])
62 mark = encoding.tolocal((file.readlines() or [''])[0])
63 if mark == '' or mark not in repo._bookmarks:
63 if mark == '' or mark not in repo._bookmarks:
64 mark = None
64 mark = None
65 finally:
65 finally:
66 file.close()
66 file.close()
67 return mark
67 return mark
68
68
69 def write(repo):
69 def write(repo):
70 '''Write bookmarks
70 '''Write bookmarks
71
71
72 Write the given bookmark => hash dictionary to the .hg/bookmarks file
72 Write the given bookmark => hash dictionary to the .hg/bookmarks file
73 in a format equal to those of localtags.
73 in a format equal to those of localtags.
74
74
75 We also store a backup of the previous state in undo.bookmarks that
75 We also store a backup of the previous state in undo.bookmarks that
76 can be copied back on rollback.
76 can be copied back on rollback.
77 '''
77 '''
78 refs = repo._bookmarks
78 refs = repo._bookmarks
79
79
80 if repo._bookmarkcurrent not in refs:
80 if repo._bookmarkcurrent not in refs:
81 setcurrent(repo, None)
81 setcurrent(repo, None)
82 for mark in refs.keys():
82 for mark in refs.keys():
83 if not valid(mark):
83 if not valid(mark):
84 raise util.Abort(_("bookmark '%s' contains illegal "
84 raise util.Abort(_("bookmark '%s' contains illegal "
85 "character" % mark))
85 "character" % mark))
86
86
87 wlock = repo.wlock()
87 wlock = repo.wlock()
88 try:
88 try:
89
89
90 file = repo.opener('bookmarks', 'w', atomictemp=True)
90 file = repo.opener('bookmarks', 'w', atomictemp=True)
91 for refspec, node in refs.iteritems():
91 for refspec, node in refs.iteritems():
92 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
92 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
93 file.close()
93 file.close()
94
94
95 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
95 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
96 try:
96 try:
97 os.utime(repo.sjoin('00changelog.i'), None)
97 os.utime(repo.sjoin('00changelog.i'), None)
98 except OSError:
98 except OSError:
99 pass
99 pass
100
100
101 finally:
101 finally:
102 wlock.release()
102 wlock.release()
103
103
104 def setcurrent(repo, mark):
104 def setcurrent(repo, mark):
105 '''Set the name of the bookmark that we are currently on
105 '''Set the name of the bookmark that we are currently on
106
106
107 Set the name of the bookmark that we are on (hg update <bookmark>).
107 Set the name of the bookmark that we are on (hg update <bookmark>).
108 The name is recorded in .hg/bookmarks.current
108 The name is recorded in .hg/bookmarks.current
109 '''
109 '''
110 current = repo._bookmarkcurrent
110 current = repo._bookmarkcurrent
111 if current == mark:
111 if current == mark:
112 return
112 return
113
113
114 if mark not in repo._bookmarks:
114 if mark not in repo._bookmarks:
115 mark = ''
115 mark = ''
116 if not valid(mark):
116 if not valid(mark):
117 raise util.Abort(_("bookmark '%s' contains illegal "
117 raise util.Abort(_("bookmark '%s' contains illegal "
118 "character" % mark))
118 "character" % mark))
119
119
120 wlock = repo.wlock()
120 wlock = repo.wlock()
121 try:
121 try:
122 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
122 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
123 file.write(encoding.fromlocal(mark))
123 file.write(encoding.fromlocal(mark))
124 file.close()
124 file.close()
125 finally:
125 finally:
126 wlock.release()
126 wlock.release()
127 repo._bookmarkcurrent = mark
127 repo._bookmarkcurrent = mark
128
128
129 def unsetcurrent(repo):
129 def unsetcurrent(repo):
130 wlock = repo.wlock()
130 wlock = repo.wlock()
131 try:
131 try:
132 try:
132 try:
133 util.unlink(repo.join('bookmarks.current'))
133 util.unlink(repo.join('bookmarks.current'))
134 repo._bookmarkcurrent = None
134 repo._bookmarkcurrent = None
135 except OSError, inst:
135 except OSError, inst:
136 if inst.errno != errno.ENOENT:
136 if inst.errno != errno.ENOENT:
137 raise
137 raise
138 finally:
138 finally:
139 wlock.release()
139 wlock.release()
140
140
141 def updatecurrentbookmark(repo, oldnode, curbranch):
141 def updatecurrentbookmark(repo, oldnode, curbranch):
142 try:
142 try:
143 return update(repo, oldnode, repo.branchtip(curbranch))
143 return update(repo, oldnode, repo.branchtip(curbranch))
144 except error.RepoLookupError:
144 except error.RepoLookupError:
145 if curbranch == "default": # no default branch!
145 if curbranch == "default": # no default branch!
146 return update(repo, oldnode, repo.lookup("tip"))
146 return update(repo, oldnode, repo.lookup("tip"))
147 else:
147 else:
148 raise util.Abort(_("branch %s not found") % curbranch)
148 raise util.Abort(_("branch %s not found") % curbranch)
149
149
150 def update(repo, parents, node):
150 def update(repo, parents, node):
151 marks = repo._bookmarks
151 marks = repo._bookmarks
152 update = False
152 update = False
153 cur = repo._bookmarkcurrent
153 cur = repo._bookmarkcurrent
154 if not cur:
154 if not cur:
155 return False
155 return False
156
156
157 toupdate = [b for b in marks if b.split('@', 1)[0] == cur.split('@', 1)[0]]
157 toupdate = [b for b in marks if b.split('@', 1)[0] == cur.split('@', 1)[0]]
158 for mark in toupdate:
158 for mark in toupdate:
159 if mark and marks[mark] in parents:
159 if mark and marks[mark] in parents:
160 old = repo[marks[mark]]
160 old = repo[marks[mark]]
161 new = repo[node]
161 new = repo[node]
162 if old.descendant(new) and mark == cur:
162 if old.descendant(new) and mark == cur:
163 marks[cur] = new.node()
163 marks[cur] = new.node()
164 update = True
164 update = True
165 if mark != cur:
165 if mark != cur:
166 del marks[mark]
166 del marks[mark]
167 if update:
167 if update:
168 repo._writebookmarks(marks)
168 repo._writebookmarks(marks)
169 return update
169 return update
170
170
171 def listbookmarks(repo):
171 def listbookmarks(repo):
172 # We may try to list bookmarks on a repo type that does not
172 # We may try to list bookmarks on a repo type that does not
173 # support it (e.g., statichttprepository).
173 # support it (e.g., statichttprepository).
174 marks = getattr(repo, '_bookmarks', {})
174 marks = getattr(repo, '_bookmarks', {})
175
175
176 d = {}
176 d = {}
177 for k, v in marks.iteritems():
177 for k, v in marks.iteritems():
178 # don't expose local divergent bookmarks
178 # don't expose local divergent bookmarks
179 if '@' not in k or k.endswith('@'):
179 if '@' not in k or k.endswith('@'):
180 d[k] = hex(v)
180 d[k] = hex(v)
181 return d
181 return d
182
182
183 def pushbookmark(repo, key, old, new):
183 def pushbookmark(repo, key, old, new):
184 w = repo.wlock()
184 w = repo.wlock()
185 try:
185 try:
186 marks = repo._bookmarks
186 marks = repo._bookmarks
187 if hex(marks.get(key, '')) != old:
187 if hex(marks.get(key, '')) != old:
188 return False
188 return False
189 if new == '':
189 if new == '':
190 del marks[key]
190 del marks[key]
191 else:
191 else:
192 if new not in repo:
192 if new not in repo:
193 return False
193 return False
194 marks[key] = repo[new].node()
194 marks[key] = repo[new].node()
195 write(repo)
195 write(repo)
196 return True
196 return True
197 finally:
197 finally:
198 w.release()
198 w.release()
199
199
200 def updatefromremote(ui, repo, remote, path):
200 def updatefromremote(ui, repo, remote, path):
201 ui.debug("checking for updated bookmarks\n")
201 ui.debug("checking for updated bookmarks\n")
202 rb = remote.listkeys('bookmarks')
202 rb = remote.listkeys('bookmarks')
203 changed = False
203 changed = False
204 for k in rb.keys():
204 for k in rb.keys():
205 if k in repo._bookmarks:
205 if k in repo._bookmarks:
206 nr, nl = rb[k], repo._bookmarks[k]
206 nr, nl = rb[k], repo._bookmarks[k]
207 if nr in repo:
207 if nr in repo:
208 cr = repo[nr]
208 cr = repo[nr]
209 cl = repo[nl]
209 cl = repo[nl]
210 if cl.rev() >= cr.rev():
210 if cl.rev() >= cr.rev():
211 continue
211 continue
212 if validdest(repo, cl, cr):
212 if validdest(repo, cl, cr):
213 repo._bookmarks[k] = cr.node()
213 repo._bookmarks[k] = cr.node()
214 changed = True
214 changed = True
215 ui.status(_("updating bookmark %s\n") % k)
215 ui.status(_("updating bookmark %s\n") % k)
216 else:
216 else:
217 if k == '@':
218 kd = ''
219 else:
220 kd = k
217 # find a unique @ suffix
221 # find a unique @ suffix
218 for x in range(1, 100):
222 for x in range(1, 100):
219 n = '%s@%d' % (k, x)
223 n = '%s@%d' % (kd, x)
220 if n not in repo._bookmarks:
224 if n not in repo._bookmarks:
221 break
225 break
222 # try to use an @pathalias suffix
226 # try to use an @pathalias suffix
223 # if an @pathalias already exists, we overwrite (update) it
227 # if an @pathalias already exists, we overwrite (update) it
224 for p, u in ui.configitems("paths"):
228 for p, u in ui.configitems("paths"):
225 if path == u:
229 if path == u:
226 n = '%s@%s' % (k, p)
230 n = '%s@%s' % (kd, p)
227
231
228 repo._bookmarks[n] = cr.node()
232 repo._bookmarks[n] = cr.node()
229 changed = True
233 changed = True
230 ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
234 ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
231 elif rb[k] in repo:
235 elif rb[k] in repo:
232 # add remote bookmarks for changes we already have
236 # add remote bookmarks for changes we already have
233 repo._bookmarks[k] = repo[rb[k]].node()
237 repo._bookmarks[k] = repo[rb[k]].node()
234 changed = True
238 changed = True
235 ui.status(_("adding remote bookmark %s\n") % k)
239 ui.status(_("adding remote bookmark %s\n") % k)
236
240
237 if changed:
241 if changed:
238 write(repo)
242 write(repo)
239
243
240 def diff(ui, dst, src):
244 def diff(ui, dst, src):
241 ui.status(_("searching for changed bookmarks\n"))
245 ui.status(_("searching for changed bookmarks\n"))
242
246
243 smarks = src.listkeys('bookmarks')
247 smarks = src.listkeys('bookmarks')
244 dmarks = dst.listkeys('bookmarks')
248 dmarks = dst.listkeys('bookmarks')
245
249
246 diff = sorted(set(smarks) - set(dmarks))
250 diff = sorted(set(smarks) - set(dmarks))
247 for k in diff:
251 for k in diff:
248 mark = ui.debugflag and smarks[k] or smarks[k][:12]
252 mark = ui.debugflag and smarks[k] or smarks[k][:12]
249 ui.write(" %-25s %s\n" % (k, mark))
253 ui.write(" %-25s %s\n" % (k, mark))
250
254
251 if len(diff) <= 0:
255 if len(diff) <= 0:
252 ui.status(_("no changed bookmarks found\n"))
256 ui.status(_("no changed bookmarks found\n"))
253 return 1
257 return 1
254 return 0
258 return 0
255
259
256 def validdest(repo, old, new):
260 def validdest(repo, old, new):
257 """Is the new bookmark destination a valid update from the old one"""
261 """Is the new bookmark destination a valid update from the old one"""
258 if old == new:
262 if old == new:
259 # Old == new -> nothing to update.
263 # Old == new -> nothing to update.
260 return False
264 return False
261 elif not old:
265 elif not old:
262 # old is nullrev, anything is valid.
266 # old is nullrev, anything is valid.
263 # (new != nullrev has been excluded by the previous check)
267 # (new != nullrev has been excluded by the previous check)
264 return True
268 return True
265 elif repo.obsstore:
269 elif repo.obsstore:
266 # We only need this complicated logic if there is obsolescence
270 # We only need this complicated logic if there is obsolescence
267 # XXX will probably deserve an optimised revset.
271 # XXX will probably deserve an optimised revset.
268
272
269 validdests = set([old])
273 validdests = set([old])
270 plen = -1
274 plen = -1
271 # compute the whole set of successors or descendants
275 # compute the whole set of successors or descendants
272 while len(validdests) != plen:
276 while len(validdests) != plen:
273 plen = len(validdests)
277 plen = len(validdests)
274 succs = set(c.node() for c in validdests)
278 succs = set(c.node() for c in validdests)
275 for c in validdests:
279 for c in validdests:
276 if c.phase() > phases.public:
280 if c.phase() > phases.public:
277 # obsolescence marker does not apply to public changeset
281 # obsolescence marker does not apply to public changeset
278 succs.update(obsolete.anysuccessors(repo.obsstore,
282 succs.update(obsolete.anysuccessors(repo.obsstore,
279 c.node()))
283 c.node()))
280 validdests = set(repo.set('%ln::', succs))
284 validdests = set(repo.set('%ln::', succs))
281 validdests.remove(old)
285 validdests.remove(old)
282 return new in validdests
286 return new in validdests
283 else:
287 else:
284 return old.descendant(new)
288 return old.descendant(new)
@@ -1,346 +1,361
1 $ "$TESTDIR/hghave" serve || exit 80
1 $ "$TESTDIR/hghave" serve || exit 80
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [phases]
4 > [phases]
5 > publish=False
5 > publish=False
6 > [extensions]
6 > [extensions]
7 > EOF
7 > EOF
8 $ cat > obs.py << EOF
8 $ cat > obs.py << EOF
9 > import mercurial.obsolete
9 > import mercurial.obsolete
10 > mercurial.obsolete._enabled = True
10 > mercurial.obsolete._enabled = True
11 > EOF
11 > EOF
12 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
12 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
13
13
14 initialize
14 initialize
15
15
16 $ hg init a
16 $ hg init a
17 $ cd a
17 $ cd a
18 $ echo 'test' > test
18 $ echo 'test' > test
19 $ hg commit -Am'test'
19 $ hg commit -Am'test'
20 adding test
20 adding test
21
21
22 set bookmarks
22 set bookmarks
23
23
24 $ hg bookmark X
24 $ hg bookmark X
25 $ hg bookmark Y
25 $ hg bookmark Y
26 $ hg bookmark Z
26 $ hg bookmark Z
27
27
28 import bookmark by name
28 import bookmark by name
29
29
30 $ hg init ../b
30 $ hg init ../b
31 $ cd ../b
31 $ cd ../b
32 $ hg book Y
32 $ hg book Y
33 $ hg book
33 $ hg book
34 * Y -1:000000000000
34 * Y -1:000000000000
35 $ hg pull ../a
35 $ hg pull ../a
36 pulling from ../a
36 pulling from ../a
37 requesting all changes
37 requesting all changes
38 adding changesets
38 adding changesets
39 adding manifests
39 adding manifests
40 adding file changes
40 adding file changes
41 added 1 changesets with 1 changes to 1 files
41 added 1 changesets with 1 changes to 1 files
42 updating bookmark Y
42 updating bookmark Y
43 adding remote bookmark X
43 adding remote bookmark X
44 adding remote bookmark Z
44 adding remote bookmark Z
45 (run 'hg update' to get a working copy)
45 (run 'hg update' to get a working copy)
46 $ hg bookmarks
46 $ hg bookmarks
47 X 0:4e3505fd9583
47 X 0:4e3505fd9583
48 Y 0:4e3505fd9583
48 Y 0:4e3505fd9583
49 Z 0:4e3505fd9583
49 Z 0:4e3505fd9583
50 $ hg debugpushkey ../a namespaces
50 $ hg debugpushkey ../a namespaces
51 bookmarks
51 bookmarks
52 phases
52 phases
53 namespaces
53 namespaces
54 obsolete
54 obsolete
55 $ hg debugpushkey ../a bookmarks
55 $ hg debugpushkey ../a bookmarks
56 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
56 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
57 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
57 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 $ hg pull -B X ../a
59 $ hg pull -B X ../a
60 pulling from ../a
60 pulling from ../a
61 no changes found
61 no changes found
62 importing bookmark X
62 importing bookmark X
63 $ hg bookmark
63 $ hg bookmark
64 X 0:4e3505fd9583
64 X 0:4e3505fd9583
65 Y 0:4e3505fd9583
65 Y 0:4e3505fd9583
66 Z 0:4e3505fd9583
66 Z 0:4e3505fd9583
67
67
68 export bookmark by name
68 export bookmark by name
69
69
70 $ hg bookmark W
70 $ hg bookmark W
71 $ hg bookmark foo
71 $ hg bookmark foo
72 $ hg bookmark foobar
72 $ hg bookmark foobar
73 $ hg push -B W ../a
73 $ hg push -B W ../a
74 pushing to ../a
74 pushing to ../a
75 searching for changes
75 searching for changes
76 no changes found
76 no changes found
77 exporting bookmark W
77 exporting bookmark W
78 [1]
78 [1]
79 $ hg -R ../a bookmarks
79 $ hg -R ../a bookmarks
80 W -1:000000000000
80 W -1:000000000000
81 X 0:4e3505fd9583
81 X 0:4e3505fd9583
82 Y 0:4e3505fd9583
82 Y 0:4e3505fd9583
83 * Z 0:4e3505fd9583
83 * Z 0:4e3505fd9583
84
84
85 delete a remote bookmark
85 delete a remote bookmark
86
86
87 $ hg book -d W
87 $ hg book -d W
88 $ hg push -B W ../a
88 $ hg push -B W ../a
89 pushing to ../a
89 pushing to ../a
90 searching for changes
90 searching for changes
91 no changes found
91 no changes found
92 deleting remote bookmark W
92 deleting remote bookmark W
93 [1]
93 [1]
94
94
95 push/pull name that doesn't exist
95 push/pull name that doesn't exist
96
96
97 $ hg push -B badname ../a
97 $ hg push -B badname ../a
98 pushing to ../a
98 pushing to ../a
99 searching for changes
99 searching for changes
100 no changes found
100 no changes found
101 bookmark badname does not exist on the local or remote repository!
101 bookmark badname does not exist on the local or remote repository!
102 [2]
102 [2]
103 $ hg pull -B anotherbadname ../a
103 $ hg pull -B anotherbadname ../a
104 pulling from ../a
104 pulling from ../a
105 abort: remote bookmark anotherbadname not found!
105 abort: remote bookmark anotherbadname not found!
106 [255]
106 [255]
107
107
108 divergent bookmarks
108 divergent bookmarks
109
109
110 $ cd ../a
110 $ cd ../a
111 $ echo c1 > f1
111 $ echo c1 > f1
112 $ hg ci -Am1
112 $ hg ci -Am1
113 adding f1
113 adding f1
114 $ hg book -f @
114 $ hg book -f X
115 $ hg book -f X
115 $ hg book
116 $ hg book
117 @ 1:0d2164f0ce0d
116 * X 1:0d2164f0ce0d
118 * X 1:0d2164f0ce0d
117 Y 0:4e3505fd9583
119 Y 0:4e3505fd9583
118 Z 1:0d2164f0ce0d
120 Z 1:0d2164f0ce0d
119
121
120 $ cd ../b
122 $ cd ../b
121 $ hg up
123 $ hg up
122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 updating bookmark foobar
125 updating bookmark foobar
124 $ echo c2 > f2
126 $ echo c2 > f2
125 $ hg ci -Am2
127 $ hg ci -Am2
126 adding f2
128 adding f2
129 $ hg book -f @
127 $ hg book -f X
130 $ hg book -f X
128 $ hg book
131 $ hg book
132 @ 1:9b140be10808
129 * X 1:9b140be10808
133 * X 1:9b140be10808
130 Y 0:4e3505fd9583
134 Y 0:4e3505fd9583
131 Z 0:4e3505fd9583
135 Z 0:4e3505fd9583
132 foo -1:000000000000
136 foo -1:000000000000
133 foobar 1:9b140be10808
137 foobar 1:9b140be10808
134
138
135 $ hg pull --config paths.foo=../a foo
139 $ hg pull --config paths.foo=../a foo
136 pulling from $TESTTMP/a (glob)
140 pulling from $TESTTMP/a (glob)
137 searching for changes
141 searching for changes
138 adding changesets
142 adding changesets
139 adding manifests
143 adding manifests
140 adding file changes
144 adding file changes
141 added 1 changesets with 1 changes to 1 files (+1 heads)
145 added 1 changesets with 1 changes to 1 files (+1 heads)
142 divergent bookmark X stored as X@foo
146 divergent bookmark X stored as X@foo
143 updating bookmark Z
147 updating bookmark Z
148 divergent bookmark @ stored as @foo
144 (run 'hg heads' to see heads, 'hg merge' to merge)
149 (run 'hg heads' to see heads, 'hg merge' to merge)
145 $ hg book
150 $ hg book
151 @ 1:9b140be10808
152 @foo 2:0d2164f0ce0d
146 * X 1:9b140be10808
153 * X 1:9b140be10808
147 X@foo 2:0d2164f0ce0d
154 X@foo 2:0d2164f0ce0d
148 Y 0:4e3505fd9583
155 Y 0:4e3505fd9583
149 Z 2:0d2164f0ce0d
156 Z 2:0d2164f0ce0d
150 foo -1:000000000000
157 foo -1:000000000000
151 foobar 1:9b140be10808
158 foobar 1:9b140be10808
152 $ hg push -f ../a
159 $ hg push -f ../a
153 pushing to ../a
160 pushing to ../a
154 searching for changes
161 searching for changes
155 adding changesets
162 adding changesets
156 adding manifests
163 adding manifests
157 adding file changes
164 adding file changes
158 added 1 changesets with 1 changes to 1 files (+1 heads)
165 added 1 changesets with 1 changes to 1 files (+1 heads)
159 $ hg -R ../a book
166 $ hg -R ../a book
167 @ 1:0d2164f0ce0d
160 * X 1:0d2164f0ce0d
168 * X 1:0d2164f0ce0d
161 Y 0:4e3505fd9583
169 Y 0:4e3505fd9583
162 Z 1:0d2164f0ce0d
170 Z 1:0d2164f0ce0d
163
171
164 update a remote bookmark from a non-head to a head
172 update a remote bookmark from a non-head to a head
165
173
166 $ hg up -q Y
174 $ hg up -q Y
167 $ echo c3 > f2
175 $ echo c3 > f2
168 $ hg ci -Am3
176 $ hg ci -Am3
169 adding f2
177 adding f2
170 created new head
178 created new head
171 $ hg push ../a
179 $ hg push ../a
172 pushing to ../a
180 pushing to ../a
173 searching for changes
181 searching for changes
174 adding changesets
182 adding changesets
175 adding manifests
183 adding manifests
176 adding file changes
184 adding file changes
177 added 1 changesets with 1 changes to 1 files (+1 heads)
185 added 1 changesets with 1 changes to 1 files (+1 heads)
178 updating bookmark Y
186 updating bookmark Y
179 $ hg -R ../a book
187 $ hg -R ../a book
188 @ 1:0d2164f0ce0d
180 * X 1:0d2164f0ce0d
189 * X 1:0d2164f0ce0d
181 Y 3:f6fc62dde3c0
190 Y 3:f6fc62dde3c0
182 Z 1:0d2164f0ce0d
191 Z 1:0d2164f0ce0d
183
192
184 diverging a remote bookmark fails
193 diverging a remote bookmark fails
185
194
186 $ hg up -q 4e3505fd9583
195 $ hg up -q 4e3505fd9583
187 $ echo c4 > f2
196 $ echo c4 > f2
188 $ hg ci -Am4
197 $ hg ci -Am4
189 adding f2
198 adding f2
190 created new head
199 created new head
191 $ hg book -f Y
200 $ hg book -f Y
192
201
193 $ cat <<EOF > ../a/.hg/hgrc
202 $ cat <<EOF > ../a/.hg/hgrc
194 > [web]
203 > [web]
195 > push_ssl = false
204 > push_ssl = false
196 > allow_push = *
205 > allow_push = *
197 > EOF
206 > EOF
198
207
199 $ hg -R ../a serve -p $HGPORT2 -d --pid-file=../hg2.pid
208 $ hg -R ../a serve -p $HGPORT2 -d --pid-file=../hg2.pid
200 $ cat ../hg2.pid >> $DAEMON_PIDS
209 $ cat ../hg2.pid >> $DAEMON_PIDS
201
210
202 $ hg push http://localhost:$HGPORT2/
211 $ hg push http://localhost:$HGPORT2/
203 pushing to http://localhost:$HGPORT2/
212 pushing to http://localhost:$HGPORT2/
204 searching for changes
213 searching for changes
205 abort: push creates new remote head 4efff6d98829!
214 abort: push creates new remote head 4efff6d98829!
206 (did you forget to merge? use push -f to force)
215 (did you forget to merge? use push -f to force)
207 [255]
216 [255]
208 $ hg -R ../a book
217 $ hg -R ../a book
218 @ 1:0d2164f0ce0d
209 * X 1:0d2164f0ce0d
219 * X 1:0d2164f0ce0d
210 Y 3:f6fc62dde3c0
220 Y 3:f6fc62dde3c0
211 Z 1:0d2164f0ce0d
221 Z 1:0d2164f0ce0d
212
222
213
223
214 Unrelated marker does not alter the decision
224 Unrelated marker does not alter the decision
215
225
216 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
226 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
217 $ hg push http://localhost:$HGPORT2/
227 $ hg push http://localhost:$HGPORT2/
218 pushing to http://localhost:$HGPORT2/
228 pushing to http://localhost:$HGPORT2/
219 searching for changes
229 searching for changes
220 abort: push creates new remote head 4efff6d98829!
230 abort: push creates new remote head 4efff6d98829!
221 (did you forget to merge? use push -f to force)
231 (did you forget to merge? use push -f to force)
222 [255]
232 [255]
223 $ hg -R ../a book
233 $ hg -R ../a book
234 @ 1:0d2164f0ce0d
224 * X 1:0d2164f0ce0d
235 * X 1:0d2164f0ce0d
225 Y 3:f6fc62dde3c0
236 Y 3:f6fc62dde3c0
226 Z 1:0d2164f0ce0d
237 Z 1:0d2164f0ce0d
227
238
228 Update to a successor works
239 Update to a successor works
229
240
230 $ hg id --debug -r 3
241 $ hg id --debug -r 3
231 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
242 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
232 $ hg id --debug -r 4
243 $ hg id --debug -r 4
233 4efff6d98829d9c824c621afd6e3f01865f5439f tip Y
244 4efff6d98829d9c824c621afd6e3f01865f5439f tip Y
234 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f 4efff6d98829d9c824c621afd6e3f01865f5439f
245 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f 4efff6d98829d9c824c621afd6e3f01865f5439f
235 $ hg push http://localhost:$HGPORT2/
246 $ hg push http://localhost:$HGPORT2/
236 pushing to http://localhost:$HGPORT2/
247 pushing to http://localhost:$HGPORT2/
237 searching for changes
248 searching for changes
238 remote: adding changesets
249 remote: adding changesets
239 remote: adding manifests
250 remote: adding manifests
240 remote: adding file changes
251 remote: adding file changes
241 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
252 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
242 updating bookmark Y
253 updating bookmark Y
243 $ hg -R ../a book
254 $ hg -R ../a book
255 @ 1:0d2164f0ce0d
244 * X 1:0d2164f0ce0d
256 * X 1:0d2164f0ce0d
245 Y 4:4efff6d98829
257 Y 4:4efff6d98829
246 Z 1:0d2164f0ce0d
258 Z 1:0d2164f0ce0d
247
259
248 hgweb
260 hgweb
249
261
250 $ cat <<EOF > .hg/hgrc
262 $ cat <<EOF > .hg/hgrc
251 > [web]
263 > [web]
252 > push_ssl = false
264 > push_ssl = false
253 > allow_push = *
265 > allow_push = *
254 > EOF
266 > EOF
255
267
256 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
268 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
257 $ cat ../hg.pid >> $DAEMON_PIDS
269 $ cat ../hg.pid >> $DAEMON_PIDS
258 $ cd ../a
270 $ cd ../a
259
271
260 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
272 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
261 bookmarks
273 bookmarks
262 phases
274 phases
263 namespaces
275 namespaces
264 obsolete
276 obsolete
265 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
277 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
278 @ 9b140be1080824d768c5a4691a564088eede71f9
279 foo 0000000000000000000000000000000000000000
280 foobar 9b140be1080824d768c5a4691a564088eede71f9
266 Y 4efff6d98829d9c824c621afd6e3f01865f5439f
281 Y 4efff6d98829d9c824c621afd6e3f01865f5439f
267 foobar 9b140be1080824d768c5a4691a564088eede71f9
282 X 9b140be1080824d768c5a4691a564088eede71f9
268 Z 0d2164f0ce0d8f1d6f94351eba04b794909be66c
283 Z 0d2164f0ce0d8f1d6f94351eba04b794909be66c
269 foo 0000000000000000000000000000000000000000
270 X 9b140be1080824d768c5a4691a564088eede71f9
271 $ hg out -B http://localhost:$HGPORT/
284 $ hg out -B http://localhost:$HGPORT/
272 comparing with http://localhost:$HGPORT/
285 comparing with http://localhost:$HGPORT/
273 searching for changed bookmarks
286 searching for changed bookmarks
274 no changed bookmarks found
287 no changed bookmarks found
275 [1]
288 [1]
276 $ hg push -B Z http://localhost:$HGPORT/
289 $ hg push -B Z http://localhost:$HGPORT/
277 pushing to http://localhost:$HGPORT/
290 pushing to http://localhost:$HGPORT/
278 searching for changes
291 searching for changes
279 no changes found
292 no changes found
280 exporting bookmark Z
293 exporting bookmark Z
281 [1]
294 [1]
282 $ hg book -d Z
295 $ hg book -d Z
283 $ hg in -B http://localhost:$HGPORT/
296 $ hg in -B http://localhost:$HGPORT/
284 comparing with http://localhost:$HGPORT/
297 comparing with http://localhost:$HGPORT/
285 searching for changed bookmarks
298 searching for changed bookmarks
286 Z 0d2164f0ce0d
299 Z 0d2164f0ce0d
287 foo 000000000000
300 foo 000000000000
288 foobar 9b140be10808
301 foobar 9b140be10808
289 $ hg pull -B Z http://localhost:$HGPORT/
302 $ hg pull -B Z http://localhost:$HGPORT/
290 pulling from http://localhost:$HGPORT/
303 pulling from http://localhost:$HGPORT/
291 no changes found
304 no changes found
305 divergent bookmark @ stored as @1
306 adding remote bookmark foo
292 adding remote bookmark foobar
307 adding remote bookmark foobar
308 divergent bookmark X stored as X@1
293 adding remote bookmark Z
309 adding remote bookmark Z
294 adding remote bookmark foo
295 divergent bookmark X stored as X@1
296 importing bookmark Z
310 importing bookmark Z
297 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
311 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
298 requesting all changes
312 requesting all changes
299 adding changesets
313 adding changesets
300 adding manifests
314 adding manifests
301 adding file changes
315 adding file changes
302 added 4 changesets with 4 changes to 3 files (+2 heads)
316 added 4 changesets with 4 changes to 3 files (+2 heads)
303 updating to branch default
317 updating to branch default
304 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
305 $ hg -R cloned-bookmarks bookmarks
319 $ hg -R cloned-bookmarks bookmarks
320 @ 1:9b140be10808
306 X 1:9b140be10808
321 X 1:9b140be10808
307 Y 3:4efff6d98829
322 Y 3:4efff6d98829
308 Z 2:0d2164f0ce0d
323 Z 2:0d2164f0ce0d
309 foo -1:000000000000
324 foo -1:000000000000
310 foobar 1:9b140be10808
325 foobar 1:9b140be10808
311
326
312 $ cd ..
327 $ cd ..
313
328
314 Pushing a bookmark should only push the changes required by that
329 Pushing a bookmark should only push the changes required by that
315 bookmark, not all outgoing changes:
330 bookmark, not all outgoing changes:
316 $ hg clone http://localhost:$HGPORT/ addmarks
331 $ hg clone http://localhost:$HGPORT/ addmarks
317 requesting all changes
332 requesting all changes
318 adding changesets
333 adding changesets
319 adding manifests
334 adding manifests
320 adding file changes
335 adding file changes
321 added 4 changesets with 4 changes to 3 files (+2 heads)
336 added 4 changesets with 4 changes to 3 files (+2 heads)
322 updating to branch default
337 updating to branch default
323 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
338 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
324 $ cd addmarks
339 $ cd addmarks
325 $ echo foo > foo
340 $ echo foo > foo
326 $ hg add foo
341 $ hg add foo
327 $ hg commit -m 'add foo'
342 $ hg commit -m 'add foo'
328 $ echo bar > bar
343 $ echo bar > bar
329 $ hg add bar
344 $ hg add bar
330 $ hg commit -m 'add bar'
345 $ hg commit -m 'add bar'
331 $ hg co "tip^"
346 $ hg co "tip^"
332 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
347 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
333 $ hg book add-foo
348 $ hg book add-foo
334 $ hg book -r tip add-bar
349 $ hg book -r tip add-bar
335 Note: this push *must* push only a single changeset, as that's the point
350 Note: this push *must* push only a single changeset, as that's the point
336 of this test.
351 of this test.
337 $ hg push -B add-foo --traceback
352 $ hg push -B add-foo --traceback
338 pushing to http://localhost:$HGPORT/
353 pushing to http://localhost:$HGPORT/
339 searching for changes
354 searching for changes
340 remote: adding changesets
355 remote: adding changesets
341 remote: adding manifests
356 remote: adding manifests
342 remote: adding file changes
357 remote: adding file changes
343 remote: added 1 changesets with 1 changes to 1 files
358 remote: added 1 changesets with 1 changes to 1 files
344 exporting bookmark add-foo
359 exporting bookmark add-foo
345
360
346 $ cd ..
361 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now