/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
1
# Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
2
#
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.
7
#
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.
12
#
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
17
"""A Git repository implementation that uses a Bazaar transport."""
18
19
20
from dulwich.errors import (
21
    NotGitRepository,
0.246.7 by Jelmer Vernooij
more work.
22
    NoIndexPresent,
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
23
    )
0.246.4 by Jelmer Vernooij
more work on transportgit.
24
from dulwich.objects import (
25
    ShaFile,
26
    )
27
from dulwich.object_store import (
28
    PackBasedObjectStore,
29
    PACKDIR,
30
    )
31
from dulwich.pack import (
0.246.7 by Jelmer Vernooij
more work.
32
    PackData,
0.246.4 by Jelmer Vernooij
more work on transportgit.
33
    Pack,
0.200.936 by Jelmer Vernooij
Test transportgit.
34
    iter_sha1,
0.246.7 by Jelmer Vernooij
more work.
35
    load_pack_index_file,
0.200.936 by Jelmer Vernooij
Test transportgit.
36
    write_pack_index_v2,
0.246.4 by Jelmer Vernooij
more work on transportgit.
37
    )
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
38
from dulwich.repo import (
39
    BaseRepo,
0.246.8 by Jelmer Vernooij
simplify refs handling.
40
    DictRefsContainer,
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
41
    OBJECTDIR,
0.246.8 by Jelmer Vernooij
simplify refs handling.
42
    read_info_refs,
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
43
    )
44
45
from bzrlib.errors import (
0.200.933 by Jelmer Vernooij
Allow directories to already exist :-)
46
    FileExists,
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
47
    NoSuchFile,
0.200.946 by Jelmer Vernooij
Fix reading pack files over http.
48
    TransportNotPossible,
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
49
    )
50
51
52
class TransportRepo(BaseRepo):
53
54
    def __init__(self, transport):
55
        self.transport = transport
0.200.720 by Jelmer Vernooij
Avoid loading bzr-git/dulwich when not necessary.
56
        try:
57
            if self.transport.has(".git/info/refs"):
58
                self.bare = False
59
                self._controltransport = self.transport.clone('.git')
60
            elif self.transport.has("info/refs"):
61
                self.bare = True
62
                self._controltransport = self.transport
63
            else:
64
                raise NotGitRepository(self.transport)
65
        except NoSuchFile:
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
66
            raise NotGitRepository(self.transport)
67
        object_store = TransportObjectStore(
68
            self._controltransport.clone(OBJECTDIR))
0.246.8 by Jelmer Vernooij
simplify refs handling.
69
        refs = {}
70
        refs["HEAD"] = self._controltransport.get_bytes("HEAD").rstrip("\n")
71
        refs.update(read_info_refs(self._controltransport.get('info/refs')))
72
        super(TransportRepo, self).__init__(object_store, 
73
                DictRefsContainer(refs))
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
74
75
    def get_named_file(self, path):
76
        """Get a file from the control dir with a specific name.
77
78
        Although the filename should be interpreted as a filename relative to
79
        the control dir in a disk-baked Repo, the object returned need not be
80
        pointing to a file in that location.
81
82
        :param path: The path to the file, relative to the control dir.
83
        :return: An open file object, or None if the file does not exist.
84
        """
85
        try:
86
            return self._controltransport.get(path.lstrip('/'))
87
        except NoSuchFile:
88
            return None
89
90
    def open_index(self):
91
        """Open the index for this repository."""
0.246.9 by Jelmer Vernooij
Remove unused write code.
92
        raise NoIndexPresent()
0.246.1 by Jelmer Vernooij
Add TransportRepo class.
93
94
    def __repr__(self):
95
        return "<TransportRepo for %r>" % self.transport
96
0.246.4 by Jelmer Vernooij
more work on transportgit.
97
98
class TransportObjectStore(PackBasedObjectStore):
99
    """Git-style object store that exists on disk."""
100
101
    def __init__(self, transport):
102
        """Open an object store.
103
104
        :param transport: Transport to open data from
105
        """
106
        super(TransportObjectStore, self).__init__()
107
        self.transport = transport
108
        self.pack_transport = self.transport.clone(PACKDIR)
0.200.889 by Jelmer Vernooij
Fix fetching over HTTP. We really need tests for this...
109
    
110
    def _pack_cache_stale(self):
111
        return False # FIXME
0.246.4 by Jelmer Vernooij
more work on transportgit.
112
0.256.1 by Jelmer Vernooij
Allow using manual listing for pack contents.
113
    def _pack_names(self):
114
        try:
115
            f = self.transport.get('info/packs')
116
        except NoSuchFile:
117
            return self.pack_transport.list_dir(".")
118
        else:
0.200.935 by Jelmer Vernooij
Allow using manual listing for pack contents.
119
            ret = []
0.256.1 by Jelmer Vernooij
Allow using manual listing for pack contents.
120
            for line in f.readlines():
121
                line = line.rstrip("\n")
122
                if not line:
123
                    continue
124
                (kind, name) = line.split(" ", 1)
125
                if kind != "P":
126
                    continue
0.200.935 by Jelmer Vernooij
Allow using manual listing for pack contents.
127
                ret.append(name)
128
            return ret
0.256.1 by Jelmer Vernooij
Allow using manual listing for pack contents.
129
0.246.4 by Jelmer Vernooij
more work on transportgit.
130
    def _load_packs(self):
