1
# Copyright (C) 2007-2009 Jelmer Vernooij <jelmer@samba.org>
1
# Copyright (C) 2007-2008 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
18
18
from bzrlib import urlutils
19
19
from bzrlib.bzrdir import BzrDir, BzrDirFormat
20
from bzrlib.errors import BzrError, NoSuchFile, NotLocalUrl
20
from bzrlib.errors import NoSuchFile, NotLocalUrl
21
21
from bzrlib.lockable_files import TransportLock
22
22
from bzrlib.repository import Repository
23
23
from bzrlib.trace import info
24
24
from bzrlib.transport import Transport
26
from bzrlib.plugins.git import lazy_check_versions
26
from bzrlib.plugins.git import git
29
27
from bzrlib.plugins.git.branch import GitBranch
30
from bzrlib.plugins.git.errors import NoSuchRef
31
28
from bzrlib.plugins.git.dir import GitDir
32
29
from bzrlib.plugins.git.foreign import ForeignBranch
33
30
from bzrlib.plugins.git.repository import GitFormat, GitRepository
41
from dulwich.errors import GitProtocolError
42
from dulwich.pack import PackData, Pack, PackIndex
44
# Don't run any tests on GitSmartTransport as it is not intended to be
45
# a full implementation of Transport
46
def get_test_permutations():
35
from dulwich.pack import PackData
50
38
class GitSmartTransport(Transport):
55
43
assert scheme == "git"
56
44
hostport, self._path = urllib.splithost(loc)
57
45
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
58
self._client = _client
60
def has(self, relpath):
63
def _get_client(self):
64
if self._client is not None:
68
return git.client.TCPGitClient(self._host, self._port, thin_packs=False)
46
if _client is not None:
47
self._client = _client
49
self._client = git.client.TCPGitClient(self._host, self._port)
70
51
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
71
52
if progress is None:
72
53
def progress(text):
73
54
info("git: %s" % text)
74
client = self._get_client()
55
self._client.fetch_pack(self._path, determine_wants, graph_walker,
58
def fetch_objects(self, determine_wants, graph_walker, progress=None):
59
fd, path = tempfile.mkstemp(dir=self.pack_dir(), suffix=".pack")
60
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
76
client.fetch_pack(self._path, determine_wants,
77
graph_walker, pack_data, progress)
78
except GitProtocolError, e:
64
for o in p.iterobjects():
81
69
def get(self, path):
82
70
raise NoSuchFile(path)
84
def abspath(self, relpath):
85
return urlutils.join(self.base, relpath)
87
72
def clone(self, offset=None):
88
73
"""See Transport.clone()."""
105
90
def open_repository(self):
106
91
return RemoteGitRepository(self, self._lockfiles)
108
def open_branch(self, _unsupported=False):
93
def open_branch(self):
109
94
repo = self.open_repository()
110
95
# TODO: Support for multiple branches in one bzrdir in bzrlib!
111
96
return RemoteGitBranch(self, repo, "HEAD", self._lockfiles)
114
99
raise NotLocalUrl(self.transport.base)
117
class EmptyObjectStoreIterator(dict):
119
def iterobjects(self):
123
class TemporaryPackIterator(Pack):
125
def __init__(self, path, resolve_ext_ref):
126
self.resolve_ext_ref = resolve_ext_ref
127
super(TemporaryPackIterator, self).__init__(path)
131
if self._idx is None:
132
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
133
self._idx = PackIndex(self._idx_path)
137
os.remove(self._data_path)
138
os.remove(self._idx_path)
141
102
class RemoteGitRepository(GitRepository):
143
104
def __init__(self, gitdir, lockfiles):
148
109
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
151
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
152
fd, path = tempfile.mkstemp(suffix=".pack")
153
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
155
if os.path.getsize(path) == 0:
156
return EmptyObjectStoreIterator()
157
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
160
113
class RemoteGitBranch(GitBranch):
162
115
def __init__(self, bzrdir, repository, name, lockfiles):
163
116
def determine_wants(heads):
164
if not name in heads:
165
raise NoSuchRef(name)
166
117
self._ref = heads[name]
167
118
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
168
119
lambda x: mutter("git: %s" % x))
171
122
def last_revision(self):
172
123
return self.mapping.revision_id_foreign_to_bzr(self._ref)
174
def _synchronize_history(self, destination, revision_id):
175
"""See Branch._synchronize_history()."""
176
destination.generate_revision_history(self.last_revision())