Show More
@@ -586,9 +586,9 b' def git_post_receive(unused_repo_path, r' | |||||
586 | try: |
|
586 | try: | |
587 | subprocessio.run_command(cmd, env=os.environ.copy()) |
|
587 | subprocessio.run_command(cmd, env=os.environ.copy()) | |
588 | except Exception: |
|
588 | except Exception: | |
589 | cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', '"HEAD"', |
|
589 | push_ref_name = push_ref['name'] | |
590 | '"refs/heads/%s"' % push_ref['name']] |
|
590 | cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', '"HEAD"', f'"refs/heads/{push_ref_name}"'] | |
591 |
print( |
|
591 | print(f"Setting default branch to {push_ref_name}") | |
592 | subprocessio.run_command(cmd, env=os.environ.copy()) |
|
592 | subprocessio.run_command(cmd, env=os.environ.copy()) | |
593 |
|
593 | |||
594 | cmd = [settings.GIT_EXECUTABLE, 'for-each-ref', |
|
594 | cmd = [settings.GIT_EXECUTABLE, 'for-each-ref', |
@@ -40,7 +40,7 b' from dulwich.repo import Repo as Dulwich' | |||||
40 | from dulwich.server import update_server_info |
|
40 | from dulwich.server import update_server_info | |
41 |
|
41 | |||
42 | from vcsserver import exceptions, settings, subprocessio |
|
42 | from vcsserver import exceptions, settings, subprocessio | |
43 | from vcsserver.str_utils import safe_str, safe_int, safe_bytes |
|
43 | from vcsserver.str_utils import safe_str, safe_int, safe_bytes, ascii_str, ascii_bytes | |
44 | from vcsserver.base import RepoFactory, obfuscate_qs, ArchiveNode, archive_repo |
|
44 | from vcsserver.base import RepoFactory, obfuscate_qs, ArchiveNode, archive_repo | |
45 | from vcsserver.hgcompat import ( |
|
45 | from vcsserver.hgcompat import ( | |
46 | hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler) |
|
46 | hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler) | |
@@ -51,7 +51,7 b' DIR_STAT = stat.S_IFDIR' | |||||
51 | FILE_MODE = stat.S_IFMT |
|
51 | FILE_MODE = stat.S_IFMT | |
52 | GIT_LINK = objects.S_IFGITLINK |
|
52 | GIT_LINK = objects.S_IFGITLINK | |
53 | PEELED_REF_MARKER = b'^{}' |
|
53 | PEELED_REF_MARKER = b'^{}' | |
54 |
|
54 | HEAD_MARKER = b'HEAD' | ||
55 |
|
55 | |||
56 | log = logging.getLogger(__name__) |
|
56 | log = logging.getLogger(__name__) | |
57 |
|
57 | |||
@@ -107,8 +107,9 b' class GitFactory(RepoFactory):' | |||||
107 |
|
107 | |||
108 | def _create_repo(self, wire, create, use_libgit2=False): |
|
108 | def _create_repo(self, wire, create, use_libgit2=False): | |
109 | if use_libgit2: |
|
109 | if use_libgit2: | |
110 | return Repository(wire['path']) |
|
110 | return Repository(safe_bytes(wire['path'])) | |
111 | else: |
|
111 | else: | |
|
112 | # dulwich mode | |||
112 | repo_path = safe_str(wire['path'], to_encoding=settings.WIRE_ENCODING) |
|
113 | repo_path = safe_str(wire['path'], to_encoding=settings.WIRE_ENCODING) | |
113 | return Repo(repo_path) |
|
114 | return Repo(repo_path) | |
114 |
|
115 | |||
@@ -610,13 +611,25 b' class GitRemote(RemoteBase):' | |||||
610 |
|
611 | |||
611 | determine_wants = repo.object_store.determine_wants_all |
|
612 | determine_wants = repo.object_store.determine_wants_all | |
612 | if refs: |
|
613 | if refs: | |
613 | def determine_wants_requested(references): |
|
614 | refs = [ascii_bytes(x) for x in refs] | |
614 | return [references[r] for r in references if r in refs] |
|
615 | ||
|
616 | def determine_wants_requested(remote_refs): | |||
|
617 | determined = [] | |||
|
618 | for ref_name, ref_hash in remote_refs.items(): | |||
|
619 | bytes_ref_name = safe_bytes(ref_name) | |||
|
620 | ||||
|
621 | if bytes_ref_name in refs: | |||
|
622 | bytes_ref_hash = safe_bytes(ref_hash) | |||
|
623 | determined.append(bytes_ref_hash) | |||
|
624 | return determined | |||
|
625 | ||||
|
626 | # swap with our custom requested wants | |||
615 | determine_wants = determine_wants_requested |
|
627 | determine_wants = determine_wants_requested | |
616 |
|
628 | |||
617 | try: |
|
629 | try: | |
618 | remote_refs = client.fetch( |
|
630 | remote_refs = client.fetch( | |
619 | path=url, target=repo, determine_wants=determine_wants) |
|
631 | path=url, target=repo, determine_wants=determine_wants) | |
|
632 | ||||
620 | except NotGitRepository as e: |
|
633 | except NotGitRepository as e: | |
621 | log.warning( |
|
634 | log.warning( | |
622 | 'Trying to fetch from "%s" failed, not a Git repository.', url) |
|
635 | 'Trying to fetch from "%s" failed, not a Git repository.', url) | |
@@ -641,13 +654,13 b' class GitRemote(RemoteBase):' | |||||
641 |
|
654 | |||
642 | if refs and not update_after: |
|
655 | if refs and not update_after: | |
643 | # mikhail: explicitly set the head to the last ref. |
|
656 | # mikhail: explicitly set the head to the last ref. | |
644 |
repo[ |
|
657 | repo[HEAD_MARKER] = remote_refs[refs[-1]] | |
645 |
|
658 | |||
646 | if update_after: |
|
659 | if update_after: | |
647 | # we want to checkout HEAD |
|
660 | # we want to checkout HEAD | |
648 |
repo[ |
|
661 | repo[HEAD_MARKER] = remote_refs[HEAD_MARKER] | |
649 | index.build_index_from_tree(repo.path, repo.index_path(), |
|
662 | index.build_index_from_tree(repo.path, repo.index_path(), | |
650 |
repo.object_store, repo[ |
|
663 | repo.object_store, repo[HEAD_MARKER].tree) | |
651 | return remote_refs |
|
664 | return remote_refs | |
652 |
|
665 | |||
653 | @reraise_safe_exceptions |
|
666 | @reraise_safe_exceptions | |
@@ -680,7 +693,7 b' class GitRemote(RemoteBase):' | |||||
680 | log.debug("Skipping peeled reference %s", ref) |
|
693 | log.debug("Skipping peeled reference %s", ref) | |
681 | continue |
|
694 | continue | |
682 | # don't sync HEAD |
|
695 | # don't sync HEAD | |
683 |
if ref in [ |
|
696 | if ref in [HEAD_MARKER]: | |
684 | continue |
|
697 | continue | |
685 |
|
698 | |||
686 | remote_refs[ref] = sha |
|
699 | remote_refs[ref] = sha | |
@@ -1292,6 +1305,10 b' class GitRemote(RemoteBase):' | |||||
1292 | from vcsserver.hook_utils import install_git_hooks |
|
1305 | from vcsserver.hook_utils import install_git_hooks | |
1293 | bare = self.bare(wire) |
|
1306 | bare = self.bare(wire) | |
1294 | path = wire['path'] |
|
1307 | path = wire['path'] | |
|
1308 | binary_dir = settings.BINARY_DIR | |||
|
1309 | executable = None | |||
|
1310 | if binary_dir: | |||
|
1311 | executable = os.path.join(binary_dir, 'python3') | |||
1295 | return install_git_hooks(path, bare, force_create=force) |
|
1312 | return install_git_hooks(path, bare, force_create=force) | |
1296 |
|
1313 | |||
1297 | @reraise_safe_exceptions |
|
1314 | @reraise_safe_exceptions |
@@ -152,7 +152,7 b' class MercurialFactory(RepoFactory):' | |||||
152 |
|
152 | |||
153 | def _create_repo(self, wire, create): |
|
153 | def _create_repo(self, wire, create): | |
154 | baseui = self._create_config(wire["config"]) |
|
154 | baseui = self._create_config(wire["config"]) | |
155 |
return instance(baseui, |
|
155 | return instance(baseui, safe_bytes(wire["path"]), create) | |
156 |
|
156 | |||
157 | def repo(self, wire, create=False): |
|
157 | def repo(self, wire, create=False): | |
158 | """ |
|
158 | """ | |
@@ -757,12 +757,13 b' class HgRemote(RemoteBase):' | |||||
757 |
|
757 | |||
758 | @reraise_safe_exceptions |
|
758 | @reraise_safe_exceptions | |
759 | def revs_from_revspec(self, wire, rev_spec, *args, **kwargs): |
|
759 | def revs_from_revspec(self, wire, rev_spec, *args, **kwargs): | |
760 | other_path = kwargs.pop('other_path', None) |
|
760 | org_path = safe_bytes(wire["path"]) | |
|
761 | other_path = safe_bytes(kwargs.pop('other_path', '')) | |||
761 |
|
762 | |||
762 | # case when we want to compare two independent repositories |
|
763 | # case when we want to compare two independent repositories | |
763 | if other_path and other_path != wire["path"]: |
|
764 | if other_path and other_path != wire["path"]: | |
764 | baseui = self._factory._create_config(wire["config"]) |
|
765 | baseui = self._factory._create_config(wire["config"]) | |
765 |
repo = unionrepo.makeunionrepository(baseui, other_path, |
|
766 | repo = unionrepo.makeunionrepository(baseui, other_path, org_path) | |
766 | else: |
|
767 | else: | |
767 | repo = self._factory.repo(wire) |
|
768 | repo = self._factory.repo(wire) | |
768 | return list(repo.revs(rev_spec, *args)) |
|
769 | return list(repo.revs(rev_spec, *args)) | |
@@ -815,9 +816,11 b' class HgRemote(RemoteBase):' | |||||
815 | return _tags(context_uid, repo_id) |
|
816 | return _tags(context_uid, repo_id) | |
816 |
|
817 | |||
817 | @reraise_safe_exceptions |
|
818 | @reraise_safe_exceptions | |
818 |
def update(self, wire, node= |
|
819 | def update(self, wire, node='', clean=False): | |
819 | repo = self._factory.repo(wire) |
|
820 | repo = self._factory.repo(wire) | |
820 | baseui = self._factory._create_config(wire['config']) |
|
821 | baseui = self._factory._create_config(wire['config']) | |
|
822 | node = safe_bytes(node) | |||
|
823 | ||||
821 | commands.update(baseui, repo, node=node, clean=clean) |
|
824 | commands.update(baseui, repo, node=node, clean=clean) | |
822 |
|
825 | |||
823 | @reraise_safe_exceptions |
|
826 | @reraise_safe_exceptions | |
@@ -855,7 +858,7 b' class HgRemote(RemoteBase):' | |||||
855 | repo = self._factory.repo(wire) |
|
858 | repo = self._factory.repo(wire) | |
856 | changelog = repo.changelog |
|
859 | changelog = repo.changelog | |
857 | lookup = repo.lookup |
|
860 | lookup = repo.lookup | |
858 | a = changelog.ancestor(lookup(revision1), lookup(revision2)) |
|
861 | a = changelog.ancestor(lookup(safe_bytes(revision1)), lookup(safe_bytes(revision2))) | |
859 | return hex(a) |
|
862 | return hex(a) | |
860 |
|
863 | |||
861 | @reraise_safe_exceptions |
|
864 | @reraise_safe_exceptions | |
@@ -933,19 +936,29 b' class HgRemote(RemoteBase):' | |||||
933 | repo, remote, heads=commit_ids, force=None).cgresult |
|
936 | repo, remote, heads=commit_ids, force=None).cgresult | |
934 |
|
937 | |||
935 | @reraise_safe_exceptions |
|
938 | @reraise_safe_exceptions | |
936 |
def pull_cmd(self, wire, source, bookmark= |
|
939 | def pull_cmd(self, wire, source, bookmark='', branch='', revision='', hooks=True): | |
937 | repo = self._factory.repo(wire) |
|
940 | repo = self._factory.repo(wire) | |
938 | baseui = self._factory._create_config(wire['config'], hooks=hooks) |
|
941 | baseui = self._factory._create_config(wire['config'], hooks=hooks) | |
939 |
|
942 | |||
|
943 | source = safe_bytes(source) | |||
|
944 | ||||
940 | # Mercurial internally has a lot of logic that checks ONLY if |
|
945 | # Mercurial internally has a lot of logic that checks ONLY if | |
941 | # option is defined, we just pass those if they are defined then |
|
946 | # option is defined, we just pass those if they are defined then | |
942 | opts = {} |
|
947 | opts = {} | |
943 | if bookmark: |
|
948 | if bookmark: | |
|
949 | if isinstance(branch, list): | |||
|
950 | bookmark = [safe_bytes(x) for x in bookmark] | |||
|
951 | else: | |||
|
952 | bookmark = safe_bytes(bookmark) | |||
944 | opts['bookmark'] = bookmark |
|
953 | opts['bookmark'] = bookmark | |
945 | if branch: |
|
954 | if branch: | |
|
955 | if isinstance(branch, list): | |||
|
956 | branch = [safe_bytes(x) for x in branch] | |||
|
957 | else: | |||
|
958 | branch = safe_bytes(branch) | |||
946 | opts['branch'] = branch |
|
959 | opts['branch'] = branch | |
947 | if revision: |
|
960 | if revision: | |
948 | opts['rev'] = revision |
|
961 | opts['rev'] = safe_bytes(revision) | |
949 |
|
962 | |||
950 | commands.pull(baseui, repo, source, **opts) |
|
963 | commands.pull(baseui, repo, source, **opts) | |
951 |
|
964 | |||
@@ -1040,10 +1053,10 b' class HgRemote(RemoteBase):' | |||||
1040 | raise exceptions.AbortException(e)(repr(e)) |
|
1053 | raise exceptions.AbortException(e)(repr(e)) | |
1041 |
|
1054 | |||
1042 | @reraise_safe_exceptions |
|
1055 | @reraise_safe_exceptions | |
1043 |
def bookmark(self, wire, bookmark, revision= |
|
1056 | def bookmark(self, wire, bookmark, revision=''): | |
1044 | repo = self._factory.repo(wire) |
|
1057 | repo = self._factory.repo(wire) | |
1045 | baseui = self._factory._create_config(wire['config']) |
|
1058 | baseui = self._factory._create_config(wire['config']) | |
1046 | commands.bookmark(baseui, repo, bookmark, rev=revision, force=True) |
|
1059 | commands.bookmark(baseui, repo, safe_bytes(bookmark), rev=safe_bytes(revision), force=True) | |
1047 |
|
1060 | |||
1048 | @reraise_safe_exceptions |
|
1061 | @reraise_safe_exceptions | |
1049 | def install_hooks(self, wire, force=False): |
|
1062 | def install_hooks(self, wire, force=False): |
@@ -38,7 +38,7 b' import svn.repos' | |||||
38 | from vcsserver import svn_diff, exceptions, subprocessio, settings |
|
38 | from vcsserver import svn_diff, exceptions, subprocessio, settings | |
39 | from vcsserver.base import RepoFactory, raise_from_original, ArchiveNode, archive_repo |
|
39 | from vcsserver.base import RepoFactory, raise_from_original, ArchiveNode, archive_repo | |
40 | from vcsserver.exceptions import NoContentException |
|
40 | from vcsserver.exceptions import NoContentException | |
41 | from vcsserver.str_utils import safe_str |
|
41 | from vcsserver.str_utils import safe_str, safe_bytes | |
42 | from vcsserver.vcs_base import RemoteBase |
|
42 | from vcsserver.vcs_base import RemoteBase | |
43 | from vcsserver.lib.svnremoterepo import svnremoterepo |
|
43 | from vcsserver.lib.svnremoterepo import svnremoterepo | |
44 | log = logging.getLogger(__name__) |
|
44 | log = logging.getLogger(__name__) | |
@@ -63,7 +63,7 b' def reraise_safe_exceptions(func):' | |||||
63 | except Exception as e: |
|
63 | except Exception as e: | |
64 | if not hasattr(e, '_vcs_kind'): |
|
64 | if not hasattr(e, '_vcs_kind'): | |
65 | log.exception("Unhandled exception in svn remote call") |
|
65 | log.exception("Unhandled exception in svn remote call") | |
66 | raise_from_original(exceptions.UnhandledException(e)) |
|
66 | raise_from_original(exceptions.UnhandledException(e), e) | |
67 | raise |
|
67 | raise | |
68 | return wrapper |
|
68 | return wrapper | |
69 |
|
69 | |||
@@ -328,6 +328,7 b' class SvnRemote(RemoteBase):' | |||||
328 |
|
328 | |||
329 | cache_on, context_uid, repo_id = self._cache_on(wire) |
|
329 | cache_on, context_uid, repo_id = self._cache_on(wire) | |
330 | region = self._region(wire) |
|
330 | region = self._region(wire) | |
|
331 | ||||
331 | @region.conditional_cache_on_arguments(condition=cache_on) |
|
332 | @region.conditional_cache_on_arguments(condition=cache_on) | |
332 | def _get_nodes(_repo_id, _path, _revision): |
|
333 | def _get_nodes(_repo_id, _path, _revision): | |
333 | repo = self._factory.repo(wire) |
|
334 | repo = self._factory.repo(wire) | |
@@ -425,8 +426,11 b' class SvnRemote(RemoteBase):' | |||||
425 | (src_url, )) |
|
426 | (src_url, )) | |
426 |
|
427 | |||
427 | def commit(self, wire, message, author, timestamp, updated, removed): |
|
428 | def commit(self, wire, message, author, timestamp, updated, removed): | |
428 | assert isinstance(message, str) |
|
429 | ||
429 | assert isinstance(author, str) |
|
430 | updated = [{k: safe_bytes(v) for k, v in x.items() if isinstance(v, str)} for x in updated] | |
|
431 | ||||
|
432 | message = safe_bytes(message) | |||
|
433 | author = safe_bytes(author) | |||
430 |
|
434 | |||
431 | repo = self._factory.repo(wire) |
|
435 | repo = self._factory.repo(wire) | |
432 | fsobj = svn.repos.fs(repo) |
|
436 | fsobj = svn.repos.fs(repo) | |
@@ -477,7 +481,7 b' class SvnRemote(RemoteBase):' | |||||
477 | @region.conditional_cache_on_arguments(condition=cache_on) |
|
481 | @region.conditional_cache_on_arguments(condition=cache_on) | |
478 | def _is_binary(_repo_id, _rev, _path): |
|
482 | def _is_binary(_repo_id, _rev, _path): | |
479 | raw_bytes = self.get_file_content(wire, path, rev) |
|
483 | raw_bytes = self.get_file_content(wire, path, rev) | |
480 | return raw_bytes and '\0' in raw_bytes |
|
484 | return raw_bytes and b'\0' in raw_bytes | |
481 |
|
485 | |||
482 | return _is_binary(repo_id, rev, path) |
|
486 | return _is_binary(repo_id, rev, path) | |
483 |
|
487 | |||
@@ -530,9 +534,8 b' class SvnRemote(RemoteBase):' | |||||
530 | binary_dir = settings.BINARY_DIR |
|
534 | binary_dir = settings.BINARY_DIR | |
531 | executable = None |
|
535 | executable = None | |
532 | if binary_dir: |
|
536 | if binary_dir: | |
533 | executable = os.path.join(binary_dir, 'python') |
|
537 | executable = os.path.join(binary_dir, 'python3') | |
534 | return install_svn_hooks( |
|
538 | return install_svn_hooks(repo_path, force_create=force) | |
535 | repo_path, executable=executable, force_create=force) |
|
|||
536 |
|
539 | |||
537 | @reraise_safe_exceptions |
|
540 | @reraise_safe_exceptions | |
538 | def get_hooks_info(self, wire): |
|
541 | def get_hooks_info(self, wire): | |
@@ -808,7 +811,7 b' class TxnNodeProcessor(object):' | |||||
808 | """ |
|
811 | """ | |
809 |
|
812 | |||
810 | def __init__(self, node, txn_root): |
|
813 | def __init__(self, node, txn_root): | |
811 |
assert isinstance(node['path'], |
|
814 | assert isinstance(node['path'], bytes) | |
812 |
|
815 | |||
813 | self.node = node |
|
816 | self.node = node | |
814 | self.txn_root = txn_root |
|
817 | self.txn_root = txn_root | |
@@ -844,7 +847,8 b' class TxnNodeProcessor(object):' | |||||
844 | svn.fs.make_file(self.txn_root, self.node['path']) |
|
847 | svn.fs.make_file(self.txn_root, self.node['path']) | |
845 |
|
848 | |||
846 | def _update_file_content(self): |
|
849 | def _update_file_content(self): | |
847 |
assert isinstance(self.node['content'], |
|
850 | assert isinstance(self.node['content'], bytes) | |
|
851 | ||||
848 | handler, baton = svn.fs.apply_textdelta( |
|
852 | handler, baton = svn.fs.apply_textdelta( | |
849 | self.txn_root, self.node['path'], None, None) |
|
853 | self.txn_root, self.node['path'], None, None) | |
850 | svn.delta.svn_txdelta_send_string(self.node['content'], handler, baton) |
|
854 | svn.delta.svn_txdelta_send_string(self.node['content'], handler, baton) |
@@ -39,7 +39,7 b' def repeat(request):' | |||||
39 | @pytest.fixture(scope='session') |
|
39 | @pytest.fixture(scope='session') | |
40 | def vcsserver_port(request): |
|
40 | def vcsserver_port(request): | |
41 | port = get_available_port() |
|
41 | port = get_available_port() | |
42 |
print( |
|
42 | print(f'Using vcsserver port {port}') | |
43 | return port |
|
43 | return port | |
44 |
|
44 | |||
45 |
|
45 |
@@ -66,8 +66,8 b' class TestGitFetch(object):' | |||||
66 |
|
66 | |||
67 | def test_fetches_specified_commits(self): |
|
67 | def test_fetches_specified_commits(self): | |
68 | selected_refs = { |
|
68 | selected_refs = { | |
69 | 'refs/tags/v0.1.8': '74ebce002c088b8a5ecf40073db09375515ecd68', |
|
69 | 'refs/tags/v0.1.8': b'74ebce002c088b8a5ecf40073db09375515ecd68', | |
70 | 'refs/tags/v0.1.3': '5a3a8fb005554692b16e21dee62bf02667d8dc3e', |
|
70 | 'refs/tags/v0.1.3': b'5a3a8fb005554692b16e21dee62bf02667d8dc3e', | |
71 | } |
|
71 | } | |
72 |
|
72 | |||
73 | def side_effect(determine_wants, *args, **kwargs): |
|
73 | def side_effect(determine_wants, *args, **kwargs): |
General Comments 0
You need to be logged in to leave comments.
Login now