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