23
23
from bzrlib.trace import info
24
24
from bzrlib.transport import Transport
26
from bzrlib.plugins.git import git
26
from bzrlib.plugins.git import lazy_check_versions
27
29
from bzrlib.plugins.git.branch import GitBranch
30
from bzrlib.plugins.git.errors import NoSuchRef
28
31
from bzrlib.plugins.git.dir import GitDir
29
32
from bzrlib.plugins.git.foreign import ForeignBranch
30
33
from bzrlib.plugins.git.repository import GitFormat, GitRepository
35
from dulwich.pack import PackData
41
from dulwich.pack import PackData, Pack, PackIndex
43
# Don't run any tests on GitSmartTransport as it is not intended to be
44
# a full implementation of Transport
45
def get_test_permutations():
38
49
class GitSmartTransport(Transport):
43
54
assert scheme == "git"
44
55
hostport, self._path = urllib.splithost(loc)
45
56
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
46
if _client is not None:
47
self._client = _client
49
self._client = git.client.TCPGitClient(self._host, self._port)
57
self._client = _client
59
def has(self, relpath):
62
def _get_client(self):
63
if self._client is not None:
67
return git.client.TCPGitClient(self._host, self._port,
68
capabilities=["multi_ack", "side-band-64k", "ofs-delta", "side-band"])
51
70
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
52
71
if progress is None:
53
72
def progress(text):
54
73
info("git: %s" % text)
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)
64
for o in p.iterobjects():
74
self._get_client().fetch_pack(self._path, determine_wants,
75
graph_walker, pack_data, progress)
69
77
def get(self, path):
70
78
raise NoSuchFile(path)
80
def abspath(self, relpath):
81
return urlutils.join(self.base, relpath)
72
83
def clone(self, offset=None):
73
84
"""See Transport.clone()."""
90
101
def open_repository(self):
91
102
return RemoteGitRepository(self, self._lockfiles)
93
def open_branch(self):
104
def open_branch(self, _unsupported=False):
94
105
repo = self.open_repository()
95
106
# TODO: Support for multiple branches in one bzrdir in bzrlib!
96
107
return RemoteGitBranch(self, repo, "HEAD", self._lockfiles)
99
110
raise NotLocalUrl(self.transport.base)
113
class EmptyObjectStoreIterator(dict):
115
def iterobjects(self):
119
class TemporaryPackIterator(Pack):
121
def __init__(self, path, resolve_ext_ref):
122
self.resolve_ext_ref = resolve_ext_ref
123
super(TemporaryPackIterator, self).__init__(path)
127
if self._idx is None:
128
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
129
self._idx = PackIndex(self._idx_path)
133
os.remove(self._data_path)
134
os.remove(self._idx_path)
102
137
class RemoteGitRepository(GitRepository):
104
139
def __init__(self, gitdir, lockfiles):
109
144
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
147
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
148
fd, path = tempfile.mkstemp(suffix=".pack")
149
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
151
if os.path.getsize(path) == 0:
152
return EmptyObjectStoreIterator()
153
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
113
156
class RemoteGitBranch(GitBranch):
115
158
def __init__(self, bzrdir, repository, name, lockfiles):
116
159
def determine_wants(heads):
160
if not name in heads:
161
raise NoSuchRef(name)
117
162
self._ref = heads[name]
118
163
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
119
164
lambda x: mutter("git: %s" % x))
122
167
def last_revision(self):
123
168
return self.mapping.revision_id_foreign_to_bzr(self._ref)
170
def _synchronize_history(self, destination, revision_id):
171
"""See Branch._synchronize_history()."""
172
destination.generate_revision_history(self.last_revision())