hgitaly 2.7.1__tar.gz → 2.8.0__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 (296) hide show
  1. {hgitaly-2.7.1 → hgitaly-2.8.0}/PKG-INFO +1 -1
  2. hgitaly-2.8.0/hgitaly/VERSION +1 -0
  3. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/diff.py +47 -20
  4. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/message.py +4 -0
  5. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/diff.py +4 -1
  6. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/operations.py +21 -1
  7. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/ref.py +95 -3
  8. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/repository.py +1 -12
  9. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_diff.py +46 -1
  10. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_operations.py +10 -0
  11. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_ref.py +77 -0
  12. hgitaly-2.8.0/hgitaly/stub/commit_pb2.py +251 -0
  13. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/mercurial_repository_pb2.py +13 -5
  14. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/mercurial_repository_pb2_grpc.py +41 -0
  15. hgitaly-2.8.0/hgitaly/stub/repository_pb2.py +388 -0
  16. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/repository_pb2_grpc.py +0 -35
  17. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_errors.py +6 -6
  18. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_messages.py +5 -0
  19. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly.egg-info/PKG-INFO +1 -1
  20. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly.egg-info/SOURCES.txt +0 -129
  21. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/comparison.py +88 -22
  22. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_commit.py +1 -1
  23. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_diff.py +26 -2
  24. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_mercurial_repository.py +32 -0
  25. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_operations.py +16 -26
  26. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_ref.py +127 -1
  27. hgitaly-2.7.1/.coveragerc +0 -5
  28. hgitaly-2.7.1/.gitlab-ci.yml +0 -150
  29. hgitaly-2.7.1/.hgignore +0 -34
  30. hgitaly-2.7.1/.hgtags +0 -123
  31. hgitaly-2.7.1/ci/heptapod-sftp-push +0 -31
  32. hgitaly-2.7.1/ci/heptapod-sign-package +0 -34
  33. hgitaly-2.7.1/ci/heptapod_known_hosts.ssh +0 -4
  34. hgitaly-2.7.1/ci/upload-rhgitaly +0 -43
  35. hgitaly-2.7.1/conftest.py +0 -88
  36. hgitaly-2.7.1/dev-requirements.txt +0 -2
  37. hgitaly-2.7.1/examples/client.py +0 -48
  38. hgitaly-2.7.1/examples/client_list_lcft.py +0 -55
  39. hgitaly-2.7.1/generate-stubs +0 -33
  40. hgitaly-2.7.1/hgitaly/VERSION +0 -1
  41. hgitaly-2.7.1/hgitaly/license_detector/GPL-2.sample +0 -339
  42. hgitaly-2.7.1/hgitaly/stub/commit_pb2.py +0 -251
  43. hgitaly-2.7.1/hgitaly/stub/repository_pb2.py +0 -396
  44. hgitaly-2.7.1/hgitaly/testing/data/authorized_keys +0 -1
  45. hgitaly-2.7.1/hgitaly/testing/data/backup_additional_no_git.tar +0 -0
  46. hgitaly-2.7.1/hgitaly/testing/data/id_ecdsa_user +0 -38
  47. hgitaly-2.7.1/hgitaly/testing/data/known_hosts +0 -1
  48. hgitaly-2.7.1/hgitaly/testing/data/ssh_host_ecdsa_key +0 -9
  49. hgitaly-2.7.1/hgitaly/testing/data/ssh_host_ecdsa_key.pub +0 -1
  50. hgitaly-2.7.1/hgitaly/testing/data/sshd_config +0 -17
  51. hgitaly-2.7.1/lint +0 -3
  52. hgitaly-2.7.1/protos/analysis.proto +0 -62
  53. hgitaly-2.7.1/protos/blob.proto +0 -299
  54. hgitaly-2.7.1/protos/cleanup.proto +0 -88
  55. hgitaly-2.7.1/protos/cluster.proto +0 -102
  56. hgitaly-2.7.1/protos/commit.proto +0 -956
  57. hgitaly-2.7.1/protos/conflicts.proto +0 -137
  58. hgitaly-2.7.1/protos/diff.proto +0 -613
  59. hgitaly-2.7.1/protos/errors.proto +0 -228
  60. hgitaly-2.7.1/protos/hook.proto +0 -203
  61. hgitaly-2.7.1/protos/internal.proto +0 -37
  62. hgitaly-2.7.1/protos/lint.proto +0 -75
  63. hgitaly-2.7.1/protos/log.proto +0 -162
  64. hgitaly-2.7.1/protos/mercurial-changeset.proto +0 -96
  65. hgitaly-2.7.1/protos/mercurial-operations.proto +0 -163
  66. hgitaly-2.7.1/protos/mercurial-repository.proto +0 -278
  67. hgitaly-2.7.1/protos/namespace.proto +0 -98
  68. hgitaly-2.7.1/protos/objectpool.proto +0 -173
  69. hgitaly-2.7.1/protos/operations.proto +0 -1139
  70. hgitaly-2.7.1/protos/packfile.proto +0 -26
  71. hgitaly-2.7.1/protos/partition.proto +0 -62
  72. hgitaly-2.7.1/protos/praefect.proto +0 -222
  73. hgitaly-2.7.1/protos/ref.proto +0 -593
  74. hgitaly-2.7.1/protos/remote.proto +0 -153
  75. hgitaly-2.7.1/protos/repository.proto +0 -1348
  76. hgitaly-2.7.1/protos/server.proto +0 -144
  77. hgitaly-2.7.1/protos/service_config.proto +0 -86
  78. hgitaly-2.7.1/protos/shared.proto +0 -248
  79. hgitaly-2.7.1/protos/smarthttp.proto +0 -121
  80. hgitaly-2.7.1/protos/ssh.proto +0 -150
  81. hgitaly-2.7.1/protos/transaction.proto +0 -104
  82. hgitaly-2.7.1/protos/wiki.proto +0 -211
  83. hgitaly-2.7.1/ruby/.ruby-version +0 -1
  84. hgitaly-2.7.1/ruby/Gemfile +0 -5
  85. hgitaly-2.7.1/ruby/README.md +0 -48
  86. hgitaly-2.7.1/ruby/generate-grpc-lib +0 -63
  87. hgitaly-2.7.1/ruby/hgitaly.gemspec +0 -25
  88. hgitaly-2.7.1/ruby/lib/hgitaly/mercurial-changeset_pb.rb +0 -69
  89. hgitaly-2.7.1/ruby/lib/hgitaly/mercurial-changeset_services_pb.rb +0 -25
  90. hgitaly-2.7.1/ruby/lib/hgitaly/mercurial-operations_pb.rb +0 -103
  91. hgitaly-2.7.1/ruby/lib/hgitaly/mercurial-operations_services_pb.rb +0 -39
  92. hgitaly-2.7.1/ruby/lib/hgitaly/mercurial-repository_pb.rb +0 -130
  93. hgitaly-2.7.1/ruby/lib/hgitaly/mercurial-repository_services_pb.rb +0 -68
  94. hgitaly-2.7.1/ruby/lib/hgitaly/version.rb +0 -4
  95. hgitaly-2.7.1/ruby/lib/hgitaly.rb +0 -11
  96. hgitaly-2.7.1/ruby/run.rb +0 -39
  97. hgitaly-2.7.1/run-all-tests +0 -19
  98. hgitaly-2.7.1/rust/Cargo.lock +0 -2421
  99. hgitaly-2.7.1/rust/Cargo.toml +0 -3
  100. hgitaly-2.7.1/rust/Makefile +0 -69
  101. hgitaly-2.7.1/rust/build-from-tarball.sh +0 -30
  102. hgitaly-2.7.1/rust/check-line-width +0 -48
  103. hgitaly-2.7.1/rust/dependencies/README.md +0 -19
  104. hgitaly-2.7.1/rust/dependencies/mercurial.patch +0 -48
  105. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/any.proto +0 -158
  106. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/api.proto +0 -208
  107. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/compiler/plugin.proto +0 -183
  108. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/descriptor.proto +0 -911
  109. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/duration.proto +0 -116
  110. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/empty.proto +0 -52
  111. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/field_mask.proto +0 -245
  112. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/source_context.proto +0 -48
  113. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/struct.proto +0 -95
  114. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/timestamp.proto +0 -147
  115. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/type.proto +0 -187
  116. hgitaly-2.7.1/rust/dependencies/proto/google/protobuf/wrappers.proto +0 -123
  117. hgitaly-2.7.1/rust/go-enry.rev +0 -1
  118. hgitaly-2.7.1/rust/lint +0 -14
  119. hgitaly-2.7.1/rust/mercurial.rev +0 -1
  120. hgitaly-2.7.1/rust/rhgitaly/Cargo.toml +0 -40
  121. hgitaly-2.7.1/rust/rhgitaly/build.rs +0 -43
  122. hgitaly-2.7.1/rust/rhgitaly/clippy.toml +0 -6
  123. hgitaly-2.7.1/rust/rhgitaly/src/config.rs +0 -130
  124. hgitaly-2.7.1/rust/rhgitaly/src/errors.rs +0 -123
  125. hgitaly-2.7.1/rust/rhgitaly/src/generated/README.md +0 -7
  126. hgitaly-2.7.1/rust/rhgitaly/src/git.rs +0 -293
  127. hgitaly-2.7.1/rust/rhgitaly/src/gitlab/mod.rs +0 -42
  128. hgitaly-2.7.1/rust/rhgitaly/src/gitlab/reference.rs +0 -83
  129. hgitaly-2.7.1/rust/rhgitaly/src/gitlab/revision.rs +0 -320
  130. hgitaly-2.7.1/rust/rhgitaly/src/gitlab/state.rs +0 -508
  131. hgitaly-2.7.1/rust/rhgitaly/src/glob.rs +0 -45
  132. hgitaly-2.7.1/rust/rhgitaly/src/lib.rs +0 -40
  133. hgitaly-2.7.1/rust/rhgitaly/src/main.rs +0 -113
  134. hgitaly-2.7.1/rust/rhgitaly/src/mercurial.rs +0 -1362
  135. hgitaly-2.7.1/rust/rhgitaly/src/message.rs +0 -469
  136. hgitaly-2.7.1/rust/rhgitaly/src/metadata.rs +0 -27
  137. hgitaly-2.7.1/rust/rhgitaly/src/oid.rs +0 -87
  138. hgitaly-2.7.1/rust/rhgitaly/src/process.rs +0 -39
  139. hgitaly-2.7.1/rust/rhgitaly/src/repository.rs +0 -695
  140. hgitaly-2.7.1/rust/rhgitaly/src/service/analysis.rs +0 -184
  141. hgitaly-2.7.1/rust/rhgitaly/src/service/blob.rs +0 -256
  142. hgitaly-2.7.1/rust/rhgitaly/src/service/commit/find_commits.rs +0 -202
  143. hgitaly-2.7.1/rust/rhgitaly/src/service/commit/get_tree_entries.rs +0 -291
  144. hgitaly-2.7.1/rust/rhgitaly/src/service/commit/last_commits.rs +0 -567
  145. hgitaly-2.7.1/rust/rhgitaly/src/service/commit/mod.rs +0 -492
  146. hgitaly-2.7.1/rust/rhgitaly/src/service/commit/tree_entry.rs +0 -155
  147. hgitaly-2.7.1/rust/rhgitaly/src/service/diff.rs +0 -92
  148. hgitaly-2.7.1/rust/rhgitaly/src/service/mercurial_repository.rs +0 -172
  149. hgitaly-2.7.1/rust/rhgitaly/src/service/mod.rs +0 -13
  150. hgitaly-2.7.1/rust/rhgitaly/src/service/ref.rs +0 -634
  151. hgitaly-2.7.1/rust/rhgitaly/src/service/repository.rs +0 -275
  152. hgitaly-2.7.1/rust/rhgitaly/src/service/server.rs +0 -34
  153. hgitaly-2.7.1/rust/rhgitaly/src/sidecar.rs +0 -184
  154. hgitaly-2.7.1/rust/rhgitaly/src/streaming.rs +0 -339
  155. hgitaly-2.7.1/rust/rhgitaly/src/util.rs +0 -132
  156. hgitaly-2.7.1/rust/rs-enry.rev +0 -1
  157. hgitaly-2.7.1/rust/src-tarball.sh +0 -60
  158. hgitaly-2.7.1/test-requirements.txt +0 -7
  159. {hgitaly-2.7.1 → hgitaly-2.8.0}/LICENSE +0 -0
  160. {hgitaly-2.7.1 → hgitaly-2.8.0}/MANIFEST.in +0 -0
  161. {hgitaly-2.7.1 → hgitaly-2.8.0}/README.md +0 -0
  162. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgext3rd/__init__.py +0 -0
  163. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgext3rd/hgitaly/__init__.py +0 -0
  164. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgext3rd/hgitaly/revset.py +0 -0
  165. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgext3rd/hgitaly/tests/__init__.py +0 -0
  166. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgext3rd/hgitaly/tests/test_revset.py +0 -0
  167. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgext3rd/hgitaly/tests/test_serve.py +0 -0
  168. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/__init__.py +0 -0
  169. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/branch.py +0 -0
  170. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/changelog.py +0 -0
  171. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/errors.py +0 -0
  172. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/feature.py +0 -0
  173. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/file_content.py +0 -0
  174. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/file_context.py +0 -0
  175. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/git.py +0 -0
  176. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/gitlab_ref.py +0 -0
  177. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/license_detector/__init__.py +0 -0
  178. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/license_detector/spdx-licenses.json +0 -0
  179. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/linguist/__init__.py +0 -0
  180. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/linguist/languages.json +0 -0
  181. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/logging.py +0 -0
  182. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/manifest.py +0 -0
  183. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/oid.py +0 -0
  184. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/pagination.py +0 -0
  185. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/path.py +0 -0
  186. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/peer.py +0 -0
  187. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/procutil.py +0 -0
  188. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/repository.py +0 -0
  189. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/revision.py +0 -0
  190. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/revset.py +0 -0
  191. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/scripts.py +0 -0
  192. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/__init__.py +0 -0
  193. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/address.py +0 -0
  194. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/mono.py +0 -0
  195. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/prefork.py +0 -0
  196. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/tests/__init__.py +0 -0
  197. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/tests/test_address.py +0 -0
  198. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/tests/test_mono.py +0 -0
  199. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/tests/test_prefork.py +0 -0
  200. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/tests/test_worker.py +0 -0
  201. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/server/worker.py +0 -0
  202. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/__init__.py +0 -0
  203. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/analysis.py +0 -0
  204. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/blob.py +0 -0
  205. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/commit.py +0 -0
  206. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/interceptors.py +0 -0
  207. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/mercurial_changeset.py +0 -0
  208. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/mercurial_operations.py +0 -0
  209. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/mercurial_repository.py +0 -0
  210. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/server.py +0 -0
  211. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/__init__.py +0 -0
  212. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/fixture.py +0 -0
  213. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_analysis.py +0 -0
  214. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_blob.py +0 -0
  215. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_commit.py +0 -0
  216. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_default_branch.py +0 -0
  217. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_mercurial_changeset.py +0 -0
  218. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_mercurial_operations.py +0 -0
  219. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_mercurial_repository.py +0 -0
  220. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_repository_service.py +0 -0
  221. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/service/tests/test_server.py +0 -0
  222. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/servicer.py +0 -0
  223. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/ssh.py +0 -0
  224. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stream.py +0 -0
  225. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/__init__.py +0 -0
  226. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/analysis_pb2.py +0 -0
  227. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/analysis_pb2_grpc.py +0 -0
  228. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/blob_pb2.py +0 -0
  229. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/blob_pb2_grpc.py +0 -0
  230. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/commit_pb2_grpc.py +0 -0
  231. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/diff_pb2.py +0 -0
  232. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/diff_pb2_grpc.py +0 -0
  233. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/errors_pb2.py +0 -0
  234. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/errors_pb2_grpc.py +0 -0
  235. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/lint_pb2.py +0 -0
  236. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/lint_pb2_grpc.py +0 -0
  237. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/mercurial_changeset_pb2.py +0 -0
  238. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/mercurial_changeset_pb2_grpc.py +0 -0
  239. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/mercurial_operations_pb2.py +0 -0
  240. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/mercurial_operations_pb2_grpc.py +0 -0
  241. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/operations_pb2.py +0 -0
  242. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/operations_pb2_grpc.py +0 -0
  243. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/ref_pb2.py +0 -0
  244. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/ref_pb2_grpc.py +0 -0
  245. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/server_pb2.py +0 -0
  246. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/server_pb2_grpc.py +0 -0
  247. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/shared_pb2.py +0 -0
  248. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/stub/shared_pb2_grpc.py +0 -0
  249. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tag.py +0 -0
  250. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/__init__.py +0 -0
  251. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/bundle.py +0 -0
  252. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/context.py +0 -0
  253. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/grpc.py +0 -0
  254. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/ssh.py +0 -0
  255. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/sshd.py +0 -0
  256. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/tests/__init__.py +0 -0
  257. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/testing/tests/test_sshd.py +0 -0
  258. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/__init__.py +0 -0
  259. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/common.py +0 -0
  260. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_branch.py +0 -0
  261. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_diff.py +0 -0
  262. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_feature.py +0 -0
  263. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_file_context.py +0 -0
  264. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_gitlab_ref.py +0 -0
  265. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_license_detector.py +0 -0
  266. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_linguist.py +0 -0
  267. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_manifest.py +0 -0
  268. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_oid.py +0 -0
  269. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_peer.py +0 -0
  270. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_repository.py +0 -0
  271. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_revision.py +0 -0
  272. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_revset.py +0 -0
  273. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_servicer.py +0 -0
  274. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_stream.py +0 -0
  275. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_tag.py +0 -0
  276. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/tests/test_workdir.py +0 -0
  277. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/util.py +0 -0
  278. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly/workdir.py +0 -0
  279. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly.egg-info/dependency_links.txt +0 -0
  280. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly.egg-info/entry_points.txt +0 -0
  281. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly.egg-info/requires.txt +0 -0
  282. {hgitaly-2.7.1 → hgitaly-2.8.0}/hgitaly.egg-info/top_level.txt +0 -0
  283. {hgitaly-2.7.1 → hgitaly-2.8.0}/install-requirements.txt +0 -0
  284. {hgitaly-2.7.1 → hgitaly-2.8.0}/setup.cfg +0 -0
  285. {hgitaly-2.7.1 → hgitaly-2.8.0}/setup.py +0 -0
  286. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/__init__.py +0 -0
  287. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/conftest.py +0 -0
  288. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/gitaly.py +0 -0
  289. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +0 -0
  290. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/rhgitaly.py +0 -0
  291. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_blob_tree.py +0 -0
  292. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_comparison.py +0 -0
  293. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_gitaly_server.py +0 -0
  294. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_repository_service.py +0 -0
  295. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_rhgitaly_server.py +0 -0
  296. {hgitaly-2.7.1 → hgitaly-2.8.0}/tests_with_gitaly/test_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hgitaly
