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