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.bzrdir import (
28
from bzrlib.errors import (
33
from bzrlib.foreign import (
36
from bzrlib.lockable_files import (
39
from bzrlib.repository import (
42
from bzrlib.trace import (
45
from bzrlib.transport import (
49
from bzrlib.plugins.git import (
54
from bzrlib.plugins.git.branch import (
57
from bzrlib.plugins.git.errors import (
58
GitSmartRemoteNotSupported,
61
from bzrlib.plugins.git.dir import (
64
from bzrlib.plugins.git.repository import (
70
from dulwich.errors import (
73
from dulwich.pack import (
38
from dulwich.pack import PackData, Pack
83
from dulwich.pack import load_pack_index
85
from dulwich.pack import PackIndex as load_pack_index
88
# Don't run any tests on GitSmartTransport as it is not intended to be
89
# a full implementation of Transport
90
def get_test_permutations():
41
94
class GitSmartTransport(Transport):
43
96
def __init__(self, url, _client=None):
44
97
Transport.__init__(self, url)
45
98
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
46
assert scheme == "git"
47
99
hostport, self._path = urllib.splithost(loc)
48
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
100
(self._host, self._port) = urllib.splitnport(hostport, None)
49
101
self._client = _client
103
def has(self, relpath):
51
106
def _get_client(self):
52
if self._client is not None:
56
return git.client.TCPGitClient(self._host, self._port)
107
raise NotImplementedError(self._get_client)
58
109
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
59
110
if progress is None:
60
111
def progress(text):
61
112
info("git: %s" % text)
62
self._get_client().fetch_pack(self._path, determine_wants,
63
graph_walker, pack_data, progress)
113
client = self._get_client()
115
client.fetch_pack(self._path, determine_wants,
116
graph_walker, pack_data, progress)
117
except GitProtocolError, e:
65
120
def get(self, path):
66
121
raise NoSuchFile(path)
76
131
newurl = urlutils.join(self.base, offset)
78
return GitSmartTransport(newurl, self._client)
133
return self.__class__(newurl, self._client)
136
class TCPGitSmartTransport(GitSmartTransport):
140
def _get_client(self):
141
if self._client is not None:
145
return git.client.TCPGitClient(self._host, self._port, thin_packs=False,
146
report_activity=self._report_activity)
149
class SSHGitSmartTransport(GitSmartTransport):
153
def _get_client(self):
154
if self._client is not None:
158
return git.client.SSHGitClient(self._host, self._port, thin_packs=False,
159
report_activity=self._report_activity)
81
162
class RemoteGitDir(GitDir):
98
179
raise NotLocalUrl(self.transport.base)
182
class EmptyObjectStoreIterator(dict):
184
def iterobjects(self):
188
class TemporaryPackIterator(Pack):
190
def __init__(self, path, resolve_ext_ref):
191
super(TemporaryPackIterator, self).__init__(path)
192
self.resolve_ext_ref = resolve_ext_ref
196
if self._idx is None:
197
if self._data is None:
198
self._data = PackData(self._data_path)
199
pb = ui.ui_factory.nested_progress_bar()
201
def report_progress(cur, total):
202
pb.update("generating index", cur, total)
203
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref,
204
progress=report_progress)
207
self._idx = load_pack_index(self._idx_path)
211
os.remove(self._data_path)
212
os.remove(self._idx_path)
101
215
class RemoteGitRepository(GitRepository):
103
217
def __init__(self, gitdir, lockfiles):
104
218
GitRepository.__init__(self, gitdir, lockfiles)
222
def inventories(self):
223
raise GitSmartRemoteNotSupported()
227
raise GitSmartRemoteNotSupported()
231
raise GitSmartRemoteNotSupported()
234
if self._refs is not None:
236
def determine_wants(heads):
239
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
240
lambda x: None, lambda x: mutter("git: %s" % x))
106
243
def fetch_pack(self, determine_wants, graph_walker, pack_data,
108
245
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
111
def fetch_objects(self, determine_wants, graph_walker, progress=None):
248
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
112
249
fd, path = tempfile.mkstemp(suffix=".pack")
113
250
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():
252
if os.path.getsize(path) == 0:
253
return EmptyObjectStoreIterator()
254
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
257
class RemoteGitTagDict(tag.BasicTags):
259
def __init__(self, branch):
261
self.repository = branch.repository
263
def get_tag_dict(self):
265
refs = self.repository.get_refs()
266
for k,v in refs.iteritems():
267
if k.startswith("refs/tags/") and not k.endswith("^{}"):
268
v = refs.get(k+"^{}", v)
269
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
272
def set_tag(self, name, revid):
273
# FIXME: Not supported yet, should do a push of a new ref
274
raise NotImplementedError(self.set_tag)
125
277
class RemoteGitBranch(GitBranch):
127
279
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))
280
heads = repository.get_refs()
281
if not name in heads:
282
raise NoSuchRef(name)
283
self._ref = heads[name]
134
284
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
136
286
def last_revision(self):