3
- Version: 2.7.1
3
+ Version: 2.8.0
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
+ 2.8.0
@@ -46,17 +46,19 @@ Status_Type_Map = dict(
46
46
  added=ChangedPaths.Status.ADDED,
47
47
  modified=ChangedPaths.Status.MODIFIED,
48
48
  removed=ChangedPaths.Status.DELETED,
49
+ renamed=ChangedPaths.Status.RENAMED,
49
50
  # Note: Mercurial includes TYPE_CHANGE
50
51
  # (symlink, regular file, submodule...etc) in MODIFIED status
51
52
  )
52
53
  """Mapping status object attributes to ChangedPaths enum."""
53
54
 
54
55
  COPIED = ChangedPaths.Status.COPIED
56
+ RENAMED = ChangedPaths.Status.RENAMED
55
57
  DIFF_HUNKS_START_RX = re.compile(rb'^(--- )|^(Binary file)')
56
58
  """To match the header line right before hunks start getting dumped."""
57
59
 
58
60
 
59
- def changed_paths(repo, from_ctx, to_ctx, base_path):
61
+ def changed_paths(repo, from_ctx, to_ctx, base_path, find_renames=False):
60
62
  if base_path is None:
61
63
  matcher = None
62
64
  path_trim_at = 0
@@ -74,26 +76,33 @@ def changed_paths(repo, from_ctx, to_ctx, base_path):
74
76
  patterns=[b'path:' + base_path])
