~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/branchview.py

  • Committer: Robey Pointer
  • Date: 2007-01-14 23:45:53 UTC
  • Revision ID: robey@lag.net-20070114234553-l8zu9z144flojfpn
slight cleanup, and add '-f' option for running in the foreground.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright (C) 2006  Robey Pointer <robey@lag.net>
 
3
#
 
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.
 
8
#
 
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.
 
13
#
 
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
 
17
#
 
18
 
 
19
"""
 
20
collection of configuration and objects related to a bazaar branch.
 
21
"""
 
22
 
 
23
import logging
 
24
import posixpath
 
25
import threading
 
26
 
 
27
import turbogears
 
28
from cherrypy import HTTPRedirect
 
29
 
 
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
 
41
 
 
42
 
 
43
with_history_lock = util.with_lock('_history_lock', 'History')
 
44
 
 
45
 
 
46
class BranchView (object):
 
47
    def __init__(self, group_name, name, subfolder, absfolder, config, project_config):
 
48
        self._group_name = group_name
 
49
        self._name = name
 
50
        self._folder = subfolder
 
51
        self._absfolder = absfolder
 
52
        self._config = config
 
53
        self._project_config = project_config
 
54
        self.log = logging.getLogger('loggerhead.%s' % (name,))
 
55
        
 
56
        # branch history
 
57
        self._history_lock = threading.RLock()
 
58
        self._history = None
 
59
        self._closed = False
 
60
        
 
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)
 
68
        
 
69
        # force history object to be loaded:
 
70
        self.get_history()
 
71
        
 
72
        turbogears.startup.call_on_shutdown.append(self.close)
 
73
    
 
74
    @with_history_lock
 
75
    def close(self):
 
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()
 
80
        self._history = None
 
81
        self._closed = True
 
82
            
 
83
    config = property(lambda self: self._config)
 
84
    
 
85
    name = property(lambda self: self._name)
 
86
 
 
87
    group_name = property(lambda self: self._group_name)
 
88
    
 
89
    def _get_friendly_name(self):
 
90
        name = self._config.get('branch_name', None)
 
91
        if name is not None:
 
92
            return name
 
93
        # try branch-specific config?
 
94
        name = self.get_history().get_config().get_nickname()
 
95
        if name is not None:
 
96
            return name
 
97
        return self._name
 
98
 
 
99
    friendly_name = property(_get_friendly_name)
 
100
 
 
101
    def _get_description(self):
 
102
        description = self._config.get('description', None)
 
103
        if description is not None:
 
104
            return description
 
105
        # try branch-specific config?
 
106
        description = self.get_history().get_config().get_user_option('description')
 
107
        return description
 
108
        
 
109
    description = property(_get_description)
 
110
    
 
111
    def _get_branch_url(self):
 
112
        url = self._config.get('url', None)
 
113
        if url is not None:
 
114
            return url
 
115
        # try to assemble one from the project, if an url_prefix was defined.
 
116
        url = self._project_config.get('url_prefix', None)
 
117
        if url is not None:
 
118
            return posixpath.join(url, self._folder) + '/'
 
119
        # try branch-specific config?
 
120
        url = self.get_history().get_config().get_user_option('public_url')
 
121
        return url
 
122
        
 
123
    branch_url = property(_get_branch_url)
 
124
    
 
125
    @turbogears.expose()
 
126
    def index(self):
 
127
        raise HTTPRedirect(self.url('/changes'))
 
128
 
 
129
    @with_history_lock
 
130
    def get_history(self):
 
131
        """
 
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.
 
136
        """
 
137
        if self._closed:
 
138
            return None
 
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))
 
151
        return self._history
 
152
    
 
153
    def check_rebuild(self):
 
154
        h = self.get_history()
 
155
        if h is not None:
 
156
            h.check_rebuild()
 
157
    
 
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)
 
164
 
 
165
    def last_updated(self):
 
166
        h = self.get_history()
 
167
        change = h.get_changes([ h.last_revid ])[0]
 
168
        return change.date