15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
from bzrlib.errors import (
31
from bzrlib.trace import (
34
from bzrlib.transport import (
38
from bzrlib.plugins.git import (
43
from bzrlib.plugins.git.branch import (
47
from bzrlib.plugins.git.errors import (
48
GitSmartRemoteNotSupported,
51
from bzrlib.plugins.git.dir import (
54
from bzrlib.plugins.git.mapping import (
57
from bzrlib.plugins.git.repository import (
63
from dulwich.errors import (
66
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.errors import NoSuchRef
29
from bzrlib.plugins.git.dir import GitDir
30
from bzrlib.plugins.git.foreign import ForeignBranch
31
from bzrlib.plugins.git.repository import GitFormat, GitRepository
76
from dulwich.pack import load_pack_index
78
from dulwich.pack import PackIndex as load_pack_index
81
# Don't run any tests on GitSmartTransport as it is not intended to be
82
# a full implementation of Transport
83
def get_test_permutations():
38
from dulwich.pack import PackData, Pack
87
41
class GitSmartTransport(Transport):
89
43
def __init__(self, url, _client=None):
90
44
Transport.__init__(self, url)
91
45
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
46
assert scheme == "git"
92
47
hostport, self._path = urllib.splithost(loc)
93
(self._username, hostport) = urllib.splituser(hostport)
94
(self._host, self._port) = urllib.splitnport(hostport, None)
48
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
95
49
self._client = _client
97
def has(self, relpath):
100
51
def _get_client(self):
101
raise NotImplementedError(self._get_client)
52
if self._client is not None:
56
return git.client.TCPGitClient(self._host, self._port)
106
58
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
107
59
if progress is None:
108
60
def progress(text):
109
61
info("git: %s" % text)
110
client = self._get_client()
112
return client.fetch_pack(self._get_path(), determine_wants,
113
graph_walker, pack_data, progress)
114
except GitProtocolError, e:
117
def send_pack(self, get_changed_refs, generate_pack_contents):
118
client = self._get_client()
120
return client.send_pack(self._get_path(), get_changed_refs,
121
generate_pack_contents)
122
except GitProtocolError, e:
62
self._get_client().fetch_pack(self._path, determine_wants,
63
graph_walker, pack_data, progress)
125
65
def get(self, path):
126
66
raise NoSuchFile(path)
136
76
newurl = urlutils.join(self.base, offset)
138
return self.__class__(newurl, self._client)
141
class TCPGitSmartTransport(GitSmartTransport):
145
def _get_client(self):
146
if self._client is not None:
150
return git.client.TCPGitClient(self._host, self._port, thin_packs=False,
151
report_activity=self._report_activity)
154
class SSHGitSmartTransport(GitSmartTransport):
159
if self._path.startswith("/~/"):
160
return self._path[3:]
163
def _get_client(self):
164
if self._client is not None:
168
return git.client.SSHGitClient(self._host, self._port, self._username,
169
thin_packs=False, report_activity=self._report_activity)
78
return GitSmartTransport(newurl, self._client)
172
81
class RemoteGitDir(GitDir):
190
98
raise NotLocalUrl(self.transport.base)
193
class EmptyObjectStoreIterator(dict):
195
def iterobjects(self):
199
class TemporaryPackIterator(Pack):
201
def __init__(self, path, resolve_ext_ref):
202
super(TemporaryPackIterator, self).__init__(path)
203
self.resolve_ext_ref = resolve_ext_ref
207
if self._idx is None:
208
if self._data is None:
209
self._data = PackData(self._data_path)
210
pb = ui.ui_factory.nested_progress_bar()
212
def report_progress(cur, total):
213
pb.update("generating index", cur, total)
214
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref,
215
progress=report_progress)
218
self._idx = load_pack_index(self._idx_path)
222
os.remove(self._data_path)
223
os.remove(self._idx_path)
226
101
class RemoteGitRepository(GitRepository):
228
103
def __init__(self, gitdir, lockfiles):
229
104
GitRepository.__init__(self, gitdir, lockfiles)
233
def inventories(self):
234
raise GitSmartRemoteNotSupported()
238
raise GitSmartRemoteNotSupported()
242
raise GitSmartRemoteNotSupported()
245
if self._refs is not None:
247
self._refs = self.bzrdir.root_transport.fetch_pack(lambda x: [], None,
248
lambda x: None, lambda x: mutter("git: %s" % x))
251
106
def fetch_pack(self, determine_wants, graph_walker, pack_data,
253
return self._transport.fetch_pack(determine_wants, graph_walker,
256
def send_pack(self, get_changed_refs, generate_pack_contents):
257
return self._transport.send_pack(get_changed_refs, generate_pack_contents)
259
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
108
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
111
def fetch_objects(self, determine_wants, graph_walker, progress=None):
260
112
fd, path = tempfile.mkstemp(suffix=".pack")
261
113
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
263
if os.path.getsize(path) == 0:
264
return EmptyObjectStoreIterator()
265
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
267
def lookup_git_revid(self, bzr_revid):
268
# This won't work for any round-tripped bzr revisions, but it's a start..
270
return mapping_registry.revision_id_bzr_to_foreign(bzr_revid)
271
except InvalidRevisionId:
272
raise NoSuchRevision(self, bzr_revid)
275
class RemoteGitTagDict(tag.BasicTags):
277
def __init__(self, branch):
279
self.repository = branch.repository
281
def get_tag_dict(self):
282
return extract_tags(self.repository.get_refs(), self.branch.mapping)
284
def set_tag(self, name, revid):
285
# FIXME: Not supported yet, should do a push of a new ref
286
raise NotImplementedError(self.set_tag)
116
basename = path[:-len(".pack")]
118
p.create_index_v2(basename+".idx")
119
for o in Pack(basename).iterobjects():
289
125
class RemoteGitBranch(GitBranch):
291
127
def __init__(self, bzrdir, repository, name, lockfiles):
293
super(RemoteGitBranch, self).__init__(bzrdir, repository, name,
296
def revision_history(self):
297
raise GitSmartRemoteNotSupported()
128
def determine_wants(heads):
129
if not name in heads:
130
raise NoSuchRef(name)
131
self._ref = heads[name]
132
bzrdir.root_transport.fetch_pack(determine_wants, None, lambda x: None,
133
lambda x: mutter("git: %s" % x))
134
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
299
136
def last_revision(self):
300
return self.mapping.revision_id_foreign_to_bzr(self.head)
304
if self._ref is not None:
306
heads = self.repository.get_refs()
307
if not self.name in heads:
308
raise NoSuchRef(name)
309
self._ref = heads[self.name]
137
return self.mapping.revision_id_foreign_to_bzr(self._ref)
312
139
def _synchronize_history(self, destination, revision_id):
313
140
"""See Branch._synchronize_history()."""