75
77
  path_trim_at = len(base_path) + 1
76
78
 
77
- copied = list(copy_changed_paths(
78
- from_ctx,
79
- to_ctx,
80
- copies.pathcopies(from_ctx, to_ctx, match=matcher),
81
- trim_at=path_trim_at))
82
- copied_paths = set(cp.path for cp in copied)
79
+ copy_info = copies.pathcopies(from_ctx, to_ctx, match=matcher)
80
+ # copies do not distinguish actual copies from renames. The difference
81
+ # will be that a rename goes with deletion of the original.
83
82
 
84
83
  status = from_ctx.status(to_ctx, match=matcher)
85
- for path in status_changed_paths(from_ctx, to_ctx, status,
86
- trim_at=path_trim_at):
87
- if path.path not in copied_paths:
88
- yield path
89
-
90
- yield from iter(copied)
91
-
92
-
93
- def status_changed_paths(from_ctx, to_ctx, status, trim_at=0):
84
+ # this will remove renames from copy_info, keeping only actual copies
85
+ yield from status_changed_paths(from_ctx, to_ctx, status, copy_info,
86
+ find_renames=find_renames,
87
+ trim_at=path_trim_at)
88
+ yield from copy_changed_paths(from_ctx,
89
+ to_ctx,
90
+ copy_info,
91
+ trim_at=path_trim_at)
92
+
93
+
94
+ def status_changed_paths(from_ctx, to_ctx, status, copy_info,
95
+ find_renames=False, trim_at=0):
96
+ rcopy_info = {v: k for k, v in copy_info.items()}
94
97
  """Return ChangedPaths from Mercurial status object"""
