18
18
from bzrlib import urlutils
19
19
from bzrlib.bzrdir import BzrDir, BzrDirFormat
20
from bzrlib.errors import NoSuchFile, NotLocalUrl
20
from bzrlib.errors import BzrError, 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 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.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():
38
50
class GitSmartTransport(Transport):
43
55
assert scheme == "git"
44
56
hostport, self._path = urllib.splithost(loc)
45
57
(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)
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,
69
capabilities=["multi_ack", "side-band-64k", "ofs-delta", "side-band"])
51
71
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
52
72
if progress is None:
53
73
def progress(text):
54
74
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)
75
client = self._get_client()
64
for o in p.iterobjects():
77
client.fetch_pack(self._path, determine_wants,
78
graph_walker, pack_data, progress)
79
except GitProtocolError, e:
69
82
def get(self, path):
70
83
raise NoSuchFile(path)
85
def abspath(self, relpath):
86
return urlutils.join(self.base, relpath)
72
88
def clone(self, offset=None):
73
89
"""See Transport.clone()."""
90
106
def open_repository(self):
91
107
return RemoteGitRepository(self, self._lockfiles)
93
def open_branch(self):
109
def open_branch(self, _unsupported=False):
94
110
repo = self.open_repository()
95
111
# TODO: Support for multiple branches in one bzrdir in bzrlib!
96
112
return RemoteGitBranch(self, repo, "HEAD", self._lockfiles)
99
115
raise NotLocalUrl(self.transport.base)
118
class EmptyObjectStoreIterator(dict):
120
def iterobjects(self):
124
class TemporaryPackIterator(Pack):
126
def __init__(self, path, resolve_ext_ref):
127
self.resolve_ext_ref = resolve_ext_ref
128
super(TemporaryPackIterator, self).__init__(path)
132
if self._idx is None:
133
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
134
self._idx = PackIndex(self._idx_path)
138
os.remove(self._data_path)
139
os.remove(self._idx_path)
102
142
class RemoteGitRepository(GitRepository):
104
144
def __init__(self, gitdir, lockfiles):
109
149
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
152
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
153
fd, path = tempfile.mkstemp(suffix=".pack")
154
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
156
if os.path.getsize(path) == 0:
157
return EmptyObjectStoreIterator()
158
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
113
161
class RemoteGitBranch(GitBranch):
115
163
def __init__(self, bzrdir, repository, name, lockfiles):
116
164
def determine_wants(heads):
165
if not name in heads:
166
raise NoSuchRef(name)
117
167
self._ref = heads[name]
118
168
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
119
169
lambda x: mutter("git: %s" % x))
122
172
def last_revision(self):
123
173
return self.mapping.revision_id_foreign_to_bzr(self._ref)
175
def _synchronize_history(self, destination, revision_id):
176
"""See Branch._synchronize_history()."""
177
destination.generate_revision_history(self.last_revision())