##// END OF EJS Templates
bookmarks: update and updatecurrentbookmark return status...
Kevin Bullock -
r15621:01368835 default
parent child Browse files
Show More
@@ -1,228 +1,229 b''
1 1 # Mercurial bookmark support code
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from mercurial.i18n import _
9 9 from mercurial.node import hex
10 10 from mercurial import encoding, error, util
11 11 import errno, os
12 12
13 13 def valid(mark):
14 14 for c in (':', '\0', '\n', '\r'):
15 15 if c in mark:
16 16 return False
17 17 return True
18 18
19 19 def read(repo):
20 20 '''Parse .hg/bookmarks file and return a dictionary
21 21
22 22 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
23 23 in the .hg/bookmarks file.
24 24 Read the file and return a (name=>nodeid) dictionary
25 25 '''
26 26 bookmarks = {}
27 27 try:
28 28 for line in repo.opener('bookmarks'):
29 29 line = line.strip()
30 30 if not line:
31 31 continue
32 32 if ' ' not in line:
33 33 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
34 34 continue
35 35 sha, refspec = line.split(' ', 1)
36 36 refspec = encoding.tolocal(refspec)
37 37 try:
38 38 bookmarks[refspec] = repo.changelog.lookup(sha)
39 39 except error.RepoLookupError:
40 40 pass
41 41 except IOError, inst:
42 42 if inst.errno != errno.ENOENT:
43 43 raise
44 44 return bookmarks
45 45
46 46 def readcurrent(repo):
47 47 '''Get the current bookmark
48 48
49 49 If we use gittishsh branches we have a current bookmark that
50 50 we are on. This function returns the name of the bookmark. It
51 51 is stored in .hg/bookmarks.current
52 52 '''
53 53 mark = None
54 54 try:
55 55 file = repo.opener('bookmarks.current')
56 56 except IOError, inst:
57 57 if inst.errno != errno.ENOENT:
58 58 raise
59 59 return None
60 60 try:
61 61 # No readline() in posixfile_nt, reading everything is cheap
62 62 mark = encoding.tolocal((file.readlines() or [''])[0])
63 63 if mark == '' or mark not in repo._bookmarks:
64 64 mark = None
65 65 finally:
66 66 file.close()
67 67 return mark
68 68
69 69 def write(repo):
70 70 '''Write bookmarks
71 71
72 72 Write the given bookmark => hash dictionary to the .hg/bookmarks file
73 73 in a format equal to those of localtags.
74 74
75 75 We also store a backup of the previous state in undo.bookmarks that
76 76 can be copied back on rollback.
77 77 '''
78 78 refs = repo._bookmarks
79 79
80 80 if repo._bookmarkcurrent not in refs:
81 81 setcurrent(repo, None)
82 82 for mark in refs.keys():
83 83 if not valid(mark):
84 84 raise util.Abort(_("bookmark '%s' contains illegal "
85 85 "character" % mark))
86 86
87 87 wlock = repo.wlock()
88 88 try:
89 89
90 90 file = repo.opener('bookmarks', 'w', atomictemp=True)
91 91 for refspec, node in refs.iteritems():
92 92 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
93 93 file.close()
94 94
95 95 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
96 96 try:
97 97 os.utime(repo.sjoin('00changelog.i'), None)
98 98 except OSError:
99 99 pass
100 100
101 101 finally:
102 102 wlock.release()
103 103
104 104 def setcurrent(repo, mark):
105 105 '''Set the name of the bookmark that we are currently on
106 106
107 107 Set the name of the bookmark that we are on (hg update <bookmark>).
108 108 The name is recorded in .hg/bookmarks.current
109 109 '''
110 110 current = repo._bookmarkcurrent
111 111 if current == mark:
112 112 return
113 113
114 114 if mark not in repo._bookmarks:
115 115 mark = ''
116 116 if not valid(mark):
117 117 raise util.Abort(_("bookmark '%s' contains illegal "
118 118 "character" % mark))
119 119
120 120 wlock = repo.wlock()
121 121 try:
122 122 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
123 123 file.write(encoding.fromlocal(mark))
124 124 file.close()
125 125 finally:
126 126 wlock.release()
127 127 repo._bookmarkcurrent = mark
128 128
129 129 def updatecurrentbookmark(repo, oldnode, curbranch):
130 130 try:
131 update(repo, oldnode, repo.branchtags()[curbranch])
131 return update(repo, oldnode, repo.branchtags()[curbranch])
132 132 except KeyError:
133 133 if curbranch == "default": # no default branch!
134 update(repo, oldnode, repo.lookup("tip"))
134 return update(repo, oldnode, repo.lookup("tip"))
135 135 else:
136 136 raise util.Abort(_("branch %s not found") % curbranch)
137 137
138 138 def update(repo, parents, node):
139 139 marks = repo._bookmarks
140 140 update = False
141 141 mark = repo._bookmarkcurrent
142 142 if mark and marks[mark] in parents:
143 143 old = repo[marks[mark]]
144 144 new = repo[node]
145 145 if new in old.descendants():
146 146 marks[mark] = new.node()
147 147 update = True
148 148 if update:
149 149 repo._writebookmarks(marks)
150 return update
150 151
151 152 def listbookmarks(repo):
152 153 # We may try to list bookmarks on a repo type that does not
153 154 # support it (e.g., statichttprepository).
154 155 marks = getattr(repo, '_bookmarks', {})
155 156
156 157 d = {}
157 158 for k, v in marks.iteritems():
158 159 # don't expose local divergent bookmarks
159 160 if '@' not in k and not k.endswith('@'):
160 161 d[k] = hex(v)
161 162 return d
162 163
163 164 def pushbookmark(repo, key, old, new):
164 165 w = repo.wlock()
165 166 try:
166 167 marks = repo._bookmarks
167 168 if hex(marks.get(key, '')) != old:
168 169 return False
169 170 if new == '':
170 171 del marks[key]
171 172 else:
172 173 if new not in repo:
173 174 return False
174 175 marks[key] = repo[new].node()
175 176 write(repo)
176 177 return True
177 178 finally:
178 179 w.release()
179 180
180 181 def updatefromremote(ui, repo, remote, path):
181 182 ui.debug("checking for updated bookmarks\n")
182 183 rb = remote.listkeys('bookmarks')
183 184 changed = False
184 185 for k in rb.keys():
185 186 if k in repo._bookmarks:
186 187 nr, nl = rb[k], repo._bookmarks[k]
187 188 if nr in repo:
188 189 cr = repo[nr]
189 190 cl = repo[nl]
190 191 if cl.rev() >= cr.rev():
191 192 continue
192 193 if cr in cl.descendants():
193 194 repo._bookmarks[k] = cr.node()
194 195 changed = True
195 196 ui.status(_("updating bookmark %s\n") % k)
196 197 else:
197 198 # find a unique @ suffix
198 199 for x in range(1, 100):
199 200 n = '%s@%d' % (k, x)
200 201 if n not in repo._bookmarks:
201 202 break
202 203 # try to use an @pathalias suffix
203 204 # if an @pathalias already exists, we overwrite (update) it
204 205 for p, u in ui.configitems("paths"):
205 206 if path == u:
206 207 n = '%s@%s' % (k, p)
207 208
208 209 repo._bookmarks[n] = cr.node()
209 210 changed = True
210 211 ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
211 212
212 213 if changed:
213 214 write(repo)
214 215
215 216 def diff(ui, repo, remote):
216 217 ui.status(_("searching for changed bookmarks\n"))
217 218
218 219 lmarks = repo.listkeys('bookmarks')
219 220 rmarks = remote.listkeys('bookmarks')
220 221
221 222 diff = sorted(set(rmarks) - set(lmarks))
222 223 for k in diff:
223 224 ui.write(" %-25s %s\n" % (k, rmarks[k][:12]))
224 225
225 226 if len(diff) <= 0:
226 227 ui.status(_("no changed bookmarks found\n"))
227 228 return 1
228 229 return 0
General Comments 0
You need to be logged in to leave comments. Login now