95
98
  for stype in ['added', 'modified', 'removed']:
96
99
  for path in status.__getattribute__(stype):
100
+ copied_from = copy_info.get(path)
101
+ if copied_from is not None:
102
+ if copied_from not in status.removed or find_renames:
103
+ continue
104
+
105
+ old_path = b''
97
106
  if stype == 'added':
98
107
  old_mode = OBJECT_MODE_DOES_NOT_EXIST
99
108
  old_blob_id = NULL_BLOB_OID
@@ -102,8 +111,21 @@ def status_changed_paths(from_ctx, to_ctx, status, trim_at=0):
102
111
  old_blob_id = ctx_blob_oid(from_ctx, path)
103
112
 
104
113
  if stype == 'removed':
105
- new_mode = OBJECT_MODE_DOES_NOT_EXIST
106
- new_blob_id = NULL_BLOB_OID
114
+ new_path = rcopy_info.get(path)
115
+ if new_path is None:
116
+ new_mode = OBJECT_MODE_DOES_NOT_EXIST
117
+ new_blob_id = NULL_BLOB_OID
118
+ else:
119
+ del copy_info[new_path]
120
+ if find_renames:
121
+ stype = 'renamed'
122
+ old_path = path
123
+ path = new_path
124
+ new_mode = git_perms(to_ctx.filectx(new_path))
125
+ new_blob_id = ctx_blob_oid(to_ctx, new_path)
126
+ else:
127
+ new_mode = OBJECT_MODE_DOES_NOT_EXIST
128
+ new_blob_id = NULL_BLOB_OID
107
129
  else:
