2
# Copyright (C) 2006 Robey Pointer <robey@lag.net>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
collection of configuration and objects related to a bazaar branch.
28
from cherrypy import HTTPRedirect
30
from loggerhead import util
31
from loggerhead.changecache import ChangeCache
32
from loggerhead.history import History
33
from loggerhead.textindex import TextIndex
34
from loggerhead.controllers.changelog_ui import ChangeLogUI
35
from loggerhead.controllers.atom_ui import AtomUI
36
from loggerhead.controllers.revision_ui import RevisionUI
37
from loggerhead.controllers.inventory_ui import InventoryUI
38
from loggerhead.controllers.annotate_ui import AnnotateUI
39
from loggerhead.controllers.download_ui import DownloadUI
40
from loggerhead.controllers.bundle_ui import BundleUI
43
with_history_lock = util.with_lock('_history_lock', 'History')
46
class BranchView (object):
47
def __init__(self, group_name, name, subfolder, absfolder, config, project_config):
48
self._group_name = group_name
50
self._folder = subfolder
51
self._absfolder = absfolder
53
self._project_config = project_config
54
self.log = logging.getLogger('loggerhead.%s' % (name,))
57
self._history_lock = threading.RLock()
61
self.changes = ChangeLogUI(self)
62
self.revision = RevisionUI(self)
63
self.files = InventoryUI(self)
64
self.annotate = AnnotateUI(self)
65
self.download = DownloadUI(self)
66
self.atom = AtomUI(self)
67
self.bundle = BundleUI(self)
69
# force history object to be loaded:
72
turbogears.startup.call_on_shutdown.append(self.close)
76
# it's important that we cleanly detach the history, so the cache
77
# files can be closed correctly and hopefully remain uncorrupted.
78
# this should also stop any ongoing indexing.
79
self._history.detach()
83
config = property(lambda self: self._config)
85
name = property(lambda self: self._name)
87
group_name = property(lambda self: self._group_name)
89
def _get_friendly_name(self):
90
name = self._config.get('branch_name', None)
93
# try branch-specific config?
94
name = self.get_history().get_config().get_nickname()
99
friendly_name = property(_get_friendly_name)
101
def _get_description(self):
102
description = self._config.get('description', None)
103
if description is not None:
105
# try branch-specific config?
106
description = self.get_history().get_config().get_user_option('description')
109
description = property(_get_description)
111
def _get_branch_url(self):
112
url = self._config.get('url', None)
115
# try to assemble one from the project, if an url_prefix was defined.
116
url = self._project_config.get('url_prefix', None)
118
return posixpath.join(url, self._folder) + '/'
119
# try branch-specific config?
120
url = self.get_history().get_config().get_user_option('public_branch')
123
branch_url = property(_get_branch_url)
127
raise HTTPRedirect(self.url('/changes'))
130
def get_history(self):
132
get an up-to-date History object, safely. each page-view calls this
133
method, and normally it will get the same History object as on previous
134
calls. but if the bazaar branch on-disk has been updated since this
135
History was created, a new object will be created and returned.
139
if (self._history is None) or self._history.out_of_date():
140
self.log.debug('Reload branch history...')
141
if self._history is not None:
142
self._history.detach()
143
self._history = History.from_folder(self._absfolder, self._name)
144
cache_path = self._config.get('cachepath', None)
145
if cache_path is None:
146
# try the project config
147
cache_path = self._project_config.get('cachepath', None)
148
if cache_path is not None:
149
self._history.use_cache(ChangeCache(self._history, cache_path))
150
self._history.use_search_index(TextIndex(self._history, cache_path))
153
def check_rebuild(self):
154
h = self.get_history()
158
def url(self, elements, **kw):
159
if not isinstance(elements, list):
160
elements = [elements]
161
if elements[0].startswith('/'):
162
elements[0] = elements[0][1:]
163
return turbogears.url([ '/' + self.group_name, self.name ] + elements, **kw)
165
def last_updated(self):
166
h = self.get_history()
167
change = h.get_changes([ h.last_revid ])[0]