~bzr-pqm/bzr/bzr.dev

1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
1
# Copyright (C) 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Implementation of Transport that decorates another transport.
18
19
This does not change the transport behaviour at all, but provides all the 
20
stub functions to allow other decorators to be written easily.
21
"""
22
23
from bzrlib.transport import get_transport, Transport, Server
24
25
26
class TransportDecorator(Transport):
27
    """A no-change decorator for Transports.
1634.1.1 by Robert Collins
Merge NFS LockDir support (Aaron Bentley, Robert Collins).
28
29
    Subclasses of this are new transports that are based on an
30
    underlying transport and can override or intercept some 
31
    behavior.  For example ReadonlyTransportDecorator prevents 
32
    all write attempts, and FakeNFSTransportDecorator simulates 
33
    some NFS quirks.
34
35
    This decorator class is not directly usable as a decorator:
36
    you must use a subclass which has overridden the _get_url_prefix() class
37
    method to return the url prefix for the subclass.
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
38
    """
39
40
    def __init__(self, url, _decorated=None):
41
        """Set the 'base' path where files will be stored.
42
        
43
        _decorated is a private parameter for cloning."""
44
        prefix = self._get_url_prefix()
1608.2.10 by Martin Pool
(TransportDecorator) better assertions
45
        assert url.startswith(prefix), \
46
                "url %r doesn't start with decorator prefix %r" % \
47
                (url, prefix)
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
48
        decorated_url = url[len(prefix):]
49
        if _decorated is None:
50
            self._decorated = get_transport(decorated_url)
51
        else:
52
            self._decorated = _decorated
53
        super(TransportDecorator, self).__init__(
54
            prefix + self._decorated.base)
55
56
    def abspath(self, relpath):
57
        """See Transport.abspath()."""
58
        return self._get_url_prefix() + self._decorated.abspath(relpath)
59
1666.1.6 by Robert Collins
Make knit the default format.
60
    def append(self, relpath, f, mode=None):
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
61
        """See Transport.append()."""
1666.1.6 by Robert Collins
Make knit the default format.
62
        return self._decorated.append(relpath, f, mode=mode)
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
63
64
    def clone(self, offset=None):
65
        """See Transport.clone()."""
66
        decorated_clone = self._decorated.clone(offset)
67
        return self.__class__(
68
            self._get_url_prefix() + decorated_clone.base, decorated_clone)
69
70
    def delete(self, relpath):
71
        """See Transport.delete()."""
72
        return self._decorated.delete(relpath)
73
74
    def delete_tree(self, relpath):
75
        """See Transport.delete_tree()."""
76
        return self._decorated.delete_tree(relpath)
77
78
    @classmethod
79
    def _get_url_prefix(self):
80
        """Return the URL prefix of this decorator."""
81
        raise NotImplementedError(self._get_url_prefix)
82
83
    def get(self, relpath):
84
        """See Transport.get()."""
85
        return self._decorated.get(relpath)
86
87
    def has(self, relpath):
88
        """See Transport.has()."""
89
        return self._decorated.has(relpath)
90
91
    def is_readonly(self):
92
        """See Transport.is_readonly."""
93
        return self._decorated.is_readonly()
94
95
    def mkdir(self, relpath, mode=None):
96
        """See Transport.mkdir()."""
97
        return self._decorated.mkdir(relpath, mode)
98
99
    def put(self, relpath, f, mode=None):
100
        """See Transport.put()."""
101
        return self._decorated.put(relpath, f, mode)
102
    
103
    def listable(self):
104
        """See Transport.listable."""
105
        return self._decorated.listable()
106
107
    def iter_files_recursive(self):
108
        """See Transport.iter_files_recursive()."""
109
        return self._decorated.iter_files_recursive()
110
    
111
    def list_dir(self, relpath):
112
        """See Transport.list_dir()."""
113
        return self._decorated.list_dir(relpath)
1608.2.3 by Martin Pool
Add default Transport.rename() to TransportDecorator
114
115
    def rename(self, rel_from, rel_to):
116
        return self._decorated.rename(rel_from, rel_to)
1558.10.2 by Robert Collins
Refactor the FakeNFS support into a TransportDecorator.
117
    
118
    def rmdir(self, relpath):
119
        """See Transport.rmdir."""
120
        return self._decorated.rmdir(relpath)
121
122
    def should_cache(self):
123
        """See Transport.should_cache()."""
124
        return self._decorated.should_cache()
125
126
    def stat(self, relpath):
127
        """See Transport.stat()."""
128
        return self._decorated.stat(relpath)
129
130
    def lock_read(self, relpath):
131
        """See Transport.lock_read."""
132
        return self._decorated.lock_read(relpath)
133
134
    def lock_write(self, relpath):
135
        """See Transport.lock_write."""
136
        return self._decorated.lock_write(relpath)
137
138
139
class DecoratorServer(Server):
140
    """Server for the TransportDecorator for testing with.
141
    
142
    To use this when subclassing TransportDecorator, override override the
143
    get_decorator_class method.
144
    """
145
146
    def setUp(self, server=None):
147
        """See bzrlib.transport.Server.setUp.
148
149
        :server: decorate the urls given by server. If not provided a
150
        LocalServer is created.
151
        """
152
        if server is not None:
153
            self._made_server = False
154
            self._server = server
155
        else:
156
            from bzrlib.transport.local import LocalRelpathServer
157
            self._made_server = True
158
            self._server = LocalRelpathServer()
159
            self._server.setUp()
160
161
    def tearDown(self):
162
        """See bzrlib.transport.Server.tearDown."""
163
        if self._made_server:
164
            self._server.tearDown()
165
166
    def get_decorator_class(self):
167
        """Return the class of the decorators we should be constructing."""
168
        raise NotImplementedError(self.get_decorator_class)
169
170
    def get_url_prefix(self):
171
        """What URL prefix does this decorator produce?"""
172
        return self.get_decorator_class()._get_url_prefix()
173
174
    def get_bogus_url(self):
175
        """See bzrlib.transport.Server.get_bogus_url."""
176
        return self.get_url_prefix() + self._server.get_bogus_url()
177
178
    def get_url(self):
179
        """See bzrlib.transport.Server.get_url."""
180
        return self.get_url_prefix() + self._server.get_url()
181
182
183
def get_test_permutations():
184
    """Return the permutations to be used in testing.
185
    
186
    The Decorator class is not directly usable, and testing it would not have
187
    any benefit - its the concrete classes which need to be tested.
188
    """
189
    return []