/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: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
76
76
    NoSuchRef,
77
77
    )
78
78
from .mapping import (
 
79
    encode_git_path,
79
80
    mapping_registry,
80
81
    )
81
82
from .object_store import (
115
116
    )
116
117
import os
117
118
import select
118
 
import tempfile
119
119
 
120
120
import urllib.parse as urlparse
121
121
from urllib.parse import splituser
201
201
        return PermissionDenied(url, message)
202
202
    if message.endswith(' does not appear to be a git repository'):
203
203
        return NotBranchError(url, message)
 
204
    if message == 'pre-receive hook declined':
 
205
        return PermissionDenied(url, message)
204
206
    if re.match('(.+) is not a valid repository name',
205
207
                message.splitlines()[0]):
206
208
        return NotBranchError(url, message)
 
209
    if message == (
 
210
            'GitLab: You are not allowed to push code to protected branches '
 
211
            'on this project.'):
 
212
        return PermissionDenied(url, message)
207
213
    m = re.match(r'Permission to ([^ ]+) denied to ([^ ]+)\.', message)
208
214
    if m:
209
215
        return PermissionDenied(m.group(1), 'denied to %s' % m.group(2))
211
217
    return RemoteGitError(message)
212
218
 
213
219
 
 
220
def parse_git_hangup(url, e):
 
221
    """Parse the error lines from a git servers stderr on hangup.
 
222
 
 
223
    :param url: URL of the remote repository
 
224
    :param e: A HangupException
 
225
    """
 
226
    stderr_lines = getattr(e, 'stderr_lines', None)
 
227
    if not stderr_lines:
 
228
        return e
 
229
    if all(line.startswith(b'remote: ') for line in stderr_lines):
 
230
        stderr_lines = [
 
231
            line[len(b'remote: '):] for line in stderr_lines]
 
232
    interesting_lines = [
 
233
        line for line in stderr_lines
 
234
        if line and line.replace(b'=', b'')]
 
235
    if len(interesting_lines) == 1:
 
236
        interesting_line = interesting_lines[0]
 
237
        return parse_git_error(
 
238
            url, interesting_line.decode('utf-8', 'surrogateescape'))
 
239
    return RemoteGitError(
 
240
        b'\n'.join(stderr_lines).decode('utf-8', 'surrogateescape'))
 
241
 
 
242
 
214
243
class GitSmartTransport(Transport):
215
244
 
216
245
    def __init__(self, url, _client=None):
407
436
                write_error,
408
437
                format=(format.encode('ascii') if format else None),
409
438
                subdirs=subdirs,
410
 
                prefix=(prefix.encode('utf-8') if prefix else None))
 
439
                prefix=(encode_git_path(prefix) if prefix else None))
 
440
        except HangupException as e:
 
441
            raise parse_git_hangup(self.transport.external_url(), e)
411
442
        except GitProtocolError as e:
412
443
            raise parse_git_error(self.transport.external_url(), e)
413
444
        finally:
430
461
            self._refs = remote_refs_dict_to_container(
431
462
                result.refs, result.symrefs)
432
463
            return result
 
464
        except HangupException as e:
 
465
            raise parse_git_hangup(self.transport.external_url(), e)
433
466
        except GitProtocolError as e:
434
467
            raise parse_git_error(self.transport.external_url(), e)
435
468
        finally:
451
484
            return self._client.send_pack(
452
485
                self._client_path, get_changed_refs_wrapper,
453
486
                generate_pack_data, progress)
 
487
        except HangupException as e:
 
488
            raise parse_git_hangup(self.transport.external_url(), e)
454
489
        except GitProtocolError as e:
455
490
            raise parse_git_error(self.transport.external_url(), e)
456
491
        finally:
481
516
 
482
517
        def generate_pack_data(have, want, ofs_delta=False):
483
518
            return pack_objects_to_data([])
484
 
        self.send_pack(get_changed_refs, generate_pack_data)
 
519
        result = self.send_pack(get_changed_refs, generate_pack_data)
 
520
        if result is not None and not isinstance(result, dict):
 
521
            error = result.ref_status.get(refname)
 
522
            if error:
 
523
                raise RemoteGitError(error)
485
524
 
486
525
    @property
487
526
    def user_url(self):
545
584
 
546
585
    def push_branch(self, source, revision_id=None, overwrite=False,
547
586
                    remember=False, create_prefix=False, lossy=False,
548
 
                    name=None):
 
587
                    name=None, tag_selector=None):
549
588
        """Push the source branch into this ControlDir."""
550
589
        if revision_id is None:
551
590
            # No revision supplied by the user, default to the branch
552
591
            # revision
553
592
            revision_id = source.last_revision()
 
593
        else:
 
594
            if not source.repository.has_revision(revision_id):
 
595
                raise NoSuchRevision(source, revision_id)
554
596
 
555
597
        push_result = GitPushResult()
556
598
        push_result.workingtree_updated = None
560
602
        push_result.branch_push_result = None
561
603
        repo = self.find_repository()
562
604
        refname = self._get_selected_ref(name)
563
 
        ref_chain, old_sha = self.get_refs_container().follow(refname)
564
 
        if ref_chain:
565
 
            actual_refname = ref_chain[-1]
566
 
        else:
 
605
        try:
 
606
            ref_chain, old_sha = self.get_refs_container().follow(refname)
 
607
        except NotBranchError:
567
608
            actual_refname = refname
 
609
            old_sha = None
 
610
        else:
 
611
            if ref_chain:
 
612
                actual_refname = ref_chain[-1]
 
