##// END OF EJS Templates
bookmarks: drop superfluous strip
Matt Mackall -
r14847:400ba7cc default
parent child Browse files
Show More
@@ -1,214 +1,214 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 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
10 from mercurial import encoding, error, util
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 in line:
30 if ' ' not in line:
31 if line:
31 if line:
32 msg = _('malformed line in .hg/bookmarks: %r\n')
32 msg = _('malformed line in .hg/bookmarks: %r\n')
33 repo.ui.warn( msg % line)
33 repo.ui.warn( msg % line)
34 continue
34 continue
35 sha, refspec = line.strip().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 error.RepoLookupError:
39 except error.RepoLookupError:
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 posixfile_nt, reading everything is cheap
61 # No readline() in posixfile_nt, 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.rename()
93 file.rename()
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.rename()
124 file.rename()
125 finally:
125 finally:
126 wlock.release()
126 wlock.release()
127 repo._bookmarkcurrent = mark
127 repo._bookmarkcurrent = mark
128
128
129 def updatecurrentbookmark(repo, oldnode, curbranch):
129 def updatecurrentbookmark(repo, oldnode, curbranch):
130 try:
130 try:
131 update(repo, oldnode, repo.branchtags()[curbranch])
131 update(repo, oldnode, repo.branchtags()[curbranch])
132 except KeyError:
132 except KeyError:
133 if curbranch == "default": # no default branch!
133 if curbranch == "default": # no default branch!
134 update(repo, oldnode, repo.lookup("tip"))
134 update(repo, oldnode, repo.lookup("tip"))
135 else:
135 else:
136 raise util.Abort(_("branch %s not found") % curbranch)
136 raise util.Abort(_("branch %s not found") % curbranch)
137
137
138 def update(repo, parents, node):
138 def update(repo, parents, node):
139 marks = repo._bookmarks
139 marks = repo._bookmarks
140 update = False
140 update = False
141 mark = repo._bookmarkcurrent
141 mark = repo._bookmarkcurrent
142 if mark and marks[mark] in parents:
142 if mark and marks[mark] in parents:
143 old = repo[marks[mark]]
143 old = repo[marks[mark]]
144 new = repo[node]
144 new = repo[node]
145 if new in old.descendants():
145 if new in old.descendants():
146 marks[mark] = new.node()
146 marks[mark] = new.node()
147 update = True
147 update = True
148 if update:
148 if update:
149 write(repo)
149 write(repo)
150
150
151 def listbookmarks(repo):
151 def listbookmarks(repo):
152 # We may try to list bookmarks on a repo type that does not
152 # We may try to list bookmarks on a repo type that does not
153 # support it (e.g., statichttprepository).
153 # support it (e.g., statichttprepository).
154 if not hasattr(repo, '_bookmarks'):
154 if not hasattr(repo, '_bookmarks'):
155 return {}
155 return {}
156
156
157 d = {}
157 d = {}
158 for k, v in repo._bookmarks.iteritems():
158 for k, v in repo._bookmarks.iteritems():
159 d[k] = hex(v)
159 d[k] = hex(v)
160 return d
160 return d
161
161
162 def pushbookmark(repo, key, old, new):
162 def pushbookmark(repo, key, old, new):
163 w = repo.wlock()
163 w = repo.wlock()
164 try:
164 try:
165 marks = repo._bookmarks
165 marks = repo._bookmarks
166 if hex(marks.get(key, '')) != old:
166 if hex(marks.get(key, '')) != old:
167 return False
167 return False
168 if new == '':
168 if new == '':
169 del marks[key]
169 del marks[key]
170 else:
170 else:
171 if new not in repo:
171 if new not in repo:
172 return False
172 return False
173 marks[key] = repo[new].node()
173 marks[key] = repo[new].node()
174 write(repo)
174 write(repo)
175 return True
175 return True
176 finally:
176 finally:
177 w.release()
177 w.release()
178
178
179 def updatefromremote(ui, repo, remote):
179 def updatefromremote(ui, repo, remote):
180 ui.debug("checking for updated bookmarks\n")
180 ui.debug("checking for updated bookmarks\n")
181 rb = remote.listkeys('bookmarks')
181 rb = remote.listkeys('bookmarks')
182 changed = False
182 changed = False
183 for k in rb.keys():
183 for k in rb.keys():
184 if k in repo._bookmarks:
184 if k in repo._bookmarks:
185 nr, nl = rb[k], repo._bookmarks[k]
185 nr, nl = rb[k], repo._bookmarks[k]
186 if nr in repo:
186 if nr in repo:
187 cr = repo[nr]
187 cr = repo[nr]
188 cl = repo[nl]
188 cl = repo[nl]
189 if cl.rev() >= cr.rev():
189 if cl.rev() >= cr.rev():
190 continue
190 continue
191 if cr in cl.descendants():
191 if cr in cl.descendants():
192 repo._bookmarks[k] = cr.node()
192 repo._bookmarks[k] = cr.node()
193 changed = True
193 changed = True
194 ui.status(_("updating bookmark %s\n") % k)
194 ui.status(_("updating bookmark %s\n") % k)
195 else:
195 else:
196 ui.warn(_("not updating divergent"
196 ui.warn(_("not updating divergent"
197 " bookmark %s\n") % k)
197 " bookmark %s\n") % k)
198 if changed:
198 if changed:
199 write(repo)
199 write(repo)
200
200
201 def diff(ui, repo, remote):
201 def diff(ui, repo, remote):
202 ui.status(_("searching for changed bookmarks\n"))
202 ui.status(_("searching for changed bookmarks\n"))
203
203
204 lmarks = repo.listkeys('bookmarks')
204 lmarks = repo.listkeys('bookmarks')
205 rmarks = remote.listkeys('bookmarks')
205 rmarks = remote.listkeys('bookmarks')
206
206
207 diff = sorted(set(rmarks) - set(lmarks))
207 diff = sorted(set(rmarks) - set(lmarks))
208 for k in diff:
208 for k in diff:
209 ui.write(" %-25s %s\n" % (k, rmarks[k][:12]))
209 ui.write(" %-25s %s\n" % (k, rmarks[k][:12]))
210
210
211 if len(diff) <= 0:
211 if len(diff) <= 0:
212 ui.status(_("no changed bookmarks found\n"))
212 ui.status(_("no changed bookmarks found\n"))
213 return 1
213 return 1
214 return 0
214 return 0
General Comments 0
You need to be logged in to leave comments. Login now