15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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 (
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 import git
27
from bzrlib.plugins.git.branch import GitBranch
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
82
from dulwich.pack import load_pack_index
84
from dulwich.pack import PackIndex as load_pack_index
87
# Don't run any tests on GitSmartTransport as it is not intended to be
88
# a full implementation of Transport
89
def get_test_permutations():
35
from dulwich.pack import PackData
93
38
class GitSmartTransport(Transport):
95
40
def __init__(self, url, _client=None):
96
41
Transport.__init__(self, url)
97
42
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
43
assert scheme == "git"
98
44
hostport, self._path = urllib.splithost(loc)
99
45
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
100
self._client = _client
102
def has(self, relpath):
105
def _get_client(self):
106
raise NotImplementedError(self._get_client)
46
if _client is not None:
47
self._client = _client
49
self._client = git.client.TCPGitClient(self._host, self._port)
108
51
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
109
52
if progress is None:
110
53
def progress(text):
111
54
info("git: %s" % text)
112
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)
114
client.fetch_pack(self._path, determine_wants,
115
graph_walker, pack_data, progress)
116
except GitProtocolError, e:
64
for o in p.iterobjects():
119
69
def get(self, path):
120
70
raise NoSuchFile(path)
122
def abspath(self, relpath):
123
return urlutils.join(self.base, relpath)
125
72
def clone(self, offset=None):
126
73
"""See Transport.clone()."""
127
74
if offset is None:
130
77
newurl = urlutils.join(self.base, offset)
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)
79
return GitSmartTransport(newurl, self._client)
155
82
class RemoteGitDir(GitDir):
172
99
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)
201
102
class RemoteGitRepository(GitRepository):
203
104
def __init__(self, gitdir, lockfiles):
204
105
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))
229
107
def fetch_pack(self, determine_wants, graph_walker, pack_data,
231
109
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
234
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
235
fd, path = tempfile.mkstemp(suffix=".pack")
236
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
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)
263
113
class RemoteGitBranch(GitBranch):
265
115
def __init__(self, bzrdir, repository, name, lockfiles):
266
heads = repository.get_refs()
267
if not name in heads:
268
raise NoSuchRef(name)
269
self._ref = heads[name]
116
def determine_wants(heads):
117
self._ref = heads[name]
118
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
119
lambda x: mutter("git: %s" % x))
270
120
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
272
122
def last_revision(self):
273
123
return self.mapping.revision_id_foreign_to_bzr(self._ref)
275
def _synchronize_history(self, destination, revision_id):
276
"""See Branch._synchronize_history()."""
277
destination.generate_revision_history(self.last_revision())