/loggerhead/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/loggerhead/trunk
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
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
72 by Robey Pointer
make the cache folder and branch url (prefix) be optional settings on the
24
import posixpath
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
25
import threading
111 by Robey Pointer
urlquote the url elements in branch.url() for bug 88286
26
import urllib
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
27
28
import turbogears
29
from cherrypy import HTTPRedirect
30
31
from loggerhead import util
128.1.55 by Michael Hudson
plumbing for a file change cache
32
from loggerhead.changecache import ChangeCache, FileChangeCache
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
33
from loggerhead.history import History
34
from loggerhead.textindex import TextIndex
35
from loggerhead.controllers.changelog_ui import ChangeLogUI
36
from loggerhead.controllers.atom_ui import AtomUI
37
from loggerhead.controllers.revision_ui import RevisionUI
38
from loggerhead.controllers.inventory_ui import InventoryUI
39
from loggerhead.controllers.annotate_ui import AnnotateUI
40
from loggerhead.controllers.download_ui import DownloadUI
51 by Robey Pointer
add the ability to download a bundle for a revision.
41
from loggerhead.controllers.bundle_ui import BundleUI
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
42
43
49 by Robey Pointer
add top-level page listing available branches. also a patch from matty to not require external-url in atom feeds any more
44
with_history_lock = util.with_lock('_history_lock', 'History')
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
45
46
47
class BranchView (object):
155.1.3 by Michael Hudson
hack at config system and make diff size limit a config item
48
    def __init__(self, group_name, name, subfolder, absfolder, config,
49
                 project_config, root_config):
49 by Robey Pointer
add top-level page listing available branches. also a patch from matty to not require external-url in atom feeds any more
50
        self._group_name = group_name
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
51
        self._name = name
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
52
        self._folder = subfolder
53
        self._absfolder = absfolder
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
54
        self._config = config
72 by Robey Pointer
make the cache folder and branch url (prefix) be optional settings on the
55
        self._project_config = project_config
155.1.3 by Michael Hudson
hack at config system and make diff size limit a config item
56
        self._root_config = root_config
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
57
        self.log = logging.getLogger('loggerhead.%s' % (name,))
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
58
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
59
        # branch history
60
        self._history_lock = threading.RLock()
61
        self._history = None
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
62
        self._closed = False
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
63
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
64
        self.changes = ChangeLogUI(self)
65
        self.revision = RevisionUI(self)
66
        self.files = InventoryUI(self)
67
        self.annotate = AnnotateUI(self)
68
        self.download = DownloadUI(self)
69
        self.atom = AtomUI(self)
51 by Robey Pointer
add the ability to download a bundle for a revision.
70
        self.bundle = BundleUI(self)
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
71
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
72
        # force history object to be loaded:
73
        self.get_history()
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
74
69 by Robey Pointer
switch the cache and text index to use file locking so they can be used by
75
        turbogears.startup.call_on_shutdown.append(self.close)
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
76
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
77
    @with_history_lock
69 by Robey Pointer
switch the cache and text index to use file locking so they can be used by
78
    def close(self):
79
        # it's important that we cleanly detach the history, so the cache
80
        # files can be closed correctly and hopefully remain uncorrupted.
81
        # this should also stop any ongoing indexing.
82
        self._history.detach()
83
        self._history = None
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
84
        self._closed = True
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
85
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
86
    config = property(lambda self: self._config)
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
87
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
88
    name = property(lambda self: self._name)
49 by Robey Pointer
add top-level page listing available branches. also a patch from matty to not require external-url in atom feeds any more
89
90
    group_name = property(lambda self: self._group_name)
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
91
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
92
    def _get_friendly_name(self):
93
        name = self._config.get('branch_name', None)
94
        if name is not None:
95
            return name
96
        # try branch-specific config?
97
        name = self.get_history().get_config().get_nickname()
98
        if name is not None:
99
            return name
100
        return self._name
101
102
    friendly_name = property(_get_friendly_name)
103
104
    def _get_description(self):
105
        description = self._config.get('description', None)
106
        if description is not None:
107
            return description
108
        # try branch-specific config?
