~bzr-pqm/bzr/bzr.dev

1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
1
#! /usr/bin/python
2
3
# Copyright (C) 2005 Canonical Ltd
4
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
9
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
1393.1.19 by Martin Pool
- add WeaveStore.__iter__, __contains__ and copy_multi()
19
# XXX: Some consideration of the problems that might occur if there are
20
# files whose id differs only in case.  That should probably be forbidden.
21
22
23
from cStringIO import StringIO
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
24
import os
1224 by Martin Pool
- new method WeaveStore.get_weave_or_empty
25
import errno
1223 by Martin Pool
- store inventories in weave
26
27
from bzrlib.weavefile import read_weave, write_weave_v5
28
from bzrlib.weave import Weave
1430 by Robert Collins
touchup the prefixed-store patch
29
from bzrlib.store import TransportStore, hash_prefix
1223 by Martin Pool
- store inventories in weave
30
from bzrlib.atomicfile import AtomicFile
1429 by Robert Collins
merge in niemeyers prefixed-store patch
31
from bzrlib.errors import NoSuchFile, FileExists
1393.1.19 by Martin Pool
- add WeaveStore.__iter__, __contains__ and copy_multi()
32
from bzrlib.trace import mutter
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
33
34
1430 by Robert Collins
touchup the prefixed-store patch
35
class WeaveStore(TransportStore):
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
36
    """Collection of several weave files in a directory.
37
38
    This has some shortcuts for reading and writing them.
39
    """
1393.1.19 by Martin Pool
- add WeaveStore.__iter__, __contains__ and copy_multi()
40
    FILE_SUFFIX = '.weave'
41
1429 by Robert Collins
merge in niemeyers prefixed-store patch
42
    def __init__(self, transport, prefixed=False):
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
43
        self._transport = transport
1429 by Robert Collins
merge in niemeyers prefixed-store patch
44
        self._prefixed = prefixed
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
45
1223 by Martin Pool
- store inventories in weave
46
    def filename(self, file_id):
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
47
        """Return the path relative to the transport root."""
1429 by Robert Collins
merge in niemeyers prefixed-store patch
48
        if self._prefixed:
49
            return hash_prefix(file_id) + file_id + WeaveStore.FILE_SUFFIX
50
        else:
51
            return file_id + WeaveStore.FILE_SUFFIX
52
1393.1.19 by Martin Pool
- add WeaveStore.__iter__, __contains__ and copy_multi()
53
    def __iter__(self):
54
        l = len(WeaveStore.FILE_SUFFIX)
1429 by Robert Collins
merge in niemeyers prefixed-store patch
55
        for relpath, st in self._iter_relpaths():
56
            if relpath.endswith(WeaveStore.FILE_SUFFIX):
57
                yield os.path.basename(relpath[:-l])
1393.1.19 by Martin Pool
- add WeaveStore.__iter__, __contains__ and copy_multi()
58
59
    def __contains__(self, fileid):
60
        """"""
61
        return self._transport.has(self.filename(fileid))
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
62
63
    def _get(self, file_id):
64
        return self._transport.get(self.filename(file_id))
65
66
    def _put(self, file_id, f):
1429 by Robert Collins
merge in niemeyers prefixed-store patch
67
        if self._prefixed:
68
            try:
69
                self._transport.mkdir(hash_prefix(file_id))
70
            except FileExists:
71
                pass
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
72
        return self._transport.put(self.filename(file_id), f)
1223 by Martin Pool
- store inventories in weave
73
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
74
    def get_weave(self, file_id, transaction):
75
        weave = transaction.map.find_weave(file_id)
76
        if weave:
77
            mutter("cache hit in %s for %s", self, file_id)
78
            return weave
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
79
        w = read_weave(self._get(file_id))
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
80
        transaction.map.add_weave(file_id, w)
81
        transaction.register_clean(w)
1363 by Martin Pool
- add quick-and-dirty cache for weaves to speed check command
82
        return w
1262 by Martin Pool
- fetch should also copy ancestry records
83
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
84
    def get_lines(self, file_id, rev_id, transaction):
1262 by Martin Pool
- fetch should also copy ancestry records
85
        """Return text from a particular version of a weave.
86
87
        Returned as a list of lines."""
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
88
        w = self.get_weave(file_id, transaction)
1262 by Martin Pool
- fetch should also copy ancestry records
89
        return w.get(w.lookup(rev_id))
1196 by Martin Pool
- [WIP] retrieve historical texts from weaves
90
    
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
91
    def get_weave_or_empty(self, file_id, transaction):
1224 by Martin Pool
- new method WeaveStore.get_weave_or_empty
92
        """Return a weave, or an empty one if it doesn't exist.""" 
93
        try:
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
94
            return self.get_weave(file_id, transaction)
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
95
        except NoSuchFile:
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
96
            weave = Weave(weave_name=file_id)
97
            transaction.map.add_weave(file_id, weave)
98
            transaction.register_clean(weave)
99
            return weave
1224 by Martin Pool
- new method WeaveStore.get_weave_or_empty
100
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
101
    def put_weave(self, file_id, weave, transaction):
1223 by Martin Pool
- store inventories in weave
102
        """Write back a modified weave"""
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
103
        transaction.register_dirty(weave)
104
        # TODO FOR WRITE TRANSACTIONS: this should be done in a callback
105
        # from the transaction, when it decides to save.
1393.2.2 by John Arbash Meinel
Updated stores to use Transport
106
        sio = StringIO()
107
        write_weave_v5(weave, sio)
108
        sio.seek(0)
109
        self._put(file_id, sio)
1223 by Martin Pool
- store inventories in weave
110
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
111
    def add_text(self, file_id, rev_id, new_lines, parents, transaction):
112
        w = self.get_weave_or_empty(file_id, transaction)
1223 by Martin Pool
- store inventories in weave
113
        parent_idxs = map(w.lookup, parents)
114
        w.add(rev_id, parent_idxs, new_lines)
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
115
        self.put_weave(file_id, w, transaction)
1223 by Martin Pool
- store inventories in weave
116
        
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
117
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents,
118
                           transaction):
119
        w = self.get_weave_or_empty(file_id, transaction)
1092.2.22 by Robert Collins
text_version and name_version unification looking reasonable
120
        parent_idxs = map(w.lookup, parents)
121
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
1417.1.8 by Robert Collins
use transactions in the weave store interface, which enables caching for log
122
        self.put_weave(file_id, w, transaction)
1223 by Martin Pool
- store inventories in weave
123
     
1393.1.19 by Martin Pool
- add WeaveStore.__iter__, __contains__ and copy_multi()
124
    def copy_multi(self, from_store, file_ids):
125
        assert isinstance(from_store, WeaveStore)
126
        for f in file_ids:
127
            mutter("copy weave {%s} into %s", f, self)
128
            self._put(f, from_store._get(f))