/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/git/remote.py

  • Committer: Martin
  • Date: 2018-11-18 19:48:57 UTC
  • mto: This revision was merged to the branch mainline in revision 7205.
  • Revision ID: gzlist@googlemail.com-20181118194857-mqty4xka790jf934
Fix remaining whitespace lint in codebase

Enables rules W191, W291, W293, and W391 for flake8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
from __future__ import absolute_import
20
20
 
21
21
import gzip
22
 
from io import BytesIO
23
22
import re
24
23
 
25
24
from .. import (
48
47
    PermissionDenied,
49
48
    UninitializableFormat,
50
49
    )
51
 
from ..revision import NULL_REVISION
52
50
from ..revisiontree import RevisionTree
53
 
from ..sixish import (
54
 
    text_type,
55
 
    viewitems,
56
 
    )
 
51
from ..sixish import text_type
57
52
from ..transport import (
58
53
    Transport,
59
54
    register_urlparse_netloc_protocol,
61
56
 
62
57
from . import (
63
58
    lazy_check_versions,
64
 
    is_github_url,
65
59
    user_agent_for_github,
66
60
    )
67
61
lazy_check_versions()
92
86
    )
93
87
from .repository import (
94
88
    GitRepository,
95
 
    GitRepositoryFormat,
96
89
    )
