hgitaly 18.4.0a0__tar.gz → 18.4.1__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 (309) hide show
  1. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/PKG-INFO +2 -2
  2. hgitaly-18.4.1/hgitaly/VERSION +1 -0
  3. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/message.py +5 -0
  4. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/mercurial_operations.py +156 -7
  5. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/operations.py +2 -2
  6. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/repository.py +6 -3
  7. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/fixture.py +23 -2
  8. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_mercurial_operations.py +132 -0
  9. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_repository_service.py +4 -3
  10. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/servicer.py +3 -1
  11. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_operations_pb2.py +29 -19
  12. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_operations_pb2_grpc.py +45 -1
  13. hgitaly-18.4.1/hgitaly/testing/repo.py +26 -0
  14. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/storage.py +17 -1
  15. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/common.py +1 -0
  16. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly.egg-info/PKG-INFO +2 -2
  17. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly.egg-info/SOURCES.txt +1 -138
  18. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly.egg-info/requires.txt +1 -1
  19. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/install-requirements.txt +1 -1
  20. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_mercurial_aux_git.py +3 -3
  21. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_repository_service.py +62 -9
  22. hgitaly-18.4.0a0/.coveragerc +0 -5
  23. hgitaly-18.4.0a0/.gitlab-ci.yml +0 -154
  24. hgitaly-18.4.0a0/.hgignore +0 -36
  25. hgitaly-18.4.0a0/.hgtags +0 -168
  26. hgitaly-18.4.0a0/ci/heptapod-sftp-push +0 -31
  27. hgitaly-18.4.0a0/ci/heptapod-sign-package +0 -34
  28. hgitaly-18.4.0a0/ci/heptapod_known_hosts.ssh +0 -4
  29. hgitaly-18.4.0a0/ci/upload-rhgitaly +0 -43
  30. hgitaly-18.4.0a0/conftest.py +0 -100
  31. hgitaly-18.4.0a0/dev-requirements.txt +0 -2
  32. hgitaly-18.4.0a0/examples/client.py +0 -48
  33. hgitaly-18.4.0a0/examples/client_list_lcft.py +0 -55
  34. hgitaly-18.4.0a0/generate-stubs +0 -34
  35. hgitaly-18.4.0a0/hgitaly/VERSION +0 -1
  36. hgitaly-18.4.0a0/hgitaly/testing/data/authorized_keys +0 -1
  37. hgitaly-18.4.0a0/hgitaly/testing/data/backup_additional_no_git.tar +0 -0
  38. hgitaly-18.4.0a0/hgitaly/testing/data/id_ecdsa_user +0 -38
  39. hgitaly-18.4.0a0/hgitaly/testing/data/known_hosts +0 -2
  40. hgitaly-18.4.0a0/hgitaly/testing/data/ssh_host_ecdsa_key +0 -9
  41. hgitaly-18.4.0a0/hgitaly/testing/data/ssh_host_ecdsa_key.pub +0 -1
  42. hgitaly-18.4.0a0/hgitaly/testing/data/ssh_host_ed25519 +0 -8
  43. hgitaly-18.4.0a0/hgitaly/testing/data/ssh_host_ed25519.pub +0 -1
  44. hgitaly-18.4.0a0/hgitaly/testing/data/sshd_config +0 -17
  45. hgitaly-18.4.0a0/lint +0 -7
  46. hgitaly-18.4.0a0/protos/analysis.proto +0 -62
  47. hgitaly-18.4.0a0/protos/blob.proto +0 -299
  48. hgitaly-18.4.0a0/protos/cleanup.proto +0 -88
  49. hgitaly-18.4.0a0/protos/cluster.proto +0 -134
  50. hgitaly-18.4.0a0/protos/commit.proto +0 -996
  51. hgitaly-18.4.0a0/protos/conflicts.proto +0 -137
  52. hgitaly-18.4.0a0/protos/diff.proto +0 -644
  53. hgitaly-18.4.0a0/protos/errors.proto +0 -234
  54. hgitaly-18.4.0a0/protos/hook.proto +0 -205
  55. hgitaly-18.4.0a0/protos/internal.proto +0 -37
  56. hgitaly-18.4.0a0/protos/lint.proto +0 -75
  57. hgitaly-18.4.0a0/protos/log.proto +0 -137
  58. hgitaly-18.4.0a0/protos/mercurial-aux-git.proto +0 -32
  59. hgitaly-18.4.0a0/protos/mercurial-changeset.proto +0 -96
  60. hgitaly-18.4.0a0/protos/mercurial-operations.proto +0 -230
  61. hgitaly-18.4.0a0/protos/mercurial-repository.proto +0 -364
  62. hgitaly-18.4.0a0/protos/namespace.proto +0 -98
  63. hgitaly-18.4.0a0/protos/objectpool.proto +0 -173
  64. hgitaly-18.4.0a0/protos/operations.proto +0 -1161
  65. hgitaly-18.4.0a0/protos/packfile.proto +0 -26
  66. hgitaly-18.4.0a0/protos/partition.proto +0 -70
  67. hgitaly-18.4.0a0/protos/praefect.proto +0 -222
  68. hgitaly-18.4.0a0/protos/ref.proto +0 -600
  69. hgitaly-18.4.0a0/protos/remote.proto +0 -153
  70. hgitaly-18.4.0a0/protos/repository.proto +0 -1458
  71. hgitaly-18.4.0a0/protos/server.proto +0 -123
  72. hgitaly-18.4.0a0/protos/service_config.proto +0 -86
  73. hgitaly-18.4.0a0/protos/shared.proto +0 -248
  74. hgitaly-18.4.0a0/protos/smarthttp.proto +0 -121
  75. hgitaly-18.4.0a0/protos/ssh.proto +0 -109
  76. hgitaly-18.4.0a0/protos/transaction.proto +0 -104
  77. hgitaly-18.4.0a0/protos/wiki.proto +0 -211
  78. hgitaly-18.4.0a0/ruby/.ruby-version +0 -1
  79. hgitaly-18.4.0a0/ruby/Gemfile +0 -5
  80. hgitaly-18.4.0a0/ruby/README.md +0 -48
  81. hgitaly-18.4.0a0/ruby/generate-grpc-lib +0 -63
  82. hgitaly-18.4.0a0/ruby/hgitaly.gemspec +0 -25
  83. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-aux-git_pb.rb +0 -14
  84. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-aux-git_services_pb.rb +0 -29
  85. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-changeset_pb.rb +0 -69
  86. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-changeset_services_pb.rb +0 -25
  87. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-operations_pb.rb +0 -133
  88. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-operations_services_pb.rb +0 -53
  89. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-repository_pb.rb +0 -163
  90. hgitaly-18.4.0a0/ruby/lib/hgitaly/mercurial-repository_services_pb.rb +0 -79
  91. hgitaly-18.4.0a0/ruby/lib/hgitaly/version.rb +0 -4
  92. hgitaly-18.4.0a0/ruby/lib/hgitaly.rb +0 -13
  93. hgitaly-18.4.0a0/ruby/run.rb +0 -39
  94. hgitaly-18.4.0a0/run-all-tests +0 -24
  95. hgitaly-18.4.0a0/rust/Cargo.lock +0 -3898
  96. hgitaly-18.4.0a0/rust/Cargo.toml +0 -4
  97. hgitaly-18.4.0a0/rust/Makefile +0 -77
  98. hgitaly-18.4.0a0/rust/build-from-tarball.sh +0 -30
  99. hgitaly-18.4.0a0/rust/check-line-width +0 -48
  100. hgitaly-18.4.0a0/rust/dependencies/README.md +0 -19
  101. hgitaly-18.4.0a0/rust/dependencies/mercurial.patch +0 -51
  102. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/any.proto +0 -158
  103. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/api.proto +0 -208
  104. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/compiler/plugin.proto +0 -183
  105. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/descriptor.proto +0 -911
  106. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/duration.proto +0 -116
  107. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/empty.proto +0 -52
  108. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/field_mask.proto +0 -245
  109. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/source_context.proto +0 -48
  110. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/struct.proto +0 -95
  111. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/timestamp.proto +0 -147
  112. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/type.proto +0 -187
  113. hgitaly-18.4.0a0/rust/dependencies/proto/google/protobuf/wrappers.proto +0 -123
  114. hgitaly-18.4.0a0/rust/go-enry.rev +0 -1
  115. hgitaly-18.4.0a0/rust/lint +0 -14
  116. hgitaly-18.4.0a0/rust/mercurial.rev +0 -1
  117. hgitaly-18.4.0a0/rust/rhgitaly/Cargo.toml +0 -56
  118. hgitaly-18.4.0a0/rust/rhgitaly/build.rs +0 -92
  119. hgitaly-18.4.0a0/rust/rhgitaly/clippy.toml +0 -6
  120. hgitaly-18.4.0a0/rust/rhgitaly/src/bundle.rs +0 -282
  121. hgitaly-18.4.0a0/rust/rhgitaly/src/config.rs +0 -172
  122. hgitaly-18.4.0a0/rust/rhgitaly/src/errors.rs +0 -141
  123. hgitaly-18.4.0a0/rust/rhgitaly/src/generated/README.md +0 -7
  124. hgitaly-18.4.0a0/rust/rhgitaly/src/git.rs +0 -293
  125. hgitaly-18.4.0a0/rust/rhgitaly/src/gitlab/mod.rs +0 -50
  126. hgitaly-18.4.0a0/rust/rhgitaly/src/gitlab/reference.rs +0 -83
  127. hgitaly-18.4.0a0/rust/rhgitaly/src/gitlab/revision.rs +0 -320
  128. hgitaly-18.4.0a0/rust/rhgitaly/src/gitlab/state.rs +0 -508
  129. hgitaly-18.4.0a0/rust/rhgitaly/src/glob.rs +0 -233
  130. hgitaly-18.4.0a0/rust/rhgitaly/src/lib.rs +0 -45
  131. hgitaly-18.4.0a0/rust/rhgitaly/src/main.rs +0 -147
  132. hgitaly-18.4.0a0/rust/rhgitaly/src/mercurial.rs +0 -1389
  133. hgitaly-18.4.0a0/rust/rhgitaly/src/message.rs +0 -468
  134. hgitaly-18.4.0a0/rust/rhgitaly/src/metadata.rs +0 -61
  135. hgitaly-18.4.0a0/rust/rhgitaly/src/oid.rs +0 -86
  136. hgitaly-18.4.0a0/rust/rhgitaly/src/process.rs +0 -39
  137. hgitaly-18.4.0a0/rust/rhgitaly/src/repository/spawner.rs +0 -576
  138. hgitaly-18.4.0a0/rust/rhgitaly/src/repository.rs +0 -605
  139. hgitaly-18.4.0a0/rust/rhgitaly/src/service/analysis.rs +0 -183
  140. hgitaly-18.4.0a0/rust/rhgitaly/src/service/blob.rs +0 -260
  141. hgitaly-18.4.0a0/rust/rhgitaly/src/service/commit/find_commits.rs +0 -206
  142. hgitaly-18.4.0a0/rust/rhgitaly/src/service/commit/get_tree_entries.rs +0 -291
  143. hgitaly-18.4.0a0/rust/rhgitaly/src/service/commit/last_commits.rs +0 -569
  144. hgitaly-18.4.0a0/rust/rhgitaly/src/service/commit/tree_entry.rs +0 -154
  145. hgitaly-18.4.0a0/rust/rhgitaly/src/service/commit.rs +0 -654
  146. hgitaly-18.4.0a0/rust/rhgitaly/src/service/diff.rs +0 -137
  147. hgitaly-18.4.0a0/rust/rhgitaly/src/service/mercurial_aux_git.rs +0 -180
  148. hgitaly-18.4.0a0/rust/rhgitaly/src/service/mercurial_repository.rs +0 -496
  149. hgitaly-18.4.0a0/rust/rhgitaly/src/service/mod.rs +0 -19
  150. hgitaly-18.4.0a0/rust/rhgitaly/src/service/ref.rs +0 -515
  151. hgitaly-18.4.0a0/rust/rhgitaly/src/service/remote.rs +0 -793
  152. hgitaly-18.4.0a0/rust/rhgitaly/src/service/repository.rs +0 -983
  153. hgitaly-18.4.0a0/rust/rhgitaly/src/service/server.rs +0 -60
  154. hgitaly-18.4.0a0/rust/rhgitaly/src/sidecar.rs +0 -234
  155. hgitaly-18.4.0a0/rust/rhgitaly/src/ssh.rs +0 -102
  156. hgitaly-18.4.0a0/rust/rhgitaly/src/streaming.rs +0 -402
  157. hgitaly-18.4.0a0/rust/rhgitaly/src/util.rs +0 -132
  158. hgitaly-18.4.0a0/rust/rs-enry.rev +0 -1
  159. hgitaly-18.4.0a0/rust/src-tarball.sh +0 -70
  160. hgitaly-18.4.0a0/test-requirements.txt +0 -8
  161. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/LICENSE +0 -0
  162. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/MANIFEST.in +0 -0
  163. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/README.md +0 -0
  164. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgext3rd/__init__.py +0 -0
  165. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgext3rd/hgitaly/__init__.py +0 -0
  166. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgext3rd/hgitaly/revset.py +0 -0
  167. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgext3rd/hgitaly/tests/__init__.py +0 -0
  168. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgext3rd/hgitaly/tests/test_revset.py +0 -0
  169. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgext3rd/hgitaly/tests/test_serve.py +0 -0
  170. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/__init__.py +0 -0
  171. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/branch.py +0 -0
  172. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/changelog.py +0 -0
  173. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/diff.py +0 -0
  174. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/errors.py +0 -0
  175. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/feature.py +0 -0
  176. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/file_content.py +0 -0
  177. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/file_context.py +0 -0
  178. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/git.py +0 -0
  179. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/gitlab_ref.py +0 -0
  180. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/identification.py +0 -0
  181. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/logging.py +0 -0
  182. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/manifest.py +0 -0
  183. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/oid.py +0 -0
  184. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/pagination.py +0 -0
  185. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/path.py +0 -0
  186. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/peer.py +0 -0
  187. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/procutil.py +0 -0
  188. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/repository.py +0 -0
  189. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/revision.py +0 -0
  190. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/revset.py +0 -0
  191. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/scripts.py +0 -0
  192. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/__init__.py +0 -0
  193. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/address.py +0 -0
  194. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/mono.py +0 -0
  195. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/prefork.py +0 -0
  196. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/tests/__init__.py +0 -0
  197. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/tests/test_address.py +0 -0
  198. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/tests/test_mono.py +0 -0
  199. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/tests/test_prefork.py +0 -0
  200. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/tests/test_worker.py +0 -0
  201. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/server/worker.py +0 -0
  202. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/__init__.py +0 -0
  203. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/analysis.py +0 -0
  204. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/blob.py +0 -0
  205. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/commit.py +0 -0
  206. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/diff.py +0 -0
  207. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/interceptors.py +0 -0
  208. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/mercurial_changeset.py +0 -0
  209. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/mercurial_repository.py +0 -0
  210. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/ref.py +0 -0
  211. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/server.py +0 -0
  212. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/__init__.py +0 -0
  213. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_analysis.py +0 -0
  214. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_blob.py +0 -0
  215. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_commit.py +0 -0
  216. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_default_branch.py +0 -0
  217. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_diff.py +0 -0
  218. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_mercurial_changeset.py +0 -0
  219. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_mercurial_repository.py +0 -0
  220. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_operations.py +0 -0
  221. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_ref.py +0 -0
  222. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/service/tests/test_server.py +0 -0
  223. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/ssh.py +0 -0
  224. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stream.py +0 -0
  225. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/__init__.py +0 -0
  226. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/analysis_pb2.py +0 -0
  227. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/analysis_pb2_grpc.py +0 -0
  228. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/blob_pb2.py +0 -0
  229. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/blob_pb2_grpc.py +0 -0
  230. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/commit_pb2.py +0 -0
  231. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/commit_pb2_grpc.py +0 -0
  232. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/diff_pb2.py +0 -0
  233. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/diff_pb2_grpc.py +0 -0
  234. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/errors_pb2.py +0 -0
  235. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/errors_pb2_grpc.py +0 -0
  236. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/lint_pb2.py +0 -0
  237. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/lint_pb2_grpc.py +0 -0
  238. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_aux_git_pb2.py +0 -0
  239. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_aux_git_pb2_grpc.py +0 -0
  240. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_changeset_pb2.py +0 -0
  241. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_changeset_pb2_grpc.py +0 -0
  242. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_repository_pb2.py +0 -0
  243. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/mercurial_repository_pb2_grpc.py +0 -0
  244. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/operations_pb2.py +0 -0
  245. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/operations_pb2_grpc.py +0 -0
  246. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/ref_pb2.py +0 -0
  247. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/ref_pb2_grpc.py +0 -0
  248. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/remote_pb2.py +0 -0
  249. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/remote_pb2_grpc.py +0 -0
  250. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/repository_pb2.py +0 -0
  251. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/repository_pb2_grpc.py +0 -0
  252. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/server_pb2.py +0 -0
  253. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/server_pb2_grpc.py +0 -0
  254. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/shared_pb2.py +0 -0
  255. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/stub/shared_pb2_grpc.py +0 -0
  256. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tag.py +0 -0
  257. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/__init__.py +0 -0
  258. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/bundle.py +0 -0
  259. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/context.py +0 -0
  260. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/grpc.py +0 -0
  261. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/multiprocessing.py +0 -0
  262. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/ssh.py +0 -0
  263. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/sshd.py +0 -0
  264. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/tests/__init__.py +0 -0
  265. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/testing/tests/test_sshd.py +0 -0
  266. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/__init__.py +0 -0
  267. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_branch.py +0 -0
  268. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_diff.py +0 -0
  269. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_errors.py +0 -0
  270. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_feature.py +0 -0
  271. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_file_context.py +0 -0
  272. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_gitlab_ref.py +0 -0
  273. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_identification.py +0 -0
  274. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_manifest.py +0 -0
  275. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_messages.py +0 -0
  276. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_oid.py +0 -0
  277. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_peer.py +0 -0
  278. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_repository.py +0 -0
  279. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_revision.py +0 -0
  280. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_revset.py +0 -0
  281. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_servicer.py +0 -0
  282. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_stream.py +0 -0
  283. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_tag.py +0 -0
  284. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/tests/test_workdir.py +0 -0
  285. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/util.py +0 -0
  286. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly/workdir.py +0 -0
  287. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly.egg-info/dependency_links.txt +0 -0
  288. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly.egg-info/entry_points.txt +0 -0
  289. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/hgitaly.egg-info/top_level.txt +0 -0
  290. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/setup.cfg +0 -0
  291. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/setup.py +0 -0
  292. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/__init__.py +0 -0
  293. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/comparison.py +0 -0
  294. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/conftest.py +0 -0
  295. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/gitaly.py +0 -0
  296. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +0 -0
  297. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/rhgitaly.py +0 -0
  298. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_blob_tree.py +0 -0
  299. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_commit.py +0 -0
  300. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_comparison.py +0 -0
  301. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_diff.py +0 -0
  302. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_gitaly_server.py +0 -0
  303. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_mercurial_operations.py +0 -0
  304. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_mercurial_repository.py +0 -0
  305. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_operations.py +0 -0
  306. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_ref.py +0 -0
  307. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_remote.py +0 -0
  308. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/tests_with_gitaly/test_rhgitaly_server.py +0 -0
  309. {hgitaly-18.4.0a0 → hgitaly-18.4.1}/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.4.0a0
