/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.358.2 by Jelmer Vernooij
Refresh copyright headers, add my email.
1
# Copyright (C) 2007-2018 Jelmer Vernooij <jelmer@jelmer.uk>
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
0.358.1 by Jelmer Vernooij
Fix FSF address.
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
16
0.358.3 by Jelmer Vernooij
Enable absolute import.
17
"""Remote dirs, repositories and branches."""
18
0.200.1594 by Jelmer Vernooij
Use absolute_import everywhere.
19
from __future__ import absolute_import
20
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
21
import gzip
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
22
import re
23
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
24
from .. import (
0.200.596 by Jelmer Vernooij
Import RemoteGitBranch._get_config().
25
    config,
0.200.707 by Jelmer Vernooij
Add debug routines.
26
    debug,
0.404.5 by Jelmer Vernooij
Check for diverged branches during push.
27
    errors,
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
28
    osutils,
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
29
    trace,
0.200.333 by Jelmer Vernooij
Support progress reporting when creating index.
30
    ui,
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
31
    urlutils,
32
    )
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
33
from ..push import (
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
34
    PushResult,
35
    )
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
36
from ..errors import (
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
37
    AlreadyBranchError,
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
38
    BzrError,
0.404.5 by Jelmer Vernooij
Check for diverged branches during push.
39
    DivergedBranches,
0.200.1412 by Jelmer Vernooij
Implement GitControlDirFormat.supports_transport.
40
    InProcessTransport,
0.200.415 by Jelmer Vernooij
make 'bzr pull --revision' work for remote repositories.
41
    InvalidRevisionId,
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
42
    NoSuchFile,
0.200.415 by Jelmer Vernooij
make 'bzr pull --revision' work for remote repositories.
43
    NoSuchRevision,
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
44
    NoSuchTag,
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
45
    NotBranchError,
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
46
    NotLocalUrl,
7103.1.2 by Jelmer Vernooij
Handle PermissionDenied.
47
    PermissionDenied,
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
48
    UninitializableFormat,
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
49
    )
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
50
from ..revisiontree import RevisionTree
6986.2.2 by Jelmer Vernooij
Merge trunk.
51
from ..sixish import text_type
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
52
from ..transport import (
0.200.292 by Jelmer Vernooij
Fix formatting.
53
    Transport,
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
54
    register_urlparse_netloc_protocol,
0.200.292 by Jelmer Vernooij
Fix formatting.
55
    )
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
56
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
57
from . import (
0.200.292 by Jelmer Vernooij
Fix formatting.
58
    lazy_check_versions,
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
59
    user_agent_for_github,
0.200.292 by Jelmer Vernooij
Fix formatting.
60
    )
