~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/weave.py

Exclude more files from dumb-rsync upload

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
# files whose id differs only in case.  That should probably be forbidden.
21
21
 
22
22
 
 
23
import errno
 
24
import os
23
25
from cStringIO import StringIO
24
 
import os
25
 
import errno
 
26
import urllib
26
27
 
27
28
from bzrlib.weavefile import read_weave, write_weave_v5
28
29
from bzrlib.weave import Weave
29
 
from bzrlib.store import Store
 
30
from bzrlib.store import TransportStore, hash_prefix
30
31
from bzrlib.atomicfile import AtomicFile
31
 
from bzrlib.errors import NoSuchFile
 
32
from bzrlib.errors import NoSuchFile, FileExists
32
33
from bzrlib.trace import mutter
33
34
 
34
35
 
35
 
 
36
 
 
37
 
class WeaveStore(Store):
 
36
class WeaveStore(TransportStore):
38
37
    """Collection of several weave files in a directory.
39
38
 
40
39
    This has some shortcuts for reading and writing them.
41
40
    """
42
41
    FILE_SUFFIX = '.weave'
43
42
 
44
 
    def __init__(self, transport):
 
43
    def __init__(self, transport, prefixed=False, precious=False):
45
44
        self._transport = transport
46
 
        self._cache = {}
47
 
        self.enable_cache = False
48
 
 
 
45
        self._prefixed = prefixed
 
46
        self._precious = precious
49
47
 
50
48
    def filename(self, file_id):
51
49
        """Return the path relative to the transport root."""
52
 
        return file_id + WeaveStore.FILE_SUFFIX
 
50
        if self._prefixed:
 
51
            return hash_prefix(file_id) + urllib.quote(file_id) + WeaveStore.FILE_SUFFIX
 
52
        else:
 
53
            return urllib.quote(file_id) + WeaveStore.FILE_SUFFIX
53
54
 
54
55
    def __iter__(self):
55
56
        l = len(WeaveStore.FILE_SUFFIX)
56
 
        for f in self._transport.list_dir('.'):
57
 
            if f.endswith(WeaveStore.FILE_SUFFIX):
58
 
                f = f[:-l]
59
 
                yield f
 
57
        for relpath in self._iter_files_recursive():
 
58
            if relpath.endswith(WeaveStore.FILE_SUFFIX):
 
59
                yield os.path.basename(relpath[:-l])
60
60
 
61
 
    def __contains__(self, fileid):
62
 
        """"""
 
61
    def has_id(self, fileid):
63
62
        return self._transport.has(self.filename(fileid))
64
63
 
65
64
    def _get(self, file_id):
66
65
        return self._transport.get(self.filename(file_id))
67
66
 
68
67
    def _put(self, file_id, f):
 
68
        if self._prefixed:
 
69
            try:
 
70
                self._transport.mkdir(hash_prefix(file_id))
 
71
            except FileExists:
 
72
                pass
69
73
        return self._transport.put(self.filename(file_id), f)
70
74
 
71
 
 
72
 
    def get_weave(self, file_id):
73
 
        if self.enable_cache:
74
 
            if file_id in self._cache:
75
 
                return self._cache[file_id]
 
75
    def get_weave(self, file_id, transaction):
 
76
        weave = transaction.map.find_weave(file_id)
 
77
        if weave:
 
78
            mutter("cache hit in %s for %s", self, file_id)
 
79
            return weave
76
80
        w = read_weave(self._get(file_id))
77
 
        if self.enable_cache:
78
 
            self._cache[file_id] = w
 
81
        transaction.map.add_weave(file_id, w)
 
82
        transaction.register_clean(w, precious=self._precious)
79
83
        return w
80
84
 
81
 
 
82
 
    def get_lines(self, file_id, rev_id):
 
85
    def get_lines(self, file_id, rev_id, transaction):
83
86
        """Return text from a particular version of a weave.
84
87
 
85
88
        Returned as a list of lines."""
86
 
        w = self.get_weave(file_id)
 
89
        w = self.get_weave(file_id, transaction)
87
90
        return w.get(w.lookup(rev_id))
88
91
    
89
 
 
90
 
    def get_weave_or_empty(self, file_id):
 
92
    def get_weave_or_empty(self, file_id, transaction):
91
93
        """Return a weave, or an empty one if it doesn't exist.""" 
92
94
        try:
93
 
            inf = self._get(file_id)
 
95
            return self.get_weave(file_id, transaction)
94
96
        except NoSuchFile:
95
 
            return Weave(weave_name=file_id)
96
 
        else:
97
 
            return read_weave(inf)
98
 
    
 
97
            weave = Weave(weave_name=file_id)
 
98
            transaction.map.add_weave(file_id, weave)
 
99
            transaction.register_clean(weave, precious=self._precious)
 
100
            return weave
99
101
 
100
 
    def put_weave(self, file_id, weave):
 
102
    def put_weave(self, file_id, weave, transaction):
101
103
        """Write back a modified weave"""
102
 
        if self.enable_cache:
103
 
            self._cache[file_id] = weave
104
 
 
 
104
        transaction.register_dirty(weave)
 
105
        # TODO FOR WRITE TRANSACTIONS: this should be done in a callback
 
106
        # from the transaction, when it decides to save.
105
107
        sio = StringIO()
106
108
        write_weave_v5(weave, sio)
107
109
        sio.seek(0)
108
 
 
109
110
        self._put(file_id, sio)
110
111
 
111
 
 
112
 
    def add_text(self, file_id, rev_id, new_lines, parents):
113
 
        w = self.get_weave_or_empty(file_id)
 
112
    def add_text(self, file_id, rev_id, new_lines, parents, transaction):
 
113
        w = self.get_weave_or_empty(file_id, transaction)
114
114
        parent_idxs = map(w.lookup, parents)
115
115
        w.add(rev_id, parent_idxs, new_lines)
116
 
        self.put_weave(file_id, w)
 
116
        self.put_weave(file_id, w, transaction)
117
117
        
118
 
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents):
119
 
        w = self.get_weave_or_empty(file_id)
 
118
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents,
 
119
                           transaction):
 
120
        w = self.get_weave_or_empty(file_id, transaction)
120
121
        parent_idxs = map(w.lookup, parents)
121
122
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
122
 
        self.put_weave(file_id, w)
 
123
        self.put_weave(file_id, w, transaction)
123
124
     
124
125
    def copy_multi(self, from_store, file_ids):
125
126
        assert isinstance(from_store, WeaveStore)