/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/store/weave.py

  • Committer: Robert Collins
  • Date: 2005-10-09 23:42:12 UTC
  • Revision ID: robertc@robertcollins.net-20051009234212-7973344d900afb0b
merge in niemeyers prefixed-store patch

Show diffs side-by-side

added added

removed removed

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