97
90
from .refs import (
98
91
    branch_name_to_ref,
125
118
 
126
119
try:
127
120
    import urllib.parse as urlparse
128
 
    from urllib.parse import splituser
 
121
    from urllib.parse import splituser, splitnport
129
122
except ImportError:
130
123
    import urlparse
131
 
    from urllib import splituser
 
124
    from urllib import splituser, splitnport
132
125
 
133
126
# urlparse only supports a limited number of schemes by default
134
127
register_urlparse_netloc_protocol('git')
167
160
    :param url: Git URL
168
161
    :return: Tuple with host, port, username, path.
169
162
    """
170
 
    parsed_url = urlparse.urlparse(url)
171
 
    path = urlparse.unquote(parsed_url.path)
 
163
    (scheme, netloc, loc, _, _) = urlparse.urlsplit(url)
 
164
    path = urlparse.unquote(loc)
172
165
    if path.startswith("/~"):
173
166
        path = path[1:]
174
 
    return ((parsed_url.hostname or '', parsed_url.port, parsed_url.username, path))
 
167
    (username, hostport) = splituser(netloc)
 
168
    (host, port) = splitnport(hostport, None)
 
169
    return (host, port, username, path)
175
170
 
176
171
 
177
172
class RemoteGitError(BzrError):
202
197
                message.endswith(' not found.'))):
203
198
        return NotBranchError(url, message)
204
199
    if message == "HEAD failed to update":
205
 
        base_url = urlutils.strip_segment_parameters(url)
 
200
        base_url, _ = urlutils.split_segment_parameters(url)
206
201
        return HeadUpdateFailed(base_url)
207
202
    if message.startswith('access denied or repository not exported:'):
208
 
        extra, path = message.split(':', 1)
209
 
        return PermissionDenied(path.strip(), extra)
 
203
        extra, path = message.split(': ', 1)
 
204
        return PermissionDenied(path, extra)
210
205
    if message.endswith('You are not allowed to push code to this project.'):
211
206
        return PermissionDenied(url, message)
212
207
    if message.endswith(' does not appear to be a git repository'):
213
208
        return NotBranchError(url, message)
214
 
    if re.match('(.+) is not a valid repository name',
215
 
                message.splitlines()[0]):
216
 
        return NotBranchError(url, message)
217
209
    m = re.match(r'Permission to ([^ ]+) denied to ([^ ]+)\.', message)
218
210
    if m:
219
211
        return PermissionDenied(m.group(1), 'denied to %s' % m.group(2))
453
445
        else:
454
446
            pb = None
455
447
 
456
 
        def get_changed_refs_wrapper(remote_refs):
457
 
            if self._refs is not None:
458
 
                update_refs_container(self._refs, remote_refs)
459
 
            return get_changed_refs(remote_refs)
 
448
        def get_changed_refs_wrapper(refs):
 
449
            # TODO(jelmer): This drops symref information
 
450
            self._refs = remote_refs_dict_to_container(refs)
 
451
            return get_changed_refs(refs)
460
452
        try:
461
453
            return self._client.send_pack(
462
454
                self._client_path, get_changed_refs_wrapper,
472
464
        refname = self._get_selected_ref(name, ref)
473
465
        if refname != b'HEAD' and refname in self.get_refs_container():
474
466
            raise AlreadyBranchError(self.user_url)
475
 
        ref_chain, unused_sha = self.get_refs_container().follow(
476
 
            self._get_selected_ref(name))
477
 
        if ref_chain and ref_chain[0] == b'HEAD':
478
 
            refname = ref_chain[1]
 
467
        if refname in self.get_refs_container():
 
468
            ref_chain, unused_sha = self.get_refs_container().follow(
 
469
                self._get_selected_ref(None))
 
470
            if ref_chain[0] == b'HEAD':
 
471
                refname = ref_chain[1]
479
472
        repo = self.open_repository()
480
473
        return RemoteGitBranch(self, repo, refname)
481
474
 
483
476
        refname = self._get_selected_ref(name)
484
477
 
485
478
        def get_changed_refs(old_refs):
486
 
            ret = {}
487
 
            if refname not in old_refs:
 
479
            ret = dict(old_refs)
 
480
            if refname not in ret:
488
481
                raise NotBranchError(self.user_url)
489
482
            ret[refname] = dulwich.client.ZERO_SHA
490
483
            return ret
555
548
 
556
549
    def push_branch(self, source, revision_id=None, overwrite=False,
557
550
                    remember=False, create_prefix=False, lossy=False,
558
 
                    name=None, tag_selector=None):
 
551
                    name=None):
559
552
        """Push the source branch into this ControlDir."""
560
553
        if revision_id is None:
561
554
            # No revision supplied by the user, default to the branch
570
563
        push_result.branch_push_result = None
571
564
        repo = self.find_repository()
572
565
        refname = self._get_selected_ref(name)
573
 
        ref_chain, old_sha = self.get_refs_container().follow(refname)
574
 
        if ref_chain:
575
 
            actual_refname = ref_chain[-1]
576
 
        else:
577
 
            actual_refname = refname
578
566
        if isinstance(source, GitBranch) and lossy:
579
567
            raise errors.LossyPushToSameVCS(source.controldir, self)
580
568
        source_store = get_object_store(source.repository)
581
 
        fetch_tags = source.get_config_stack().get('branch.fetch_tags')
582
 
        def get_changed_refs(remote_refs):
583
 
            if self._refs is not None:
584
 
                update_refs_container(self._refs, remote_refs)
585
 
            ret = {}
586
 
            # TODO(jelmer): Unpeel if necessary
587
 
            push_result.new_original_revid = revision_id
588
 
            if lossy:
589
 
                new_sha = source_store._lookup_revision_sha1(revision_id)
590
 
            else:
591
 
                try:
592
 
                    new_sha = repo.lookup_bzr_revision_id(revision_id)[0]
593
 
                except errors.NoSuchRevision:
594
 
                    raise errors.NoRoundtrippingSupport(
595
 
                        source, self.open_branch(name=name, nascent_ok=True))
596
 
            if not overwrite:
597
 
                if remote_divergence(old_sha, new_sha, source_store):
598
 
                    raise DivergedBranches(
599
 
                        source, self.open_branch(name, nascent_ok=True))
600
 
            ret[actual_refname] = new_sha
601
 
            if fetch_tags:
602
 
                for tagname, revid in viewitems(source.tags.get_tag_dict()):
603
 
                    if tag_selector and not tag_selector(tagname):
604
 
                        continue
605
 
                    if lossy:
606
 
                        try:
607
 
                            new_sha = source_store._lookup_revision_sha1(revid)
608
 
                        except KeyError:
609
 
                            if source.repository.has_revision(revid):
610
 
                                raise
611
 
                    else:
612
 
                        try:
613
 
                            new_sha = repo.lookup_bzr_revision_id(revid)[0]
614
 
                        except errors.NoSuchRevision:
615
 
                            continue
616
 
                    ret[tag_name_to_ref(tagname)] = new_sha
617
 
            return ret
618
569
        with source_store.lock_read():
 
570
            def get_changed_refs(refs):
 
571
                self._refs = remote_refs_dict_to_container(refs)
 
572
                ret = dict(refs)
 
573
                # TODO(jelmer): Unpeel if necessary
 
574
                push_result.new_original_revid = revision_id
 
575
                if lossy:
 
576
                    new_sha = source_store._lookup_revision_sha1(revision_id)
 
577
                else:
 
578
                    try:
 
579
                        new_sha = repo.lookup_bzr_revision_id(revision_id)[0]
 
580
                    except errors.NoSuchRevision:
 
581
                        raise errors.NoRoundtrippingSupport(
 
582
                            source, self.open_branch(name=name, nascent_ok=True))
 
583
                if not overwrite:
 
584
                    if remote_divergence(ret.get(refname), new_sha,
 
585
                                         source_store):
 
586
                        raise DivergedBranches(
 
587
                            source, self.open_branch(name, nascent_ok=True))
 
588
                ret[refname] = new_sha
 
589
                return ret
619
590
            if lossy:
620
591
                generate_pack_data = source_store.generate_lossy_pack_data
621
592
            else:
622
593
                generate_pack_data = source_store.generate_pack_data
623
594
            new_refs = self.send_pack(get_changed_refs, generate_pack_data)
624
595
        push_result.new_revid = repo.lookup_foreign_revision_id(
625
 
            new_refs[actual_refname])
626
 
        if old_sha is not None:
627
 
            push_result.old_revid = repo.lookup_foreign_revision_id(old_sha)
628
 
        else:
629
 
            push_result.old_revid = NULL_REVISION
630
 
        if self._refs is not None:
631
 
            update_refs_container(self._refs, new_refs)
 
596
            new_refs[refname])
 
597
        try:
 
598
            old_remote = self._refs[refname]
 
599
        except KeyError:
 
600
            old_remote = ZERO_SHA
 
601
        push_result.old_revid = repo.lookup_foreign_revision_id(old_remote)
 
602
        self._refs = remote_refs_dict_to_container(new_refs)
632
603
        push_result.target_branch = self.open_branch(name)
633
 
        if old_sha is not None:
 
604
        if old_remote != ZERO_SHA:
634
605
            push_result.branch_push_result = GitBranchPushResult()
635
606
            push_result.branch_push_result.source_branch = source
636
607
            push_result.branch_push_result.target_branch = (
666
637
 
667
638
    def _idx_load_or_generate(self, path):
668
639
        if not os.path.exists(path):
669
 
            with ui.ui_factory.nested_progress_bar() as pb:
 
640
            pb = ui.ui_factory.nested_progress_bar()
 
641
            try:
670
642
                def report_progress(cur, total):
671
643
                    pb.update("generating index", cur, total)
672
 
                self.data.create_index(path, progress=report_progress)
 
644
                self.data.create_index(path,
 
645
                                       progress=report_progress)
 
646
            finally:
 
647
                pb.finished()
673
648
        return load_pack_index(path)
674
649
 
675
650
    def __del__(self):
685
660
 
686
661
    def __init__(self, transport, *args, **kwargs):
687
662
        self.transport = transport
688
 
        url = urlutils.URL.from_string(transport.external_url())
689
 
        url.user = url.quoted_user = None
690
 
        url.password = url.quoted_password = None
691
 
        url = urlutils.strip_segment_parameters(str(url))
692
 
        super(BzrGitHttpClient, self).__init__(url, *args, **kwargs)
 
663
        super(BzrGitHttpClient, self).__init__(
 
664
            transport.external_url(), *args, **kwargs)
693
665
 
694
666
    def _http_request(self, url, headers=None, data=None,
695
667
                      allow_compression=False):
704
676
            `redirect_location` properties, and `read` is a consumable read
705
677
            method for the response data.
706
678
        """
707
 
        if is_github_url(url):
708
 
            headers['User-agent'] = user_agent_for_github()
 
679
        from breezy.transport.http._urllib2_wrappers import Request
 
680
        headers['User-agent'] = user_agent_for_github()
709
681
        headers["Pragma"] = "no-cache"
710
682
        if allow_compression:
711
683
            headers["Accept-Encoding"] = "gzip"
712
684
        else:
713
685
            headers["Accept-Encoding"] = "identity"
714
686
 
715
 
        response = self.transport.request(
 
687
        request = Request(
716
688
            ('GET' if data is None else 'POST'),
717
 
            url,
718
 
            body=data,
719
 
            headers=headers, retries=8)
720
 
 
721
 
        if response.status == 404:
 
689
            url, data, headers,
 
690
            accepted_errors=[200, 404])
 
691
        request.follow_redirections = True
 
692
 
 
693
        response = self.transport._perform(request)
 
694
 
 
695
        if response.code == 404:
722
696
            raise NotGitRepository()
723
 
        elif response.status != 200:
 
697
        elif response.code != 200:
724
698
            raise GitProtocolError("unexpected http resp %d for %s" %
725
 
                                   (response.status, url))
 
699
                                   (response.code, url))