108
130
  new_mode = git_perms(to_ctx.filectx(path))
109
131
  new_blob_id = ctx_blob_oid(to_ctx, path)
@@ -114,11 +136,13 @@ def status_changed_paths(from_ctx, to_ctx, status, trim_at=0):
114
136
  new_mode=new_mode,
115
137
  old_blob_id=old_blob_id,
116
138
  new_blob_id=new_blob_id,
139
+ old_path=old_path,
117
140
  status=Status_Type_Map[stype]
118
141
  )
119
142
 
120
143
 
121
- def copy_changed_paths(from_ctx, to_ctx, path_copies, trim_at=0):
144
+ def copy_changed_paths(from_ctx, to_ctx, path_copies,
145
+ trim_at=0, find_renames=False):
122
146
  """Return ChangedPaths for the given paths, relative to base_path.
123
147
 
124
148
  Given that Gitaly currently (gitaly@c54d613d0) does not pass
@@ -129,8 +153,11 @@ def copy_changed_paths(from_ctx, to_ctx, path_copies, trim_at=0):
129
153
  for target, source in path_copies.items():
130
154
  yield ChangedPaths(path=target[trim_at:],
131
155
  status=COPIED,
132
- old_mode=git_perms(to_ctx.filectx(source)),
156
+ old_mode=git_perms(from_ctx.filectx(source)),
157
+ old_blob_id=ctx_blob_oid(from_ctx, source),
133
158
  new_mode=git_perms(to_ctx.filectx(target)),
159
+ new_blob_id=ctx_blob_oid(to_ctx, target),
160
+ old_path=source[trim_at:],
134
161
  )
135
162
 
136
163
 
@@ -87,6 +87,10 @@ def message_to_string(message):
87
87
  return result
88
88
 
89
89
 
90
+ def as_dict(message):
91
+ return {descr.name: value for descr, value in message.ListFields()}
92
+
93
+
90
94
  class Logging:
91
95
  """Wrapper of requests and responses for sensible logging.
92
96
 
@@ -521,8 +521,11 @@ class DiffServicer(DiffServiceServicer, HGitalyServicer):
521
521
  for cp in cids_paths]
522
522
  extracted.append((left_ctx, right_ctx, path))
523
523
 
524
+ find_renames = request.find_renames
524
525
  for paths in chunked(path for extr in extracted
525
- for path in changed_paths(repo, *extr)):
526
+ for path in changed_paths(
527
+ repo, *extr,
528
+ find_renames=find_renames)):
526
529
  yield FindChangedPathsResponse(paths=paths)
527
530
 
528
531
  def GetPatchID(self, request: GetPatchIDRequest,
@@ -152,7 +152,27 @@ class OperationServicer(OperationServiceServicer, HGitalyServicer):
152
152
  False)
153
153
  with operation_error_treatment(context, UserSquashError,
154
154
  logger=logger):
155
- self.repo_command(wd.repo, context, 'fold', **opts)
155
+ retcode = self.repo_command(wd.repo, context, 'fold', **opts)
156
+ if retcode == 1:
157
+ revs = wd.repo.revs(revset)
158
+ if len(revs) == 1:
159
+ rev = next(iter(revs))
160
+ self.repo_command(wd.repo, context, 'update', rev)
161
+ self.repo_command(
162
+ wd.repo, context, 'amend',
163
+ message=message,
164
+ note=(b"Description changed for squash request "
165
+ b"for a single changeset"),
166
+ )
167
+ else: # pragma no cover
168
+ # This block is currently unreachable from tests
169
+ # and is here in case of unexpected behaviour change
170
+ # in the `fold` command.
171
+ context.abort(
172
+ StatusCode.INTERNAL,
173
+ "Internal return code 1, but zero or more than "
174
+ "one changeset for revset %r" % revset
175
+ )
156
176
  self.repo_command(wd.repo, context, 'update', start_ctx.hex())
157
177
  # The workdir repo does not have to be reloaded, whereas the
158
178
  # main repo would. We just need to regrab the end changeset
@@ -28,6 +28,8 @@ from hgext3rd.heptapod.special_ref import (
28
28
  )
29
29
  from hgext3rd.heptapod.keep_around import (
30
30
  parse_keep_around_ref,
31
+ iter_keep_arounds,
32
+ init_keep_arounds,
31
33
  )
32
34
 
