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
81
from dulwich.pack import load_pack_index
83
from dulwich.pack import PackIndex as load_pack_index
86
# Don't run any tests on GitSmartTransport as it is not intended to be
87
# a full implementation of Transport
88
def get_test_permutations():
38
92
class GitSmartTransport(Transport):
43
97
assert scheme == "git"
44
98
hostport, self._path = urllib.splithost(loc)
45
99
(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)
100
self._client = _client
102
def has(self, relpath):
105
def _get_client(self):
106
if self._client is not None:
110
return git.client.TCPGitClient(self._host, self._port, thin_packs=False)
51
112
def fetch_pack(self, determine_wants, graph_walker, pack_data, progress=None):
52
113
if progress is None:
53
114
def progress(text):
54
115
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)
116
client = self._get_client()
64
for o in p.iterobjects():
118
client.fetch_pack(self._path, determine_wants,
119
graph_walker, pack_data, progress)
120
except GitProtocolError, e:
69
123
def get(self, path):
70
124
raise NoSuchFile(path)
126
def abspath(self, relpath):
127
return urlutils.join(self.base, relpath)
72
129
def clone(self, offset=None):
73
130
"""See Transport.clone()."""
74
131
if offset is None:
99
156
raise NotLocalUrl(self.transport.base)
159
class EmptyObjectStoreIterator(dict):
161
def iterobjects(self):
165
class TemporaryPackIterator(Pack):
167
def __init__(self, path, resolve_ext_ref):
168
self.resolve_ext_ref = resolve_ext_ref
169
super(TemporaryPackIterator, self).__init__(path)
173
if self._idx is None:
174
if self._data is None:
175
self._data = PackData(self._data_path)
176
self._data.create_index_v2(self._idx_path, self.resolve_ext_ref)
177
self._idx = load_pack_index(self._idx_path)
181
os.remove(self._data_path)
182
os.remove(self._idx_path)
102
185
class RemoteGitRepository(GitRepository):
104
187
def __init__(self, gitdir, lockfiles):
105
188
GitRepository.__init__(self, gitdir, lockfiles)
192
if self._refs is not None:
194
def determine_wants(heads):
197
self.bzrdir.root_transport.fetch_pack(determine_wants, None,
198
lambda x: None, lambda x: mutter("git: %s" % x))
107
201
def fetch_pack(self, determine_wants, graph_walker, pack_data,
109
203
self._transport.fetch_pack(determine_wants, graph_walker, pack_data,
206
def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref, progress=None):
207
fd, path = tempfile.mkstemp(suffix=".pack")
208
self.fetch_pack(determine_wants, graph_walker, lambda x: os.write(fd, x), progress)
210
if os.path.getsize(path) == 0:
211
return EmptyObjectStoreIterator()
212
return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
215
class RemoteGitTagDict(tag.BasicTags):
217
def __init__(self, branch):
219
self.repository = branch.repository
221
def get_tag_dict(self):
223
refs = self.repository.get_refs()
224
for k,v in refs.iteritems():
225
if k.startswith("refs/tags/") and not k.endswith("^{}"):
226
v = refs.get(k+"^{}", v)
227
ret[k[len("refs/tags/"):]] = self.branch.mapping.revision_id_foreign_to_bzr(v)
230
def set_tag(self, name, revid):
231
# FIXME: Not supported yet, should do a push of a new ref
232
raise NotImplementedError(self.set_tag)
113
235
class RemoteGitBranch(GitBranch):
115
237
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))
238
heads = repository.get_refs()
239
if not name in heads:
240
raise NoSuchRef(name)
241
self._ref = heads[name]
120
242
super(RemoteGitBranch, self).__init__(bzrdir, repository, name, self._ref, lockfiles)
122
244
def last_revision(self):
123
245
return self.mapping.revision_id_foreign_to_bzr(self._ref)
247
def _synchronize_history(self, destination, revision_id):
248
"""See Branch._synchronize_history()."""
249
destination.generate_revision_history(self.last_revision())