hgitaly 18.2.2__tar.gz → 18.2.4__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-18.2.2/hgitaly.egg-info → hgitaly-18.2.4}/PKG-INFO +1 -1
- hgitaly-18.2.4/hgitaly/VERSION +1 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/operations.py +43 -41
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_operations.py +63 -1
- {hgitaly-18.2.2 → hgitaly-18.2.4/hgitaly.egg-info}/PKG-INFO +1 -1
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_operations.py +2 -3
- hgitaly-18.2.2/hgitaly/VERSION +0 -1
- {hgitaly-18.2.2 → hgitaly-18.2.4}/LICENSE +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/MANIFEST.in +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/README.md +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/revset.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/tests/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/tests/test_revset.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/tests/test_serve.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/branch.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/changelog.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/diff.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/errors.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/feature.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/file_content.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/file_context.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/git.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/gitlab_ref.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/identification.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/logging.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/manifest.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/message.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/oid.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/pagination.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/path.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/peer.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/procutil.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/repository.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/revision.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/revset.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/scripts.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/address.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/mono.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/prefork.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_address.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_mono.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_prefork.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_worker.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/worker.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/analysis.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/blob.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/commit.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/diff.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/interceptors.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/mercurial_changeset.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/mercurial_operations.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/mercurial_repository.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/ref.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/repository.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/server.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/fixture.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_analysis.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_blob.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_commit.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_default_branch.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_diff.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_mercurial_changeset.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_mercurial_operations.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_mercurial_repository.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_ref.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_repository_service.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_server.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/servicer.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/ssh.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stream.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/analysis_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/analysis_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/blob_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/blob_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/commit_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/commit_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/diff_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/diff_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/errors_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/errors_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/lint_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/lint_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_aux_git_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_aux_git_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_changeset_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_changeset_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_operations_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_operations_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_repository_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_repository_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/operations_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/operations_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/ref_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/ref_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/remote_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/remote_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/repository_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/repository_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/server_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/server_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/shared_pb2.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/shared_pb2_grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tag.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/bundle.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/context.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/grpc.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/multiprocessing.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/ssh.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/sshd.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/storage.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/tests/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/tests/test_sshd.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/common.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_branch.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_diff.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_errors.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_feature.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_file_context.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_gitlab_ref.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_identification.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_manifest.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_messages.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_oid.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_peer.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_repository.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_revision.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_revset.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_servicer.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_stream.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_tag.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_workdir.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/util.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/workdir.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/SOURCES.txt +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/dependency_links.txt +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/entry_points.txt +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/requires.txt +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/top_level.txt +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/install-requirements.txt +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/setup.cfg +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/setup.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/__init__.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/comparison.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/conftest.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/gitaly.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/rhgitaly.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_blob_tree.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_commit.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_comparison.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_diff.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_gitaly_server.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_mercurial_aux_git.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_mercurial_operations.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_mercurial_repository.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_ref.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_remote.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_repository_service.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_rhgitaly_server.py +0 -0
- {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_server.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
18.2.4
|
|
@@ -361,9 +361,14 @@ class OperationServicer(OperationServiceServicer, HGitalyServicer):
|
|
|
361
361
|
start_ctx = repo[ZERO_SHA]
|
|
362
362
|
if commit_header.branch_name:
|
|
363
363
|
old_oid = commit_header.expected_old_oid.encode('ascii')
|
|
364
|
-
if old_oid
|
|
365
|
-
|
|
366
|
-
|
|
364
|
+
if old_oid:
|
|
365
|
+
old_ctx = gitlab_revision_changeset(repo, gl_branch)
|
|
366
|
+
if (
|
|
367
|
+
(old_ctx is None and old_oid != ZERO_SHA)
|
|
368
|
+
or (old_ctx is not None and old_ctx.hex() != old_oid)
|
|
369
|
+
):
|
|
370
|
+
context.abort(StatusCode.INVALID_ARGUMENT,
|
|
371
|
+
"wrong old oid")
|
|
367
372
|
|
|
368
373
|
if to_publish and self.heptapod_permission != 'publish':
|
|
369
374
|
context.abort(
|
|
@@ -426,7 +431,9 @@ class OperationServicer(OperationServiceServicer, HGitalyServicer):
|
|
|
426
431
|
|
|
427
432
|
if header.action in (ActionType.CREATE,
|
|
428
433
|
ActionType.UPDATE):
|
|
429
|
-
content_handler = UserCommitFilesContent(
|
|
434
|
+
content_handler = UserCommitFilesContent(
|
|
435
|
+
context, wd, header
|
|
436
|
+
)
|
|
430
437
|
else:
|
|
431
438
|
content_handler = None
|
|
432
439
|
|
|
@@ -477,6 +484,31 @@ class OperationServicer(OperationServiceServicer, HGitalyServicer):
|
|
|
477
484
|
)
|
|
478
485
|
|
|
479
486
|
|
|
487
|
+
def validate_checkout_path(context, relpath):
|
|
488
|
+
# absolute paths are interpreted by Gitaly as relative to the
|
|
489
|
+
# root of checkout.
|
|
490
|
+
relpath = relpath.lstrip(b'/')
|
|
491
|
+
|
|
492
|
+
for p in FORBIDDEN_IN_PATHS:
|
|
493
|
+
if p in relpath:
|
|
494
|
+
relpath_str = relpath.decode('utf-8', 'surrogateescape')
|
|
495
|
+
|
|
496
|
+
if p == DIRECTORY_CLIMB_UP:
|
|
497
|
+
# ill-named by upstream
|
|
498
|
+
error_type = 'ERROR_TYPE_DIRECTORY_TRAVERSAL'
|
|
499
|
+
msg = 'Path cannot include directory traversal'
|
|
500
|
+
else:
|
|
501
|
+
error_type = 'ERROR_TYPE_INVALID_PATH'
|
|
502
|
+
msg = f'invalid path: "{relpath_str}"'
|
|
503
|
+
|
|
504
|
+
index_error(context,
|
|
505
|
+
status_code='INVALID_ARGUMENT',
|
|
506
|
+
error_type=error_type,
|
|
507
|
+
msg=msg,
|
|
508
|
+
path=relpath)
|
|
509
|
+
return relpath
|
|
510
|
+
|
|
511
|
+
|
|
480
512
|
class UserCommitFilesAction:
|
|
481
513
|
|
|
482
514
|
def __init__(self, context, header, working_dir, changed_files):
|
|
@@ -485,9 +517,8 @@ class UserCommitFilesAction:
|
|
|
485
517
|
self.changed_files = changed_files
|
|
486
518
|
|
|
487
519
|
wd = self.working_dir = working_dir
|
|
488
|
-
|
|
489
|
-
self.
|
|
490
|
-
self.abspath = wd.file_path(relpath)
|
|
520
|
+
self.relpath = validate_checkout_path(context, header.file_path)
|
|
521
|
+
self.abspath = wd.file_path(self.relpath)
|
|
491
522
|
|
|
492
523
|
def __call__(self):
|
|
493
524
|
action = self.header.action
|
|
@@ -504,36 +535,6 @@ class UserCommitFilesAction:
|
|
|
504
535
|
elif action == ActionType.CHMOD:
|
|
505
536
|
return self.chmod()
|
|
506
537
|
|
|
507
|
-
def validate(self, relpath):
|
|
508
|
-
if os.path.isabs(relpath):
|
|
509
|
-
index_error(
|
|
510
|
-
self.context,
|
|
511
|
-
status_code='INVALID_ARGUMENT',
|
|
512
|
-
error_type='ERROR_TYPE_INVALID_PATH',
|
|
513
|
-
msg='absolute',
|
|
514
|
-
path=relpath,
|
|
515
|
-
)
|
|
516
|
-
|
|
517
|
-
for p in FORBIDDEN_IN_PATHS:
|
|
518
|
-
if p in relpath:
|
|
519
|
-
relpath_str = relpath.decode('utf-8', 'surrogateescape')
|
|
520
|
-
|
|
521
|
-
if p == DIRECTORY_CLIMB_UP:
|
|
522
|
-
# ill-named by upstream
|
|
523
|
-
error_type = 'ERROR_TYPE_DIRECTORY_TRAVERSAL'
|
|
524
|
-
msg = 'Path cannot include directory traversal'
|
|
525
|
-
else:
|
|
526
|
-
error_type = 'ERROR_TYPE_INVALID_PATH'
|
|
527
|
-
msg = f'invalid path: "{relpath_str}"'
|
|
528
|
-
|
|
529
|
-
index_error(
|
|
530
|
-
self.context,
|
|
531
|
-
status_code='INVALID_ARGUMENT',
|
|
532
|
-
error_type=error_type,
|
|
533
|
-
msg=msg,
|
|
534
|
-
path=relpath,
|
|
535
|
-
)
|
|
536
|
-
|
|
537
538
|
def create(self):
|
|
538
539
|
if os.path.exists(self.abspath):
|
|
539
540
|
index_error(
|
|
@@ -600,8 +601,8 @@ class UserCommitFilesAction:
|
|
|
600
601
|
def move(self):
|
|
601
602
|
self.require_file_absence()
|
|
602
603
|
abspath = self.abspath
|
|
603
|
-
prev_relpath = self.
|
|
604
|
-
|
|
604
|
+
prev_relpath = validate_checkout_path(self.context,
|
|
605
|
+
self.header.previous_path)
|
|
605
606
|
prev_abspath = self.working_dir.file_path(prev_relpath)
|
|
606
607
|
self.require_file_existence(abspath=prev_abspath,
|
|
607
608
|
relpath=prev_relpath)
|
|
@@ -636,8 +637,9 @@ class UserCommitFilesAction:
|
|
|
636
637
|
|
|
637
638
|
class UserCommitFilesContent:
|
|
638
639
|
|
|
639
|
-
def __init__(self, workdir, header):
|
|
640
|
-
|
|
640
|
+
def __init__(self, context, workdir, header):
|
|
641
|
+
relpath = validate_checkout_path(context, header.file_path)
|
|
642
|
+
self.file_path = workdir.file_path(relpath)
|
|
641
643
|
self.fobj = open(self.file_path, 'wb')
|
|
642
644
|
self.make_hg_executable = (header.action == ActionType.CREATE
|
|
643
645
|
and header.execute_filemode)
|
|
@@ -24,6 +24,7 @@ from hgext3rd.heptapod.branch import (
|
|
|
24
24
|
gitlab_branches,
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
+
from hgitaly.revision import ZERO_SHA_STR
|
|
27
28
|
from hgitaly.stub.operations_pb2 import (
|
|
28
29
|
OperationBranchUpdate,
|
|
29
30
|
UserCommitFilesAction,
|
|
@@ -757,7 +758,7 @@ def test_user_commit_files(operations_fixture, tmpdir):
|
|
|
757
758
|
assert exc_info.value.code() == StatusCode.ALREADY_EXISTS
|
|
758
759
|
|
|
759
760
|
# invalid paths
|
|
760
|
-
for path in ('double//slash', '../../../good.joke'
|
|
761
|
+
for path in ('double//slash', '../../../good.joke'):
|
|
761
762
|
with pytest.raises(RpcError) as exc_info:
|
|
762
763
|
commit_files(
|
|
763
764
|
branch_name=gl_branch,
|
|
@@ -793,6 +794,21 @@ def test_user_commit_files(operations_fixture, tmpdir):
|
|
|
793
794
|
)
|
|
794
795
|
assert exc_info.value.code() == StatusCode.INVALID_ARGUMENT
|
|
795
796
|
|
|
797
|
+
# leading slash is interpreted as meaning the root of checkout
|
|
798
|
+
resp = commit_files(
|
|
799
|
+
branch_name=gl_branch,
|
|
800
|
+
commit_message=b'Deleted intopic',
|
|
801
|
+
actions=(dict(action=ActionType.CREATE,
|
|
802
|
+
file_path=b'/etc/shadow',
|
|
803
|
+
content=b"This is in repo!",
|
|
804
|
+
),
|
|
805
|
+
)
|
|
806
|
+
)
|
|
807
|
+
hex11 = resp.branch_update.commit_id.encode()
|
|
808
|
+
wrapper.reload()
|
|
809
|
+
clone_pull_update(hex11)
|
|
810
|
+
assert (clone.path / 'etc/shadow').read_binary() == b"This is in repo!"
|
|
811
|
+
|
|
796
812
|
# bogus request flows
|
|
797
813
|
header_req = fixture.user_commit_files_header(
|
|
798
814
|
branch_name=gl_other_branch,
|
|
@@ -817,3 +833,49 @@ def test_user_commit_files(operations_fixture, tmpdir):
|
|
|
817
833
|
UserCommitFilesRequest(action=UserCommitFilesAction())
|
|
818
834
|
])
|
|
819
835
|
assert exc_info.value.code() == StatusCode.INVALID_ARGUMENT
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def test_user_commit_files_null_old_oid(operations_fixture, tmpdir):
|
|
839
|
+
fixture = operations_fixture
|
|
840
|
+
commit_files = fixture.user_commit_files
|
|
841
|
+
ActionType = UserCommitFilesActionHeader.ActionType
|
|
842
|
+
|
|
843
|
+
fixture.hg_native = True # TODO just remove hg-git now
|
|
844
|
+
fixture.heptapod_permission = 'publish'
|
|
845
|
+
wrapper = fixture.repo_wrapper
|
|
846
|
+
with open(wrapper.path / '.hg/hgrc', 'a') as hgrcf:
|
|
847
|
+
# this is part of the normally included `required.hgrc` of
|
|
848
|
+
# py-heptapod
|
|
849
|
+
hgrcf.write('\n'.join((
|
|
850
|
+
"[experimental]",
|
|
851
|
+
"topic.publish-bare-branch = yes"
|
|
852
|
+
""
|
|
853
|
+
)))
|
|
854
|
+
|
|
855
|
+
gl_topic = b'topic/default/zetop'
|
|
856
|
+
gl_branch = b'branch/default'
|
|
857
|
+
|
|
858
|
+
wrapper.commit_file('foo') # first commit on `branch/default`
|
|
859
|
+
|
|
860
|
+
# now let's start a topic, passing explicitely old_oid indicating
|
|
861
|
+
# that is does not exist yet
|
|
862
|
+
two_lines = b"zz\nsecond proto message"
|
|
863
|
+
resp = commit_files(
|
|
864
|
+
branch_name=gl_topic,
|
|
865
|
+
start_branch_name=gl_branch,
|
|
866
|
+
commit_message=b'New topic',
|
|
867
|
+
expected_old_oid=ZERO_SHA_STR,
|
|
868
|
+
actions=(dict(action=ActionType.CREATE,
|
|
869
|
+
file_path=b'intop',
|
|
870
|
+
content=two_lines,
|
|
871
|
+
),
|
|
872
|
+
)
|
|
873
|
+
)
|
|
874
|
+
hex1 = resp.branch_update.commit_id.encode()
|
|
875
|
+
|
|
876
|
+
wrapper.reload()
|
|
877
|
+
ctx1 = wrapper.repo[hex1]
|
|
878
|
+
|
|
879
|
+
assert ctx1.description() == b'New topic'
|
|
880
|
+
assert ctx1.branch() == b'default'
|
|
881
|
+
assert ctx1.topic() == b'zetop'
|
|
@@ -382,7 +382,7 @@ def test_compare_commit_files(comparison):
|
|
|
382
382
|
branch_name=b'branch/default',
|
|
383
383
|
tail_requests=ucf_actions(dict(
|
|
384
384
|
action=ActionType.CREATE,
|
|
385
|
-
file_path=b'foo',
|
|
385
|
+
file_path=b'/foo',
|
|
386
386
|
content=b'foo content')),
|
|
387
387
|
)
|
|
388
388
|
|
|
@@ -498,8 +498,7 @@ def test_compare_commit_files(comparison):
|
|
|
498
498
|
))
|
|
499
499
|
)
|
|
500
500
|
|
|
501
|
-
# invalid path
|
|
502
|
-
# seems to ignore them, thankfully)
|
|
501
|
+
# invalid path
|
|
503
502
|
for path in ('double//slash', '../../../good.joke'):
|
|
504
503
|
for action in ('CREATE', 'CREATE_DIR', 'CHMOD',
|
|
505
504
|
'UPDATE', 'DELETE', 'MOVE'):
|
hgitaly-18.2.2/hgitaly/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
18.2.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|