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.dir import GitDir
29
from bzrlib.plugins.git.foreign import ForeignBranch
30
from bzrlib.plugins.git.repository import GitFormat, GitRepository
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 (
56
from bzrlib.plugins.git.dir import (
59
from bzrlib.plugins.git.foreign import (
62
from bzrlib.plugins.git.repository import (
68
from dulwich.errors import (
71
from dulwich.pack import (
35
from dulwich.pack import PackData
82
# Don't run any tests on GitSmartTransport as it is not intended to be
83
# a full implementation of Transport
84
def get_test_permutations():
38
88
class GitSmartTransport(Transport):
43
93
assert scheme == "git"
44
94
hostport, self._path = urllib.splithost(loc)
45
95
(self._host, self._port) = urllib.splitnport(hostport, git.protocol.TCP_GIT_PORT)
46
if _client is not None:
47
self._client = _client
49
self._client = git.client.TCPGitClient(self._host, self._port)
96
self._client = _client
98
def has(self, relpath):
101
def _get_client(self):
102
if self._client is not None:
106
return git.client.TCPGitClient(self._host, self._port, thin_packs=False)
51
108
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
52
109
if progress is None:
53
110
def progress(text):
54
111
info("git: %s" % text)
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)
112
client = self._get_client()
64
for o in p.iterobjects():
114
client.fetch_pack(self._path, determine_wants,
115
graph_walker, pack_data, progress)
116
except GitProtocolError, e:
69
119
def get(self, path):
70
120
raise NoSuchFile(path)
122
def abspath(self, relpath):
123
return urlutils.join(self.base, relpath)
72
125
def clone(self, offset=None):
73
126
"""See Transport.clone()."""
74
127
if offset is None:
99
152
raise NotLocalUrl(self.transport.base)
155
class EmptyObjectStoreIterator(dict):
157
def iterobjects(self):
161
class TemporaryPackIterator(Pack):
163
def __init__(self, path, resolve_ext_ref):
164
self.resolve_ext_ref = resolve_ext_ref
165
super(TemporaryPackIterator, self).__init__(path)
169
if self._idx is None:
170
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
171
self._idx = PackIndex(self._idx_path)
175
os.remove(self._data_path)
176
os.remove(self._idx_path)
102
179
class RemoteGitRepository(GitRepository):
104
181
def __init__(self, gitdir, lockfiles):
105
182
GitRepository.__init__(self, gitdir, lockfiles)
186
if self._refs is not None:
188
def determine_wants(heads):
191
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
192
lambda x: None, lambda x: mutter("git: %s" % x))
107
195
def fetch_pack(self, determine_wants, graph_walker, pack_data,
109
197
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
200
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
201
fd, path = tempfile.mkstemp(suffix=".pack")
202
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
204
if os.path.getsize(path) == 0:
205
return EmptyObjectStoreIterator()
206
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
209
class RemoteGitTagDict(tag.BasicTags):
211
def __init__(self, branch):
213
self.repository = branch.repository
215
def get_tag_dict(self):
217
refs = self.repository.get_refs()
218
for k,v in refs.iteritems():
219
if k.startswith("refs/tags/") and not k.endswith("^{}"):
220
v = refs.get(k+"^{}", v)
221
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
224
def set_tag(self, name, revid):
225
# FIXME: Not supported yet, should do a push of a new ref
226
raise NotImplementedError(self.set_tag)
113
229
class RemoteGitBranch(GitBranch):
115
231
def __init__(self, bzrdir, repository, name, lockfiles):
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))
232
heads = repository.get_refs()
233
if not name in heads:
234
raise NoSuchRef(name)
235
self._ref = heads[name]
120
236
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
122
238
def last_revision(self):
123
239
return self.mapping.revision_id_foreign_to_bzr(self._ref)
241
def _synchronize_history(self, destination, revision_id):
242
"""See Branch._synchronize_history()."""
243
destination.generate_revision_history(self.last_revision())