~bzr-pqm/bzr/bzr.dev

2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
1
# Copyright (C) 2005 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
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
#
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
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
#
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
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
1608.2.1 by Martin Pool
[merge] Storage filename escaping
17
"""A store that keeps the full text of every version.
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
18
19
This store keeps uncompressed versions of the full text. It does not
20
do any sort of delta compression.
21
"""
22
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
23
import gzip
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
24
import os
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
25
from cStringIO import StringIO
26
27
from bzrlib import osutils
28
from bzrlib.errors import BzrError, NoSuchFile, FileExists
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
29
import bzrlib.store
30
from bzrlib.trace import mutter
31
32
1092.2.24 by Robert Collins
merge from martins newformat branch - brings in transport abstraction
33
34
class TextStore(bzrlib.store.TransportStore):
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
35
    """Store that holds files indexed by unique names.
36
37
    Files can be added, but not modified once they are in.  Typically
38
    the hash is used as the name, or something else known to be unique,
39
    such as a UUID.
40
1393.2.4 by John Arbash Meinel
All tests pass.
41
    Files are stored uncompressed, with no delta compression.
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
42
    """
43
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
44
    def _add_compressed(self, fn, f):
45
        from cStringIO import StringIO
46
        from bzrlib.osutils import pumpfile
47
        
48
        if isinstance(f, basestring):
49
            f = StringIO(f)
50
            
51
        sio = StringIO()
52
        gf = gzip.GzipFile(mode='wb', fileobj=sio)
53
        # if pumpfile handles files that don't fit in ram,
54
        # so will this function
55
        pumpfile(f, gf)
56
        gf.close()
57
        sio.seek(0)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
58
        self._try_put(fn, sio)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
59
1442.1.28 by Robert Collins
pull up core TransportStore.add from TextStore.add and CompressedTextStore.add
60
    def _add(self, fn, f):
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
61
        if self._compressed:
62
            self._add_compressed(fn, f)
63
        else:
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
64
            self._try_put(fn, f)
65
66
    def _try_put(self, fn, f):
67
        try:
1955.3.9 by John Arbash Meinel
Find more occurrances of put() and replace with put_file or put_bytes
68
            self._transport.put_file(fn, f, mode=self._file_mode)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
69
        except NoSuchFile:
70
            if not self._prefixed:
71
                raise
72
            try:
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
73
                self._transport.mkdir(os.path.dirname(fn), mode=self._dir_mode)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
74
            except FileExists:
75
                pass
1955.3.9 by John Arbash Meinel
Find more occurrances of put() and replace with put_file or put_bytes
76
            self._transport.put_file(fn, f, mode=self._file_mode)
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
77
1442.1.39 by Robert Collins
unify has() implementations for TransportStore classes
78
    def _get(self, fn):
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
79
        if fn.endswith('.gz'):
80
            return self._get_compressed(fn)
81
        else:
82
            return self._transport.get(fn)
83
84
    def _copy_one(self, fileid, suffix, other, pb):
85
        # TODO: Once the copy_to interface is improved to allow a source
86
        #       and destination targets, then we can always do the copy
87
        #       as long as other is a TextStore
88
        if not (isinstance(other, TextStore)
89
            and other._prefixed == self._prefixed):
90
            return super(TextStore, self)._copy_one(fileid, suffix, other, pb)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
91
92
        mutter('_copy_one: %r, %r', fileid, suffix)
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
93
        path = other._get_name(fileid, suffix)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
94
        if path is None:
95
            raise KeyError(fileid + '-' + str(suffix))
96
97
        try:
1608.2.1 by Martin Pool
[merge] Storage filename escaping
98
            result = other._transport.copy_to([path], self._transport,
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
99
                                              mode=self._file_mode)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
100
        except NoSuchFile:
101
            if not self._prefixed:
102
                raise
103
            try:
3350.6.1 by Robert Collins
* New ``versionedfile.KeyMapper`` interface to abstract out the access to
104
                self._transport.mkdir(osutils.dirname(path), mode=self._dir_mode)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
105
            except FileExists:
106
                pass
1551.3.11 by Aaron Bentley
Merge from Robert
107
            result = other._transport.copy_to([path], self._transport,
1185.58.4 by John Arbash Meinel
Added permission checking to Branch, and propogated that change into the stores.
108
                                              mode=self._file_mode)
1185.16.159 by John Arbash Meinel
Updated the stores, all tests pass, and a store doesn't have to be 100% compressed
109
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
110
        if result != 1:
111
            raise BzrError('Unable to copy file: %r' % (path,))
112
113
    def _get_compressed(self, filename):
114
        """Returns a file reading from a particular entry."""
115
        f = self._transport.get(filename)
116
        # gzip.GzipFile.read() requires a tell() function
117
        # but some transports return objects that cannot seek
118
        # so buffer them in a StringIO instead
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
119
        if getattr(f, 'tell', None) is not None:
1185.16.157 by John Arbash Meinel
Added ability for TextStore to handle both compressed and uncompressed, it just looks for one type first
120
            return gzip.GzipFile(mode='rb', fileobj=f)
121
        else:
122
            from cStringIO import StringIO
123
            sio = StringIO(f.read())
124
            return gzip.GzipFile(mode='rb', fileobj=sio)