hgitaly 1.3.1__tar.gz → 2.10.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 (173) hide show
  1. {hgitaly-1.3.1/hgitaly.egg-info → hgitaly-2.10.0}/PKG-INFO +10 -1
  2. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgext3rd/hgitaly/__init__.py +9 -0
  3. hgitaly-2.10.0/hgitaly/VERSION +1 -0
  4. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/diff.py +47 -20
  5. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/errors.py +24 -0
  6. hgitaly-2.10.0/hgitaly/file_content.py +160 -0
  7. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/gitlab_ref.py +12 -2
  8. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/logging.py +10 -6
  9. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/message.py +4 -0
  10. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/repository.py +0 -28
  11. hgitaly-2.10.0/hgitaly/scripts.py +264 -0
  12. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/mono.py +3 -0
  13. hgitaly-2.10.0/hgitaly/service/analysis.py +51 -0
  14. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/commit.py +64 -11
  15. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/diff.py +5 -2
  16. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/interceptors.py +14 -2
  17. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/mercurial_operations.py +20 -12
  18. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/operations.py +34 -2
  19. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/ref.py +106 -4
  20. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/repository.py +5 -76
  21. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/server.py +11 -0
  22. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/fixture.py +12 -6
  23. hgitaly-2.10.0/hgitaly/service/tests/test_analysis.py +111 -0
  24. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_commit.py +51 -22
  25. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_diff.py +46 -1
  26. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_mercurial_operations.py +56 -40
  27. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_operations.py +22 -23
  28. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_ref.py +113 -20
  29. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_repository_service.py +4 -105
  30. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_server.py +8 -0
  31. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/ssh.py +2 -0
  32. hgitaly-2.10.0/hgitaly/stub/analysis_pb2.py +41 -0
  33. hgitaly-2.10.0/hgitaly/stub/analysis_pb2_grpc.py +78 -0
  34. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/blob_pb2.py +16 -16
  35. hgitaly-2.10.0/hgitaly/stub/commit_pb2.py +255 -0
  36. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/commit_pb2_grpc.py +2 -0
  37. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/diff_pb2.py +62 -22
  38. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/diff_pb2_grpc.py +106 -0
  39. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/errors_pb2.py +3 -1
  40. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/lint_pb2.py +4 -3
  41. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/mercurial_repository_pb2.py +16 -8
  42. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/mercurial_repository_pb2_grpc.py +41 -0
  43. hgitaly-2.10.0/hgitaly/stub/operations_pb2.py +201 -0
  44. hgitaly-2.10.0/hgitaly/stub/remote_pb2.py +55 -0
  45. hgitaly-2.10.0/hgitaly/stub/remote_pb2_grpc.py +151 -0
  46. hgitaly-2.10.0/hgitaly/stub/repository_pb2.py +390 -0
  47. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/repository_pb2_grpc.py +73 -141
  48. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/server_pb2.py +17 -17
  49. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/server_pb2_grpc.py +25 -23
  50. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/shared_pb2.py +11 -9
  51. hgitaly-2.10.0/hgitaly/testing/storage.py +27 -0
  52. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/common.py +8 -8
  53. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_branch.py +4 -1
  54. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_errors.py +6 -6
  55. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_gitlab_ref.py +20 -2
  56. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_messages.py +5 -0
  57. {hgitaly-1.3.1 → hgitaly-2.10.0/hgitaly.egg-info}/PKG-INFO +10 -1
  58. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly.egg-info/SOURCES.txt +12 -0
  59. hgitaly-2.10.0/hgitaly.egg-info/entry_points.txt +2 -0
  60. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly.egg-info/requires.txt +2 -2
  61. {hgitaly-1.3.1 → hgitaly-2.10.0}/install-requirements.txt +2 -2
  62. {hgitaly-1.3.1 → hgitaly-2.10.0}/setup.py +11 -0
  63. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/comparison.py +247 -101
  64. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/conftest.py +53 -3
  65. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/gitaly.py +8 -4
  66. hgitaly-2.10.0/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +169 -0
  67. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/rhgitaly.py +26 -3
  68. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_blob_tree.py +174 -1
  69. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_commit.py +221 -8
  70. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_diff.py +48 -14
  71. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_gitaly_server.py +7 -4
  72. hgitaly-2.10.0/tests_with_gitaly/test_mercurial_repository.py +232 -0
  73. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_operations.py +37 -30
  74. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_ref.py +127 -1
  75. hgitaly-2.10.0/tests_with_gitaly/test_remote.py +125 -0
  76. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_repository_service.py +41 -75
  77. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_server.py +15 -2
  78. hgitaly-1.3.1/hgitaly/VERSION +0 -1
  79. hgitaly-1.3.1/hgitaly/stub/commit_pb2.py +0 -251
  80. hgitaly-1.3.1/hgitaly/stub/operations_pb2.py +0 -197
  81. hgitaly-1.3.1/hgitaly/stub/repository_pb2.py +0 -401
  82. hgitaly-1.3.1/tests_with_gitaly/hgitaly_rhgitaly_comparison.py +0 -50
  83. {hgitaly-1.3.1 → hgitaly-2.10.0}/LICENSE +0 -0
  84. {hgitaly-1.3.1 → hgitaly-2.10.0}/MANIFEST.in +0 -0
  85. {hgitaly-1.3.1 → hgitaly-2.10.0}/README.md +0 -0
  86. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgext3rd/__init__.py +0 -0
  87. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgext3rd/hgitaly/revset.py +0 -0
  88. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgext3rd/hgitaly/tests/__init__.py +0 -0
  89. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgext3rd/hgitaly/tests/test_revset.py +0 -0
  90. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgext3rd/hgitaly/tests/test_serve.py +0 -0
  91. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/__init__.py +0 -0
  92. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/branch.py +0 -0
  93. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/changelog.py +0 -0
  94. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/feature.py +0 -0
  95. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/file_context.py +0 -0
  96. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/git.py +0 -0
  97. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/license_detector/__init__.py +0 -0
  98. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/license_detector/spdx-licenses.json +0 -0
  99. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/linguist/__init__.py +0 -0
  100. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/linguist/languages.json +0 -0
  101. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/manifest.py +0 -0
  102. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/oid.py +0 -0
  103. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/pagination.py +0 -0
  104. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/path.py +0 -0
  105. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/peer.py +0 -0
  106. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/procutil.py +0 -0
  107. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/revision.py +0 -0
  108. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/revset.py +0 -0
  109. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/__init__.py +0 -0
  110. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/address.py +0 -0
  111. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/prefork.py +0 -0
  112. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/tests/__init__.py +0 -0
  113. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/tests/test_address.py +0 -0
  114. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/tests/test_mono.py +0 -0
  115. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/tests/test_prefork.py +0 -0
  116. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/tests/test_worker.py +0 -0
  117. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/server/worker.py +0 -0
  118. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/__init__.py +0 -0
  119. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/blob.py +0 -0
  120. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/mercurial_changeset.py +0 -0
  121. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/mercurial_repository.py +0 -0
  122. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/__init__.py +0 -0
  123. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_blob.py +0 -0
  124. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_default_branch.py +0 -0
  125. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_mercurial_changeset.py +0 -0
  126. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/service/tests/test_mercurial_repository.py +0 -0
  127. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/servicer.py +0 -0
  128. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stream.py +0 -0
  129. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/__init__.py +0 -0
  130. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/blob_pb2_grpc.py +0 -0
  131. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/errors_pb2_grpc.py +0 -0
  132. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/lint_pb2_grpc.py +0 -0
  133. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/mercurial_changeset_pb2.py +0 -0
  134. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/mercurial_changeset_pb2_grpc.py +0 -0
  135. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/mercurial_operations_pb2.py +0 -0
  136. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/mercurial_operations_pb2_grpc.py +0 -0
  137. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/operations_pb2_grpc.py +0 -0
  138. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/ref_pb2.py +0 -0
  139. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/ref_pb2_grpc.py +0 -0
  140. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/stub/shared_pb2_grpc.py +0 -0
  141. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tag.py +0 -0
  142. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/__init__.py +0 -0
  143. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/bundle.py +0 -0
  144. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/context.py +0 -0
  145. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/grpc.py +0 -0
  146. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/ssh.py +0 -0
  147. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/sshd.py +0 -0
  148. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/tests/__init__.py +0 -0
  149. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/testing/tests/test_sshd.py +0 -0
  150. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/__init__.py +0 -0
  151. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_diff.py +0 -0
  152. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_feature.py +0 -0
  153. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_file_context.py +0 -0
  154. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_license_detector.py +0 -0
  155. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_linguist.py +0 -0
  156. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_manifest.py +0 -0
  157. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_oid.py +0 -0
  158. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_peer.py +0 -0
  159. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_repository.py +0 -0
  160. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_revision.py +0 -0
  161. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_revset.py +0 -0
  162. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_servicer.py +0 -0
  163. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_stream.py +0 -0
  164. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_tag.py +0 -0
  165. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/tests/test_workdir.py +0 -0
  166. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/util.py +0 -0
  167. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly/workdir.py +0 -0
  168. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly.egg-info/dependency_links.txt +0 -0
  169. {hgitaly-1.3.1 → hgitaly-2.10.0}/hgitaly.egg-info/top_level.txt +0 -0
  170. {hgitaly-1.3.1 → hgitaly-2.10.0}/setup.cfg +0 -0
  171. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/__init__.py +0 -0
  172. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_comparison.py +0 -0
  173. {hgitaly-1.3.1 → hgitaly-2.10.0}/tests_with_gitaly/test_rhgitaly_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hgitaly