3
+ Version: 18.4.1
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
@@ -10,7 +10,7 @@ Keywords: hg mercurial heptapod gitlab
10
10
  Requires-Python: >=3.8
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: heptapod>=5.2.0dev0
13
+ Requires-Dist: heptapod>=5.4.0
14
14
  Requires-Dist: protobuf~=6.31.1
15
15
  Requires-Dist: grpcio~=1.74.0
16
16
  Requires-Dist: grpcio-status~=1.74.0
@@ -0,0 +1 @@
1
+ 18.4.1
@@ -19,6 +19,7 @@ from .stub.shared_pb2 import (
19
19
  GitCommit,
20
20
  SignatureType,
21
21
  Tag,
22
+ User,
22
23
  )
23
24
  from .stub.commit_pb2 import (
24
25
  ListLastCommitsForTreeResponse,
@@ -138,6 +139,10 @@ def commit_author(ctx):
138
139
  )
139
140
 
140
141
 
142
+ def user_for_hg(user: User) -> bytes:
143
+ return b'%s <%s>' % (user.name, user.email)
144
+
145
+
141
146
  def commit_stats(ctx):
142
147
  if len(ctx.parents()) > 1:
143
148
  # Gitaly does not provide the stats for merge commits
@@ -15,11 +15,25 @@ from mercurial.node import nullhex as NULL_NODE_HEX
15
15
  from mercurial.phases import (
16
16
  public as PUBLIC,
17
17
  )