0.246.7 by Jelmer Vernooij
more work.
131
        ret = []
0.256.1 by Jelmer Vernooij
Allow using manual listing for pack contents.
132
        for name in self._pack_names():
0.246.9 by Jelmer Vernooij
Remove unused write code.
133
            if name.startswith("pack-") and name.endswith(".pack"):
0.200.946 by Jelmer Vernooij
Fix reading pack files over http.
134
                try:
135
                    size = self.pack_transport.stat(name).st_size
136
                except TransportNotPossible:
0.200.950 by Jelmer Vernooij
Load packs lazily.
137
                    def pd():
138
                        # FIXME: This reads the whole pack file at once
139
                        from cStringIO import StringIO
140
                        f = self.pack_transport.get(name)
141
                        contents = f.read()
142
                        return PackData(name, StringIO(contents), size=len(contents))
0.200.946 by Jelmer Vernooij
Fix reading pack files over http.
143
                else:
0.200.950 by Jelmer Vernooij
Load packs lazily.
144
                    pd = lambda: PackData(name, self.pack_transport.get(name),
0.200.946 by Jelmer Vernooij
Fix reading pack files over http.
145
                            size=size)
0.246.9 by Jelmer Vernooij
Remove unused write code.
146
                idxname = name.replace(".pack", ".idx")
0.200.950 by Jelmer Vernooij
Load packs lazily.
147
                idx = lambda: load_pack_index_file(idxname, self.pack_transport.get(idxname))
148
                pack = Pack.from_lazy_objects(pd, idx)
149
                ret.append(pack)
0.246.7 by Jelmer Vernooij
more work.
150
        return ret
0.246.4 by Jelmer Vernooij
more work on transportgit.
151
152
    def _iter_loose_objects(self):
153
        for base in self.transport.list_dir('.'):
154
            if len(base) != 2:
155
                continue
156
            for rest in self.transport.list_dir(base):
157
                yield base+rest
158
159
    def _split_loose_object(self, sha):
160
        return (sha[:2], sha[2:])
161
162
    def _get_loose_object(self, sha):
163
        path = '%s/%s' % self._split_loose_object(sha)
164
        try:
0.200.903 by Jelmer Vernooij
Fix compatibility with newer versions of Dulwich.
165
            return ShaFile.from_file(self.transport.get(path))
0.246.4 by Jelmer Vernooij
more work on transportgit.
166
        except NoSuchFile:
167
            return None
168
169
    def add_object(self, obj):
170
        """Add a single object to this object store.
171
172
        :param obj: Object to add
173
        """
174
        (dir, file) = self._split_loose_object(obj.id)
0.200.933 by Jelmer Vernooij
Allow directories to already exist :-)
175
        try:
176
            self.transport.mkdir(dir)
177
        except FileExists:
178
            pass
0.246.4 by Jelmer Vernooij
more work on transportgit.
179
        path = "%s/%s" % (dir, file)
180
        if self.transport.has(path):
181
            return # Already there, no need to write again
182
        self.transport.put_bytes(path, obj.as_legacy_object())
183
0.200.937 by Jelmer Vernooij
Avoid using os module in transportgit.
184
    def move_in_pack(self, f):
0.200.936 by Jelmer Vernooij
Test transportgit.
185
        """Move a specific file containing a pack into the pack directory.
186
187
        :note: The file should be on the same file system as the
188
            packs directory.
189
190
        :param path: Path to the pack file.
191
        """
0.200.937 by Jelmer Vernooij
Avoid using os module in transportgit.
192
        f.seek(0)
193
        p = PackData(None, f, len(f.getvalue()))
0.200.936 by Jelmer Vernooij
Test transportgit.
194
        entries = p.sorted_entries()
0.200.937 by Jelmer Vernooij
Avoid using os module in transportgit.
195
        basename = "pack-%s" % iter_sha1(entry[0] for entry in entries)
196
        f.seek(0)
197
        self.pack_transport.put_file(basename + ".pack", f)
198
        index_path = self.pack_transport.local_abspath(basename+".idx")
199
        write_pack_index_v2(index_path, entries, p.get_stored_checksum())
200
        idx = load_pack_index_file(basename+".idx",
201
                self.pack_transport.get(basename+".idx"))
202
        final_pack = Pack.from_objects(p, idx)
0.200.936 by Jelmer Vernooij
Test transportgit.
203
        self._add_known_pack(final_pack)
204
        return final_pack
205
0.246.4 by Jelmer Vernooij
more work on transportgit.
206
    def add_pack(self):
207
        """Add a new pack to this object store. 
208
209
        :return: Fileobject to write to and a commit function to 
210
            call when the pack is finished.
211
        """
0.200.937 by Jelmer Vernooij
Avoid using os module in transportgit.
212
        from cStringIO import StringIO
213
        f = StringIO()
0.200.936 by Jelmer Vernooij
Test transportgit.
214
        def commit():
0.200.937 by Jelmer Vernooij
Avoid using os module in transportgit.
215
            if len(f.getvalue()) > 0:
216
                return self.move_in_pack(f)
0.200.936 by Jelmer Vernooij
Test transportgit.
217
            else:
218
                return None
219
        return f, commit
0.200.934 by Jelmer Vernooij
Add init function.
220
221
    @classmethod
222
    def init(cls, transport):
223
        transport.mkdir('info')
224
        transport.mkdir(PACKDIR)
225
        return cls(transport)