109
        description = self.get_history().get_config().get_user_option('description')
110
        return description
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
111
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
112
    description = property(_get_description)
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
113
72 by Robey Pointer
make the cache folder and branch url (prefix) be optional settings on the
114
    def _get_branch_url(self):
115
        url = self._config.get('url', None)
116
        if url is not None:
117
            return url
118
        # try to assemble one from the project, if an url_prefix was defined.
119
        url = self._project_config.get('url_prefix', None)
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
120
        if url is not None:
121
            return posixpath.join(url, self._folder) + '/'
122
        # try branch-specific config?
95 by Robey Pointer
use "public_branch" as the config key since that seems to be what everyone
123
        url = self.get_history().get_config().get_user_option('public_branch')
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
124
        return url
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
125
72 by Robey Pointer
make the cache folder and branch url (prefix) be optional settings on the
126
    branch_url = property(_get_branch_url)
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
127
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
128
    @turbogears.expose()
129
    def index(self):
130
        raise HTTPRedirect(self.url('/changes'))
131
155.1.3 by Michael Hudson
hack at config system and make diff size limit a config item
132
    def get_config_item(self, item, default=None):
133
        for conf in self._config, self._project_config, self._root_config:
134
            if item in conf:
135
                return conf[item]
136
        return default
137
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
138
    @with_history_lock
139
    def get_history(self):
140
        """
141
        get an up-to-date History object, safely.  each page-view calls this
142
        method, and normally it will get the same History object as on previous
143
        calls.  but if the bazaar branch on-disk has been updated since this
144
        History was created, a new object will be created and returned.
145
        """
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
146
        if self._closed:
147
            return None
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
148
        if (self._history is None) or self._history.out_of_date():
149
            self.log.debug('Reload branch history...')
150
            if self._history is not None:
151
                self._history.detach()
128.1.55 by Michael Hudson
plumbing for a file change cache
152
            _history = self._history = History.from_folder(
153
                self._absfolder, self._name)
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
154
            cache_path = self._config.get('cachepath', None)
72 by Robey Pointer
make the cache folder and branch url (prefix) be optional settings on the
155
            if cache_path is None:
156
                # try the project config
157
                cache_path = self._project_config.get('cachepath', None)
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
158
            if cache_path is not None:
128.1.55 by Michael Hudson
plumbing for a file change cache
159
                _history.use_cache(ChangeCache(_history, cache_path))
160
                _history.use_file_cache(FileChangeCache(_history, cache_path))
161
                _history.use_search_index(TextIndex(_history, cache_path))
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
162
        return self._history
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
163
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
164
    def check_rebuild(self):
165
        h = self.get_history()
74 by Robey Pointer
add the ability to auto-publish anything found under a particular folder.
166
        if h is not None:
167
            h.check_rebuild()
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
168
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
169
    def url(self, elements, **kw):
128.2.17 by Robey Pointer
add context_url method to simplify contextual urls in the templates, and
170
        "build an url relative to this branch"
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
171
        if not isinstance(elements, list):
172
            elements = [elements]
173
        if elements[0].startswith('/'):
174
            elements[0] = elements[0][1:]
111 by Robey Pointer
urlquote the url elements in branch.url() for bug 88286
175
        elements = [urllib.quote(x) for x in elements]
49 by Robey Pointer
add top-level page listing available branches. also a patch from matty to not require external-url in atom feeds any more
176
        return turbogears.url([ '/' + self.group_name, self.name ] + elements, **kw)
48 by Robey Pointer
the big migration of branch-specific data to a BranchView object: actually
177
128.2.17 by Robey Pointer
add context_url method to simplify contextual urls in the templates, and
178
    def context_url(self, elements, **kw):
179
        "build an url relative to this branch, bringing along browsing context"
180
        return self.url(elements, **util.get_context(**kw))
144.1.10 by Michael Hudson
run reindent.py over the loggerhead package
181
49 by Robey Pointer
add top-level page listing available branches. also a patch from matty to not require external-url in atom feeds any more
182
    def last_updated(self):
183
        h = self.get_history()
184
        change = h.get_changes([ h.last_revid ])[0]
185
        return change.date