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.
Files changed (170) hide show
  1. {hgitaly-18.2.2/hgitaly.egg-info → hgitaly-18.2.4}/PKG-INFO +1 -1
  2. hgitaly-18.2.4/hgitaly/VERSION +1 -0
  3. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/operations.py +43 -41
  4. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_operations.py +63 -1
  5. {hgitaly-18.2.2 → hgitaly-18.2.4/hgitaly.egg-info}/PKG-INFO +1 -1
  6. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_operations.py +2 -3
  7. hgitaly-18.2.2/hgitaly/VERSION +0 -1
  8. {hgitaly-18.2.2 → hgitaly-18.2.4}/LICENSE +0 -0
  9. {hgitaly-18.2.2 → hgitaly-18.2.4}/MANIFEST.in +0 -0
  10. {hgitaly-18.2.2 → hgitaly-18.2.4}/README.md +0 -0
  11. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/__init__.py +0 -0
  12. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/__init__.py +0 -0
  13. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/revset.py +0 -0
  14. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/tests/__init__.py +0 -0
  15. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/tests/test_revset.py +0 -0
  16. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgext3rd/hgitaly/tests/test_serve.py +0 -0
  17. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/__init__.py +0 -0
  18. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/branch.py +0 -0
  19. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/changelog.py +0 -0
  20. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/diff.py +0 -0
  21. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/errors.py +0 -0
  22. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/feature.py +0 -0
  23. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/file_content.py +0 -0
  24. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/file_context.py +0 -0
  25. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/git.py +0 -0
  26. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/gitlab_ref.py +0 -0
  27. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/identification.py +0 -0
  28. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/logging.py +0 -0
  29. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/manifest.py +0 -0
  30. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/message.py +0 -0
  31. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/oid.py +0 -0
  32. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/pagination.py +0 -0
  33. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/path.py +0 -0
  34. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/peer.py +0 -0
  35. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/procutil.py +0 -0
  36. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/repository.py +0 -0
  37. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/revision.py +0 -0
  38. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/revset.py +0 -0
  39. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/scripts.py +0 -0
  40. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/__init__.py +0 -0
  41. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/address.py +0 -0
  42. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/mono.py +0 -0
  43. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/prefork.py +0 -0
  44. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/__init__.py +0 -0
  45. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_address.py +0 -0
  46. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_mono.py +0 -0
  47. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_prefork.py +0 -0
  48. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/tests/test_worker.py +0 -0
  49. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/server/worker.py +0 -0
  50. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/__init__.py +0 -0
  51. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/analysis.py +0 -0
  52. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/blob.py +0 -0
  53. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/commit.py +0 -0
  54. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/diff.py +0 -0
  55. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/interceptors.py +0 -0
  56. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/mercurial_changeset.py +0 -0
  57. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/mercurial_operations.py +0 -0
  58. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/mercurial_repository.py +0 -0
  59. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/ref.py +0 -0
  60. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/repository.py +0 -0
  61. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/server.py +0 -0
  62. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/__init__.py +0 -0
  63. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/fixture.py +0 -0
  64. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_analysis.py +0 -0
  65. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_blob.py +0 -0
  66. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_commit.py +0 -0
  67. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_default_branch.py +0 -0
  68. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_diff.py +0 -0
  69. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_mercurial_changeset.py +0 -0
  70. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_mercurial_operations.py +0 -0
  71. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_mercurial_repository.py +0 -0
  72. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_ref.py +0 -0
  73. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_repository_service.py +0 -0
  74. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/service/tests/test_server.py +0 -0
  75. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/servicer.py +0 -0
  76. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/ssh.py +0 -0
  77. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stream.py +0 -0
  78. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/__init__.py +0 -0
  79. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/analysis_pb2.py +0 -0
  80. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/analysis_pb2_grpc.py +0 -0
  81. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/blob_pb2.py +0 -0
  82. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/blob_pb2_grpc.py +0 -0
  83. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/commit_pb2.py +0 -0
  84. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/commit_pb2_grpc.py +0 -0
  85. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/diff_pb2.py +0 -0
  86. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/diff_pb2_grpc.py +0 -0
  87. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/errors_pb2.py +0 -0
  88. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/errors_pb2_grpc.py +0 -0
  89. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/lint_pb2.py +0 -0
  90. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/lint_pb2_grpc.py +0 -0
  91. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_aux_git_pb2.py +0 -0
  92. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_aux_git_pb2_grpc.py +0 -0
  93. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_changeset_pb2.py +0 -0
  94. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_changeset_pb2_grpc.py +0 -0
  95. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_operations_pb2.py +0 -0
  96. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_operations_pb2_grpc.py +0 -0
  97. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_repository_pb2.py +0 -0
  98. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/mercurial_repository_pb2_grpc.py +0 -0
  99. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/operations_pb2.py +0 -0
  100. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/operations_pb2_grpc.py +0 -0
  101. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/ref_pb2.py +0 -0
  102. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/ref_pb2_grpc.py +0 -0
  103. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/remote_pb2.py +0 -0
  104. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/remote_pb2_grpc.py +0 -0
  105. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/repository_pb2.py +0 -0
  106. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/repository_pb2_grpc.py +0 -0
  107. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/server_pb2.py +0 -0
  108. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/server_pb2_grpc.py +0 -0
  109. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/shared_pb2.py +0 -0
  110. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/stub/shared_pb2_grpc.py +0 -0
  111. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tag.py +0 -0
  112. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/__init__.py +0 -0
  113. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/bundle.py +0 -0
  114. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/context.py +0 -0
  115. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/grpc.py +0 -0
  116. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/multiprocessing.py +0 -0
  117. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/ssh.py +0 -0
  118. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/sshd.py +0 -0
  119. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/storage.py +0 -0
  120. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/tests/__init__.py +0 -0
  121. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/testing/tests/test_sshd.py +0 -0
  122. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/__init__.py +0 -0
  123. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/common.py +0 -0
  124. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_branch.py +0 -0
  125. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_diff.py +0 -0
  126. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_errors.py +0 -0
  127. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_feature.py +0 -0
  128. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_file_context.py +0 -0
  129. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_gitlab_ref.py +0 -0
  130. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_identification.py +0 -0
  131. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_manifest.py +0 -0
  132. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_messages.py +0 -0
  133. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_oid.py +0 -0
  134. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_peer.py +0 -0
  135. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_repository.py +0 -0
  136. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_revision.py +0 -0
  137. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_revset.py +0 -0
  138. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_servicer.py +0 -0
  139. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_stream.py +0 -0
  140. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_tag.py +0 -0
  141. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/tests/test_workdir.py +0 -0
  142. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/util.py +0 -0
  143. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly/workdir.py +0 -0
  144. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/SOURCES.txt +0 -0
  145. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/dependency_links.txt +0 -0
  146. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/entry_points.txt +0 -0
  147. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/requires.txt +0 -0
  148. {hgitaly-18.2.2 → hgitaly-18.2.4}/hgitaly.egg-info/top_level.txt +0 -0
  149. {hgitaly-18.2.2 → hgitaly-18.2.4}/install-requirements.txt +0 -0
  150. {hgitaly-18.2.2 → hgitaly-18.2.4}/setup.cfg +0 -0
  151. {hgitaly-18.2.2 → hgitaly-18.2.4}/setup.py +0 -0
  152. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/__init__.py +0 -0
  153. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/comparison.py +0 -0
  154. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/conftest.py +0 -0
  155. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/gitaly.py +0 -0
  156. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +0 -0
  157. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/rhgitaly.py +0 -0
  158. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_blob_tree.py +0 -0
  159. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_commit.py +0 -0
  160. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_comparison.py +0 -0
  161. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_diff.py +0 -0
  162. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_gitaly_server.py +0 -0
  163. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_mercurial_aux_git.py +0 -0
  164. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_mercurial_operations.py +0 -0
  165. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_mercurial_repository.py +0 -0
  166. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_ref.py +0 -0
  167. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_remote.py +0 -0
  168. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_repository_service.py +0 -0
  169. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_rhgitaly_server.py +0 -0
  170. {hgitaly-18.2.2 → hgitaly-18.2.4}/tests_with_gitaly/test_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hgitaly
3
- Version: 18.2.2
3
+ Version: 18.2.4
4
4
  Summary: Server-side implementation of Gitaly protocol for Mercurial
5
5
  Home-page: https://foss.heptapod.net/heptapod/hgitaly
6
6
  Author: Georges Racinet
@@ -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 and start_ctx.hex() != old_oid:
365
- context.abort(StatusCode.INVALID_ARGUMENT,
366
- "wrong old oid")
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(wd, header)
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
- relpath = self.relpath = header.file_path
489
- self.validate(relpath)
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.header.previous_path
604
- self.validate(prev_relpath)
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
- self.file_path = workdir.file_path(header.file_path)
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', '/etc/shadow'):
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'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hgitaly
3
- Version: 18.2.2
3
+ Version: 18.2.4
4
4
  Summary: Server-side implementation of Gitaly protocol for Mercurial
5
5
  Home-page: https://foss.heptapod.net/heptapod/hgitaly
6
6
  Author: Georges Racinet
@@ -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 (Gitaly does not reject absolute paths and actually
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'):
@@ -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