hgitaly 2.5.3__tar.gz → 2.5.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hgitaly-2.5.3 → hgitaly-2.5.5}/.hgtags +2 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/PKG-INFO +1 -1
- hgitaly-2.5.5/hgitaly/VERSION +1 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/diff.py +47 -20
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/message.py +4 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/diff.py +4 -1
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/ref.py +95 -3
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_diff.py +46 -1
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_ref.py +77 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_messages.py +5 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly.egg-info/PKG-INFO +1 -1
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/comparison.py +88 -22
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_commit.py +1 -1
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_diff.py +26 -2
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_operations.py +17 -27
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_ref.py +127 -1
- hgitaly-2.5.3/hgitaly/VERSION +0 -1
- {hgitaly-2.5.3 → hgitaly-2.5.5}/.coveragerc +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/.gitlab-ci.yml +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/.hgignore +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/LICENSE +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/MANIFEST.in +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/README.md +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ci/heptapod-sftp-push +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ci/heptapod-sign-package +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ci/heptapod_known_hosts.ssh +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ci/upload-rhgitaly +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/conftest.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/dev-requirements.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/examples/client.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/examples/client_list_lcft.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/generate-stubs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgext3rd/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgext3rd/hgitaly/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgext3rd/hgitaly/revset.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgext3rd/hgitaly/tests/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgext3rd/hgitaly/tests/test_revset.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgext3rd/hgitaly/tests/test_serve.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/branch.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/changelog.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/errors.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/feature.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/file_content.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/file_context.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/git.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/gitlab_ref.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/license_detector/GPL-2.sample +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/license_detector/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/license_detector/spdx-licenses.json +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/linguist/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/linguist/languages.json +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/logging.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/manifest.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/oid.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/pagination.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/path.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/peer.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/procutil.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/repository.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/revision.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/revset.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/scripts.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/address.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/mono.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/prefork.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/tests/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/tests/test_address.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/tests/test_mono.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/tests/test_prefork.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/tests/test_worker.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/server/worker.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/analysis.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/blob.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/commit.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/interceptors.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/mercurial_changeset.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/mercurial_operations.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/mercurial_repository.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/operations.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/repository.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/server.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/fixture.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_analysis.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_blob.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_commit.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_default_branch.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_mercurial_changeset.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_mercurial_operations.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_mercurial_repository.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_operations.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_repository_service.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/service/tests/test_server.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/servicer.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/ssh.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stream.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/analysis_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/analysis_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/blob_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/blob_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/commit_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/commit_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/diff_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/diff_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/errors_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/errors_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/lint_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/lint_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/mercurial_changeset_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/mercurial_changeset_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/mercurial_operations_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/mercurial_operations_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/mercurial_repository_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/mercurial_repository_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/operations_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/operations_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/ref_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/ref_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/repository_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/repository_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/server_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/server_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/shared_pb2.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/stub/shared_pb2_grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tag.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/bundle.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/context.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/authorized_keys +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/backup_additional_no_git.tar +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/id_ecdsa_user +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/known_hosts +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/ssh_host_ecdsa_key +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/ssh_host_ecdsa_key.pub +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/data/sshd_config +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/grpc.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/ssh.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/sshd.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/tests/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/testing/tests/test_sshd.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/common.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_branch.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_diff.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_errors.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_feature.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_file_context.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_gitlab_ref.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_license_detector.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_linguist.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_manifest.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_oid.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_peer.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_repository.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_revision.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_revset.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_servicer.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_stream.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_tag.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/tests/test_workdir.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/util.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly/workdir.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly.egg-info/SOURCES.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly.egg-info/dependency_links.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly.egg-info/entry_points.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly.egg-info/requires.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/hgitaly.egg-info/top_level.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/install-requirements.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/lint +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/analysis.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/blob.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/cleanup.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/cluster.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/commit.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/conflicts.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/diff.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/errors.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/hook.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/internal.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/lint.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/log.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/mercurial-changeset.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/mercurial-operations.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/mercurial-repository.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/namespace.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/objectpool.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/operations.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/packfile.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/praefect.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/ref.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/remote.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/repository.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/server.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/service_config.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/shared.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/smarthttp.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/ssh.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/transaction.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/protos/wiki.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/.ruby-version +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/Gemfile +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/README.md +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/generate-grpc-lib +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/hgitaly.gemspec +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/mercurial-changeset_pb.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/mercurial-changeset_services_pb.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/mercurial-operations_pb.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/mercurial-operations_services_pb.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/mercurial-repository_pb.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/mercurial-repository_services_pb.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly/version.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/lib/hgitaly.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/ruby/run.rb +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/run-all-tests +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/Cargo.lock +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/Cargo.toml +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/Makefile +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/build-from-tarball.sh +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/check-line-width +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/README.md +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/mercurial.patch +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/any.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/api.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/compiler/plugin.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/descriptor.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/duration.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/empty.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/field_mask.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/source_context.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/struct.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/timestamp.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/type.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/dependencies/proto/google/protobuf/wrappers.proto +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/go-enry.rev +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/lint +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/mercurial.rev +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/Cargo.toml +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/build.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/clippy.toml +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/config.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/errors.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/generated/README.md +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/git.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/gitlab/mod.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/gitlab/reference.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/gitlab/revision.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/gitlab/state.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/glob.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/lib.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/main.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/mercurial.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/message.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/metadata.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/oid.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/process.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/repository.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/analysis.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/blob.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/commit/find_commits.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/commit/get_tree_entries.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/commit/last_commits.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/commit/mod.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/commit/tree_entry.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/diff.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/mercurial_repository.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/mod.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/ref.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/repository.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/service/server.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/sidecar.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/streaming.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rhgitaly/src/util.rs +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/rs-enry.rev +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/rust/src-tarball.sh +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/setup.cfg +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/setup.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/test-requirements.txt +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/__init__.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/conftest.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/gitaly.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/rhgitaly.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_blob_tree.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_comparison.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_gitaly_server.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_mercurial_repository.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_repository_service.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_rhgitaly_server.py +0 -0
- {hgitaly-2.5.3 → hgitaly-2.5.5}/tests_with_gitaly/test_server.py +0 -0
|
@@ -118,3 +118,5 @@ a118debbf0a0deaa94b02ed0007ab2ef0f2b73c3 2.4.0
|
|
|
118
118
|
c1b00e1bc1bf0a2d41907b345c48cf795f910a4f 2.5.0
|
|
119
119
|
136dff98ddc1315e6db9479d9b6dd2c2204c2e5f 2.5.1
|
|
120
120
|
7dbcba18d83708ff81d8cec9696a86d24ed5d20a 2.5.2
|
|
121
|
+
3a83836b7408f1318a80f1ba97051086596edd12 2.5.3
|
|
122
|
+
3c955f8f106db667acb67a1cc5fa06b4a7e218e6 2.5.4
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.5.5
|
|
@@ -46,17 +46,19 @@ Status_Type_Map = dict(
|
|
|
46
46
|
added=ChangedPaths.Status.ADDED,
|
|
47
47
|
modified=ChangedPaths.Status.MODIFIED,
|
|
48
48
|
removed=ChangedPaths.Status.DELETED,
|
|
49
|
+
renamed=ChangedPaths.Status.RENAMED,
|
|
49
50
|
# Note: Mercurial includes TYPE_CHANGE
|
|
50
51
|
# (symlink, regular file, submodule...etc) in MODIFIED status
|
|
51
52
|
)
|
|
52
53
|
"""Mapping status object attributes to ChangedPaths enum."""
|
|
53
54
|
|
|
54
55
|
COPIED = ChangedPaths.Status.COPIED
|
|
56
|
+
RENAMED = ChangedPaths.Status.RENAMED
|
|
55
57
|
DIFF_HUNKS_START_RX = re.compile(rb'^(--- )|^(Binary file)')
|
|
56
58
|
"""To match the header line right before hunks start getting dumped."""
|
|
57
59
|
|
|
58
60
|
|
|
59
|
-
def changed_paths(repo, from_ctx, to_ctx, base_path):
|
|
61
|
+
def changed_paths(repo, from_ctx, to_ctx, base_path, find_renames=False):
|
|
60
62
|
if base_path is None:
|
|
61
63
|
matcher = None
|
|
62
64
|
path_trim_at = 0
|
|
@@ -74,26 +76,33 @@ def changed_paths(repo, from_ctx, to_ctx, base_path):
|
|
|
74
76
|
patterns=[b'path:' + base_path])
|
|
75
77
|
path_trim_at = len(base_path) + 1
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
copies.pathcopies(from_ctx, to_ctx, match=matcher),
|
|
81
|
-
trim_at=path_trim_at))
|
|
82
|
-
copied_paths = set(cp.path for cp in copied)
|
|
79
|
+
copy_info = copies.pathcopies(from_ctx, to_ctx, match=matcher)
|
|
80
|
+
# copies do not distinguish actual copies from renames. The difference
|
|
81
|
+
# will be that a rename goes with deletion of the original.
|
|
83
82
|
|
|
84
83
|
status = from_ctx.status(to_ctx, match=matcher)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
# this will remove renames from copy_info, keeping only actual copies
|
|
85
|
+
yield from status_changed_paths(from_ctx, to_ctx, status, copy_info,
|
|
86
|
+
find_renames=find_renames,
|
|
87
|
+
trim_at=path_trim_at)
|
|
88
|
+
yield from copy_changed_paths(from_ctx,
|
|
89
|
+
to_ctx,
|
|
90
|
+
copy_info,
|
|
91
|
+
trim_at=path_trim_at)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def status_changed_paths(from_ctx, to_ctx, status, copy_info,
|
|
95
|
+
find_renames=False, trim_at=0):
|
|
96
|
+
rcopy_info = {v: k for k, v in copy_info.items()}
|
|
94
97
|
"""Return ChangedPaths from Mercurial status object"""
|
|
95
98
|
for stype in ['added', 'modified', 'removed']:
|
|
96
99
|
for path in status.__getattribute__(stype):
|
|
100
|
+
copied_from = copy_info.get(path)
|
|
101
|
+
if copied_from is not None:
|
|
102
|
+
if copied_from not in status.removed or find_renames:
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
old_path = b''
|
|
97
106
|
if stype == 'added':
|
|
98
107
|
old_mode = OBJECT_MODE_DOES_NOT_EXIST
|
|
99
108
|
old_blob_id = NULL_BLOB_OID
|
|
@@ -102,8 +111,21 @@ def status_changed_paths(from_ctx, to_ctx, status, trim_at=0):
|
|
|
102
111
|
old_blob_id = ctx_blob_oid(from_ctx, path)
|
|
103
112
|
|
|
104
113
|
if stype == 'removed':
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
new_path = rcopy_info.get(path)
|
|
115
|
+
if new_path is None:
|
|
116
|
+
new_mode = OBJECT_MODE_DOES_NOT_EXIST
|
|
117
|
+
new_blob_id = NULL_BLOB_OID
|
|
118
|
+
else:
|
|
119
|
+
del copy_info[new_path]
|
|
120
|
+
if find_renames:
|
|
121
|
+
stype = 'renamed'
|
|
122
|
+
old_path = path
|
|
123
|
+
path = new_path
|
|
124
|
+
new_mode = git_perms(to_ctx.filectx(new_path))
|
|
125
|
+
new_blob_id = ctx_blob_oid(to_ctx, new_path)
|
|
126
|
+
else:
|
|
127
|
+
new_mode = OBJECT_MODE_DOES_NOT_EXIST
|
|
128
|
+
new_blob_id = NULL_BLOB_OID
|
|
107
129
|
else:
|
|
108
130
|
new_mode = git_perms(to_ctx.filectx(path))
|
|
109
131
|
new_blob_id = ctx_blob_oid(to_ctx, path)
|
|
@@ -114,11 +136,13 @@ def status_changed_paths(from_ctx, to_ctx, status, trim_at=0):
|
|
|
114
136
|
new_mode=new_mode,
|
|
115
137
|
old_blob_id=old_blob_id,
|
|
116
138
|
new_blob_id=new_blob_id,
|
|
139
|
+
old_path=old_path,
|
|
117
140
|
status=Status_Type_Map[stype]
|
|
118
141
|
)
|
|
119
142
|
|
|
120
143
|
|
|
121
|
-
def copy_changed_paths(from_ctx, to_ctx, path_copies,
|
|
144
|
+
def copy_changed_paths(from_ctx, to_ctx, path_copies,
|
|
145
|
+
trim_at=0, find_renames=False):
|
|
122
146
|
"""Return ChangedPaths for the given paths, relative to base_path.
|
|
123
147
|
|
|
124
148
|
Given that Gitaly currently (gitaly@c54d613d0) does not pass
|
|
@@ -129,8 +153,11 @@ def copy_changed_paths(from_ctx, to_ctx, path_copies, trim_at=0):
|
|
|
129
153
|
for target, source in path_copies.items():
|
|
130
154
|
yield ChangedPaths(path=target[trim_at:],
|
|
131
155
|
status=COPIED,
|
|
132
|
-
old_mode=git_perms(
|
|
156
|
+
old_mode=git_perms(from_ctx.filectx(source)),
|
|
157
|
+
old_blob_id=ctx_blob_oid(from_ctx, source),
|
|
133
158
|
new_mode=git_perms(to_ctx.filectx(target)),
|
|
159
|
+
new_blob_id=ctx_blob_oid(to_ctx, target),
|
|
160
|
+
old_path=source[trim_at:],
|
|
134
161
|
)
|
|
135
162
|
|
|
136
163
|
|
|
@@ -521,8 +521,11 @@ class DiffServicer(DiffServiceServicer, HGitalyServicer):
|
|
|
521
521
|
for cp in cids_paths]
|
|
522
522
|
extracted.append((left_ctx, right_ctx, path))
|
|
523
523
|
|
|
524
|
+
find_renames = request.find_renames
|
|
524
525
|
for paths in chunked(path for extr in extracted
|
|
525
|
-
for path in changed_paths(
|
|
526
|
+
for path in changed_paths(
|
|
527
|
+
repo, *extr,
|
|
528
|
+
find_renames=find_renames)):
|
|
526
529
|
yield FindChangedPathsResponse(paths=paths)
|
|
527
530
|
|
|
528
531
|
def GetPatchID(self, request: GetPatchIDRequest,
|
|
@@ -28,6 +28,8 @@ from hgext3rd.heptapod.special_ref import (
|
|
|
28
28
|
)
|
|
29
29
|
from hgext3rd.heptapod.keep_around import (
|
|
30
30
|
parse_keep_around_ref,
|
|
31
|
+
iter_keep_arounds,
|
|
32
|
+
init_keep_arounds,
|
|
31
33
|
)
|
|
32
34
|
|
|
33
35
|
from ..errors import (
|
|
@@ -40,6 +42,8 @@ from ..pagination import (
|
|
|
40
42
|
)
|
|
41
43
|
from ..revision import (
|
|
42
44
|
CHANGESET_HASH_BYTES_REGEXP,
|
|
45
|
+
ZERO_SHA,
|
|
46
|
+
ZERO_SHA_STR,
|
|
43
47
|
gitlab_revision_hash,
|
|
44
48
|
)
|
|
45
49
|
from ..stream import (
|
|
@@ -51,6 +55,7 @@ from ..stub.shared_pb2 import (
|
|
|
51
55
|
)
|
|
52
56
|
from ..stub.errors_pb2 import (
|
|
53
57
|
ReferenceNotFoundError,
|
|
58
|
+
ReferenceStateMismatchError,
|
|
54
59
|
)
|
|
55
60
|
from ..stub.ref_pb2 import (
|
|
56
61
|
FindDefaultBranchNameRequest,
|
|
@@ -74,6 +79,9 @@ from ..stub.ref_pb2 import (
|
|
|
74
79
|
FindBranchResponse,
|
|
75
80
|
DeleteRefsRequest,
|
|
76
81
|
DeleteRefsResponse,
|
|
82
|
+
UpdateReferencesError,
|
|
83
|
+
UpdateReferencesRequest,
|
|
84
|
+
UpdateReferencesResponse,
|
|
77
85
|
ListBranchNamesContainingCommitRequest,
|
|
78
86
|
ListBranchNamesContainingCommitResponse,
|
|
79
87
|
ListTagNamesContainingCommitRequest,
|
|
@@ -87,9 +95,6 @@ from ..stub.ref_pb2 import (
|
|
|
87
95
|
)
|
|
88
96
|
from ..stub.ref_pb2_grpc import RefServiceServicer
|
|
89
97
|
|
|
90
|
-
from ..revision import (
|
|
91
|
-
ZERO_SHA_STR,
|
|
92
|
-
)
|
|
93
98
|
from ..branch import (
|
|
94
99
|
BranchSortBy,
|
|
95
100
|
gitlab_branch_head,
|
|
@@ -273,6 +278,93 @@ class RefServicer(RefServiceServicer, HGitalyServicer):
|
|
|
273
278
|
return FindBranchResponse(
|
|
274
279
|
branch=Branch(name=name, target_commit=message.commit(head)))
|
|
275
280
|
|
|
281
|
+
def UpdateReferences(self,
|
|
282
|
+
request: UpdateReferencesRequest,
|
|
283
|
+
context) -> UpdateReferencesResponse:
|
|
284
|
+
self.STATUS_CODE_STORAGE_NOT_FOUND = StatusCode.INVALID_ARGUMENT
|
|
285
|
+
first = True
|
|
286
|
+
special_changes = []
|
|
287
|
+
ka_changes = []
|
|
288
|
+
for req in request:
|
|
289
|
+
if first:
|
|
290
|
+
# blobs are given by oid, hence as in direct changeset Node
|
|
291
|
+
# IDs, the unfiltered repo is the right one for the task
|
|
292
|
+
repo = self.load_repo(req.repository, context).unfiltered()
|
|
293
|
+
first = False
|
|
294
|
+
|
|
295
|
+
for upd in req.updates:
|
|
296
|
+
if len(upd.new_object_id) != 40:
|
|
297
|
+
oid = upd.new_object_id.decode('ascii', 'replace')
|
|
298
|
+
context.abort(StatusCode.INVALID_ARGUMENT,
|
|
299
|
+
"validating new object ID: "
|
|
300
|
+
f'invalid object ID: "{oid}", '
|
|
301
|
+
f"expected length 40, got {len(oid)}")
|
|
302
|
+
|
|
303
|
+
ref_path = upd.reference
|
|
304
|
+
change = (upd.old_object_id, upd.new_object_id)
|
|
305
|
+
if change[0] == change[1]:
|
|
306
|
+
# let's not waste resources for this
|
|
307
|
+
continue
|
|
308
|
+
|
|
309
|
+
# consider only special refs and keep-arounds, as other refs
|
|
310
|
+
# (branches and tags) are only reflecting changesets content,
|
|
311
|
+
# setting them independently makes no sense with Mercurial
|
|
312
|
+
special_ref = parse_special_ref(ref_path)
|
|
313
|
+
if special_ref is not None:
|
|
314
|
+
special_changes.append((special_ref, change))
|
|
315
|
+
continue
|
|
316
|
+
|
|
317
|
+
ka = parse_keep_around_ref(upd.reference)
|
|
318
|
+
if ka is not None:
|
|
319
|
+
if (
|
|
320
|
+
upd.new_object_id != ZERO_SHA
|
|
321
|
+
and ka != upd.new_object_id
|
|
322
|
+
):
|
|
323
|
+
context.abort(StatusCode.INVALID_ARGUMENT,
|
|
324
|
+
"Inconsistent keep-around.")
|
|
325
|
+
ka_changes.append(change)
|
|
326
|
+
|
|
327
|
+
with repo.lock():
|
|
328
|
+
# keeping promise of atomicity of this method
|
|
329
|
+
special_existing = special_refs(repo)
|
|
330
|
+
if special_existing is GITLAB_TYPED_REFS_MISSING:
|
|
331
|
+
special_existing = {}
|
|
332
|
+
for name, (old_id, new_id) in special_changes:
|
|
333
|
+
existing = special_existing.get(name)
|
|
334
|
+
if old_id == ZERO_SHA and existing is not None:
|
|
335
|
+
context.abort(StatusCode.INTERNAL,
|
|
336
|
+
"committing update: "
|
|
337
|
+
"reference already exists")
|
|
338
|
+
elif old_id and old_id != ZERO_SHA and existing != old_id:
|
|
339
|
+
Mismatch = ReferenceStateMismatchError # just too long!
|
|
340
|
+
structured_abort(
|
|
341
|
+
context, StatusCode.ABORTED,
|
|
342
|
+
"reference does not point to expected object",
|
|
343
|
+
UpdateReferencesError(
|
|
344
|
+
reference_state_mismatch=Mismatch(
|
|
345
|
+
reference_name=b'refs/' + name,
|
|
346
|
+
expected_object_id=old_id,
|
|
347
|
+
actual_object_id=existing)))
|
|
348
|
+
elif new_id == ZERO_SHA:
|
|
349
|
+
del special_existing[name]
|
|
350
|
+
else:
|
|
351
|
+
special_existing[name] = new_id
|
|
352
|
+
|
|
353
|
+
# TODO make a collect_keep_arounds() or keep_arounds_set()
|
|
354
|
+
ka_existing = set(iter_keep_arounds(repo))
|
|
355
|
+
ka_existing.discard(GITLAB_TYPED_REFS_MISSING)
|
|
356
|
+
for old_id, new_id in ka_changes:
|
|
357
|
+
# bogus requests have already been prohibited
|
|
358
|
+
if new_id == ZERO_SHA:
|
|
359
|
+
ka_existing.discard(old_id)
|
|
360
|
+
else:
|
|
361
|
+
ka_existing.add(new_id)
|
|
362
|
+
|
|
363
|
+
write_special_refs(repo, special_existing)
|
|
364
|
+
init_keep_arounds(repo, ka_existing)
|
|
365
|
+
|
|
366
|
+
return UpdateReferencesResponse()
|
|
367
|
+
|
|
276
368
|
def DeleteRefs(self,
|
|
277
369
|
request: DeleteRefsRequest,
|
|
278
370
|
context) -> DeleteRefsResponse:
|
|
@@ -127,7 +127,7 @@ class DiffFixture(ServiceFixture):
|
|
|
127
127
|
(changed.status, perm_change))
|
|
128
128
|
return by_file
|
|
129
129
|
|
|
130
|
-
def find_changed_paths_commits(self, commits, compare_to=()):
|
|
130
|
+
def find_changed_paths_commits(self, commits, compare_to=(), **kw):
|
|
131
131
|
"""Wrap FindChangedPaths used with CommitRequest.
|
|
132
132
|
|
|
133
133
|
:param compare_to: if given, will be used in all requests, hoping
|
|
@@ -141,6 +141,7 @@ class DiffFixture(ServiceFixture):
|
|
|
141
141
|
commit_revision=c,
|
|
142
142
|
parent_commit_revisions=compare_to))
|
|
143
143
|
for c in commits],
|
|
144
|
+
**kw
|
|
144
145
|
)
|
|
145
146
|
|
|
146
147
|
def find_changed_paths_tree(self, left_oid, right_oid):
|
|
@@ -686,6 +687,50 @@ def test_find_changed_paths_copy_in_tree(diff_fixture):
|
|
|
686
687
|
}
|
|
687
688
|
|
|
688
689
|
|
|
690
|
+
def test_find_changed_paths_rename(diff_fixture):
|
|
691
|
+
wrapper = diff_fixture.repo_wrapper
|
|
692
|
+
|
|
693
|
+
(wrapper.path / 'subdir').mkdir() # avoid all lengths to be 3
|
|
694
|
+
(wrapper.path / 'subdir/bar').write_text('some bar')
|
|
695
|
+
ctx0 = wrapper.commit(rel_paths=['subdir'], add_remove=True)
|
|
696
|
+
|
|
697
|
+
wrapper.command(b'mv', wrapper.repo.root + b'/subdir/bar',
|
|
698
|
+
wrapper.repo.root + b'/subdir/baz')
|
|
699
|
+
ctx1 = wrapper.commit(rel_paths=['subdir'])
|
|
700
|
+
|
|
701
|
+
repo = wrapper.repo
|
|
702
|
+
|
|
703
|
+
sub0_oid, sub1_oid = [tree_oid(repo, ctx.hex().decode('ascii'), b'subdir')
|
|
704
|
+
for ctx in (ctx0, ctx1)]
|
|
705
|
+
ret = diff_fixture.find_changed_paths_commits(
|
|
706
|
+
[ctx1.hex()],
|
|
707
|
+
compare_to=[ctx0.hex()],
|
|
708
|
+
find_renames=False,
|
|
709
|
+
)
|
|
710
|
+
assert ret == {
|
|
711
|
+
b'subdir/baz': [(ChangedPaths.Status.ADDED,
|
|
712
|
+
(OBJECT_MODE_DOES_NOT_EXIST,
|
|
713
|
+
OBJECT_MODE_NON_EXECUTABLE),
|
|
714
|
+
)],
|
|
715
|
+
b'subdir/bar': [(ChangedPaths.Status.DELETED,
|
|
716
|
+
(OBJECT_MODE_NON_EXECUTABLE,
|
|
717
|
+
OBJECT_MODE_DOES_NOT_EXIST)
|
|
718
|
+
)],
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
ret = diff_fixture.find_changed_paths_commits(
|
|
722
|
+
[ctx1.hex()],
|
|
723
|
+
compare_to=[ctx0.hex()],
|
|
724
|
+
find_renames=True,
|
|
725
|
+
)
|
|
726
|
+
assert ret == {
|
|
727
|
+
b'subdir/baz': [(ChangedPaths.Status.RENAMED, None)],
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
# TODO test the case of rename with duplication:
|
|
731
|
+
# hg cp foo bar; hg mv foo bar2
|
|
732
|
+
|
|
733
|
+
|
|
689
734
|
def test_get_patch_id(diff_fixture):
|
|
690
735
|
wrapper = diff_fixture.repo_wrapper
|
|
691
736
|
patch_id = diff_fixture.get_patch_id
|
|
@@ -30,6 +30,7 @@ from hgext3rd.heptapod.keep_around import (
|
|
|
30
30
|
from hgitaly import feature
|
|
31
31
|
from hgitaly.errors import parse_assert_structured_error
|
|
32
32
|
from hgitaly.revision import (
|
|
33
|
+
ZERO_SHA,
|
|
33
34
|
ZERO_SHA_STR,
|
|
34
35
|
)
|
|
35
36
|
from hgitaly.tests.common import (
|
|
@@ -56,6 +57,7 @@ from hgitaly.stub.ref_pb2 import (
|
|
|
56
57
|
FindRefsByOIDRequest,
|
|
57
58
|
FindTagError,
|
|
58
59
|
FindTagRequest,
|
|
60
|
+
UpdateReferencesRequest,
|
|
59
61
|
)
|
|
60
62
|
from hgitaly.stub.ref_pb2_grpc import RefServiceStub
|
|
61
63
|
|
|
@@ -85,6 +87,10 @@ class RefFixture(ServiceFixture):
|
|
|
85
87
|
metadata=feature.as_grpc_metadata(self.feature_flags),
|
|
86
88
|
)
|
|
87
89
|
|
|
90
|
+
def ref_exists(self, ref, **kw):
|
|
91
|
+
kw.setdefault('repository', self.grpc_repo)
|
|
92
|
+
return self.stub.RefExists(RefExistsRequest(ref=ref, **kw)).value
|
|
93
|
+
|
|
88
94
|
def list_refs(self, patterns=(b"refs/", ), **kw):
|
|
89
95
|
return [(ref.name, ref.target)
|
|
90
96
|
for resp in self.stub.ListRefs(
|
|
@@ -97,6 +103,22 @@ class RefFixture(ServiceFixture):
|
|
|
97
103
|
kw.setdefault('repository', self.grpc_repo)
|
|
98
104
|
return self.stub.FindRefsByOID(FindRefsByOIDRequest(**kw)).refs
|
|
99
105
|
|
|
106
|
+
def update_refs(self, updates, **kw):
|
|
107
|
+
Update = UpdateReferencesRequest.Update
|
|
108
|
+
kw.setdefault('repository', self.grpc_repo)
|
|
109
|
+
|
|
110
|
+
update_messages = []
|
|
111
|
+
for ref_path, old_id, new_id in updates:
|
|
112
|
+
upd_kw = dict(reference=ref_path, new_object_id=new_id)
|
|
113
|
+
if old_id is not None:
|
|
114
|
+
upd_kw['old_object_id'] = old_id
|
|
115
|
+
update_messages.append(Update(**upd_kw))
|
|
116
|
+
|
|
117
|
+
return self.stub.UpdateReferences(
|
|
118
|
+
iter([UpdateReferencesRequest(updates=[upd], **kw)
|
|
119
|
+
for upd in update_messages])
|
|
120
|
+
)
|
|
121
|
+
|
|
100
122
|
|
|
101
123
|
@pytest.fixture
|
|
102
124
|
def ref_fixture(grpc_channel, server_repos_root):
|
|
@@ -633,3 +655,58 @@ def test_list_refs(ref_fixture):
|
|
|
633
655
|
assert fixture.find_refs_by_oid(
|
|
634
656
|
oid=sha1, sort_field='refname', limit=1
|
|
635
657
|
) == ['refs/heads/branch/default']
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
def test_update_references(ref_fixture):
|
|
661
|
+
fixture = ref_fixture
|
|
662
|
+
wrapper = fixture.repo_wrapper
|
|
663
|
+
|
|
664
|
+
sha0 = wrapper.write_commit('afoo', message="Some foo").hex()
|
|
665
|
+
sha1 = wrapper.write_commit('afoo', message="Some foo").hex()
|
|
666
|
+
|
|
667
|
+
pipeline_1 = b'refs/pipelines/1'
|
|
668
|
+
ka_0 = b'refs/keep-around/' + sha0
|
|
669
|
+
fixture.update_refs([(pipeline_1, ZERO_SHA, sha1),
|
|
670
|
+
(ka_0, ZERO_SHA, sha0),
|
|
671
|
+
])
|
|
672
|
+
assert fixture.ref_exists(ka_0)
|
|
673
|
+
assert fixture.ref_exists(pipeline_1)
|
|
674
|
+
assert fixture.list_refs(patterns=[b'refs/pipelines/']) == [
|
|
675
|
+
(pipeline_1, sha1.decode())
|
|
676
|
+
]
|
|
677
|
+
|
|
678
|
+
fixture.update_refs([(pipeline_1, sha1, sha0),
|
|
679
|
+
(ka_0, sha0, ZERO_SHA),
|
|
680
|
+
])
|
|
681
|
+
assert not fixture.ref_exists(ka_0)
|
|
682
|
+
assert fixture.list_refs(patterns=[b'refs/pipelines/']) == [
|
|
683
|
+
(pipeline_1, sha0.decode())
|
|
684
|
+
]
|
|
685
|
+
|
|
686
|
+
# edge case equivalent to no-op
|
|
687
|
+
fixture.update_refs([(pipeline_1, sha0, sha0)])
|
|
688
|
+
assert fixture.list_refs(patterns=[b'refs/pipelines/']) == [
|
|
689
|
+
(pipeline_1, sha0.decode())
|
|
690
|
+
]
|
|
691
|
+
|
|
692
|
+
# error cases
|
|
693
|
+
with pytest.raises(grpc.RpcError) as exc_info:
|
|
694
|
+
fixture.update_refs([(pipeline_1, None, b'branch/default')])
|
|
695
|
+
assert exc_info.value.code() == grpc.StatusCode.INVALID_ARGUMENT
|
|
696
|
+
|
|
697
|
+
with pytest.raises(grpc.RpcError) as exc_info:
|
|
698
|
+
fixture.update_refs([(ka_0, None, sha1)])
|
|
699
|
+
assert exc_info.value.code() == grpc.StatusCode.INVALID_ARGUMENT
|
|
700
|
+
|
|
701
|
+
with pytest.raises(grpc.RpcError) as exc_info:
|
|
702
|
+
fixture.update_refs([(pipeline_1, ZERO_SHA, sha1)])
|
|
703
|
+
assert exc_info.value.code() == grpc.StatusCode.INTERNAL
|
|
704
|
+
assert 'reference already exists' in exc_info.value.details()
|
|
705
|
+
|
|
706
|
+
with pytest.raises(grpc.RpcError) as exc_info:
|
|
707
|
+
fixture.update_refs([(pipeline_1, sha1, sha0)])
|
|
708
|
+
assert exc_info.value.code() == grpc.StatusCode.ABORTED
|
|
709
|
+
|
|
710
|
+
# deletions
|
|
711
|
+
fixture.update_refs([(pipeline_1, sha0, ZERO_SHA)])
|
|
712
|
+
assert not fixture.ref_exists(pipeline_1)
|
|
@@ -54,6 +54,11 @@ def test_tag(tmpdir):
|
|
|
54
54
|
assert tag.signature_type == SignatureType.PGP
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
def test_as_dict():
|
|
58
|
+
d = dict(storage_name='thestore', relative_path='a/b/c')
|
|
59
|
+
assert message.as_dict(Repository(**d)) == d
|
|
60
|
+
|
|
61
|
+
|
|
57
62
|
def test_commit_author():
|
|
58
63
|
|
|
59
64
|
class FakeContext:
|
|
@@ -35,6 +35,7 @@ from hgitaly.errors import (
|
|
|
35
35
|
parse_structured_error,
|
|
36
36
|
)
|
|
37
37
|
from hgitaly import feature
|
|
38
|
+
from hgitaly import message
|
|
38
39
|
from hgitaly.errors import HGITALY_ISSUES_URL
|
|
39
40
|
from hgitaly.gitlab_ref import (
|
|
40
41
|
keep_around_ref_path,
|
|
@@ -264,6 +265,59 @@ class BaseRpcHelper:
|
|
|
264
265
|
for k, v in defaults.items():
|
|
265
266
|
kwargs.setdefault(k, v)
|
|
266
267
|
|
|
268
|
+
def structured_errors_git_converter(self, fields, error_git_cls=None):
|
|
269
|
+
"""Return a function that is suitable for `to_git` in handler.
|
|
270
|
+
|
|
271
|
+
This matches the common pattern of the structured error being
|
|
272
|
+
an enum with subobject variants
|
|
273
|
+
Only full hash string or bytes values are supported and lists of
|
|
274
|
+
these are supported at this point
|
|
275
|
+
|
|
276
|
+
:param fields: a list of :class:`dict`with keys:
|
|
277
|
+
|
|
278
|
+
- `hg_field`: name of the variant for HGitaly
|
|
279
|
+
- `git_field`: name of the variant for Gitaly,
|
|
280
|
+
defaults to `hg_field`
|
|
281
|
+
- `git_cls`: variant class to use for Gitaly, defaults to the
|
|
282
|
+
received HGitaly variant class
|
|
283
|
+
- `subfields`: list of names of fields in the varian to convert.
|
|
284
|
+
Use the `[]` suffix to specify that a field is
|
|
285
|
+
repeated.
|
|
286
|
+
"""
|
|
287
|
+
def to_git(error):
|
|
288
|
+
if error_git_cls is None:
|
|
289
|
+
error_git_class = error.__class__ # pragma no cover
|
|
290
|
+
else:
|
|
291
|
+
error_git_class = error_git_cls
|
|
292
|
+
for descr in fields:
|
|
293
|
+
name = descr['hg_field']
|
|
294
|
+
new_name = descr.get('git_field', name)
|
|
295
|
+
if error.HasField(name):
|
|
296
|
+
subobj = getattr(error, name)
|
|
297
|
+
git_cls = descr.get('git_cls', subobj.__class__)
|
|
298
|
+
# direct assignment to repeated values is not possible
|
|
299
|
+
# so we copy in a dict and reinstantiate
|
|
300
|
+
subitems = message.as_dict(subobj)
|
|
301
|
+
for field in descr['subfields']:
|
|
302
|
+
repeated = field.endswith('[]')
|
|
303
|
+
if repeated:
|
|
304
|
+
field = field[:-2]
|
|
305
|
+
hg_val = subitems.get(field)
|
|
306
|
+
if hg_val is None:
|
|
307
|
+
continue # pragma no cover
|
|
308
|
+
|
|
309
|
+
if repeated:
|
|
310
|
+
git_val = [self.hg2git(sha) for sha in hg_val]
|
|
311
|
+
else:
|
|
312
|
+
git_val = self.hg2git(hg_val)
|
|
313
|
+
subitems[field] = git_val
|
|
314
|
+
subobj = git_cls(**subitems)
|
|
315
|
+
return error_git_class(**{new_name: subobj})
|
|
316
|
+
|
|
317
|
+
raise AssertionError("Unexpected error variant") # pragma no cover
|
|
318
|
+
|
|
319
|
+
return to_git
|
|
320
|
+
|
|
267
321
|
def assert_compare_grpc_exceptions(self, exc0, exc1,
|
|
268
322
|
same_details=True,
|
|
269
323
|
vcses=('hg', 'git'),
|
|
@@ -319,12 +373,13 @@ class BaseRpcHelper:
|
|
|
319
373
|
if extracted:
|
|
320
374
|
assert extracted[0]['code'] == extracted[1]['code']
|
|
321
375
|
if vcses[1] == 'git':
|
|
322
|
-
git_norm = handler.get('git_normalizer')
|
|
323
|
-
if git_norm is not None:
|
|
324
|
-
git_norm(extracted[1]['error'])
|
|
325
376
|
extracted[0]['error'] = handler['to_git'](
|
|
326
377
|
extracted[0]['error'])
|
|
327
378
|
|
|
379
|
+
norm = handler.get('normalizer')
|
|
380
|
+
if norm is not None:
|
|
381
|
+
norm(extracted[0]['error'])
|
|
382
|
+
norm(extracted[1]['error'])
|
|
328
383
|
assert extracted[0]['error'] == extracted[1]['error']
|
|
329
384
|
|
|
330
385
|
# already done and a priori not directly comparable
|
|
@@ -413,15 +468,17 @@ class RpcHelper(BaseRpcHelper):
|
|
|
413
468
|
return keep_around_ref_path(self.hg2git(hg_sha))
|
|
414
469
|
|
|
415
470
|
def request_kwargs_to_git(self, hg_kwargs):
|
|
416
|
-
|
|
417
|
-
for
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
471
|
+
# attr_path_to_git updates lists in place, because it needs
|
|
472
|
+
# to do so in the case of scalar lists for Messages. Hence in the
|
|
473
|
+
# case of dicts, we need to perform the deep copy.
|
|
474
|
+
git_kwargs = deepcopy(hg_kwargs)
|
|
475
|
+
sha_attr_paths = [path.split('.') for path in self.request_sha_attrs]
|
|
476
|
+
for attr_path in sha_attr_paths:
|
|
477
|
+
self.attr_path_to_git(git_kwargs, attr_path,
|
|
478
|
+
accessor=lambda d, k: d.get(k),
|
|
479
|
+
setter=lambda d, k, v: d.__setitem__(k, v),
|
|
480
|
+
has_field=lambda d, f: f in d,
|
|
481
|
+
)
|
|
425
482
|
return git_kwargs
|
|
426
483
|
|
|
427
484
|
def revspec_to_git(self, revspec):
|
|
@@ -445,16 +502,20 @@ class RpcHelper(BaseRpcHelper):
|
|
|
445
502
|
def response_to_git(self, resp):
|
|
446
503
|
sha_attr_paths = [path.split('.') for path in self.response_sha_attrs]
|
|
447
504
|
if self.streaming:
|
|
448
|
-
for
|
|
449
|
-
self.message_to_git(
|
|
505
|
+
for msg in resp:
|
|
506
|
+
self.message_to_git(msg, sha_attr_paths)
|
|
450
507
|
else:
|
|
451
508
|
self.message_to_git(resp, sha_attr_paths)
|
|
452
509
|
|
|
453
|
-
def message_to_git(self, message, attr_paths):
|
|
510
|
+
def message_to_git(self, message, attr_paths, **kw):
|
|
454
511
|
for attr_path in attr_paths:
|
|
455
|
-
self.attr_path_to_git(message, attr_path)
|
|
512
|
+
self.attr_path_to_git(message, attr_path, **kw)
|
|
456
513
|
|
|
457
|
-
def attr_path_to_git(self, message, attr_path
|
|
514
|
+
def attr_path_to_git(self, message, attr_path,
|
|
515
|
+
accessor=getattr,
|
|
516
|
+
setter=setattr,
|
|
517
|
+
has_field=lambda o, f: o.HasField(f),
|
|
518
|
+
):
|
|
458
519
|
"""Convert to Git part of message specified by an attr_path.
|
|
459
520
|
|
|
460
521
|
:param attr_path: symbolic representation, as a succession of dotted
|
|
@@ -475,11 +536,14 @@ class RpcHelper(BaseRpcHelper):
|
|
|
475
536
|
if recurse:
|
|
476
537
|
attr_name = attr_name[:-2]
|
|
477
538
|
# HasField cannot be used on repeated attributes, hence the elif
|
|
478
|
-
elif not obj
|
|
539
|
+
elif not has_field(obj, attr_name):
|
|
479
540
|
return
|
|
480
|
-
obj =
|
|
541
|
+
obj = accessor(obj, attr_name)
|
|
542
|
+
if obj is None: # can happen with an accessor for dicts
|
|
543
|
+
continue # pragma no cover TODO make unit tests for RpcHelper
|
|
481
544
|
if recurse:
|
|
482
545
|
for msg in obj:
|
|
546
|
+
# after traversal, we are sure to be on a Message instance
|
|
483
547
|
self.message_to_git(msg, [trav])
|
|
484
548
|
return
|
|
485
549
|
|
|
@@ -487,13 +551,15 @@ class RpcHelper(BaseRpcHelper):
|
|
|
487
551
|
scalar_list = obj_attr.endswith('[]')
|
|
488
552
|
if scalar_list:
|
|
489
553
|
obj_attr = obj_attr[:-2]
|
|
490
|
-
value =
|
|
554
|
+
value = accessor(obj, obj_attr)
|
|
555
|
+
if value is None:
|
|
556
|
+
return
|
|
491
557
|
|
|
492
558
|
if scalar_list:
|
|
493
559
|
for i, sha in enumerate(value):
|
|
494
|
-
value[i] = self.
|
|
560
|
+
value[i] = self.revspec_to_git(sha)
|
|
495
561
|
else:
|
|
496
|
-
|
|
562
|
+
setter(obj, obj_attr, self.revspec_to_git(value))
|
|
497
563
|
|
|
498
564
|
def call_backends(self, **hg_kwargs):
|
|
499
565
|
"""Call Gitaly and HGitaly with uniform request kwargs.
|