33
35
  from ..errors import (
@@ -40,6 +42,8 @@ from ..pagination import (
40
42
  )
41
43
  from ..revision import (
42
44
  CHANGESET_HASH_BYTES_REGEXP,
45
+ ZERO_SHA,
46
+ ZERO_SHA_STR,
43
47
  gitlab_revision_hash,
44
48
  )
45
49
  from ..stream import (
@@ -51,6 +55,7 @@ from ..stub.shared_pb2 import (
51
55
  )
52
56
  from ..stub.errors_pb2 import (
53
57
  ReferenceNotFoundError,
58
+ ReferenceStateMismatchError,
54
59
  )
55
60
  from ..stub.ref_pb2 import (
56
61
  FindDefaultBranchNameRequest,
@@ -74,6 +79,9 @@ from ..stub.ref_pb2 import (
74
79
  FindBranchResponse,
75
80
  DeleteRefsRequest,
76
81
  DeleteRefsResponse,
82
+ UpdateReferencesError,
83
+ UpdateReferencesRequest,
84
+ UpdateReferencesResponse,
77
85
  ListBranchNamesContainingCommitRequest,
78
86
  ListBranchNamesContainingCommitResponse,
79
87
  ListTagNamesContainingCommitRequest,
@@ -87,9 +95,6 @@ from ..stub.ref_pb2 import (
87
95
  )
88
96
  from ..stub.ref_pb2_grpc import RefServiceServicer
89
97
 
90
- from ..revision import (
91
- ZERO_SHA_STR,
92
- )
93
98
  from ..branch import (
94
99
  BranchSortBy,
95
100
  gitlab_branch_head,
@@ -273,6 +278,93 @@ class RefServicer(RefServiceServicer, HGitalyServicer):
273
278
  return FindBranchResponse(
274
279
  branch=Branch(name=name, target_commit=message.commit(head)))
275
280
 
281
+ def UpdateReferences(self,
282
+ request: UpdateReferencesRequest,
283
+ context) -> UpdateReferencesResponse:
284
+ self.STATUS_CODE_STORAGE_NOT_FOUND = StatusCode.INVALID_ARGUMENT
285
+ first = True
286
+ special_changes = []
287
+ ka_changes = []
288
+ for req in request:
289
+ if first:
290
+ # blobs are given by oid, hence as in direct changeset Node
291
+ # IDs, the unfiltered repo is the right one for the task
292
+ repo = self.load_repo(req.repository, context).unfiltered()
293
+ first = False
294
+
295
+ for upd in req.updates:
296
+ if len(upd.new_object_id) != 40:
297
+ oid = upd.new_object_id.decode('ascii', 'replace')
298
+ context.abort(StatusCode.INVALID_ARGUMENT,
299
+ "validating new object ID: "
300
+ f'invalid object ID: "{oid}", '
301
+ f"expected length 40, got {len(oid)}")
302
+
303
+ ref_path = upd.reference
304
+ change = (upd.old_object_id, upd.new_object_id)
305
+ if change[0] == change[1]:
306
+ # let's not waste resources for this
307
+ continue
308
+
309
+ # consider only special refs and keep-arounds, as other refs
310
+ # (branches and tags) are only reflecting changesets content,
311
+ # setting them independently makes no sense with Mercurial
312
+ special_ref = parse_special_ref(ref_path)
313
+ if special_ref is not None:
314
+ special_changes.append((special_ref, change))
315
+ continue
316
+
317
+ ka = parse_keep_around_ref(upd.reference)
318
+ if ka is not None:
319
+ if (
320
+ upd.new_object_id != ZERO_SHA
321
+ and ka != upd.new_object_id
322
+ ):
323
+ context.abort(StatusCode.INVALID_ARGUMENT,
324
+ "Inconsistent keep-around.")
325
+ ka_changes.append(change)
326
+
327
+ with repo.lock():
328
+ # keeping promise of atomicity of this method
329
+ special_existing = special_refs(repo)
330
+ if special_existing is GITLAB_TYPED_REFS_MISSING:
331
+ special_existing = {}
332
+ for name, (old_id, new_id) in special_changes:
333
+ existing = special_existing.get(name)
334
+ if old_id == ZERO_SHA and existing is not None:
335
+ context.abort(StatusCode.INTERNAL,
336
+ "committing update: "
337
+ "reference already exists")
338
+ elif old_id and old_id != ZERO_SHA and existing != old_id:
339
+ Mismatch = ReferenceStateMismatchError # just too long!
340
+ structured_abort(
341
+ context, StatusCode.ABORTED,
342
+ "reference does not point to expected object",
343
+ UpdateReferencesError(
344
+ reference_state_mismatch=Mismatch(
345
+ reference_name=b'refs/' + name,
346
+ expected_object_id=old_id,
347
+ actual_object_id=existing)))
348
+ elif new_id == ZERO_SHA:
349
+ del special_existing[name]
350
+ else:
351
+ special_existing[name] = new_id
352
+
353
+ # TODO make a collect_keep_arounds() or keep_arounds_set()
354
+ ka_existing = set(iter_keep_arounds(repo))
355
+ ka_existing.discard(GITLAB_TYPED_REFS_MISSING)
356
+ for old_id, new_id in ka_changes:
357
+ # bogus requests have already been prohibited
358
+ if new_id == ZERO_SHA:
359
+ ka_existing.discard(old_id)
360
+ else:
361
+ ka_existing.add(new_id)
362
+
363
+ write_special_refs(repo, special_existing)
364
+ init_keep_arounds(repo, ka_existing)
365
+
366
+ return UpdateReferencesResponse()
367
+
276
368
  def DeleteRefs(self,
277
369
  request: DeleteRefsRequest,
278
370
  context) -> DeleteRefsResponse:
@@ -127,8 +127,6 @@ from ..stub.repository_pb2 import (
127
127
  SetCustomHooksResponse,
128
128
  WriteRefRequest,
129
129
  WriteRefResponse,
130
- ApplyGitattributesRequest,
131
- ApplyGitattributesResponse,
132
130
  )
133
131
  from ..stub.repository_pb2_grpc import RepositoryServiceServicer
134
132
  from ..stub.shared_pb2 import (
@@ -382,15 +380,6 @@ class RepositoryServicer(RepositoryServiceServicer, HGitalyServicer):
382
380
  set_default_gitlab_branch(repo, target_branch)
383
381
  return WriteRefResponse()
384
382
 
385
- def ApplyGitattributes(self, request: ApplyGitattributesRequest,
386
- context) -> ApplyGitattributesResponse:
387
- """Method used as testing bed for the `not_implemented` helper.
388
-
389
- It is unlikely we ever implement this one, and if we do something
390
- similar, we'll probably end up defining a ApplyHgAttributes anyway.
391
- """
392
- not_implemented(context, issue=1234567)
393
-
394
383
  def CreateRepository(self, request: CreateRepositoryRequest,
395
384
  context) -> CreateRepositoryResponse:
396
385
  default_branch = request.default_branch
@@ -588,7 +577,7 @@ class RepositoryServicer(RepositoryServiceServicer, HGitalyServicer):
588
577
  if not os.path.exists(repo_path):
589
578
  # same error message as Gitaly (probably no need to repeat
590
579
  # repo details, since request often logged client-side)
591
- context.abort(StatusCode.NOT_FOUND, "repository does not exist")
580
+ context.abort(StatusCode.NOT_FOUND, "repository not found")
592
581
 
593
582
  trash_path = os.path.join(
594
583
  self.temp_dir(request.repository.storage_name, context),
@@ -127,7 +127,7 @@ class DiffFixture(ServiceFixture):
127
127
  (changed.status, perm_change))
128
128
  return by_file
129
129
 
130
- def find_changed_paths_commits(self, commits, compare_to=()):
130
+ def find_changed_paths_commits(self, commits, compare_to=(), **kw):
131
131
  """Wrap FindChangedPaths used with CommitRequest.
132
132
 
133
133
  :param compare_to: if given, will be used in all requests, hoping
@@ -141,6 +141,7 @@ class DiffFixture(ServiceFixture):
141
141
  commit_revision=c,
142
142
  parent_commit_revisions=compare_to))
143
143
  for c in commits],
144
+ **kw
144
145
  )
145
146
 
146
147
  def find_changed_paths_tree(self, left_oid, right_oid):
@@ -686,6 +687,50 @@ def test_find_changed_paths_copy_in_tree(diff_fixture):
686
687
  }
687
688
 
688
689
 
690
+ def test_find_changed_paths_rename(diff_fixture):
691
+ wrapper = diff_fixture.repo_wrapper
692
+
693
+ (wrapper.path / 'subdir').mkdir() # avoid all lengths to be 3
694
+ (wrapper.path / 'subdir/bar').write_text('some bar')
695
+ ctx0 = wrapper.commit(rel_paths=['subdir'], add_remove=True)
696
+
697
+ wrapper.command(b'mv', wrapper.repo.root + b'/subdir/bar',
698
+ wrapper.repo.root + b'/subdir/baz')
699
+ ctx1 = wrapper.commit(rel_paths=['subdir'])
700
+
701
+ repo = wrapper.repo
702
+
703
+ sub0_oid, sub1_oid = [tree_oid(repo, ctx.hex().decode('ascii'), b'subdir')
704
+ for ctx in (ctx0, ctx1)]
705
+ ret = diff_fixture.find_changed_paths_commits(
706
+ [ctx1.hex()],
707
+ compare_to=[ctx0.hex()],
708
+ find_renames=False,
709
+ )
710
+ assert ret == {
711
+ b'subdir/baz': [(ChangedPaths.Status.ADDED,
712
+ (OBJECT_MODE_DOES_NOT_EXIST,
713
+ OBJECT_MODE_NON_EXECUTABLE),
714
+ )],
715
+ b'subdir/bar': [(ChangedPaths.Status.DELETED,
716
+ (OBJECT_MODE_NON_EXECUTABLE,
717
+ OBJECT_MODE_DOES_NOT_EXIST)
718
+ )],
719
+ }
720
+
721
+ ret = diff_fixture.find_changed_paths_commits(
722
+ [ctx1.hex()],
723
+ compare_to=[ctx0.hex()],
724
+ find_renames=True,
725
+ )
726
+ assert ret == {
727
+ b'subdir/baz': [(ChangedPaths.Status.RENAMED, None)],
728
+ }
729
+
730
+ # TODO test the case of rename with duplication:
731
+ # hg cp foo bar; hg mv foo bar2
732
+
733
+
689
734
  def test_get_patch_id(diff_fixture):
690
735
  wrapper = diff_fixture.repo_wrapper
691
736
  patch_id = diff_fixture.get_patch_id
@@ -151,6 +151,16 @@ def test_user_squash(operations_fixture, project_mode, timestamp):
151
151
  squash(**kw)
152
152
  assert exc_info.value.code() == StatusCode.INVALID_ARGUMENT
153
153
 
154
+ amend_msg = b'squash becomes an amend!'
155
+ resp = squash(start_sha=sha1,
156
+ end_sha=folded_sha,
157
+ author=author,
158
+ commit_message=amend_msg)
159
+ amended_sha = resp.squash_sha.encode('ascii')
160
+ wrapper.reload()
161
+ amended_ctx = wrapper.repo[amended_sha]
162
+ assert amended_ctx.description() == amend_msg
163
+
154
164
 
155
165
  @parametrize('project_mode', ('hg-git-project',
156
166
  'native-project-without-git',
@@ -30,6 +30,7 @@ from hgext3rd.heptapod.keep_around import (
30
30
  from hgitaly import feature
31
31
  from hgitaly.errors import parse_assert_structured_error
32
32
  from hgitaly.revision import (
33
+ ZERO_SHA,
33
34
  ZERO_SHA_STR,
34
35
  )
35
36
  from hgitaly.tests.common import (
@@ -56,6 +57,7 @@ from hgitaly.stub.ref_pb2 import (
56
57
  FindRefsByOIDRequest,
57
58
  FindTagError,
58
59
  FindTagRequest,
60
+ UpdateReferencesRequest,
59
61
  )
60
62
  from hgitaly.stub.ref_pb2_grpc import RefServiceStub
61
63
 
@@ -85,6 +87,10 @@ class RefFixture(ServiceFixture):
85
87
  metadata=feature.as_grpc_metadata(self.feature_flags),
86
88
  )
87
89
 
90
+ def ref_exists(self, ref, **kw):
91
+ kw.setdefault('repository', self.grpc_repo)
92
+ return self.stub.RefExists(RefExistsRequest(ref=ref, **kw)).value
93
+
88
94
  def list_refs(self, patterns=(b"refs/", ), **kw):
89
95
  return [(ref.name, ref.target)
90
96
  for resp in self.stub.ListRefs(
@@ -97,6 +103,22 @@ class RefFixture(ServiceFixture):
97
103
  kw.setdefault('repository', self.grpc_repo)
98
104
  return self.stub.FindRefsByOID(FindRefsByOIDRequest(**kw)).refs
99
105
 
106
+ def update_refs(self, updates, **kw):
107
+ Update = UpdateReferencesRequest.Update
108
+ kw.setdefault('repository', self.grpc_repo)
109
+
110
+ update_messages = []
111
+ for ref_path, old_id, new_id in updates:
112
+ upd_kw = dict(reference=ref_path, new_object_id=new_id)
113
+ if old_id is not None:
114
+ upd_kw['old_object_id'] = old_id
115
+ update_messages.append(Update(**upd_kw))
116
+
117
+ return self.stub.UpdateReferences(
118
+ iter([UpdateReferencesRequest(updates=[upd], **kw)
119
+ for upd in update_messages])
120
+ )
121
+
100
122
 
101
123
  @pytest.fixture
102
124
  def ref_fixture(grpc_channel, server_repos_root):
@@ -633,3 +655,58 @@ def test_list_refs(ref_fixture):
633
655
  assert fixture.find_refs_by_oid(
634
656
  oid=sha1, sort_field='refname', limit=1
635
657
  ) == ['refs/heads/branch/default']
658
+
659
+
660
+ def test_update_references(ref_fixture):
661
+ fixture = ref_fixture
662
+ wrapper = fixture.repo_wrapper
663
+
664
+ sha0 = wrapper.write_commit('afoo', message="Some foo").hex()
665
+ sha1 = wrapper.write_commit('afoo', message="Some foo").hex()
666
+
667
+ pipeline_1 = b'refs/pipelines/1'
668
+ ka_0 = b'refs/keep-around/' + sha0
669
+ fixture.update_refs([(pipeline_1, ZERO_SHA, sha1),
670
+ (ka_0, ZERO_SHA, sha0),
671
+ ])
672
+ assert fixture.ref_exists(ka_0)
673
+ assert fixture.ref_exists(pipeline_1)
674
+ assert fixture.list_refs(patterns=[b'refs/pipelines/']) == [
675
+ (pipeline_1, sha1.decode())
676
+ ]
677
+
678
+ fixture.update_refs([(pipeline_1, sha1, sha0),
679
+ (ka_0, sha0, ZERO_SHA),
680
+ ])
681
+ assert not fixture.ref_exists(ka_0)
682
+ assert fixture.list_refs(patterns=[b'refs/pipelines/']) == [
683
+ (pipeline_1, sha0.decode())
684
+ ]
685
+
686
+ # edge case equivalent to no-op
687
+ fixture.update_refs([(pipeline_1, sha0, sha0)])
688
+ assert fixture.list_refs(patterns=[b'refs/pipelines/']) == [
689
+ (pipeline_1, sha0.decode())
690
+ ]
691
+
692
+ # error cases
693
+ with pytest.raises(grpc.RpcError) as exc_info:
694
+ fixture.update_refs([(pipeline_1, None, b'branch/default')])
695
+ assert exc_info.value.code() == grpc.StatusCode.INVALID_ARGUMENT
696
+
697
+ with pytest.raises(grpc.RpcError) as exc_info:
698
+ fixture.update_refs([(ka_0, None, sha1)])
699
+ assert exc_info.value.code() == grpc.StatusCode.INVALID_ARGUMENT
700
+
701
+ with pytest.raises(grpc.RpcError) as exc_info:
702
+ fixture.update_refs([(pipeline_1, ZERO_SHA, sha1)])
703
+ assert exc_info.value.code() == grpc.StatusCode.INTERNAL
704
+ assert 'reference already exists' in exc_info.value.details()
705
+
706
+ with pytest.raises(grpc.RpcError) as exc_info:
707
+ fixture.update_refs([(pipeline_1, sha1, sha0)])
708
+ assert exc_info.value.code() == grpc.StatusCode.ABORTED
709
+
710
+ # deletions
711
+ fixture.update_refs([(pipeline_1, sha0, ZERO_SHA)])
712
+ assert not fixture.ref_exists(pipeline_1)