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