15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from bzrlib import urlutils
19
from bzrlib.bzrdir import BzrDir, BzrDirFormat
20
from bzrlib.errors import NoSuchFile, NotLocalUrl
21
from bzrlib.lockable_files import TransportLock
22
from bzrlib.repository import Repository
23
from bzrlib.trace import info
24
from bzrlib.transport import Transport
26
from bzrlib.plugins.git.branch import GitBranch
27
from bzrlib.plugins.git.errors import NoSuchRef
28
from bzrlib.plugins.git.dir import GitDir
29
from bzrlib.plugins.git.foreign import ForeignBranch
30
from bzrlib.plugins.git.repository import GitFormat, GitRepository
23
from bzrlib.bzrdir import (
27
from bzrlib.errors import (
32
from bzrlib.lockable_files import (
35
from bzrlib.repository import (
38
from bzrlib.trace import (
41
from bzrlib.transport import (
45
from bzrlib.plugins.git import (
50
from bzrlib.plugins.git.branch import (
53
from bzrlib.plugins.git.errors import (
54
GitSmartRemoteNotSupported,
57
from bzrlib.plugins.git.dir import (
60
from bzrlib.plugins.git.foreign import (
63
from bzrlib.plugins.git.repository import (
69
from dulwich.errors import (
72
from dulwich.pack import (
38
from dulwich.pack import PackData, Pack
82
from dulwich.pack import load_pack_index
84
from dulwich.pack import PackIndex as load_pack_index
40
87
# Don't run any tests on GitSmartTransport as it is not intended to be
41
88
# a full implementation of Transport
48
95
def __init__(self, url, _client=None):
49
96
Transport.__init__(self, url)
50
97
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
51
assert scheme == "git"
52
98
hostport, self._path = urllib.splithost(loc)
53
99
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
54
100
self._client = _client
102
def has(self, relpath):
56
105
def _get_client(self):
57
if self._client is not None:
61
return git.client.TCPGitClient(self._host, self._port)
106
raise NotImplementedError(self._get_client)
63
108
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
64
109
if progress is None:
65
110
def progress(text):
66
111
info("git: %s" % text)
67
self._get_client().fetch_pack(self._path, determine_wants,
68
graph_walker, pack_data, progress)
112
client = self._get_client()
114
client.fetch_pack(self._path, determine_wants,
115
graph_walker, pack_data, progress)
116
except GitProtocolError, e:
70
119
def get(self, path):
71
120
raise NoSuchFile(path)
81
130
newurl = urlutils.join(self.base, offset)
83
return GitSmartTransport(newurl, self._client)
132
return self.__class__(newurl, self._client)
135
class TCPGitSmartTransport(GitSmartTransport):
137
def _get_client(self):
138
if self._client is not None:
142
return git.client.TCPGitClient(self._host, self._port, thin_packs=False)
145
class SSHGitSmartTransport(GitSmartTransport):
147
def _get_client(self):
148
if self._client is not None:
152
return git.client.SSHGitClient(self._host, self._port, thin_packs=False)
86
155
class RemoteGitDir(GitDir):
103
172
raise NotLocalUrl(self.transport.base)
175
class EmptyObjectStoreIterator(dict):
177
def iterobjects(self):
181
class TemporaryPackIterator(Pack):
183
def __init__(self, path, resolve_ext_ref):
184
super(TemporaryPackIterator, self).__init__(path)
185
self.resolve_ext_ref = resolve_ext_ref
189
if self._idx is None:
190
if self._data is None:
191
self._data = PackData(self._data_path)
192
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
193
self._idx = load_pack_index(self._idx_path)
197
os.remove(self._data_path)
198
os.remove(self._idx_path)
106
201
class RemoteGitRepository(GitRepository):
108
203
def __init__(self, gitdir, lockfiles):
109
204
GitRepository.__init__(self, gitdir, lockfiles)
208
def inventories(self):
209
raise GitSmartRemoteNotSupported()
213
raise GitSmartRemoteNotSupported()
217
raise GitSmartRemoteNotSupported()
220
if self._refs is not None:
222
def determine_wants(heads):
225
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
226
lambda x: None, lambda x: mutter("git: %s" % x))
111
229
def fetch_pack(self, determine_wants, graph_walker, pack_data,
113
231
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
116
def fetch_objects(self, determine_wants, graph_walker, progress=None):
234
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
117
235
fd, path = tempfile.mkstemp(suffix=".pack")
118
236
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
120
basename = path[:-len(".pack")]
122
p.create_index_v2(basename+".idx")
123
pack = Pack(basename)
125
return (len(p), pack.iterobjects())
238
if os.path.getsize(path) == 0:
239
return EmptyObjectStoreIterator()
240
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
243
class RemoteGitTagDict(tag.BasicTags):
245
def __init__(self, branch):
247
self.repository = branch.repository
249
def get_tag_dict(self):
251
refs = self.repository.get_refs()
252
for k,v in refs.iteritems():
253
if k.startswith("refs/tags/") and not k.endswith("^{}"):
254
v = refs.get(k+"^{}", v)
255
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
258
def set_tag(self, name, revid):
259
# FIXME: Not supported yet, should do a push of a new ref
260
raise NotImplementedError(self.set_tag)
128
263
class RemoteGitBranch(GitBranch):
130
265
def __init__(self, bzrdir, repository, name, lockfiles):
131
def determine_wants(heads):
132
if not name in heads:
133
raise NoSuchRef(name)
134
self._ref = heads[name]
135
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
136
lambda x: mutter("git: %s" % x))
266
heads = repository.get_refs()
267
if not name in heads:
268
raise NoSuchRef(name)
269
self._ref = heads[name]
137
270
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
139
272
def last_revision(self):