726
700
 
727
701
        # TODO: Optimization available by adding `preload_content=False` to the
728
702
        # request and just passing the `read` method on instead of going via
730
704
        # before issuing the next to still allow for connection reuse from the
731
705
        # pool.
732
706
        if response.getheader("Content-Encoding") == "gzip":
733
 
            read = gzip.GzipFile(fileobj=BytesIO(response.read())).read
 
707
            read = gzip.GzipFile(fileobj=response).read
734
708
        else:
735
709
            read = response.read
736
710
 
738
712
 
739
713
            def __init__(self, response):
740
714
                self._response = response
741
 
                self.status = response.status
 
715
                self.status = response.code
742
716
                self.content_type = response.getheader("Content-Type")
743
 
                self.redirect_location = response._actual.geturl()
 
717
                self.redirect_location = response.geturl()
744
718
 
745
719
            def readlines(self):
746
720
                return self._response.readlines()
747
721
 
748
722
            def close(self):
749
 
                pass
 
723
                self._response.close()
750
724
 
751
725
        return WrapResponse(response), read
752
726
 
753
727
 
754
 
def _git_url_and_path_from_transport(external_url):
755
 
    url = urlutils.strip_segment_parameters(external_url)
756
 
    return urlparse.urlsplit(url)
757
 
 
758
 
 
759
728
class RemoteGitControlDirFormat(GitControlDirFormat):
760
729
    """The .git directory control format."""