3
- Version: 1.3.1
3
+ Version: 2.10.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
@@ -10,6 +10,15 @@ 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.0.0dev0
14
+ Requires-Dist: protobuf~=4.21.0
15
+ Requires-Dist: grpcio~=1.58.0
16
+ Requires-Dist: grpcio-status~=1.58.0
17
+ Requires-Dist: grpc-interceptor
18
+ Requires-Dist: hg-loggingmod>=0.4.1
19
+ Requires-Dist: psutil
20
+ Requires-Dist: importlib_resources~=2.0.0
21
+ Requires-Dist: spdx-lookup
13
22
 
14
23
  # HGitaly
15
24
 
@@ -6,6 +6,8 @@
6
6
  # SPDX-License-Identifier: GPL-2.0-or-later
7
7
 
8
8
  # flake8: noqa E402
9
+ import os
10
+ import time
9
11
  from mercurial.i18n import _
10
12
  from mercurial import (
11
13
  demandimport,
@@ -81,6 +83,13 @@ def serve(ui, **opts):
81
83
  By default the root of repositories is read from the
82
84
  `heptapod.repositories-root` configuration item if present.
83
85
  """
86
+ # local time does not make sense for a server-oriented process,
87
+ # so let's switch to UTC. Mercurial itself is transparent about that
88
+ # server-side commits will be recorded as been done UTC, which is fine
89
+ # (it does not change the recorded time, which is always UTC, just some
90
+ # ways of displaying it).
91
+ os.environ['TZ'] = 'UTC'
92
+ time.tzset()
84
93
  listen_urls = [pycompat.sysstr(u) for u in opts['listen']]
85
94
  if not listen_urls:
86
95
  # Any default in the option declaration would be added to
@@ -0,0 +1 @@
1
+ 2.10.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
 
@@ -121,3 +121,27 @@ def operation_error_treatment(context, error_message_class, logger,
121
121
  # // The post-receive hook runs after references have been updated
122
122
  # // and any failures of it are ignored.
123
123
  logger.error("Error in GitLab post-receive hook: %r", exc.message)
124
+
125
+
126
+ class MercurialNotFound(LookupError):
127
+ """General class for all failed lookups.
128
+
129
+ Better for us that to use `hg.errors.LookupError` because the latter is
130
+ not systematically raised. Anyway, we need our own articulation point.
131
+ """
132
+
133
+
134
+ class MercurialPathNotFound(MercurialNotFound):
135
+ """Express that some path could not be found.
136
+
137
+ This is generally in the context of some changeset that the caller is
138
+ aware of, but it could be in an entire revset, in the workdir…
139
+ """
140
+
141
+
142
+ class MercurialChangesetNotFound(MercurialNotFound):
143
+ """Express that one or serveral changesets could not be found.
144
+
145
+ In case the caller did a call possibly involving several changesets,
146
+ the failing, perhaps more specific, expression can be set as argument.
147
+ """
@@ -0,0 +1,160 @@
1
+ # Copyright 2024 Georges Racinet <georges.racinet@cloudcrane.io>
2
+ #
3
+ # This software may be used and distributed according to the terms of the
4
+ # GNU General Public License version 2 or any later version.
5
+ #
6
+ # SPDX-License-Identifier: GPL-2.0-or-later
7
+ import re
8
+
9
+ from mercurial import (
10
+ error as hgerror,
11
+ )
12
+
13
+ from .errors import (
14
+ MercurialPathNotFound,
15
+ MercurialChangesetNotFound,
16
+ )
17
+ from .oid import extract_blob_oid
18
+ from .stub.analysis_pb2 import (
19
+ CheckBlobsGeneratedRequest,
20
+ )
21
+
22
+
23
+ def frozen_bytes_set(it):
24
+ return frozenset(s.encode('ascii') for s in it)
25
+
26
+
27
+ # compare go-enry/data/generated.go
28
+ GENERATED_FILE_PATH_REGEXPS = [
29
+ re.compile(b'|'.join((
30
+ rb'(^Pods|/Pods)/', # Cocoa pods
31
+ rb'(^|/)Carthage/Build/', # Carthage build
32
+ rb'\.feature\.css$', # Generated NET specflow feature file
33
+ rb'node_modules/', # Node modules
34
+ # Go vendor
35
+ rb'vendor/([-0-9A-Za-z]+\.)+(com|edu|gov|in|me|net|org|fm|io)',
36
+ rb'(Gopkg|glide).lock$', # Go lock
37
+ rb'(^|/)(\w+\.)?esy.lock$`', # Esy lock
38
+ rb'npm-shrinkwrap.json$',
39
+ rb'package-lock.json$', # NPM package lock
40
+ rb'(^|/)\.pnp\.(c|m)?js$', # Yarn plugnplay
41
+ rb'Godeps/',
42
+ rb'composer.lock$',
43
+ rb'.\.zep\.(?:c|h|php)$', # Generated by zephir
44
+ rb'Cargo.lock$',
45
+ rb'Pipfile.lock$', # Pipenv lock
46
+ rb'__generated__/', # GraphQL relay
47
+ rb'\.(js|css)\.map$', # Source map
48
+ ))),
49
+ re.compile(b'|'.join((
50
+ rb'\.designer\.(cs|vb)$', # NET designer file
51
+ )), re.IGNORECASE),
52
+ ]
53
+
54
+ # compare go-enry/data/generated.go
55
+ GENERATED_FILE_EXTENSIONS = frozen_bytes_set((
56
+ # Xcode
57
+ 'nib',
58
+ 'xcworkspacedata',
59
+ 'xcuserstate',
60
+ # TODO complete the list
61
+ ))
62
+
63
+ GENERATED_LINE_RX = re.compile(
64
+ b'|'.join((
65
+ # Source Map
66
+ rb'\A{"version":\d+',
67
+ rb'\A/\*\*Begin line maps\. \*\*/{',
68
+ # Generated NetDoc TODO should be only for .xml files
69
+ rb'\A.*$.*<doc>.*(\r)?\n.*<assembly>(\r)?\n.*</doc>(\r)?\n.*\Z',
70
+ # PEG.js
71
+ rb'^(?:[^/]|/[^\*])*/\*(?:[^\*]|\*[^/])*Generated by PEG.js',
72
+ # Generated Go (actually our version is more general, but anything
73
+ # matching this regexp is looking for trouble!
74
+ rb'Code generated by',
75
+ # Protocol Buffers, general case
76
+ b"Generated by the protocol buffer compiler. DO NOT EDIT!",
77
+ # Protocol Buffers, JavaScript (should be only line 6 and crossed with
78
+ # extension, but given the content, matching this is acceptable
79
+ # TODO unless we are looking at a code generator!
80
+ b"GENERATED CODE -- DO NOT EDIT!",
81
+ # Apache Thrift
82
+ b"Autogenerated by Thrift Compiler",
83
+ # JNI header (again more general than go-enry, because we don't want
84
+ # to assert it to be JNI, just that it is generated)
85
+ rb"/\* DO NOT EDIT THIS FILE - it is machine generated \*/",
86
+ # VCR Cassette TODO should be for .yml files only
87
+ rb"\A.*(\r)?\n.*recorded_with: VCR",
88
+ # Compiled Cython TODO should be .c files only
89
+ rb"\A.*Generated by Cython",
90
+ # (Fortran) module
91
+ rb"\A.*(PCBNEW-LibModule-V|GFORTRAN module version ')",
92
+ # Racc
93
+ rb"# This file is automatically generated by Racc",
94
+ # JFlex
95
+ rb"/\* The following code was generated by JFlex ",
96
+ # Grammar Kit
97
+ rb"// This is a generated file. Not intended for manual editing\.",
98
+ # Roxygen 2
99
+ rb"% Generated by roxygen2: do not edit by hand",
100
+ # Jison
101
+ rb"/\* (parser generated by jison |generated by jison-lex )",
102
+ # gRPC C++
103
+ rb"// Generated by the gRPC",
104
+ # Dart
105
+ rb"generated code\W{2,3}do not modify",
106
+ # Perl's PPPort
107
+ rb"Automatically created by Devel::PPPort",
108
+ # GIMP
109
+ rb'/\* GIMP [a-zA-Z0-9\- ]+ C\-Source image dump \(.+?\.c\) \*/',
110
+ (rb'/\* GIMP header image file format '
111
+ rb'\([a-zA-Z0-9\- ]+\)\: .+?\.h \*/'),
112
+ # Visual Studio 6
113
+ rb'# Microsoft Developer Studio Generated Build File',
114
+ # Haxe
115
+ rb"Generated by Haxe",
116
+ # Jooq
117
+ rb"This file is generated by jOOQ\.",
118
+ )),
119
+ re.MULTILINE
120
+ )
121
+
122
+ # TODO isMinifiedFile, hasSourceMapReference, isCompiledCoffeeScript,
123
+ # isGeneratedPostScript,
124
+ # isGeneratedUnity3DMeta (extension restrictions should really apply)
125
+ # isGeneratedGameMakerStudio, isGeneratedHTML
126
+
127
+
128
+ def is_blob_generated(repo, blob: CheckBlobsGeneratedRequest.Blob):
129
+ """"Detect if a blob is made of generated data."""
130
+ # For now the Rails application sends revisions in `commit_id:path`
131
+ # format, so close to HGitaly blob oids (!). Probably upstream does not
132
+ # want to use actual Git blob oids, but Gitaly does support them
133
+ colon_split = blob.revision.split(b':', 1)
134
+ if len(colon_split) == 2:
135
+ csid, rpath = colon_split
136
+ else: # direct oid
137
+ csid, rpath = extract_blob_oid(repo, blob.revision.decode('utf-8'))
138
+
139
+ if csid is None or rpath is None:
140
+ raise ValueError("Invalid blob oid")
141
+
142
+ extension = rpath.rsplit(b'.', 1)[-1]
143
+ if extension in GENERATED_FILE_EXTENSIONS:
144
+ return True
145
+
146
+ if any(rx.search(rpath) is not None
147
+ for rx in GENERATED_FILE_PATH_REGEXPS):
148
+ return True
149
+
150
+ try:
151
+ changeset = repo[csid]
152
+ except hgerror.RepoLookupError:
153
+ raise MercurialChangesetNotFound(csid)
154
+
155
+ try:
156
+ filectx = changeset.filectx(rpath)
157
+ except KeyError:
158
+ raise MercurialPathNotFound(rpath)
159
+
160
+ return GENERATED_LINE_RX.search(filectx.data()) is not None
@@ -28,7 +28,11 @@ from hgext3rd.heptapod.special_ref import (
28
28
  parse_special_ref,
29
29
  special_refs,
30
30
  )
31
- from hgext3rd.heptapod.keep_around import iter_keep_arounds
31
+ from hgext3rd.heptapod.keep_around import (
32
+ iter_keep_arounds,
33
+ KEEP_AROUND_REF_PREFIX,
34
+ KEEP_AROUND_REF_PREFIX_LEN,
35
+ )
32
36
 
33
37
 
34
38
  def gitlab_special_ref_target(repo, ref_path):
@@ -130,7 +134,13 @@ def has_keep_around(repo, sha):
130
134
 
131
135
  def keep_around_ref_path(sha):
132
136
  # TODO should move to py-heptapod
133
- return b'refs/keep-around/' + sha
137
+ return KEEP_AROUND_REF_PREFIX + sha
138
+
139
+
140
+ def parse_keep_around_ref_path(ref):
141
+ if not ref.startswith(KEEP_AROUND_REF_PREFIX):
142
+ return None
143
+ return ref[KEEP_AROUND_REF_PREFIX_LEN:]
134
144
 
135
145
 
136
146
  def iter_keep_arounds_as_refs(repo, deref=True, patterns=None):
@@ -4,7 +4,9 @@
4
4
  # GNU General Public License version 2 or any later version.
5
5
  #
6
6
  # SPDX-License-Identifier: GPL-2.0-or-later
7
+ import attr
7
8
  import logging
9
+ from typing import Any
8
10
 
9
11
 
10
12
  _missing = object()
@@ -28,14 +30,16 @@ def extract_correlation(context):
28
30
  return corr_id
29
31
 
30
32
 
33
+ @attr.define
31
34
  class LoggerAdapter(logging.LoggerAdapter):
32
-
33
- def __init__(self, logger, context):
34
- self.grpc_context = context
35
- self.logger = logger
35
+ logger: Any
36
+ grpc_context: Any
36
37
 
37
38
  def process(self, msg, kwargs):
39
+ extra = kwargs.get('extra')
40
+ if extra is None:
41
+ kwargs['extra'] = extra = {}
42
+
38
43
  # set on context by interceptor
39
- kwargs['extra'] = {'correlation_id':
40
- extract_correlation(self.grpc_context)}
44
+ extra['correlation_id'] = extract_correlation(self.grpc_context)
41
45
  return msg, kwargs
@@ -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
 
@@ -39,34 +39,6 @@ AUTO_PUBLISH_MAPPING = {
39
39
  AUTO_PUBLISH_REVERSE_MAPPING = {v: k for k, v in AUTO_PUBLISH_MAPPING.items()}
40
40
 
41
41
 
42
- def set_gitlab_project_full_path(repo, full_path: bytes):
43
- """Store information about the full path of GitLab Project.
44
-
45
- In GitLab terminology, ``full_path`` is the URI path, while ``path``
46
- its the last segment of ``full_path``.
47
-
48
- In Git repositories, this is stored in config. We could as well use
49
- the repo-local hgrcs, but it is simpler to use a dedicated file, and
50
- it makes sense to consider it not part of ``store`` (``svfs``), same
51
- as ``hgrc``.
52
- """
53
- with repo.wlock():
54
- repo.vfs.write(GITLAB_PROJECT_FULL_PATH_FILENAME, full_path)
55
-
56
-
57
- def get_gitlab_project_full_path(repo):
58
- """Get the full path of GitLab Project.
59
-
60
- See also :func:`set_gitlab_project_full_path`.
61
-
62
- :return: the full path, or ``None`` if not set.
63
- """
64
- try:
65
- return repo.vfs.read(GITLAB_PROJECT_FULL_PATH_FILENAME)
66
- except FileNotFoundError:
67
- return None
68
-
69
-
70
42
  def unbundle(repo, bundle_path: str, rails_sync=False):
71
43
  """Call unbundle with proper options and conversions.
72
44