0.200.200 by Jelmer Vernooij
Register lazily where possible.
61
lazy_check_versions()
62
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
63
from .branch import (
0.200.292 by Jelmer Vernooij
Fix formatting.
64
    GitBranch,
0.295.1 by Jelmer Vernooij
Split up branch formats.
65
    GitBranchFormat,
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
66
    GitBranchPushResult,
0.200.1064 by Jelmer Vernooij
Use common base class for tags.
67
    GitTags,
0.406.2 by Jelmer Vernooij
Add tests.
68
    _quick_lookup_revno,
0.200.292 by Jelmer Vernooij
Fix formatting.
69
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
70
from .dir import (
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
71
    GitControlDirFormat,
72
    GitDir,
73
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
74
from .errors import (
0.200.319 by Jelmer Vernooij
Print proper error when trying unsupported operations against a git server.
75
    GitSmartRemoteNotSupported,
0.200.292 by Jelmer Vernooij
Fix formatting.
76
    NoSuchRef,
77
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
78
from .mapping import (
0.200.415 by Jelmer Vernooij
make 'bzr pull --revision' work for remote repositories.
79
    mapping_registry,
80
    )
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
81
from .object_store import (
82
    get_object_store,
83
    )
0.404.5 by Jelmer Vernooij
Check for diverged branches during push.
84
from .push import (
85
    remote_divergence,
86
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
87
from .repository import (
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
88
    GitRepository,
89
    )
0.200.1641 by Jelmer Vernooij
Use relative imports where possible.
90
from .refs import (
0.200.872 by Jelmer Vernooij
Move refs code to separate module.
91
    branch_name_to_ref,
0.200.1487 by Jelmer Vernooij
Use peeling.
92
    is_peeled,
0.375.1 by Jelmer Vernooij
Fix remote tests, warn when fetching git->bzr and bzr->git.
93
    ref_to_tag_name,
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
94
    tag_name_to_ref,
0.200.872 by Jelmer Vernooij
Move refs code to separate module.
95
    )
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
96
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
97
import dulwich
98
import dulwich.client
0.200.292 by Jelmer Vernooij
Fix formatting.
99
from dulwich.errors import (
100
    GitProtocolError,
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
101
    HangupException,
0.200.292 by Jelmer Vernooij
Fix formatting.
102
    )
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
103
from dulwich.pack import (
104
    Pack,
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
105
    pack_objects_to_data,
0.200.289 by Jelmer Vernooij
Cope with new member variables in RepositoryFormat.
106
    )
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
107
from dulwich.protocol import ZERO_SHA
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
108
from dulwich.refs import (
109
    DictRefsContainer,
110
    SYMREF,
111
    )
112
from dulwich.repo import (
113
    NotGitRepository,
114
    )
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
115
import os
0.200.1624 by Jelmer Vernooij
Add ssh vendor for dulwich that uses the bzr ssh vendor.
116
import select
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
117
import tempfile
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
118
119
try:
120
    import urllib.parse as urlparse
121
    from urllib.parse import splituser, splitnport
122
except ImportError:
123
    import urlparse
124
    from urllib import splituser, splitnport
0.200.1555 by Jelmer Vernooij
Remove segment parameters for http smart transports.
125
126
# urlparse only supports a limited number of schemes by default
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
127
register_urlparse_netloc_protocol('git')
128
register_urlparse_netloc_protocol('git+ssh')
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
129
0.200.586 by Jelmer Vernooij
Fix issues pointed out by pyflakes.
130
from dulwich.pack import load_pack_index
0.200.306 by Jelmer Vernooij
Fix tests, split up InterGitNonGitRepository.
131
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
132
0.406.1 by Jelmer Vernooij
Properly lookup revnos for brz-git push result.
133
class GitPushResult(PushResult):
134
135
    def _lookup_revno(self, revid):
0.406.2 by Jelmer Vernooij
Add tests.
136
        try:
137
            return _quick_lookup_revno(self.source_branch, self.target_branch,
138
                revid)
139
        except GitSmartRemoteNotSupported:
140
            return None
0.406.1 by Jelmer Vernooij
Properly lookup revnos for brz-git push result.
141
142
    @property
143
    def old_revno(self):
144
        return self._lookup_revno(self.old_revid)
145
146
    @property
147
    def new_revno(self):
148
        return self._lookup_revno(self.new_revid)
149
150
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
151
# Don't run any tests on GitSmartTransport as it is not intended to be
0.200.181 by Jelmer Vernooij
Support setting tags.
152
# a full implementation of Transport
153
def get_test_permutations():
154
    return []
155
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
156
0.200.708 by Jelmer Vernooij
Factor out URL parsing.
157
def split_git_url(url):
0.200.709 by Jelmer Vernooij
When unpacking URLs, strip leftmost slash to match gits behaviour.
158
    """Split a Git URL.
159
160
    :param url: Git URL
161
    :return: Tuple with host, port, username, path.
162
    """
0.200.743 by Jelmer Vernooij
Fix URL parsing.
163
    (scheme, netloc, loc, _, _) = urlparse.urlsplit(url)
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
164
    path = urlparse.unquote(loc)
0.246.2 by Jelmer Vernooij
Improve the fix dealing with git repo's in home directories.
165
    if path.startswith("/~"):
0.200.709 by Jelmer Vernooij
When unpacking URLs, strip leftmost slash to match gits behaviour.
166
        path = path[1:]
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
167
    (username, hostport) = splituser(netloc)
168
    (host, port) = splitnport(hostport, None)
0.200.708 by Jelmer Vernooij
Factor out URL parsing.
169
    return (host, port, username, path)
170
171
0.200.1562 by Jelmer Vernooij
Add separate exception for remote errors.
172
class RemoteGitError(BzrError):
173
0.290.1 by Jelmer Vernooij
Avoid 'message' argument in RemoteGitError; apparently it breaks some versions of Python.
174
    _fmt = "Remote server error: %(msg)s"
0.200.1562 by Jelmer Vernooij
Add separate exception for remote errors.
175
176
7103.1.1 by Jelmer Vernooij
Improved error parsing for Git branches.
177
class HeadUpdateFailed(BzrError):
178
179
    _fmt = ("Unable to update remote HEAD branch. To update the master "
180
            "branch, specify the URL %(base_url)s,branch=master.")
181
182
    def __init__(self, base_url):
183
        super(HeadUpdateFailed, self).__init__()
184
        self.base_url = base_url
185
186
0.200.1275 by Jelmer Vernooij
recognize missing repositories
187
def parse_git_error(url, message):
188
    """Parse a remote git server error and return a bzr exception.
189
190
    :param url: URL of the remote repository
191
    :param message: Message sent by the remote git server
192
    """
193
    message = str(message).strip()
7103.1.1 by Jelmer Vernooij
Improved error parsing for Git branches.
194
    if (message.startswith("Could not find Repository ") or
7104.2.1 by Jelmer Vernooij
Handle another way of formatting Git "repository not found" errors.
195
        message == 'Repository not found.' or
196
        (message.startswith('Repository ') and message.endswith(' not found.'))):
0.200.1275 by Jelmer Vernooij
recognize missing repositories
197
        return NotBranchError(url, message)
0.200.1563 by Jelmer Vernooij
Improve error message.
198
    if message == "HEAD failed to update":
199
        base_url, _ = urlutils.split_segment_parameters(url)
7103.1.1 by Jelmer Vernooij
Improved error parsing for Git branches.
200
        return HeadUpdateFailed(base_url)
7103.1.2 by Jelmer Vernooij
Handle PermissionDenied.
201
    if message.startswith('access denied or repository not exported:'):
7103.1.3 by Jelmer Vernooij
Strip space.
202
        extra, path = message.split(': ', 1)
7103.1.2 by Jelmer Vernooij
Handle PermissionDenied.
203
        return PermissionDenied(path, extra)
7131.7.4 by Jelmer Vernooij
Don't use GitLab string.
204
    if message.endswith('You are not allowed to push code to this project.'):
7131.7.2 by Jelmer Vernooij
Handle github PermissionDenied.
205
        return PermissionDenied(url, message)
7131.7.3 by Jelmer Vernooij
Handle one more error.
206
    if message.endswith(' does not appear to be a git repository'):
207
        return NotBranchError(url, message)
7131.7.2 by Jelmer Vernooij
Handle github PermissionDenied.
208
    m = re.match(r'Permission to ([^ ]+) denied to ([^ ]+)\.', message)
209
    if m:
210
        return PermissionDenied(m.group(1), 'denied to %s' % m.group(2))
0.200.1275 by Jelmer Vernooij
recognize missing repositories
211
    # Don't know, just return it to the user as-is
0.200.1562 by Jelmer Vernooij
Add separate exception for remote errors.
212
    return RemoteGitError(message)
0.200.1275 by Jelmer Vernooij
recognize missing repositories
213
214
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
215
class GitSmartTransport(Transport):
216
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
217
    def __init__(self, url, _client=None):
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
218
        Transport.__init__(self, url)
0.200.708 by Jelmer Vernooij
Factor out URL parsing.
219
        (self._host, self._port, self._username, self._path) = \
220
            split_git_url(url)
0.200.707 by Jelmer Vernooij
Add debug routines.
221
        if 'transport' in debug.debug_flags:
222
            trace.mutter('host: %r, user: %r, port: %r, path: %r',
223
                         self._host, self._username, self._port, self._path)
0.200.166 by Jelmer Vernooij
don't reuse client objects.
224
        self._client = _client
0.200.1464 by Jelmer Vernooij
Warn about ignoring path segment parameters when using bzr 2.4.
225
        self._stripped_path = self._path.rsplit(",", 1)[0]
0.200.166 by Jelmer Vernooij
don't reuse client objects.
226
0.200.543 by Jelmer Vernooij
Implement GitSmartTransport.external_url().
227
    def external_url(self):
228
        return self.base
229
0.200.238 by Jelmer Vernooij
Import Transport.has().
230
    def has(self, relpath):
231
        return False
232
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
233
    def _get_client(self):
0.200.307 by Jelmer Vernooij
Support git+ssh.
234
        raise NotImplementedError(self._get_client)
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
235
0.200.470 by Jelmer Vernooij
Properly parse username in URLs.
236
    def _get_path(self):
0.200.1464 by Jelmer Vernooij
Warn about ignoring path segment parameters when using bzr 2.4.
237
        return self._stripped_path
0.200.470 by Jelmer Vernooij
Properly parse username in URLs.
238
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
239
    def get(self, path):
240
        raise NoSuchFile(path)
241
0.200.160 by Jelmer Vernooij
Implement abspath.
242
    def abspath(self, relpath):
243
        return urlutils.join(self.base, relpath)
244
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
245
    def clone(self, offset=None):
246
        """See Transport.clone()."""
247
        if offset is None:
248
            newurl = self.base
249
        else:
250
            newurl = urlutils.join(self.base, offset)
251
0.200.307 by Jelmer Vernooij
Support git+ssh.
252
        return self.__class__(newurl, self._client)
253
254
255
class TCPGitSmartTransport(GitSmartTransport):
256
0.200.332 by Jelmer Vernooij
Support activity reporting.
257
    _scheme = 'git'
258
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
259
    def _get_client(self):
0.200.307 by Jelmer Vernooij
Support git+ssh.
260
        if self._client is not None:
261
            ret = self._client
262
            self._client = None
263
            return ret
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
264
        if self._host == '':
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
265
            # return dulwich.client.LocalGitClient()
266
            return dulwich.client.SubprocessGitClient()
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
267
        return dulwich.client.TCPGitClient(self._host, self._port,
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
268
            report_activity=self._report_activity)
0.200.307 by Jelmer Vernooij
Support git+ssh.
269
270
0.200.1624 by Jelmer Vernooij
Add ssh vendor for dulwich that uses the bzr ssh vendor.
271
class SSHSocketWrapper(object):
272
273
    def __init__(self, sock):
274
        self.sock = sock
275
276
    def read(self, len=None):
277
        return self.sock.recv(len)
278
279
    def write(self, data):
280
        return self.sock.write(data)
281
282
    def can_read(self):
283
        return len(select.select([self.sock.fileno()], [], [], 0)[0]) > 0
284
285
286
class DulwichSSHVendor(dulwich.client.SSHVendor):
287
288
    def __init__(self):
6986.2.1 by Jelmer Vernooij
Move breezy.plugins.git to breezy.git.
289
        from ..transport import ssh
0.200.1624 by Jelmer Vernooij
Add ssh vendor for dulwich that uses the bzr ssh vendor.
290
        self.bzr_ssh_vendor = ssh._get_ssh_vendor()
291
292
    def run_command(self, host, command, username=None, port=None):
293
        connection = self.bzr_ssh_vendor.connect_ssh(username=username,
294
            password=None, port=port, host=host, command=command)
295
        (kind, io_object) = connection.get_sock_or_pipes()
296
        if kind == 'socket':
297
            return SSHSocketWrapper(io_object)
298
        else:
299
            raise AssertionError("Unknown io object kind %r'" % kind)
300
301
302
#dulwich.client.get_ssh_vendor = DulwichSSHVendor
303
304
0.200.307 by Jelmer Vernooij
Support git+ssh.
305
class SSHGitSmartTransport(GitSmartTransport):
306
0.200.332 by Jelmer Vernooij
Support activity reporting.
307
    _scheme = 'git+ssh'
308
0.200.470 by Jelmer Vernooij
Properly parse username in URLs.
309
    def _get_path(self):
0.200.1464 by Jelmer Vernooij
Warn about ignoring path segment parameters when using bzr 2.4.
310
        path = self._stripped_path
0.200.1318 by Jelmer Vernooij
Strip segment parameters where necessary.
311
        if path.startswith("/~/"):
312
            return path[3:]
313
        return path
0.200.470 by Jelmer Vernooij
Properly parse username in URLs.
314
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
315
    def _get_client(self):
0.200.307 by Jelmer Vernooij
Support git+ssh.
316
        if self._client is not None:
317
            ret = self._client
318
            self._client = None
319
            return ret
0.253.1 by Ross Light
Added configuration options for git-upload-pack and git-receive-pack
320
        location_config = config.LocationConfig(self.base)
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
321
        client = dulwich.client.SSHGitClient(self._host, self._port, self._username,
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
322
            report_activity=self._report_activity)
0.253.1 by Ross Light
Added configuration options for git-upload-pack and git-receive-pack
323
        # Set up alternate pack program paths
324
        upload_pack = location_config.get_user_option('git_upload_pack')
325
        if upload_pack:
0.200.949 by Jelmer Vernooij
merge support for specifying alternative paths for git executables.
326
            client.alternative_paths["upload-pack"] = upload_pack
0.253.1 by Ross Light
Added configuration options for git-upload-pack and git-receive-pack
327
        receive_pack = location_config.get_user_option('git_receive_pack')
328
        if receive_pack:
0.200.949 by Jelmer Vernooij
merge support for specifying alternative paths for git executables.
329
            client.alternative_paths["receive-pack"] = receive_pack
0.253.1 by Ross Light
Added configuration options for git-upload-pack and git-receive-pack
330
        return client
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
331
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
332
0.295.1 by Jelmer Vernooij
Split up branch formats.
333
class RemoteGitBranchFormat(GitBranchFormat):
334
335
    def get_format_description(self):
336
        return 'Remote Git Branch'
337
338
    @property
339
    def _matchingcontroldir(self):
340
        return RemoteGitControlDirFormat()
341
0.295.2 by Jelmer Vernooij
Make RemoteGitBranchFormat uninitializeable.
342
    def initialize(self, a_controldir, name=None, repository=None,
343
                   append_revisions_only=None):
344
        raise UninitializableFormat(self)
345
0.295.1 by Jelmer Vernooij
Split up branch formats.
346
0.407.1 by Jelmer Vernooij
Improve progress reporting.
347
class DefaultProgressReporter(object):
348
349
    _GIT_PROGRESS_PARTIAL_RE = re.compile(r"(.*?): +(\d+)% \((\d+)/(\d+)\)")
350
    _GIT_PROGRESS_TOTAL_RE = re.compile(r"(.*?): (\d+)")
351
352
    def __init__(self, pb):
353
        self.pb = pb
354
355
    def progress(self, text):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
356
        text = text.rstrip(b"\r\n")
357
        text = text.decode('utf-8')
7131.7.1 by Jelmer Vernooij
Handle permission denied by GitLab.
358
        if text.lower().startswith('error: '):
7018.3.2 by Jelmer Vernooij
Fix some git tests.
359
            trace.show_error('git: %s', text[len(b'error: '):])
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
360
        else:
0.407.1 by Jelmer Vernooij
Improve progress reporting.
361
            trace.mutter("git: %s", text)
362
            g = self._GIT_PROGRESS_PARTIAL_RE.match(text)
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
363
            if g is not None:
0.407.1 by Jelmer Vernooij
Improve progress reporting.
364
                (text, pct, current, total) = g.groups()
365
                self.pb.update(text, int(current), int(total))
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
366
            else:
0.407.1 by Jelmer Vernooij
Improve progress reporting.
367
                g = self._GIT_PROGRESS_TOTAL_RE.match(text)
368
                if g is not None:
369
                    (text, total) = g.groups()
370
                    self.pb.update(text, None, int(total))
371
                else:
372
                    trace.note("%s", text)
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
373
374
0.200.148 by Jelmer Vernooij
Share more infrastructure between LocalGitDir and RemoteGitDir.
375
class RemoteGitDir(GitDir):
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
376
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
377
    def __init__(self, transport, format, client, client_path):
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
378
        self._format = format
379
        self.root_transport = transport
380
        self.transport = transport
0.200.381 by Jelmer Vernooij
Support working trees properly, status and ls.
381
        self._mode_check_done = None
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
382
        self._client = client
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
383
        self._client_path = client_path
0.200.1396 by Jelmer Vernooij
Support updating tags in remote branches during pull.
384
        self.base = self.root_transport.base
0.200.1434 by Jelmer Vernooij
Move refs access to control dir.
385
        self._refs = None
0.200.1335 by Jelmer Vernooij
Move _get_client.
386
0.322.1 by Jelmer Vernooij
Fix access of remote git branches.
387
    @property
388
    def _gitrepository_class(self):
389
        return RemoteGitRepository
390
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
391
    def archive(self, format, committish, write_data, progress=None,
392
                write_error=None, subdirs=None, prefix=None):
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
393
        if progress is None:
394
            pb = ui.ui_factory.nested_progress_bar()
395
            progress = DefaultProgressReporter(pb).progress
396
        else:
397
            pb = None
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
398
        def progress_wrapper(message):
399
            if message.startswith(b"fatal: Unknown archive format \'"):
400
                format = message.strip()[len(b"fatal: Unknown archive format '"):-1]
401
                raise errors.NoSuchExportFormat(format.decode('ascii'))
402
            return progress(message)
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
403
        try:
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
404
            self._client.archive(
405
                self._client_path, committish, write_data, progress_wrapper,
406
                write_error,
407
                format=(format.encode('ascii') if format else None),
408
                subdirs=subdirs,
409
                prefix=(prefix.encode('utf-8') if prefix else None))
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
410
        except GitProtocolError as e:
411
            raise parse_git_error(self.transport.external_url(), e)
412
        finally:
413
            if pb is not None:
414
                pb.finished()
415
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
416
    def fetch_pack(self, determine_wants, graph_walker, pack_data,
417
                   progress=None):
0.200.1335 by Jelmer Vernooij
Move _get_client.
418
        if progress is None:
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
419
            pb = ui.ui_factory.nested_progress_bar()
0.407.1 by Jelmer Vernooij
Improve progress reporting.
420
            progress = DefaultProgressReporter(pb).progress
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
421
        else:
422
            pb = None
0.200.1335 by Jelmer Vernooij
Move _get_client.
423
        try:
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
424
            result = self._client.fetch_pack(
425
                self._client_path, determine_wants, graph_walker, pack_data,
426
                progress)
0.376.1 by Jelmer Vernooij
Add tests for remote operations.
427
            if result.refs is None:
428
                result.refs = {}
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
429
            self._refs = remote_refs_dict_to_container(
430
                result.refs, result.symrefs)
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
431
            return result
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
432
        except GitProtocolError as e:
0.200.1335 by Jelmer Vernooij
Move _get_client.
433
            raise parse_git_error(self.transport.external_url(), e)
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
434
        finally:
435
            if pb is not None:
436
                pb.finished()
0.200.1335 by Jelmer Vernooij
Move _get_client.
437
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
438
    def send_pack(self, get_changed_refs, generate_pack_data, progress=None):
439
        if progress is None:
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
440
            pb = ui.ui_factory.nested_progress_bar()
0.407.1 by Jelmer Vernooij
Improve progress reporting.
441
            progress = DefaultProgressReporter(pb).progress
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
442
        else:
443
            pb = None
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
444
0.419.1 by Jelmer Vernooij
Simplify pushing to Git directories.
445
        def get_changed_refs_wrapper(refs):
446
            # TODO(jelmer): This drops symref information
447
            self._refs = remote_refs_dict_to_container(refs)
448
            return get_changed_refs(refs)
0.200.1335 by Jelmer Vernooij
Move _get_client.
449
        try:
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
450
            return self._client.send_pack(
451
                self._client_path, get_changed_refs_wrapper,
452
                generate_pack_data, progress)
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
453
        except GitProtocolError as e:
0.200.1335 by Jelmer Vernooij
Move _get_client.
454
            raise parse_git_error(self.transport.external_url(), e)
0.405.1 by Jelmer Vernooij
Use same logic for interpreting progress reports everywhere.
455
        finally:
456
            if pb is not None:
457
                pb.finished()
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
458
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
459
    def create_branch(self, name=None, repository=None,
460
                      append_revisions_only=None, ref=None):
461
        refname = self._get_selected_ref(name, ref)
462
        if refname != b'HEAD' and refname in self.get_refs_container():
463
            raise AlreadyBranchError(self.user_url)
464
        if refname in self.get_refs_container():
465
            ref_chain, unused_sha = self.get_refs_container().follow(self._get_selected_ref(None))
466
            if ref_chain[0] == b'HEAD':
467
                refname = ref_chain[1]
468
        repo = self.open_repository()
469
        return RemoteGitBranch(self, repo, refname)
470
0.200.1393 by Jelmer Vernooij
Implement removal of remote branches.
471
    def destroy_branch(self, name=None):
472
        refname = self._get_selected_ref(name)
473
        def get_changed_refs(old_refs):
474
            ret = dict(old_refs)
475
            if not refname in ret:
0.200.1395 by Jelmer Vernooij
Fix error reporting.
476
                raise NotBranchError(self.user_url)
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
477
            ret[refname] = dulwich.client.ZERO_SHA
0.200.1393 by Jelmer Vernooij
Implement removal of remote branches.
478
            return ret
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
479
        def generate_pack_data(have, want, ofs_delta=False):
480
            return pack_objects_to_data([])
481
        self.send_pack(get_changed_refs, generate_pack_data)
0.200.1393 by Jelmer Vernooij
Implement removal of remote branches.
482
0.200.1068 by Jelmer Vernooij
Implement user_url/control_url.
483
    @property
484
    def user_url(self):
485
        return self.control_url
486
0.200.1314 by Jelmer Vernooij
Provide RemoteGitDir.user_transport.
487
    @property
488
    def user_transport(self):
489
        return self.root_transport
490
0.200.1395 by Jelmer Vernooij
Fix error reporting.
491
    @property
492
    def control_url(self):
493
        return self.control_transport.base
494
495
    @property
496
    def control_transport(self):
497
        return self.root_transport
498
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
499
    def open_repository(self):
0.200.1415 by Jelmer Vernooij
Fix lock files for remote directories.
500
        return RemoteGitRepository(self)
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
501
0.200.1310 by Jelmer Vernooij
Add _get_selected_ref method.
502
    def open_branch(self, name=None, unsupported=False,
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
503
            ignore_fallbacks=False, ref=None, possible_transports=None,
504
            nascent_ok=False):
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
505
        repo = self.open_repository()
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
506
        ref = self._get_selected_ref(name, ref)
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
507
        try:
508
            if not nascent_ok and ref not in self.get_refs_container():
509
                raise NotBranchError(self.root_transport.base,
510
                        controldir=self)
511
        except NotGitRepository:
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
512
            raise NotBranchError(self.root_transport.base,
513
                    controldir=self)
514
        ref_chain, unused_sha = self.get_refs_container().follow(ref)
515
        return RemoteGitBranch(self, repo, ref_chain[-1])
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
516
0.200.662 by Jelmer Vernooij
Deal with recommend_upgrade argument to open_workingtree.
517
    def open_workingtree(self, recommend_upgrade=False):
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
518
        raise NotLocalUrl(self.transport.base)
519
0.310.4 by Jelmer Vernooij
Implement RemoteControlDir.has_workingtree.
520
    def has_workingtree(self):
521
        return False
522
0.200.1489 by Jelmer Vernooij
More fixes to peel handling.
523
    def get_peeled(self, name):
524
        return self.get_refs_container().get_peeled(name)
525
0.200.1487 by Jelmer Vernooij
Use peeling.
526
    def get_refs_container(self):
0.200.1434 by Jelmer Vernooij
Move refs access to control dir.
527
        if self._refs is not None:
528
            return self._refs
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
529
        result = self.fetch_pack(lambda x: None, None,
0.200.1434 by Jelmer Vernooij
Move refs access to control dir.
530
            lambda x: None, lambda x: trace.mutter("git: %s" % x))
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
531
        self._refs = remote_refs_dict_to_container(
532
                result.refs, result.symrefs)
0.200.1434 by Jelmer Vernooij
Move refs access to control dir.
533
        return self._refs
534
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
535
    def push_branch(self, source, revision_id=None, overwrite=False,
536
                    remember=False, create_prefix=False, lossy=False,
537
                    name=None):
538
        """Push the source branch into this ControlDir."""
539
        if revision_id is None:
540
            # No revision supplied by the user, default to the branch
541
            # revision
542
            revision_id = source.last_revision()
543
0.406.1 by Jelmer Vernooij
Properly lookup revnos for brz-git push result.
544
        push_result = GitPushResult()
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
545
        push_result.workingtree_updated = None
546
        push_result.master_branch = None
547
        push_result.source_branch = source
548
        push_result.stacked_on = None
549
        push_result.branch_push_result = None
550
        repo = self.find_repository()
551
        refname = self._get_selected_ref(name)
0.407.1 by Jelmer Vernooij
Improve progress reporting.
552
        if isinstance(source, GitBranch) and lossy:
553
            raise errors.LossyPushToSameVCS(source.controldir, self)
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
554
        source_store = get_object_store(source.repository)
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
555
        with source_store.lock_read():
556
            def get_changed_refs(refs):
557
                self._refs = remote_refs_dict_to_container(refs)
558
                ret = dict(refs)
559
                # TODO(jelmer): Unpeel if necessary
0.406.4 by Jelmer Vernooij
Fall back to local branch for revno.
560
                push_result.new_original_revid = revision_id
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
561
                if lossy:
0.404.5 by Jelmer Vernooij
Check for diverged branches during push.
562
                    new_sha = source_store._lookup_revision_sha1(revision_id)
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
563
                else:
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
564
                    try:
565
                        new_sha = repo.lookup_bzr_revision_id(revision_id)[0]
566
                    except errors.NoSuchRevision:
567
                        raise errors.NoRoundtrippingSupport(
568
                            source, self.open_branch(name=name, nascent_ok=True))
0.404.5 by Jelmer Vernooij
Check for diverged branches during push.
569
                if not overwrite:
570
                    if remote_divergence(ret.get(refname), new_sha, source_store):
571
                        raise DivergedBranches(
572
                                source, self.open_branch(name, nascent_ok=True))
573
                ret[refname] = new_sha
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
574
                return ret
575
            if lossy:
576
                generate_pack_data = source_store.generate_lossy_pack_data
577
            else:
578
                generate_pack_data = source_store.generate_pack_data
579
            new_refs = self.send_pack(get_changed_refs, generate_pack_data)
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
580
        push_result.new_revid = repo.lookup_foreign_revision_id(
581
                new_refs[refname])
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
582
        try:
583
            old_remote = self._refs[refname]
584
        except KeyError:
585
            old_remote = ZERO_SHA
586
        push_result.old_revid = repo.lookup_foreign_revision_id(old_remote)
587
        self._refs = remote_refs_dict_to_container(new_refs)
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
588
        push_result.target_branch = self.open_branch(name)
0.403.3 by Jelmer Vernooij
Test RemoteGitDir.push_branch.
589
        if old_remote != ZERO_SHA:
590
            push_result.branch_push_result = GitBranchPushResult()
591
            push_result.branch_push_result.source_branch = source
592
            push_result.branch_push_result.target_branch = push_result.target_branch
593
            push_result.branch_push_result.local_branch = None
594
            push_result.branch_push_result.master_branch = push_result.target_branch
595
            push_result.branch_push_result.old_revid = push_result.old_revid
596
            push_result.branch_push_result.new_revid = push_result.new_revid
0.406.4 by Jelmer Vernooij
Fall back to local branch for revno.
597
            push_result.branch_push_result.new_original_revid = push_result.new_original_revid
0.401.4 by Jelmer Vernooij
Implement RemoteGitDir.push_branch.
598
        if source.get_push_location() is None or remember:
599
            source.set_push_location(push_result.target_branch.base)
600
        return push_result
601
0.409.1 by Jelmer Vernooij
Don't probe for commondir over remote transport.
602
    def _find_commondir(self):
603
        # There is no way to find the commondir, if there is any.
604
        return self
605
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
606
0.225.2 by Jelmer Vernooij
Handle situation when repository is already up to date during pull.
607
class EmptyObjectStoreIterator(dict):
608
609
    def iterobjects(self):
610
        return []
611
612
0.200.218 by Jelmer Vernooij
Simplify TemporaryPack implementation.
613
class TemporaryPackIterator(Pack):
614
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
615
    def __init__(self, path, resolve_ext_ref):
0.279.1 by William Grant
Support thin packs in fetch_pack and send_pack, since dulwich now handles them properly.
616
        super(TemporaryPackIterator, self).__init__(
617
            path, resolve_ext_ref=resolve_ext_ref)
0.278.2 by William Grant
Also override _idx_load rather than index, to be a bit cleaner.
618
        self._idx_load = lambda: self._idx_load_or_generate(self._idx_path)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
619
0.278.2 by William Grant
Also override _idx_load rather than index, to be a bit cleaner.
620
    def _idx_load_or_generate(self, path):
621
        if not os.path.exists(path):
622
            pb = ui.ui_factory.nested_progress_bar()
623
            try:
624
                def report_progress(cur, total):
625
                    pb.update("generating index", cur, total)
626
                self.data.create_index(path,
627
                    progress=report_progress)
628
            finally:
629
                pb.finished()
630
        return load_pack_index(path)
0.200.205 by Jelmer Vernooij
Fix remote fetching.
631
632
    def __del__(self):
0.200.611 by Jelmer Vernooij
Merge warning fix from Naoki.
633
        if self._idx is not None:
0.241.1 by Naoki INADA
Fix can't delete tempfile on Windows
634
            self._idx.close()
635
            os.remove(self._idx_path)
0.200.611 by Jelmer Vernooij
Merge warning fix from Naoki.
636
        if self._data is not None:
0.241.1 by Naoki INADA
Fix can't delete tempfile on Windows
637
            self._data.close()
638
            os.remove(self._data_path)
0.200.205 by Jelmer Vernooij
Fix remote fetching.
639
640
0.200.1337 by Jelmer Vernooij
Re-use http connection if possible.
641
class BzrGitHttpClient(dulwich.client.HttpGitClient):
642
643
    def __init__(self, transport, *args, **kwargs):
644
        self.transport = transport
645
        super(BzrGitHttpClient, self).__init__(transport.external_url(), *args, **kwargs)
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
646
647
    def _http_request(self, url, headers=None, data=None,
648
                      allow_compression=False):
649
        """Perform HTTP request.
650
651
        :param url: Request URL.
652
        :param headers: Optional custom headers to override defaults.
653
        :param data: Request data.
654
        :param allow_compression: Allow GZipped communication.
655
        :return: Tuple (`response`, `read`), where response is an `urllib3`
7140.1.1 by Jelmer Vernooij
Rollback https://code.launchpad.net/~jelmer/brz/python3-git-fix-http/+merge/356238
656
            response object with additional `content_type` and
657
            `redirect_location` properties, and `read` is a consumable read
658
            method for the response data.
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
659
        """
660
        from breezy.transport.http._urllib2_wrappers import Request
661
        headers['User-agent'] = user_agent_for_github()
662
        headers["Pragma"] = "no-cache"
663
        if allow_compression:
664
            headers["Accept-Encoding"] = "gzip"
665
        else:
666
            headers["Accept-Encoding"] = "identity"
667
668
        request = Request(
669
            ('GET' if data is None else 'POST'),
670
            url, data, headers,
671
            accepted_errors=[200, 404])
7096.1.1 by Jelmer Vernooij
Follow redirections for Git over HTP.
672
        request.follow_redirections = True
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
673
674
        response = self.transport._perform(request)
675
676
        if response.code == 404:
677
            raise NotGitRepository()
678
        elif response.code != 200:
679
            raise GitProtocolError("unexpected http resp %d for %s" %
680
                                   (response.code, url))
681
682
        # TODO: Optimization available by adding `preload_content=False` to the
683
        # request and just passing the `read` method on instead of going via
684
        # `BytesIO`, if we can guarantee that the entire response is consumed
685
        # before issuing the next to still allow for connection reuse from the
686
        # pool.
687
        if response.getheader("Content-Encoding") == "gzip":
688
            read = gzip.GzipFile(fileobj=response).read
689
        else:
690
            read = response.read
691
692
        class WrapResponse(object):
693
694
            def __init__(self, response):
695
                self._response = response
696
                self.status = response.code
697
                self.content_type = response.getheader("Content-Type")
7140.1.1 by Jelmer Vernooij
Rollback https://code.launchpad.net/~jelmer/brz/python3-git-fix-http/+merge/356238
698
                self.redirect_location = response.geturl()
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
699
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
700
            def readlines(self):
701
                return self._response.readlines()
702
0.409.2 by Jelmer Vernooij
call out to HTTP transport rather than creating new connection.
703
            def close(self):
704
                self._response.close()
705
706
        return WrapResponse(response), read
0.200.1337 by Jelmer Vernooij
Re-use http connection if possible.
707
708
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
709
class RemoteGitControlDirFormat(GitControlDirFormat):
710
    """The .git directory control format."""
711
712
    supports_workingtrees = False
713
714
    @classmethod
715
    def _known_formats(self):
716
        return set([RemoteGitControlDirFormat()])
717
0.295.1 by Jelmer Vernooij
Split up branch formats.
718
    def get_branch_format(self):
719
        return RemoteGitBranchFormat()
720
0.200.1413 by Jelmer Vernooij
Fix is_initializable()
721
    def is_initializable(self):
722
        return False
723
724
    def is_supported(self):
725
        return True
726
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
727
    def open(self, transport, _found=None):
728
        """Open this directory.
729
730
        """
731
        # we dont grok readonly - git isn't integrated with transport.
732
        url = transport.base
733
        if url.startswith('readonly+'):
734
            url = url[len('readonly+'):]
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
735
        scheme = urlparse.urlsplit(transport.external_url())[0]
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
736
        if isinstance(transport, GitSmartTransport):
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
737
            client = transport._get_client()
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
738
            client_path = transport._get_path()
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
739
        elif scheme in ("http", "https"):
740
            client = BzrGitHttpClient(transport)
0.200.1555 by Jelmer Vernooij
Remove segment parameters for http smart transports.
741
            client_path, _ = urlutils.split_segment_parameters(transport._path)
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
742
        elif scheme == 'file':
743
            client = dulwich.client.LocalGitClient()
744
            client_path = transport.local_abspath('.')
0.200.1336 by Jelmer Vernooij
Support the git smart server http protocol.
745
        else:
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
746
            raise NotBranchError(transport.base)
0.344.1 by Jelmer Vernooij
Allow using local git executable by accessing git:///some/path.
747
        if not _found:
748
            pass # TODO(jelmer): Actually probe for something
749
        return RemoteGitDir(transport, self, client, client_path)
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
750
751
    def get_format_description(self):
752
        return "Remote Git Repository"
753
754
    def initialize_on_transport(self, transport):
755
        raise UninitializableFormat(self)
756
0.200.1412 by Jelmer Vernooij
Implement GitControlDirFormat.supports_transport.
757
    def supports_transport(self, transport):
758
        try:
759
            external_url = transport.external_url()
760
        except InProcessTransport:
761
            raise NotBranchError(path=transport.base)
762
        return (external_url.startswith("http:") or
763
                external_url.startswith("https:") or
764
                external_url.startswith("git+") or
765
                external_url.startswith("git:"))
766
0.200.1137 by Jelmer Vernooij
Support BzrProber.known_formats().
767
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
768
class GitRemoteRevisionTree(RevisionTree):
769
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
770
    def archive(self, format, name, root=None, subdir=None, force_mtime=None):
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
771
        """Create an archive of this tree.
772
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
773
        :param format: Format name (e.g. 'tar')
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
774
        :param name: target file name
775
        :param root: Root directory name (or None)
776
        :param subdir: Subdirectory to export (or None)
777
        :return: Iterator over archive chunks
778
        """
779
        commit = self._repository.lookup_bzr_revision_id(
780
            self.get_revision_id())[0]
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
781
        f = tempfile.SpooledTemporaryFile()
782
        # git-upload-archive(1) generaly only supports refs. So let's see if we
783
        # can find one.
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
784
        reverse_refs = {
785
                v: k for (k, v) in
786
                self._repository.controldir.get_refs_container().as_dict().items()}
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
787
        try:
788
            committish = reverse_refs[commit]
789
        except KeyError:
790
            # No? Maybe the user has uploadArchive.allowUnreachable enabled.
791
            # Let's hope for the best.
792
            committish = commit
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
793
        self._repository.archive(
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
794
                format, committish, f.write,
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
795
                subdirs=([subdir] if subdir else None),
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
796
                prefix=(root+'/') if root else '')
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
797
        f.seek(0)
6968.4.4 by Jelmer Vernooij
Update for API changes from archive branch.
798
        return osutils.file_iterator(f)
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
799
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
800
    def is_versioned(self, path, file_id=None):
801
        raise GitSmartRemoteNotSupported(self.is_versioned, self)
802
803
    def has_filename(self, path):
804
        raise GitSmartRemoteNotSupported(self.has_filename, self)
805
806
    def get_file_text(self, path, file_id=None):
807
        raise GitSmartRemoteNotSupported(self.get_file_text, self)
808
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
809
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
810
class RemoteGitRepository(GitRepository):
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
811
0.200.319 by Jelmer Vernooij
Print proper error when trying unsupported operations against a git server.
812
    @property
0.200.1068 by Jelmer Vernooij
Implement user_url/control_url.
813
    def user_url(self):
814
        return self.control_url
815
0.200.1288 by Jelmer Vernooij
Properly raise GitRemoteNotSupported from RemoteGitRepository.
816
    def get_parent_map(self, revids):
0.200.1398 by Jelmer Vernooij
Make GitSmartRemoteNotSupported derive from UnsupportedOperation.
817
        raise GitSmartRemoteNotSupported(self.get_parent_map, self)
0.200.319 by Jelmer Vernooij
Print proper error when trying unsupported operations against a git server.
818
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
819
    def archive(self, *args, **kwargs):
820
        return self.controldir.archive(*args, **kwargs)
821
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
822
    def fetch_pack(self, determine_wants, graph_walker, pack_data,
0.200.155 by Jelmer Vernooij
Fix formatting, remove catch-all for exceptions when opening local repositories.
823
                   progress=None):
7143.2.1 by Jelmer Vernooij
Don't hardcode the list of supported archive formats.
824
        return self.controldir.fetch_pack(
825
                determine_wants, graph_walker, pack_data, progress)
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
826
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
827
    def send_pack(self, get_changed_refs, generate_pack_data):
828
        return self.controldir.send_pack(get_changed_refs, generate_pack_data)
0.200.427 by Jelmer Vernooij
make send_pack accessible.
829
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
830
    def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref,
831
                      progress=None):
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
832
        fd, path = tempfile.mkstemp(suffix=".pack")
0.200.1299 by Jelmer Vernooij
Make sure file gets closed.
833
        try:
834
            self.fetch_pack(determine_wants, graph_walker,
835
                lambda x: os.write(fd, x), progress)
836
        finally:
837
            os.close(fd)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
838
        if os.path.getsize(path) == 0:
0.225.2 by Jelmer Vernooij
Handle situation when repository is already up to date during pull.
839
            return EmptyObjectStoreIterator()
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
840
        return TemporaryPackIterator(path[:-len(".pack")], resolve_ext_ref)
0.200.167 by Jelmer Vernooij
Implement fetch_objects properly.
841
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
842
    def lookup_bzr_revision_id(self, bzr_revid, mapping=None):
0.200.415 by Jelmer Vernooij
make 'bzr pull --revision' work for remote repositories.
843
        # This won't work for any round-tripped bzr revisions, but it's a start..
844
        try:
845
            return mapping_registry.revision_id_bzr_to_foreign(bzr_revid)
846
        except InvalidRevisionId:
847
            raise NoSuchRevision(self, bzr_revid)
848
0.252.48 by Jelmer Vernooij
Implement lookup_foreign_revision for remote branches.
849
    def lookup_foreign_revision_id(self, foreign_revid, mapping=None):
850
        """Lookup a revision id.
851
852
        """
853
        if mapping is None:
854
            mapping = self.get_mapping()
855
        # Not really an easy way to parse foreign revids here..
856
        return mapping.revision_id_foreign_to_bzr(foreign_revid)
857
0.200.1446 by Jelmer Vernooij
Add stub for RemoteGitRepository.revision_tree.
858
    def revision_tree(self, revid):
6968.4.1 by Jelmer Vernooij
Add support for exporting archives in Git.
859
        return GitRemoteRevisionTree(self, revid)
0.200.1446 by Jelmer Vernooij
Add stub for RemoteGitRepository.revision_tree.
860
0.200.1481 by Jelmer Vernooij
'Implement' RemoteGitRepository.get_revisions.
861
    def get_revisions(self, revids):
862
        raise GitSmartRemoteNotSupported(self.get_revisions, self)
863
0.200.1557 by Jelmer Vernooij
Implement RemoteGitRepository.has_revisions.
864
    def has_revisions(self, revids):
865
        raise GitSmartRemoteNotSupported(self.get_revisions, self)
866
0.200.138 by Jelmer Vernooij
Add initial infrastructure for accessing remote git repositories.
867
0.200.1064 by Jelmer Vernooij
Use common base class for tags.
868
class RemoteGitTagDict(GitTags):
0.228.3 by Jelmer Vernooij
Fix tags when fetching from remotes.
869
870
    def set_tag(self, name, revid):
0.377.1 by Jelmer Vernooij
Fix some remote operations and add more tests.
871
        sha = self.branch.lookup_bzr_revision_id(revid)[0]
872
        self._set_ref(name, sha)
873
874
    def delete_tag(self, name):
875
        self._set_ref(name, dulwich.client.ZERO_SHA)
876
877
    def _set_ref(self, name, sha):
878
        ref = tag_name_to_ref(name)
879
        def get_changed_refs(old_refs):
880
            ret = dict(old_refs)
881
            if sha == dulwich.client.ZERO_SHA and ref not in ret:
882
                raise NoSuchTag(name)
883
            ret[ref] = sha
884
            return ret
885
        def generate_pack_data(have, want, ofs_delta=False):
886
            return pack_objects_to_data([])
887
        self.repository.send_pack(get_changed_refs, generate_pack_data)
0.228.3 by Jelmer Vernooij
Fix tags when fetching from remotes.
888
889
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
890
class RemoteGitBranch(GitBranch):
891
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
892
    def __init__(self, controldir, repository, name):
0.200.919 by Jelmer Vernooij
Simplify ref handling in remote.py.
893
        self._sha = None
0.295.1 by Jelmer Vernooij
Split up branch formats.
894
        super(RemoteGitBranch, self).__init__(controldir, repository, name,
895
                RemoteGitBranchFormat())
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
896
0.200.1317 by Jelmer Vernooij
Avoid NotImplementedError.
897
    def last_revision_info(self):
0.200.1398 by Jelmer Vernooij
Make GitSmartRemoteNotSupported derive from UnsupportedOperation.
898
        raise GitSmartRemoteNotSupported(self.last_revision_info, self)
0.200.1317 by Jelmer Vernooij
Avoid NotImplementedError.
899
0.200.1068 by Jelmer Vernooij
Implement user_url/control_url.
900
    @property
901
    def user_url(self):
902
        return self.control_url
903
904
    @property
905
    def control_url(self):
906
        return self.base
907
0.200.1436 by Jelmer Vernooij
Raise UnsupportedOperation for `Branch.revision_id_to_dotted_revno`,
908
    def revision_id_to_revno(self, revision_id):
909
        raise GitSmartRemoteNotSupported(self.revision_id_to_revno, self)
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
910
911
    def last_revision(self):
0.252.44 by Jelmer Vernooij
Properly look up Bazaar revision ids for revision parents in case they are round-tripped.
912
        return self.lookup_foreign_revision_id(self.head)
0.200.461 by Jelmer Vernooij
Reduce number of round trips when fetching from Git.
913
914
    @property
915
    def head(self):
0.200.919 by Jelmer Vernooij
Simplify ref handling in remote.py.
916
        if self._sha is not None:
917
            return self._sha
0.200.1648 by Jelmer Vernooij
Fix compatibility with newer versions of breezy.
918
        refs = self.controldir.get_refs_container()
0.200.1561 by Jelmer Vernooij
Some fixes for colocated branch handling.
919
        name = branch_name_to_ref(self.name)
0.200.1386 by Jelmer Vernooij
Friendlier message if HEAD is not found.
920
        try:
921
            self._sha = refs[name]
922
        except KeyError:
923
            raise NoSuchRef(name, self.repository.user_url, refs)
0.200.919 by Jelmer Vernooij
Simplify ref handling in remote.py.
924
        return self._sha
0.200.141 by Jelmer Vernooij
Separate out local and remote fetching.
925
0.200.169 by Jelmer Vernooij
Fix branch cloning.
926
    def _synchronize_history(self, destination, revision_id):
927
        """See Branch._synchronize_history()."""
928
        destination.generate_revision_history(self.last_revision())
0.200.695 by Jelmer Vernooij
Clean up trailing whitespace.
929
0.289.1 by Jelmer Vernooij
No parent location for remote repos.
930
    def _get_parent_location(self):
931
        return None
932
0.200.499 by Jelmer Vernooij
Implement RemoteBranch.{get,set}_push_location.
933
    def get_push_location(self):
934
        return None
935
936
    def set_push_location(self, url):
937
        pass
0.200.1488 by Jelmer Vernooij
Factor out remote_refs_dict_to_container.
938
0.375.1 by Jelmer Vernooij
Fix remote tests, warn when fetching git->bzr and bzr->git.
939
    def _iter_tag_refs(self):
940
        """Iterate over the tag refs.
941
942
        :param refs: Refs dictionary (name -> git sha1)
943
        :return: iterator over (ref_name, tag_name, peeled_sha1, unpeeled_sha1)
944
        """
945
        refs = self.controldir.get_refs_container()
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
946
        for ref_name, unpeeled in refs.as_dict().items():
0.375.1 by Jelmer Vernooij
Fix remote tests, warn when fetching git->bzr and bzr->git.
947
            try:
948
                tag_name = ref_to_tag_name(ref_name)
949
            except (ValueError, UnicodeDecodeError):
950
                continue
951
            peeled = refs.get_peeled(ref_name)
952
            if peeled is None:
7058.4.36 by Jelmer Vernooij
Fix peeled error.
953
                # Let's just hope it's a commit
954
                peeled = unpeeled
6973.6.2 by Jelmer Vernooij
Fix more tests.
955
            if not isinstance(tag_name, text_type):
0.375.1 by Jelmer Vernooij
Fix remote tests, warn when fetching git->bzr and bzr->git.
956
                raise TypeError(tag_name)
957
            yield (ref_name, tag_name, peeled, unpeeled)
958
7131.12.1 by Jelmer Vernooij
Support uncommit on remote git branches.
959
    def set_last_revision_info(self, revno, revid):
960
        self.generate_revision_history(revid)
961
962
    def generate_revision_history(self, revision_id, last_rev=None,
963
                                  other_branch=None):
964
        sha = self.lookup_bzr_revision_id(revision_id)[0]
965
        def get_changed_refs(old_refs):
966
            return {self.ref: sha}
967
        def generate_pack_data(have, want, ofs_delta=False):
968
            return pack_objects_to_data([])
969
        self.repository.send_pack(get_changed_refs, generate_pack_data)
970
        self._sha = sha
971
0.200.1488 by Jelmer Vernooij
Factor out remote_refs_dict_to_container.
972
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
973
def remote_refs_dict_to_container(refs_dict, symrefs_dict={}):
0.200.1488 by Jelmer Vernooij
Factor out remote_refs_dict_to_container.
974
    base = {}
975
    peeled = {}
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
976
    for k, v in refs_dict.items():
0.200.1488 by Jelmer Vernooij
Factor out remote_refs_dict_to_container.
977
        if is_peeled(k):
978
            peeled[k[:-3]] = v
979
        else:
980
            base[k] = v
6964.2.1 by Jelmer Vernooij
Initial work to support brz-git on python3.
981
    for name, target in symrefs_dict.items():
0.382.1 by Jelmer Vernooij
Various fixes for annotated tags and symrefs.
982
        base[name] = SYMREF + target
0.200.1488 by Jelmer Vernooij
Factor out remote_refs_dict_to_container.
983
    ret = DictRefsContainer(base)
984
    ret._peeled = peeled
985
    return ret