15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
24
from bzrlib.errors import (
29
from bzrlib.trace import (
32
from bzrlib.transport import (
36
from bzrlib.plugins.git import (
41
from bzrlib.plugins.git.branch import (
44
from bzrlib.plugins.git.errors import (
45
GitSmartRemoteNotSupported,
48
from bzrlib.plugins.git.dir import (
51
from bzrlib.plugins.git.repository import (
57
from dulwich.errors import (
60
from dulwich.pack import (
38
from dulwich.pack import PackData, Pack
70
from dulwich.pack import load_pack_index
72
from dulwich.pack import PackIndex as load_pack_index
75
# Don't run any tests on GitSmartTransport as it is not intended to be
76
# a full implementation of Transport
77
def get_test_permutations():
41
81
class GitSmartTransport(Transport):
43
83
def __init__(self, url, _client=None):
44
84
Transport.__init__(self, url)
45
85
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
46
assert scheme == "git"
47
86
hostport, self._path = urllib.splithost(loc)
48
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
87
(self._host, self._port) = urllib.splitnport(hostport, None)
49
88
self._client = _client
90
def has(self, relpath):
51
93
def _get_client(self):
52
if self._client is not None:
56
return git.client.TCPGitClient(self._host, self._port)
94
raise NotImplementedError(self._get_client)
58
96
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
59
97
if progress is None:
60
98
def progress(text):
61
99
info("git: %s" % text)
62
self._get_client().fetch_pack(self._path, determine_wants,
63
graph_walker, pack_data, progress)
100
client = self._get_client()
102
client.fetch_pack(self._path, determine_wants,
103
graph_walker, pack_data, progress)
104
except GitProtocolError, e:
65
107
def get(self, path):
66
108
raise NoSuchFile(path)
76
118
newurl = urlutils.join(self.base, offset)
78
return GitSmartTransport(newurl, self._client)
120
return self.__class__(newurl, self._client)
123
class TCPGitSmartTransport(GitSmartTransport):
127
def _get_client(self):
128
if self._client is not None:
132
return git.client.TCPGitClient(self._host, self._port, thin_packs=False,
133
report_activity=self._report_activity)
136
class SSHGitSmartTransport(GitSmartTransport):
140
def _get_client(self):
141
if self._client is not None:
145
return git.client.SSHGitClient(self._host, self._port, thin_packs=False,
146
report_activity=self._report_activity)
81
149
class RemoteGitDir(GitDir):
98
167
raise NotLocalUrl(self.transport.base)
170
class EmptyObjectStoreIterator(dict):
172
def iterobjects(self):
176
class TemporaryPackIterator(Pack):
178
def __init__(self, path, resolve_ext_ref):
179
super(TemporaryPackIterator, self).__init__(path)
180
self.resolve_ext_ref = resolve_ext_ref
184
if self._idx is None:
185
if self._data is None:
186
self._data = PackData(self._data_path)
187
pb = ui.ui_factory.nested_progress_bar()
189
def report_progress(cur, total):
190
pb.update("generating index", cur, total)
191
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref,
192
progress=report_progress)
195
self._idx = load_pack_index(self._idx_path)
199
os.remove(self._data_path)
200
os.remove(self._idx_path)
101
203
class RemoteGitRepository(GitRepository):
103
205
def __init__(self, gitdir, lockfiles):
104
206
GitRepository.__init__(self, gitdir, lockfiles)
210
def inventories(self):
211
raise GitSmartRemoteNotSupported()
215
raise GitSmartRemoteNotSupported()
219
raise GitSmartRemoteNotSupported()
222
if self._refs is not None:
224
def determine_wants(heads):
227
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
228
lambda x: None, lambda x: mutter("git: %s" % x))
106
231
def fetch_pack(self, determine_wants, graph_walker, pack_data,
108
233
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
111
def fetch_objects(self, determine_wants, graph_walker, progress=None):
236
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
112
237
fd, path = tempfile.mkstemp(suffix=".pack")
113
238
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
116
basename = path[:-len(".pack")]
118
p.create_index_v2(basename+".idx")
119
for o in Pack(basename).iterobjects():
240
if os.path.getsize(path) == 0:
241
return EmptyObjectStoreIterator()
242
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
245
class RemoteGitTagDict(tag.BasicTags):
247
def __init__(self, branch):
249
self.repository = branch.repository
251
def get_tag_dict(self):
253
refs = self.repository.get_refs()
254
for k,v in refs.iteritems():
255
if k.startswith("refs/tags/") and not k.endswith("^{}"):
256
v = refs.get(k+"^{}", v)
257
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
260
def set_tag(self, name, revid):
261
# FIXME: Not supported yet, should do a push of a new ref
262
raise NotImplementedError(self.set_tag)
125
265
class RemoteGitBranch(GitBranch):
127
267
def __init__(self, bzrdir, repository, name, lockfiles):
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))
268
heads = repository.get_refs()
269
if not name in heads:
270
raise NoSuchRef(name)
271
self._ref = heads[name]
134
272
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
274
def revision_history(self):
275
raise GitSmartRemoteNotSupported()
136
277
def last_revision(self):
137
278
return self.mapping.revision_id_foreign_to_bzr(self._ref)