613
            else:
 
614
                actual_refname = refname
568
615
        if isinstance(source, GitBranch) and lossy:
569
616
            raise errors.LossyPushToSameVCS(source.controldir, self)
570
617
        source_store = get_object_store(source.repository)
584
631
                    raise errors.NoRoundtrippingSupport(
585
632
                        source, self.open_branch(name=name, nascent_ok=True))
586
633
            if not overwrite:
 
634
                old_sha = remote_refs.get(actual_refname)
587
635
                if remote_divergence(old_sha, new_sha, source_store):
588
636
                    raise DivergedBranches(
589
637
                        source, self.open_branch(name, nascent_ok=True))
590
638
            ret[actual_refname] = new_sha
591
639
            if fetch_tags:
592
640
                for tagname, revid in source.tags.get_tag_dict().items():
 
641
                    if tag_selector and not tag_selector(tagname):
 
642
                        continue
593
643
                    if lossy:
594
644
                        try:
595
645
                            new_sha = source_store._lookup_revision_sha1(revid)
601
651
                            new_sha = repo.lookup_bzr_revision_id(revid)[0]
602
652
                        except errors.NoSuchRevision:
603
653
                            continue
 
654
                        else:
 
655
                            if not source.repository.has_revision(revid):
 
656
                                continue
604
657
                    ret[tag_name_to_ref(tagname)] = new_sha
605
658
            return ret
606
659
        with source_store.lock_read():
607
 
            if lossy:
608
 
                generate_pack_data = source_store.generate_lossy_pack_data
609
 
            else:
610
 
                generate_pack_data = source_store.generate_pack_data
611
 
            new_refs = self.send_pack(get_changed_refs, generate_pack_data)
 
660
            def generate_pack_data(have, want, progress=None,
 
661
                                   ofs_delta=True):
 
662
                git_repo = getattr(source.repository, '_git', None)
 
663
                if git_repo:
 
664
                    shallow = git_repo.get_shallow()
 
665
                else:
 
666
                    shallow = None
 
667
                if lossy:
 
668
                    return source_store.generate_lossy_pack_data(
 
669
                        have, want, shallow=shallow,
 
670
                        progress=progress, ofs_delta=ofs_delta)
 
671
                elif shallow:
 
672
                    return source_store.generate_pack_data(
 
673
                        have, want, shallow=shallow,
 
674
                        progress=progress, ofs_delta=ofs_delta)
 
675
                else:
 
676
                    return source_store.generate_pack_data(
 
677
                        have, want, progress=progress, ofs_delta=ofs_delta)
 
678
            dw_result = self.send_pack(get_changed_refs, generate_pack_data)
 
679
            if not isinstance(dw_result, dict):
 
680
                new_refs = dw_result.refs
 
681
                error = dw_result.ref_status.get(actual_refname)
 
682
                if error:
 
683
                    raise RemoteGitError(error)
 
684
                for ref, error in dw_result.ref_status.items():
 
685
                    if error:
 
686
                        trace.warning('unable to open ref %s: %s',
 
687
                                      ref, error)
 
688
            else:  # dulwich < 0.20.4
 
689
                new_refs = dw_result
612
690
        push_result.new_revid = repo.lookup_foreign_revision_id(
613
691
            new_refs[actual_refname])
614
692
        if old_sha is not None:
710
788
            raise NotGitRepository()
711
789
        elif response.status != 200:
712
790
            raise GitProtocolError("unexpected http resp %d for %s" %
713
 
                                   (response.code, url))
 
791
                                   (response.status, url))
714
792
 
715
793
        # TODO: Optimization available by adding `preload_content=False` to the
716
794
        # request and just passing the `read` method on instead of going via
813
891
        """
814
892
        commit = self._repository.lookup_bzr_revision_id(
815
893
            self.get_revision_id())[0]
 
894
        import tempfile
816
895
        f = tempfile.SpooledTemporaryFile()
817
896
        # git-upload-archive(1) generaly only supports refs. So let's see if we
818
897
        # can find one.
869
948
 
870
949
    def fetch_objects(self, determine_wants, graph_walker, resolve_ext_ref,
871
950
                      progress=None):
 
951
        import tempfile
872
952
        fd, path = tempfile.mkstemp(suffix=".pack")
873
953
        try:
874
954
            self.fetch_pack(determine_wants, graph_walker,
927
1007
 
928
1008
        def generate_pack_data(have, want, ofs_delta=False):
929
1009
            return pack_objects_to_data([])
930
 
        self.repository.send_pack(get_changed_refs, generate_pack_data)
 
1010
        result = self.repository.send_pack(
 
1011
            get_changed_refs, generate_pack_data)
 
1012
        if result and not isinstance(result, dict):
 
1013
            error = result.ref_status.get(ref)
 
1014
            if error:
 
1015
                raise RemoteGitError(error)
931
1016
 
932
1017
 
933
1018
class RemoteGitBranch(GitBranch):
1011
1096
            return {self.ref: sha}
1012
1097
        def generate_pack_data(have, want, ofs_delta=False):
1013
1098
            return pack_objects_to_data([])
1014
 
        self.repository.send_pack(get_changed_refs, generate_pack_data)
 
1099
        result = self.repository.send_pack(
 
1100
            get_changed_refs, generate_pack_data)
 
1101
        if result is not None and not isinstance(result, dict):
 
1102
            error = result.ref_status.get(self.ref)
 
1103
            if error:
 
1104
                raise RemoteGitError(error)
1015
1105
        self._sha = sha
1016
1106
 
1017
1107