761
730
 
768
737
    def get_branch_format(self):
769
738
        return RemoteGitBranchFormat()
770
739
 
771
 
    @property
772
 
    def repository_format(self):
773
 
        return GitRepositoryFormat()
774
 
 
775
740
    def is_initializable(self):
776
741
        return False
777
742
 
782
747
        """Open this directory.
783
748
 
784
749
        """
785
 
        split_url = _git_url_and_path_from_transport(transport.external_url())
 
750
        # we dont grok readonly - git isn't integrated with transport.
 
751
        url = transport.base
 
752
        if url.startswith('readonly+'):
 
753
            url = url[len('readonly+'):]
 
754
        scheme = urlparse.urlsplit(transport.external_url())[0]
786
755
        if isinstance(transport, GitSmartTransport):
787
756
            client = transport._get_client()
788
 
        elif split_url.scheme in ("http", "https"):
 
757
            client_path = transport._get_path()
 
758
        elif scheme in ("http", "https"):
789
759
            client = BzrGitHttpClient(transport)
790
 
        elif split_url.scheme in ('file', ):
 
760
            client_path, _ = urlutils.split_segment_parameters(transport._path)
 
761
        elif scheme == 'file':
791
762
            client = dulwich.client.LocalGitClient()
 
763
            client_path = transport.local_abspath('.')
792
764
        else:
793
765
            raise NotBranchError(transport.base)
794
766
        if not _found:
795
767
            pass  # TODO(jelmer): Actually probe for something
796
 
        return RemoteGitDir(transport, self, client, split_url.path)
 
768
        return RemoteGitDir(transport, self, client, client_path)
797
769
 
798
770
    def get_format_description(self):
799
771
        return "Remote Git Repository"
844
816
        f.seek(0)
845
817
        return osutils.file_iterator(f)
846
818
 
847
 
    def is_versioned(self, path):
 
819
    def is_versioned(self, path, file_id=None):
848
820
        raise GitSmartRemoteNotSupported(self.is_versioned, self)
849
821
 
850
822
    def has_filename(self, path):
851
823
        raise GitSmartRemoteNotSupported(self.has_filename, self)
852
824
 
853
 
    def get_file_text(self, path):
 
825
    def get_file_text(self, path, file_id=None):
854
826
        raise GitSmartRemoteNotSupported(self.get_file_text, self)
855
827
 
856
 
    def list_files(self, include_root=False, from_dir=None, recursive=True):
857
 
        raise GitSmartRemoteNotSupported(self.list_files, self)
858
 
 
859
828
 
860
829
class RemoteGitRepository(GitRepository):
861
830
 
862
 
    supports_random_access = False
863
 
 
864
831
    @property
865
832
    def user_url(self):
866
833
        return self.control_url
931
898
        ref = tag_name_to_ref(name)
932
899
 
933
900
        def get_changed_refs(old_refs):
934
 
            ret = {}
935
 
            if sha == dulwich.client.ZERO_SHA and ref not in old_refs:
 
901
            ret = dict(old_refs)
 
902
            if sha == dulwich.client.ZERO_SHA and ref not in ret:
936
903
                raise NoSuchTag(name)
937
904
            ret[ref] = sha
938
905
            return ret
1040
1007
    ret = DictRefsContainer(base)
1041
1008
    ret._peeled = peeled
1042
1009
    return ret
1043
 
 
1044
 
 
1045
 
def update_refs_container(container, refs_dict):
1046
 
    peeled = {}
1047
 
    base = {}
1048
 
    for k, v in refs_dict.items():
1049
 
        if is_peeled(k):
1050
 
            peeled[k[:-3]] = v
1051
 
        else:
1052
 
            base[k] = v
1053
 
    container._peeled = peeled
1054
 
    container._refs.update(base)