/brz/remove-bazaar

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