1
# Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
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.
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.
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
17
"""A Git repository implementation that uses a Bazaar transport."""
20
from dulwich.errors import (
24
from dulwich.objects import (
27
from dulwich.object_store import (
31
from dulwich.pack import (
36
from dulwich.repo import (
43
from bzrlib.errors import (
48
class TransportRepo(BaseRepo):
50
def __init__(self, transport):
51
self.transport = transport
53
if self.transport.has(".git/info/refs"):
55
self._controltransport = self.transport.clone('.git')
56
elif self.transport.has("info/refs"):
58
self._controltransport = self.transport
60
raise NotGitRepository(self.transport)
62
raise NotGitRepository(self.transport)
63
object_store = TransportObjectStore(
64
self._controltransport.clone(OBJECTDIR))
66
refs["HEAD"] = self._controltransport.get_bytes("HEAD").rstrip("\n")
67
refs.update(read_info_refs(self._controltransport.get('info/refs')))
68
super(TransportRepo, self).__init__(object_store,
69
DictRefsContainer(refs))
71
def get_named_file(self, path):
72
"""Get a file from the control dir with a specific name.
74
Although the filename should be interpreted as a filename relative to
75
the control dir in a disk-baked Repo, the object returned need not be
76
pointing to a file in that location.
78
:param path: The path to the file, relative to the control dir.
79
:return: An open file object, or None if the file does not exist.
82
return self._controltransport.get(path.lstrip('/'))
87
"""Open the index for this repository."""
88
raise NoIndexPresent()
91
return "<TransportRepo for %r>" % self.transport
94
class TransportObjectStore(PackBasedObjectStore):
95
"""Git-style object store that exists on disk."""
97
def __init__(self, transport):
98
"""Open an object store.
100
:param transport: Transport to open data from
102
super(TransportObjectStore, self).__init__()
103
self.transport = transport
104
self.pack_transport = self.transport.clone(PACKDIR)
106
def _load_packs(self):
108
for line in self.transport.get('info/packs').readlines():
109
line = line.rstrip("\n")
112
(kind, name) = line.split(" ", 1)
115
if name.startswith("pack-") and name.endswith(".pack"):
116
pd = PackData(name, self.pack_transport.get(name))
117
idxname = name.replace(".pack", ".idx")
118
idx = load_pack_index_file(idxname, self.pack_transport.get(idxname))
119
ret.append(Pack.from_objects(pd, idx))
122
def _iter_loose_objects(self):
123
for base in self.transport.list_dir('.'):
126
for rest in self.transport.list_dir(base):
129
def _split_loose_object(self, sha):
130
return (sha[:2], sha[2:])
132
def _get_loose_object(self, sha):
133
path = '%s/%s' % self._split_loose_object(sha)
135
return ShaFile._parse_file(self.transport.get(path).read())
139
def add_object(self, obj):
140
"""Add a single object to this object store.
142
:param obj: Object to add
144
(dir, file) = self._split_loose_object(obj.id)
145
self.transport.mkdir(dir)
146
path = "%s/%s" % (dir, file)
147
if self.transport.has(path):
148
return # Already there, no need to write again
149
self.transport.put_bytes(path, obj.as_legacy_object())
152
"""Add a new pack to this object store.
154
:return: Fileobject to write to and a commit function to
155
call when the pack is finished.
157
raise NotImplementedError(self.add_pack)