18
- from mercurial import util as hgutil
18
+ from mercurial import (
19
+ cmdutil,
20
+ commands,
21
+ error as hgerror,
22
+ util as hgutil,
23
+ )
24
+ from hgext.rebase import (
25
+ rebaseruntime,
26
+ sortsource as rebase_sort_source
27
+ )
19
28
 
20
29
  from heptapod.gitlab.branch import (
21
- NAMED_BRANCH_PREFIX,
30
+ branch_is_named_branch,
22
31
  gitlab_branch_ref,
32
+ parse_gitlab_branch,
33
+ )
34
+ from hgext3rd.heptapod.branch import (
35
+ gitlab_branches,
36
+ invalidate_gitlab_branches,
23
37
  )
24
38
 
25
39
  from .. import message
@@ -48,6 +62,8 @@ from ..workdir import (
48
62
  from ..stub.errors_pb2 import (
49
63
  MergeConflictError,
50
64
  ReferenceUpdateError,
65
+ ReferenceStateMismatchError,
66
+ ResolveRevisionError,
51
67
  )
52
68
  from ..stub.mercurial_operations_pb2 import (
53
69
  CensorRequest,
@@ -62,6 +78,9 @@ from ..stub.mercurial_operations_pb2 import (
62
78
  PublishChangesetError,
63
79
  PublishChangesetRequest,
64
80
  PublishChangesetResponse,
81
+ RebaseError,
82
+ RebaseRequest,
83
+ RebaseResponse,
65
84
  ReleaseWorkingDirectoryRequest,
66
85
  ReleaseWorkingDirectoryResponse,
67
86
  GetWorkingDirectoryRequest,
@@ -266,7 +285,7 @@ class MercurialOperationsServicer(MercurialOperationsServiceServicer,
266
285
  target_branch = request.branch
267
286
  if not target_branch:
268
287
  context.abort(StatusCode.INVALID_ARGUMENT, "empty branch name")
269
- if not target_branch.startswith(NAMED_BRANCH_PREFIX):
288
+ if not branch_is_named_branch(target_branch):
270
289
  context.abort(StatusCode.FAILED_PRECONDITION,
271
290
  "Heptapod merges are currently targeting "
272
291
  "named branches only (no topics nor bookmarks)")
@@ -384,7 +403,7 @@ class MercurialOperationsServicer(MercurialOperationsServiceServicer,
384
403
  new_changeset = self.merge(working_dir=wd,
385
404
  source_changeset=to_merge,
386
405
  user=request.user,
387
- message=request.message,
406
+ commit_message=request.message,
388
407
  unix_timestamp=unix_ts,
389
408
  context=context)
390
409
  except ConflictError as exc:
@@ -411,7 +430,7 @@ class MercurialOperationsServicer(MercurialOperationsServiceServicer,
411
430
  ))
412
431
 
413
432
  def merge(self, working_dir, context, source_changeset,
414
- user: User, message, unix_timestamp):
433
+ user: User, commit_message, unix_timestamp):
415
434
  """Merge changeset with given revno in working repository.
416
435
 
417
436
  The working repositoy is assumed to be already updated in a
@@ -424,11 +443,141 @@ class MercurialOperationsServicer(MercurialOperationsServiceServicer,
424
443
  raise ConflictError(unresolved)
425
444
  # TODO user timezone (symbolic or UTC offset?)
426
445
  self.repo_command(working_repo, context, 'commit',
427
- user=b'%s <%s>' % (user.name, user.email),
446
+ user=message.user_for_hg(user),
428
447
  date=b'%d 0' % unix_timestamp,
429
- message=message)
448
+ message=commit_message)
430
449
  return working_repo[b'.']
431
450
 
451
+ def Rebase(self, request: RebaseRequest, context) -> RebaseResponse:
452
+ logger = LoggerAdapter(base_logger, context)
453
+
454
+ repo = self.load_repo(request.repository, context,
455
+ for_mutation_by=request.user)
456
+
457
+ source = request.source
458
+ if not source:
459
+ context.abort(StatusCode.INVALID_ARGUMENT,
460
+ "empty source branch name")
461
+ dest = request.destination
462
+ if not dest:
463
+ context.abort(StatusCode.INVALID_ARGUMENT,
464
+ "empty destination branch name")
465
+
466
+ branch, topic = parse_gitlab_branch(source)
467
+ if topic is None:
468
+ structured_abort(
469
+ context,
470
+ StatusCode.INVALID_ARGUMENT,
471
+ "Not a topic",
472
+ RebaseError(pre_check=PreCheckUpdateError.NOT_A_TOPIC)
473
+ )
474
+ # todo check sha if given
475
+
476
+ dest_cs = gitlab_revision_changeset(repo, dest)
477
+ if dest_cs is None:
478
+ structured_abort(
479
+ context,
480
+ StatusCode.FAILED_PRECONDITION,
481
+ "Failed to resolve destination",
482
+ RebaseError(resolve_rev=ResolveRevisionError(revision=dest))
483
+ )
484
+ source_cs = gitlab_revision_changeset(repo, source)
485
+ if source_cs is None:
486
+ structured_abort(
487
+ context,
488
+ StatusCode.FAILED_PRECONDITION,
489
+ "Failed to resolve source",
490
+ RebaseError(resolve_rev=ResolveRevisionError(revision=source))
491
+ )
492
+ expected_sha = request.source_head_sha.encode('utf-8')
493
+ actual_sha = source_cs.hex()
494
+ if expected_sha and expected_sha != actual_sha:
495
+ structured_abort(
496
+ context,
497
+ StatusCode.FAILED_PRECONDITION,
498
+ "Source head sha mismatch",
499
+ RebaseError(ref_mismatch=ReferenceStateMismatchError(
500
+ reference_name=source,
501
+ expected_object_id=expected_sha,
502
+ actual_object_id=actual_sha))
503
+ )
504
+
505
+ # branch and topic naming rules make sure that we need no escaping
506
+ # using the head sha for reassurance
507
+ revset = b"branch('%s//%s') and ::%s" % (
508
+ branch, topic, source_cs.hex()
509
+ )
510
+ username = message.user_for_hg(request.user)
511
+ logger.info("Performing rebase, revset=%r, destination=%r",
512
+ revset, dest_cs.hex())
513
+ with self.working_dir(gl_repo=request.repository,
514
+ repo=repo,
515
+ changeset=source_cs,
516
+ context=context) as wd:
517
+ did_rebase = wd_rebase(wd, username, revset, dest_cs, context)
518
+
519
+ if not did_rebase:
520
+ return RebaseResponse()
521
+
522
+ invalidate_gitlab_branches(repo)
523
+ # do not use gitlab_revisions_changeset, as building the
524
+ # changectx would fail (`repo[new_head]` would end up in LookupError)
525
+ # we'd need to reload the repo, which is quite useless because we
526
+ # are happy with just the new Node ID
527
+ new_head = gitlab_branches(repo)[source]
528
+ return RebaseResponse(
529
+ branch_update=OperationBranchUpdate(
530
+ commit_id=new_head.decode('ascii')))
531
+
532
+
533
+ def wd_rebase(working_dir, username, revset, dest_cs, context):
534
+ """Perform the rebase in the working directory, handling errors
535
+
536
+ :returns: ``True`` if rebase actually happened
537
+ """
538
+ repo = working_dir.repo
539
+
540
+ # TODO would be nice to experiment with in-memory rebase (wouldn't
541
+ # need a working dir) but not sure what the good use cases are.
542
+ # For instance, is a small rebase on a big repo much more efficient
543
+ # in memory or should that precisely be avoided?
544
+ overrides = {
545
+ (b'experimental', b'evolution.allowunstable'): False,
546
+ (b'rebase', b'singletransaction'): True,
547
+ }
548
+ # overriding ui.username does not work, this does:
549
+ repo.ui.environ[b'HGUSER'] = username
550
+ with repo.ui.configoverride(overrides, b'rebase'):
551
+ rebase = cmdutil.findcmd(b'rebase', commands.table)[1][0]
552
+ try:
553
+ retcode = rebase(repo.ui, repo, rev=[revset], dest=dest_cs.hex())
554
+ except hgerror.ConflictResolutionRequired:
555
+ conflicts = list(mergestate.read(repo).unresolved())
556
+ runtime = rebaseruntime(repo, repo.ui)
557
+ runtime.restorestatus()
558
+ # rebase_sort_source is the generator used by rebase to
559
+ # know what to do in order. Not sure why each yielded element
560
+ # is a list though (it's a singleton in simple tested cases)
561
+ failed_rev = next(rebase_sort_source(runtime.destmap))[0]
562
+ failed_sha = repo[failed_rev].hex().decode('ascii')
563
+ current_sha = repo[None].p1().hex().decode('ascii')
564
+
565
+ # next use of this workdir should be able to recover. Still it
566
+ # is best to do it right away
567
+ rebase(repo.ui, repo, abort=True)
568
+ working_dir.purge()
569
+
570
+ structured_abort(
571
+ context,
572
+ StatusCode.FAILED_PRECONDITION,
573
+ "Rebase conflict",
574
+ RebaseError(conflict=MergeConflictError(
575
+ conflicting_files=conflicts,
576
+ conflicting_commit_ids=[current_sha, failed_sha]
577
+ ))
578
+ )
579
+ return retcode is None or retcode == 0
580
+
432
581
 
433
582
  def wd_merge(working_dir, source_cs):
434
583
  """Merge source_cs in the given a working directory (repo share).
@@ -23,7 +23,7 @@ from heptapod import (
23
23
  )
24
24
 
25
25
  from heptapod.gitlab.branch import (
26
- NAMED_BRANCH_PREFIX,
26
+ branch_is_named_branch,
27
27
  parse_gitlab_branch,
28
28
  )
29
29
 
@@ -252,7 +252,7 @@ class OperationServicer(OperationServiceServicer, HGitalyServicer):
252
252
  if not request.branch:
253
253
  context.abort(StatusCode.INVALID_ARGUMENT, "empty branch name")
254
254
 
255
- if not request.branch.startswith(NAMED_BRANCH_PREFIX):
255
+ if not branch_is_named_branch(request.branch):
256
256
  context.abort(StatusCode.FAILED_PRECONDITION,
257
257
  "Heptapod fast forwards are currently "
258
258
  "for named branches only (no topics nor bookmarks)")
@@ -36,6 +36,7 @@ from hgext3rd.heptapod.branch import set_default_gitlab_branch
36
36
  from hgext3rd.heptapod.special_ref import write_gitlab_special_ref
37
37
  from hgext3rd.heptapod.keep_around import (
38
38
  create_keep_around,
39
+ delete_keep_around,
39
40
  parse_keep_around_ref,
40
41
  )
41
42
 
@@ -337,7 +338,9 @@ class RepositoryServicer(RepositoryServiceServicer, HGitalyServicer):
337
338
 
338
339
  keep_around = parse_keep_around_ref(ref)
339
340
  if keep_around is not None:
340
- if (CHANGESET_HASH_BYTES_REGEXP.match(keep_around) is None
341
+ if target == ZERO_SHA:
342
+ delete_keep_around(repo, keep_around)
343
+ elif (CHANGESET_HASH_BYTES_REGEXP.match(keep_around) is None
341
344
  or target != keep_around):
342
345
  context.abort(
343
346
  StatusCode.INVALID_ARGUMENT,
@@ -346,8 +349,8 @@ class RepositoryServicer(RepositoryServiceServicer, HGitalyServicer):
346
349
  "target must "
347
350
  "match the ref name" % (target, ref)
348
351
  )
349
-
350
- create_keep_around(repo, target)
352
+ else:
353
+ create_keep_around(repo, target)
351
354
  return WriteRefResponse()
352
355
  except Exception:
353
356
  # TODO this is a stop-gap measure to prevent repository breakage
@@ -17,6 +17,7 @@ from hgitaly.servicer import (
17
17
  SKIP_HOOKS_MD_KEY,
18
18
  )
19
19
  from hgitaly.stub.shared_pb2 import Repository
20
+ from hgitaly.workdir import wd_path
20
21
 
21
22
  from heptapod.testhelpers import (
22
23
  LocalRepoWrapper,
@@ -37,6 +38,9 @@ from hgitaly.stub.shared_pb2 import (
37
38
  User,
38
39
  )
39
40
  from hgitaly.testing.storage import (
41
+ repo_workdirs_root,
42
+ storage_path,
43
+ storage_workdirs,
40
44
  stowed_away_git_repo_path,
41
45
  )
42
46
 
@@ -143,12 +147,12 @@ class ServiceFixture:
143
147
  self.repos_to_cleanup.append(repo_path)
144
148
  return repo_path, repo_msg
145
149
 
146
- def storage_path(self, storage_name='default'):
150
+ def storage_path(self, **storage_kw):
147
151
  """Utility method to avoid depending too much on actual disk layout.
148
152
 
149
153
  This repeats the actual implementation just once.
150
154
  """
151
- return self.server_repos_root / storage_name
155
+ return storage_path(self.server_repos_root, **storage_kw)
152
156
 
153
157
  def repo_path(self, rel_path, **kw):
154
158
  """Utility method to avoid depending too much on actual disk layout.
@@ -172,6 +176,23 @@ class ServiceFixture:
172
176
  """
173
177
  return LocalRepoWrapper.load(self.repo_path(rel_path, **kw))
174
178
 
179
+ def storage_workdirs(self, **storage_kw):
180
+ return storage_workdirs(self.server_repos_root, **storage_kw)
181
+
182
+ def repo_workdirs_root(self, grpc_repo=None):
183
+ if grpc_repo is None:
184
+ grpc_repo = self.grpc_repo
185
+ return repo_workdirs_root(self.server_repos_root, grpc_repo)
186
+
187
+ def workdir_repo_wrapper(self, wd_id, grpc_repo=None):
188
+ """Direct low level access to a workdir repo.
189
+
190
+ This doesn't go through the normal initialization procedure, hence
191
+ is suitable to check state after error recovery.
192
+ """
193
+ return LocalRepoWrapper.load(
194
+ wd_path(self.repo_workdirs_root(grpc_repo=grpc_repo), wd_id))
195
+
175
196
  def rpc(self, method_name, request):
176
197
  """Call a method, taking care of metadata."""
177
198
  return getattr(self.stub, method_name)(
@@ -15,6 +15,8 @@ from mercurial import (
15
15
  error as hg_error,
16
16
  phases,
17
17
  )
18
+ from mercurial.mergestate import mergestate
19
+ from mercurial.node import nullid as NULL_NODE
18
20
  from mercurial_testhelpers import RepoWrapper
19
21
 
20
22
  from google.protobuf.timestamp_pb2 import Timestamp
@@ -38,6 +40,9 @@ from hgitaly.stub.mercurial_operations_pb2 import (
38
40
  CensorRequest,
39
41
  MergeBranchError,
40
42
  MergeBranchRequest,
43
+ RebaseError,
44
+ RebaseRequest,
45
+ RebaseResponse,
41
46
  MercurialPermissions,
42
47
  PreCheckUpdateError,
43
48
  PublishChangesetRequest,
@@ -50,6 +55,7 @@ from hgitaly.stub.mercurial_operations_pb2_grpc import (
50
55
  MercurialOperationsServiceStub,
51
56
  )
52
57
  from hgitaly.tests.common import make_empty_repo_with_gitlab_state_maintainer
58
+ from hgitaly.testing.repo import assert_empty_repo_status
53
59
  from .fixture import MutationServiceFixture
54
60
 
55
61
  parametrize = pytest.mark.parametrize
@@ -86,6 +92,12 @@ class OperationsFixture(MutationServiceFixture):
86
92
  return self.stub.MergeBranch(MergeBranchRequest(**kw),
87
93
  metadata=self.grpc_metadata())
88
94
 
95
+ def rebase(self, **kw):
96
+ kw.setdefault('repository', self.grpc_repo)
97
+ kw.setdefault('user', self.user)
98
+ return self.stub.Rebase(RebaseRequest(**kw),
99
+ metadata=self.grpc_metadata())
100
+
89
101
  def get_workdir(self, **kw):
90
102
  kw.setdefault('client_id', self.client_id)
91
103
  kw.setdefault('incarnation_id', INCARNATION_ID)
@@ -596,6 +608,126 @@ def test_merge_branch_troubled_changesets(operations_fixture):
596
608
  assert merge_error.pre_check == PreCheckUpdateError.UNSTABLE_CHANGESET
597
609
 
598
610
 
611
+ @parametrize('project_mode', ('hg-git-project', 'native-project'))
612
+ def test_rebase_basic(operations_fixture, project_mode):
613
+ fixture = operations_fixture
614
+ rebase = fixture.rebase
615
+
616
+ fixture.hg_native = project_mode != 'hg-git-project'
617
+ wrapper = fixture.repo_wrapper
618
+
619
+ gl_branch = b'branch/default'
620
+ gl_topic = b'topic/default/zetop'
621
+
622
+ # because of the config set by fixture, this leads in all cases to
623
+ # creation of a Git repo and its `branch/default` Git branch
624
+ ctx0 = wrapper.commit_file('foo')
625
+ sha0 = ctx0.hex().decode()
626
+ default_head = wrapper.commit_file('foo')
627
+ ctx2 = wrapper.commit_file('bar', topic='zetop', parent=ctx0)
628
+ sha2 = ctx2.hex().decode()
629
+ # avoid keeping the rebased changesets visible
630
+ wrapper.update_bin(NULL_NODE)
631
+
632
+ # simple error cases
633
+ with pytest.raises(RpcError) as exc_info:
634
+ rebase(source=gl_topic)
635
+ assert exc_info.value.code() == StatusCode.INVALID_ARGUMENT
636
+ with pytest.raises(RpcError) as exc_info:
637
+ rebase(destination=gl_branch)
638
+ assert exc_info.value.code() == StatusCode.INVALID_ARGUMENT
639
+
640
+ # not a topic
641
+ with pytest.raises(RpcError) as exc_info:
642
+ rebase(source=gl_branch, destination=gl_branch)
643
+ details, rebase_error = parse_assert_structured_error(
644
+ exc_info.value, RebaseError, StatusCode.INVALID_ARGUMENT)
645
+ assert rebase_error.pre_check == PreCheckUpdateError.NOT_A_TOPIC
646
+
647
+ # unresolvable source or dest
648
+ with pytest.raises(RpcError) as exc_info:
649
+ rebase(destination=gl_branch, source=b'topic/default/unknown')
650
+ details, rebase_error = parse_assert_structured_error(
651
+ exc_info.value, RebaseError, StatusCode.FAILED_PRECONDITION)
652
+ assert rebase_error.resolve_rev.revision == b'topic/default/unknown'
653
+ with pytest.raises(RpcError) as exc_info:
654
+ rebase(source=gl_topic, destination=b'branch/unknown')
655
+ details, rebase_error = parse_assert_structured_error(
656
+ exc_info.value, RebaseError, StatusCode.FAILED_PRECONDITION)
657
+ assert rebase_error.resolve_rev.revision == b'branch/unknown'
658
+
659
+ # source_sha check failed
660
+ with pytest.raises(RpcError) as exc_info:
661
+ rebase(destination=gl_branch, source=gl_topic, source_head_sha=sha0)
662
+ details, rebase_error = parse_assert_structured_error(
663
+ exc_info.value, RebaseError, StatusCode.FAILED_PRECONDITION)
664
+ mismatch = rebase_error.ref_mismatch
665
+ assert mismatch.expected_object_id == ctx0.hex()
666
+ assert mismatch.actual_object_id == ctx2.hex()
667
+ assert mismatch.reference_name == gl_topic
668
+
669
+ # working simple case
670
+ resp = rebase(source=gl_topic, source_head_sha=sha2,
671
+ destination=gl_branch)
672
+ wrapper.reload()
673
+ new_hex = resp.branch_update.commit_id.encode('ascii')
674
+ assert new_hex
675
+ assert new_hex != ctx2.hex()
676
+ rebased = wrapper.repo[new_hex]
677
+ assert rebased.p1() == default_head
678
+ assert rebased.topic() == b'zetop'
679
+
680
+ # no-op gives empty response
681
+ wrapper.commit_file('fast-fwd', topic='ff', parent=default_head)
682
+ assert rebase(source=b'topic/default/ff',
683
+ destination=gl_branch) == RebaseResponse()
684
+
685
+
686
+ @parametrize('project_mode', ('hg-git-project', 'native-project'))
687
+ def test_rebase_conflict(operations_fixture, project_mode):
688
+ fixture = operations_fixture
689
+ rebase = fixture.rebase
690
+
691
+ fixture.hg_native = project_mode != 'hg-git-project'
692
+ wrapper = fixture.repo_wrapper
693
+
694
+ gl_branch = b'branch/default'
695
+ gl_topic = b'topic/default/zetop'
696
+
697
+ # because of the config set by fixture, this leads in all cases to
698
+ # creation of a Git repo and its `branch/default` Git branch
699
+ ctx0 = wrapper.commit_file('foo')
700
+ default_head = wrapper.commit_file('foo', content='foo')
701
+ default_sha = default_head.hex().decode()
702
+ ctx2 = wrapper.commit_file('foo', topic='zetop', parent=ctx0,
703
+ content='bar')
704
+ sha2 = ctx2.hex().decode()
705
+ # avoid keeping the rebased changesets visible
706
+ wrapper.update_bin(NULL_NODE)
707
+
708
+ initial_branches = gitlab_branches(wrapper.repo)
709
+
710
+ with pytest.raises(RpcError) as exc_info:
711
+ rebase(source=gl_topic, destination=gl_branch)
712
+ details, rebase_error = parse_assert_structured_error(
713
+ exc_info.value, RebaseError, StatusCode.FAILED_PRECONDITION)
714
+ conflict = rebase_error.conflict
715
+ assert conflict.conflicting_files == [b"foo"]
716
+ assert set(conflict.conflicting_commit_ids) == {default_sha, sha2}
717
+
718
+ # nothing changed and working dir is clean
719
+ wrapper.reload()
720
+ assert gitlab_branches(wrapper.repo) == initial_branches
721
+
722
+ wd_wrapper = fixture.workdir_repo_wrapper(0)
723
+ wd_repo = wd_wrapper.repo
724
+ ms = mergestate.read(wd_repo)
725
+ assert not list(ms.unresolved())
726
+ wctx = wd_repo[None]
727
+ assert wctx.p1() == ctx2
728
+ assert_empty_repo_status(wd_wrapper)
729
+
730
+
599
731
  @parametrize('project_mode', ('hg-git-project', 'native-project'))
600
732
  def test_censor(operations_fixture, project_mode):
601
733
  fixture = operations_fixture
@@ -456,6 +456,8 @@ def test_write_ref(fixture_with_repo):
456
456
  create_keep_around(repo, existing_ka)
457
457
  fixture.write_ref(b'refs/keep-around/' + sha, sha)
458
458
  assert set(iter_keep_arounds(repo)) == {sha, existing_ka}
459
+ fixture.write_ref(b'refs/keep-around/' + existing_ka, ZERO_SHA)
460
+ assert set(iter_keep_arounds(repo)) == {sha}
459
461
 
460
462
 
461
463
  def test_write_special_refs_exceptions(fixture_with_repo):
@@ -896,8 +898,7 @@ def test_remove_repository(fixture_with_repo, wds_success):
896
898
  os.makedirs(aux_git_dir, exist_ok=True)
897
899
  (aux_git_dir / 'anyfile').write_bytes(b'anything')
898
900
 
899
- tmp_dir = wrapper.path.parent / '+hgitaly/tmp'
900
- wds_root = tmp_dir / 'workdirs' / grpc_repo.relative_path
901
+ wds_root = fixture.repo_workdirs_root()
901
902
 
902
903
  if wds_success == 'error':
903
904
  # let's sabotage the roster file to trigger an inner exception
@@ -920,7 +921,7 @@ def test_remove_repository(fixture_with_repo, wds_success):
920
921
  assert not aux_git_dir.exists()
921
922
 
922
923
  # no leftover in the temporary directory either
923
- assert not os.listdir(tmp_dir / 'workdirs')
924
+ assert not os.listdir(fixture.storage_workdirs())
924
925
 
925
926
  # unknown storage and repo
926
927
  with pytest.raises(grpc.RpcError) as exc_info:
@@ -33,6 +33,8 @@ from .stub.shared_pb2 import (
33
33
  GARBAGE_COLLECTING_RATE_GEN2 = 250
34
34
  GARBAGE_COLLECTING_RATE_GEN1 = 20
35
35
  AUX_GIT_REPOS_RELATIVE_DIR = "+hgitaly/hg-git"
36
+ TMP_RELATIVE_DIR = "+hgitaly/tmp"
37
+ REPOS_WORKDIRS_RELATIVE_DIR = TMP_RELATIVE_DIR + '/workdirs'
36
38
  HG_GIT_MIRRORING_MD_KEY = 'x-heptapod-hg-git-mirroring'
37
39
  NATIVE_PROJECT_MD_KEY = 'x-heptapod-hg-native'
38
40
  # TODO check if there is a GitLab MD for this, it should:
@@ -357,7 +359,7 @@ class HGitalyServicer:
357
359
  :raises OSError: if creation fails.
358
360
  """
359
361
  temp_dir = os.path.join(self.storage_root_dir(storage_name, context),
360
- b'+hgitaly', b'tmp')
362
+ TMP_RELATIVE_DIR.encode('ascii'))
361
363
  if not ensure:
362
364
  return temp_dir
363
365