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
23
from bzrlib.bzrdir import (
27
from bzrlib.errors import (
21
32
from bzrlib.lockable_files import TransportLock
22
33
from bzrlib.repository import Repository
23
34
from bzrlib.trace import info
24
35
from bzrlib.transport import Transport
26
from bzrlib.plugins.git import git
37
from bzrlib.plugins.git import lazy_check_versions
27
40
from bzrlib.plugins.git.branch import GitBranch
41
from bzrlib.plugins.git.errors import NoSuchRef
28
42
from bzrlib.plugins.git.dir import GitDir
29
43
from bzrlib.plugins.git.foreign import ForeignBranch
30
from bzrlib.plugins.git.repository import GitFormat, GitRepository
44
from bzrlib.plugins.git.repository import (
50
from dulwich.errors import GitProtocolError
51
from dulwich.pack import (
35
from dulwich.pack import PackData
62
# Don't run any tests on GitSmartTransport as it is not intended to be
63
# a full implementation of Transport
64
def get_test_permutations():
38
68
class GitSmartTransport(Transport):
43
73
assert scheme == "git"
44
74
hostport, self._path = urllib.splithost(loc)
45
75
(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)
76
self._client = _client
78
def has(self, relpath):
81
def _get_client(self):
82
if self._client is not None:
86
return git.client.TCPGitClient(self._host, self._port, thin_packs=False)
51
88
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
52
89
if progress is None:
53
90
def progress(text):
54
91
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)
92
client = self._get_client()
64
for o in p.iterobjects():
94
client.fetch_pack(self._path, determine_wants,
95
graph_walker, pack_data, progress)
96
except GitProtocolError, e:
69
99
def get(self, path):
70
100
raise NoSuchFile(path)
102
def abspath(self, relpath):
103
return urlutils.join(self.base, relpath)
72
105
def clone(self, offset=None):
73
106
"""See Transport.clone()."""
74
107
if offset is None:
99
132
raise NotLocalUrl(self.transport.base)
135
class EmptyObjectStoreIterator(dict):
137
def iterobjects(self):
141
class TemporaryPackIterator(Pack):
143
def __init__(self, path, resolve_ext_ref):
144
self.resolve_ext_ref = resolve_ext_ref
145
super(TemporaryPackIterator, self).__init__(path)
149
if self._idx is None:
150
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
151
self._idx = PackIndex(self._idx_path)
155
os.remove(self._data_path)
156
os.remove(self._idx_path)
102
159
class RemoteGitRepository(GitRepository):
104
161
def __init__(self, gitdir, lockfiles):
105
162
GitRepository.__init__(self, gitdir, lockfiles)
166
if self._refs is not None:
168
def determine_wants(heads):
171
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
172
lambda x: None, lambda x: mutter("git: %s" % x))
107
175
def fetch_pack(self, determine_wants, graph_walker, pack_data,
109
177
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
180
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
181
fd, path = tempfile.mkstemp(suffix=".pack")
182
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
184
if os.path.getsize(path) == 0:
185
return EmptyObjectStoreIterator()
186
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
189
class RemoteGitTagDict(tag.BasicTags):
191
def __init__(self, branch):
193
self.repository = branch.repository
195
def get_tag_dict(self):
197
refs = self.repository.get_refs()
198
for k,v in refs.iteritems():
199
if k.startswith("refs/tags/") and not k.endswith("^{}"):
200
v = refs.get(k+"^{}", v)
201
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
204
def set_tag(self, name, revid):
205
# FIXME: Not supported yet, should do a push of a new ref
206
raise NotImplementedError(self.set_tag)
113
209
class RemoteGitBranch(GitBranch):
115
211
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))
212
heads = repository.get_refs()
213
if not name in heads:
214
raise NoSuchRef(name)
215
self._ref = heads[name]
120
216
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
122
218
def last_revision(self):
123
219
return self.mapping.revision_id_foreign_to_bzr(self._ref)
221
def _synchronize_history(self, destination, revision_id):
222
"""See Branch._synchronize_history()."""
223
destination.generate_revision_history(self.last_revision())