~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/weave.py

  • Committer: Martin Pool
  • Date: 2005-05-09 03:03:55 UTC
  • Revision ID: mbp@sourcefrog.net-20050509030355-ad6ab558d1362959
- Don't give an error if the trace file can't be opened

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
 
import errno
24
 
import os
25
 
from cStringIO import StringIO
26
 
import urllib
27
 
 
28
 
from bzrlib.weavefile import read_weave, write_weave_v5
29
 
from bzrlib.weave import Weave
30
 
from bzrlib.store import TransportStore, 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(TransportStore):
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, precious=False):
44
 
        self._transport = transport
45
 
        self._prefixed = prefixed
46
 
        self._precious = precious
47
 
 
48
 
    def filename(self, file_id):
49
 
        """Return the path relative to the transport root."""
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
54
 
 
55
 
    def __iter__(self):
56
 
        l = len(WeaveStore.FILE_SUFFIX)
57
 
        for relpath in self._iter_files_recursive():
58
 
            if relpath.endswith(WeaveStore.FILE_SUFFIX):
59
 
                yield os.path.basename(relpath[:-l])
60
 
 
61
 
    def has_id(self, fileid):
62
 
        return self._transport.has(self.filename(fileid))
63
 
 
64
 
    def _get(self, file_id):
65
 
        return self._transport.get(self.filename(file_id))
66
 
 
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
73
 
        return self._transport.put(self.filename(file_id), f)
74
 
 
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
80
 
        w = read_weave(self._get(file_id))
81
 
        transaction.map.add_weave(file_id, w)
82
 
        transaction.register_clean(w, precious=self._precious)
83
 
        return w
84
 
 
85
 
    def get_lines(self, file_id, rev_id, transaction):
86
 
        """Return text from a particular version of a weave.
87
 
 
88
 
        Returned as a list of lines."""
89
 
        w = self.get_weave(file_id, transaction)
90
 
        return w.get(w.lookup(rev_id))
91
 
    
92
 
    def get_weave_prelude_or_empty(self, file_id, transaction):
93
 
        """cheap version that reads the prelude but not the lines
94
 
        """
95
 
        weave = transaction.map.find_weave(file_id)
96
 
        if weave:
97
 
            mutter("cache hit in %s for %s", self, file_id)
98
 
            return weave
99
 
        try:
100
 
            return read_weave(self._get(file_id),prelude=True)
101
 
        except NoSuchFile:
102
 
            return Weave(weave_name=file_id)
103
 
 
104
 
    def get_weave_or_empty(self, file_id, transaction):
105
 
        """Return a weave, or an empty one if it doesn't exist.""" 
106
 
        try:
107
 
            return self.get_weave(file_id, transaction)
108
 
        except NoSuchFile:
109
 
            weave = Weave(weave_name=file_id)
110
 
            transaction.map.add_weave(file_id, weave)
111
 
            transaction.register_clean(weave, precious=self._precious)
112
 
            return weave
113
 
 
114
 
    def put_weave(self, file_id, weave, transaction):
115
 
        """Write back a modified weave"""
116
 
        transaction.register_dirty(weave)
117
 
        # TODO FOR WRITE TRANSACTIONS: this should be done in a callback
118
 
        # from the transaction, when it decides to save.
119
 
        sio = StringIO()
120
 
        write_weave_v5(weave, sio)
121
 
        sio.seek(0)
122
 
        self._put(file_id, sio)
123
 
 
124
 
    def add_text(self, file_id, rev_id, new_lines, parents, transaction):
125
 
        w = self.get_weave_or_empty(file_id, transaction)
126
 
        parent_idxs = map(w.lookup, parents)
127
 
        w.add(rev_id, parent_idxs, new_lines)
128
 
        self.put_weave(file_id, w, transaction)
129
 
        
130
 
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents,
131
 
                           transaction):
132
 
        w = self.get_weave_or_empty(file_id, transaction)
133
 
        parent_idxs = map(w.lookup, parents)
134
 
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
135
 
        self.put_weave(file_id, w, transaction)
136
 
     
137
 
    def copy_multi(self, from_store, file_ids):
138
 
        assert isinstance(from_store, WeaveStore)
139
 
        for f in file_ids:
140
 
            mutter("copy weave {%s} into %s", f, self)
141
 
            self._put(f, from_store._get(f))