Show More
@@ -44,16 +44,15 b' def _getbkfile(repo):' | |||||
44 | class bmstore(dict): |
|
44 | class bmstore(dict): | |
45 | """Storage for bookmarks. |
|
45 | """Storage for bookmarks. | |
46 |
|
46 | |||
47 |
This object should do all bookmark reads and writes, so |
|
47 | This object should do all bookmark-related reads and writes, so | |
48 |
fairly simple to replace the storage underlying |
|
48 | that it's fairly simple to replace the storage underlying | |
49 |
having to clone the logic surrounding |
|
49 | bookmarks without having to clone the logic surrounding | |
|
50 | bookmarks. This type also should manage the active bookmark, if | |||
|
51 | any. | |||
50 |
|
52 | |||
51 | This particular bmstore implementation stores bookmarks as |
|
53 | This particular bmstore implementation stores bookmarks as | |
52 | {hash}\s{name}\n (the same format as localtags) in |
|
54 | {hash}\s{name}\n (the same format as localtags) in | |
53 | .hg/bookmarks. The mapping is stored as {name: nodeid}. |
|
55 | .hg/bookmarks. The mapping is stored as {name: nodeid}. | |
54 |
|
||||
55 | This class does NOT handle the "active" bookmark state at this |
|
|||
56 | time. |
|
|||
57 | """ |
|
56 | """ | |
58 |
|
57 | |||
59 | def __init__(self, repo): |
|
58 | def __init__(self, repo): | |
@@ -79,6 +78,20 b' class bmstore(dict):' | |||||
79 | if inst.errno != errno.ENOENT: |
|
78 | if inst.errno != errno.ENOENT: | |
80 | raise |
|
79 | raise | |
81 | self._clean = True |
|
80 | self._clean = True | |
|
81 | self._active = _readactive(repo, self) | |||
|
82 | self._aclean = True | |||
|
83 | ||||
|
84 | @property | |||
|
85 | def active(self): | |||
|
86 | return self._active | |||
|
87 | ||||
|
88 | @active.setter | |||
|
89 | def active(self, mark): | |||
|
90 | if mark is not None and mark not in self: | |||
|
91 | raise AssertionError('bookmark %s does not exist!' % mark) | |||
|
92 | ||||
|
93 | self._active = mark | |||
|
94 | self._aclean = False | |||
82 |
|
95 | |||
83 | def __setitem__(self, *args, **kwargs): |
|
96 | def __setitem__(self, *args, **kwargs): | |
84 | self._clean = False |
|
97 | self._clean = False | |
@@ -107,6 +120,9 b' class bmstore(dict):' | |||||
107 | ''' |
|
120 | ''' | |
108 | msg = 'bm.write() is deprecated, use bm.recordchange(transaction)' |
|
121 | msg = 'bm.write() is deprecated, use bm.recordchange(transaction)' | |
109 | self._repo.ui.deprecwarn(msg, '3.7') |
|
122 | self._repo.ui.deprecwarn(msg, '3.7') | |
|
123 | # TODO: writing the active bookmark should probably also use a | |||
|
124 | # transaction. | |||
|
125 | self._writeactive() | |||
110 | if self._clean: |
|
126 | if self._clean: | |
111 | return |
|
127 | return | |
112 | repo = self._repo |
|
128 | repo = self._repo | |
@@ -128,8 +144,10 b' class bmstore(dict):' | |||||
128 |
|
144 | |||
129 | def _writerepo(self, repo): |
|
145 | def _writerepo(self, repo): | |
130 | """Factored out for extensibility""" |
|
146 | """Factored out for extensibility""" | |
131 |
|
|
147 | rbm = repo._bookmarks | |
132 | deactivate(repo) |
|
148 | if rbm.active not in self: | |
|
149 | rbm.active = None | |||
|
150 | rbm._writeactive() | |||
133 |
|
151 | |||
134 | wlock = repo.wlock() |
|
152 | wlock = repo.wlock() | |
135 | try: |
|
153 | try: | |
@@ -146,12 +164,33 b' class bmstore(dict):' | |||||
146 | finally: |
|
164 | finally: | |
147 | wlock.release() |
|
165 | wlock.release() | |
148 |
|
166 | |||
|
167 | def _writeactive(self): | |||
|
168 | if self._aclean: | |||
|
169 | return | |||
|
170 | wlock = self._repo.wlock() | |||
|
171 | try: | |||
|
172 | if self._active is not None: | |||
|
173 | f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True) | |||
|
174 | try: | |||
|
175 | f.write(encoding.fromlocal(self._active)) | |||
|
176 | finally: | |||
|
177 | f.close() | |||
|
178 | else: | |||
|
179 | try: | |||
|
180 | self._repo.vfs.unlink('bookmarks.current') | |||
|
181 | except OSError as inst: | |||
|
182 | if inst.errno != errno.ENOENT: | |||
|
183 | raise | |||
|
184 | finally: | |||
|
185 | wlock.release() | |||
|
186 | self._aclean = True | |||
|
187 | ||||
149 | def _write(self, fp): |
|
188 | def _write(self, fp): | |
150 | for name, node in self.iteritems(): |
|
189 | for name, node in self.iteritems(): | |
151 | fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name))) |
|
190 | fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name))) | |
152 | self._clean = True |
|
191 | self._clean = True | |
153 |
|
192 | |||
154 | def readactive(repo): |
|
193 | def _readactive(repo, marks): | |
155 | """ |
|
194 | """ | |
156 | Get the active bookmark. We can have an active bookmark that updates |
|
195 | Get the active bookmark. We can have an active bookmark that updates | |
157 | itself as we commit. This function returns the name of that bookmark. |
|
196 | itself as we commit. This function returns the name of that bookmark. | |
@@ -172,7 +211,7 b' def readactive(repo):' | |||||
172 | # static-http which only tries to load the file when we try |
|
211 | # static-http which only tries to load the file when we try | |
173 | # to read from it. |
|
212 | # to read from it. | |
174 | mark = encoding.tolocal((file.readlines() or [''])[0]) |
|
213 | mark = encoding.tolocal((file.readlines() or [''])[0]) | |
175 |
if mark == '' or mark not in |
|
214 | if mark == '' or mark not in marks: | |
176 | mark = None |
|
215 | mark = None | |
177 | except IOError as inst: |
|
216 | except IOError as inst: | |
178 | if inst.errno != errno.ENOENT: |
|
217 | if inst.errno != errno.ENOENT: | |
@@ -188,35 +227,15 b' def activate(repo, mark):' | |||||
188 | follow new commits that are made. |
|
227 | follow new commits that are made. | |
189 | The name is recorded in .hg/bookmarks.current |
|
228 | The name is recorded in .hg/bookmarks.current | |
190 | """ |
|
229 | """ | |
191 | if mark not in repo._bookmarks: |
|
230 | repo._bookmarks.active = mark | |
192 | raise AssertionError('bookmark %s does not exist!' % mark) |
|
231 | repo._bookmarks._writeactive() | |
193 |
|
||||
194 | active = repo._activebookmark |
|
|||
195 | if active == mark: |
|
|||
196 | return |
|
|||
197 |
|
||||
198 | wlock = repo.wlock() |
|
|||
199 | try: |
|
|||
200 | file = repo.vfs('bookmarks.current', 'w', atomictemp=True) |
|
|||
201 | file.write(encoding.fromlocal(mark)) |
|
|||
202 | file.close() |
|
|||
203 | finally: |
|
|||
204 | wlock.release() |
|
|||
205 | repo._activebookmark = mark |
|
|||
206 |
|
232 | |||
207 | def deactivate(repo): |
|
233 | def deactivate(repo): | |
208 | """ |
|
234 | """ | |
209 | Unset the active bookmark in this repository. |
|
235 | Unset the active bookmark in this repository. | |
210 | """ |
|
236 | """ | |
211 | wlock = repo.wlock() |
|
237 | repo._bookmarks.active = None | |
212 | try: |
|
238 | repo._bookmarks._writeactive() | |
213 | repo.vfs.unlink('bookmarks.current') |
|
|||
214 | repo._activebookmark = None |
|
|||
215 | except OSError as inst: |
|
|||
216 | if inst.errno != errno.ENOENT: |
|
|||
217 | raise |
|
|||
218 | finally: |
|
|||
219 | wlock.release() |
|
|||
220 |
|
239 | |||
221 | def isactivewdirparent(repo): |
|
240 | def isactivewdirparent(repo): | |
222 | """ |
|
241 | """ | |
@@ -266,7 +285,7 b' def update(repo, parents, node):' | |||||
266 | deletefrom = parents |
|
285 | deletefrom = parents | |
267 | marks = repo._bookmarks |
|
286 | marks = repo._bookmarks | |
268 | update = False |
|
287 | update = False | |
269 |
active = |
|
288 | active = marks.active | |
270 | if not active: |
|
289 | if not active: | |
271 | return False |
|
290 | return False | |
272 |
|
291 |
@@ -2530,13 +2530,14 b' def amend(ui, repo, commitfunc, old, ext' | |||||
2530 | # First, do a regular commit to record all changes in the working |
|
2530 | # First, do a regular commit to record all changes in the working | |
2531 | # directory (if there are any) |
|
2531 | # directory (if there are any) | |
2532 | ui.callhooks = False |
|
2532 | ui.callhooks = False | |
2533 |
activebookmark = repo._ |
|
2533 | activebookmark = repo._bookmarks.active | |
2534 | try: |
|
2534 | try: | |
2535 |
repo._ |
|
2535 | repo._bookmarks.active = None | |
2536 | opts['message'] = 'temporary amend commit for %s' % old |
|
2536 | opts['message'] = 'temporary amend commit for %s' % old | |
2537 | node = commit(ui, repo, commitfunc, pats, opts) |
|
2537 | node = commit(ui, repo, commitfunc, pats, opts) | |
2538 | finally: |
|
2538 | finally: | |
2539 |
repo._ |
|
2539 | repo._bookmarks.active = activebookmark | |
|
2540 | repo._bookmarks.recordchange(tr) | |||
2540 | ui.callhooks = True |
|
2541 | ui.callhooks = True | |
2541 | ctx = repo[node] |
|
2542 | ctx = repo[node] | |
2542 |
|
2543 |
@@ -459,13 +459,13 b' class localrepository(object):' | |||||
459 | pass |
|
459 | pass | |
460 | return proxycls(self, name) |
|
460 | return proxycls(self, name) | |
461 |
|
461 | |||
462 | @repofilecache('bookmarks') |
|
462 | @repofilecache('bookmarks', 'bookmarks.current') | |
463 | def _bookmarks(self): |
|
463 | def _bookmarks(self): | |
464 | return bookmarks.bmstore(self) |
|
464 | return bookmarks.bmstore(self) | |
465 |
|
465 | |||
466 | @repofilecache('bookmarks.current') |
|
466 | @property | |
467 | def _activebookmark(self): |
|
467 | def _activebookmark(self): | |
468 |
return |
|
468 | return self._bookmarks.active | |
469 |
|
469 | |||
470 | def bookmarkheads(self, bookmark): |
|
470 | def bookmarkheads(self, bookmark): | |
471 | name = bookmark.split('@', 1)[0] |
|
471 | name = bookmark.split('@', 1)[0] |
General Comments 0
You need to be logged in to leave comments.
Login now