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
23
from bzrlib.bzrdir import (
27
from bzrlib.errors import (
32
from bzrlib.foreign import (
35
from bzrlib.lockable_files import (
38
from bzrlib.repository import (
41
from bzrlib.trace import (
44
from bzrlib.transport import (
48
from bzrlib.plugins.git import (
53
from bzrlib.plugins.git.branch import (
56
from bzrlib.plugins.git.errors import (
57
GitSmartRemoteNotSupported,
60
from bzrlib.plugins.git.dir import (
63
from bzrlib.plugins.git.repository import (
69
from dulwich.errors import (
72
from dulwich.pack import (
38
from dulwich.pack import PackData, Pack
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():
41
93
class GitSmartTransport(Transport):
43
95
def __init__(self, url, _client=None):
44
96
Transport.__init__(self, url)
45
97
(scheme, _, loc, _, _) = urlparse.urlsplit(url)
46
assert scheme == "git"
47
98
hostport, self._path = urllib.splithost(loc)
48
99
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
49
100
self._client = _client
102
def has(self, relpath):
51
105
def _get_client(self):
52
if self._client is not None:
56
return git.client.TCPGitClient(self._host, self._port)
106
raise NotImplementedError(self._get_client)
58
108
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
59
109
if progress is None:
60
110
def progress(text):
61
111
info("git: %s" % text)
62
self._get_client().fetch_pack(self._path, determine_wants,
63
graph_walker, pack_data, progress)
112
client = self._get_client()
114
client.fetch_pack(self._path, determine_wants,
115
graph_walker, pack_data, progress)
116
except GitProtocolError, e:
65
119
def get(self, path):
66
120
raise NoSuchFile(path)
76
130
newurl = urlutils.join(self.base, offset)
78
return GitSmartTransport(newurl, self._client)
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)
81
155
class RemoteGitDir(GitDir):
98
172
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)
101
201
class RemoteGitRepository(GitRepository):
103
203
def __init__(self, gitdir, lockfiles):
104
204
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))
106
229
def fetch_pack(self, determine_wants, graph_walker, pack_data,
108
231
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
111
def fetch_objects(self, determine_wants, graph_walker, progress=None):
234
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
112
235
fd, path = tempfile.mkstemp(suffix=".pack")
113
236
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():
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)
125
263
class RemoteGitBranch(GitBranch):
127
265
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))
266
heads = repository.get_refs()
267
if not name in heads:
268
raise NoSuchRef(name)
269
self._ref = heads[name]
134
270
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
136
272
def last_revision(self):