pygit2 1.17.0__tar.gz → 1.18.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 (189) hide show
  1. {pygit2-1.17.0 → pygit2-1.18.0}/AUTHORS.md +8 -2
  2. {pygit2-1.17.0 → pygit2-1.18.0}/CHANGELOG.md +63 -5
  3. {pygit2-1.17.0 → pygit2-1.18.0}/PKG-INFO +15 -2
  4. {pygit2-1.17.0 → pygit2-1.18.0}/build.sh +1 -0
  5. {pygit2-1.17.0 → pygit2-1.18.0}/build_tag.py +2 -1
  6. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/__init__.py +34 -15
  7. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/_build.py +2 -2
  8. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/_pygit2.pyi +1 -1
  9. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/callbacks.py +63 -8
  10. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/config.py +2 -2
  11. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/credentials.py +22 -8
  12. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/callbacks.h +6 -0
  13. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/commit.h +5 -0
  14. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/repository.h +1 -1
  15. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/errors.py +1 -1
  16. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/ffi.py +1 -1
  17. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/refspec.py +1 -1
  18. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/remotes.py +41 -35
  19. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/repository.py +50 -24
  20. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/utils.py +7 -7
  21. {pygit2-1.17.0 → pygit2-1.18.0}/pyproject.toml +9 -9
  22. {pygit2-1.17.0 → pygit2-1.18.0}/src/blob.c +20 -12
  23. {pygit2-1.17.0 → pygit2-1.18.0}/src/odb_backend.c +1 -1
  24. {pygit2-1.17.0 → pygit2-1.18.0}/src/oid.c +49 -1
  25. {pygit2-1.17.0 → pygit2-1.18.0}/src/pygit2.c +1 -1
  26. {pygit2-1.17.0 → pygit2-1.18.0}/src/reference.c +10 -1
  27. {pygit2-1.17.0 → pygit2-1.18.0}/src/repository.c +2 -2
  28. {pygit2-1.17.0 → pygit2-1.18.0}/src/signature.c +1 -1
  29. {pygit2-1.17.0 → pygit2-1.18.0}/src/tree.c +7 -6
  30. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_commit.py +2 -2
  31. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_credentials.py +0 -2
  32. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_diff.py +77 -1
  33. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_merge.py +59 -32
  34. pygit2-1.18.0/test/test_nonunicode.py +48 -0
  35. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_object.py +2 -2
  36. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_odb.py +1 -1
  37. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_oid.py +7 -0
  38. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_remote.py +101 -28
  39. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_repository.py +22 -3
  40. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_repository_bare.py +9 -9
  41. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_tree.py +1 -1
  42. {pygit2-1.17.0 → pygit2-1.18.0}/test/utils.py +5 -6
  43. {pygit2-1.17.0 → pygit2-1.18.0}/COPYING +0 -0
  44. {pygit2-1.17.0 → pygit2-1.18.0}/Makefile +0 -0
  45. {pygit2-1.17.0 → pygit2-1.18.0}/README.md +0 -0
  46. {pygit2-1.17.0 → pygit2-1.18.0}/SPONSORS.md +0 -0
  47. {pygit2-1.17.0 → pygit2-1.18.0}/mypy-stubtest.ini +0 -0
  48. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/_run.py +0 -0
  49. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/blame.py +0 -0
  50. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/blob.py +0 -0
  51. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/branches.py +0 -0
  52. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/attr.h +0 -0
  53. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/blame.h +0 -0
  54. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/buffer.h +0 -0
  55. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/checkout.h +0 -0
  56. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/clone.h +0 -0
  57. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/common.h +0 -0
  58. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/config.h +0 -0
  59. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/describe.h +0 -0
  60. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/diff.h +0 -0
  61. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/errors.h +0 -0
  62. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/graph.h +0 -0
  63. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/index.h +0 -0
  64. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/indexer.h +0 -0
  65. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/merge.h +0 -0
  66. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/net.h +0 -0
  67. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/oid.h +0 -0
  68. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/pack.h +0 -0
  69. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/proxy.h +0 -0
  70. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/refspec.h +0 -0
  71. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/remote.h +0 -0
  72. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/revert.h +0 -0
  73. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/stash.h +0 -0
  74. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/strarray.h +0 -0
  75. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/submodule.h +0 -0
  76. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/transport.h +0 -0
  77. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/decl/types.h +0 -0
  78. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/enums.py +0 -0
  79. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/filter.py +0 -0
  80. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/index.py +0 -0
  81. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/legacyenums.py +0 -0
  82. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/packbuilder.py +0 -0
  83. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/py.typed +0 -0
  84. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/references.py +0 -0
  85. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/settings.py +0 -0
  86. {pygit2-1.17.0 → pygit2-1.18.0}/pygit2/submodules.py +0 -0
  87. {pygit2-1.17.0 → pygit2-1.18.0}/pytest.ini +0 -0
  88. {pygit2-1.17.0 → pygit2-1.18.0}/requirements-test.txt +0 -0
  89. {pygit2-1.17.0 → pygit2-1.18.0}/requirements.txt +0 -0
  90. {pygit2-1.17.0 → pygit2-1.18.0}/setup.cfg +0 -0
  91. {pygit2-1.17.0 → pygit2-1.18.0}/setup.py +0 -0
  92. {pygit2-1.17.0 → pygit2-1.18.0}/src/branch.c +0 -0
  93. {pygit2-1.17.0 → pygit2-1.18.0}/src/branch.h +0 -0
  94. {pygit2-1.17.0 → pygit2-1.18.0}/src/commit.c +0 -0
  95. {pygit2-1.17.0 → pygit2-1.18.0}/src/diff.c +0 -0
  96. {pygit2-1.17.0 → pygit2-1.18.0}/src/diff.h +0 -0
  97. {pygit2-1.17.0 → pygit2-1.18.0}/src/error.c +0 -0
  98. {pygit2-1.17.0 → pygit2-1.18.0}/src/error.h +0 -0
  99. {pygit2-1.17.0 → pygit2-1.18.0}/src/filter.c +0 -0
  100. {pygit2-1.17.0 → pygit2-1.18.0}/src/filter.h +0 -0
  101. {pygit2-1.17.0 → pygit2-1.18.0}/src/mailmap.c +0 -0
  102. {pygit2-1.17.0 → pygit2-1.18.0}/src/mailmap.h +0 -0
  103. {pygit2-1.17.0 → pygit2-1.18.0}/src/note.c +0 -0
  104. {pygit2-1.17.0 → pygit2-1.18.0}/src/note.h +0 -0
  105. {pygit2-1.17.0 → pygit2-1.18.0}/src/object.c +0 -0
  106. {pygit2-1.17.0 → pygit2-1.18.0}/src/object.h +0 -0
  107. {pygit2-1.17.0 → pygit2-1.18.0}/src/odb.c +0 -0
  108. {pygit2-1.17.0 → pygit2-1.18.0}/src/odb.h +0 -0
  109. {pygit2-1.17.0 → pygit2-1.18.0}/src/odb_backend.h +0 -0
  110. {pygit2-1.17.0 → pygit2-1.18.0}/src/oid.h +0 -0
  111. {pygit2-1.17.0 → pygit2-1.18.0}/src/options.c +0 -0
  112. {pygit2-1.17.0 → pygit2-1.18.0}/src/options.h +0 -0
  113. {pygit2-1.17.0 → pygit2-1.18.0}/src/patch.c +0 -0
  114. {pygit2-1.17.0 → pygit2-1.18.0}/src/patch.h +0 -0
  115. {pygit2-1.17.0 → pygit2-1.18.0}/src/refdb.c +0 -0
  116. {pygit2-1.17.0 → pygit2-1.18.0}/src/refdb.h +0 -0
  117. {pygit2-1.17.0 → pygit2-1.18.0}/src/refdb_backend.c +0 -0
  118. {pygit2-1.17.0 → pygit2-1.18.0}/src/refdb_backend.h +0 -0
  119. {pygit2-1.17.0 → pygit2-1.18.0}/src/reference.h +0 -0
  120. {pygit2-1.17.0 → pygit2-1.18.0}/src/repository.h +0 -0
  121. {pygit2-1.17.0 → pygit2-1.18.0}/src/revspec.c +0 -0
  122. {pygit2-1.17.0 → pygit2-1.18.0}/src/revspec.h +0 -0
  123. {pygit2-1.17.0 → pygit2-1.18.0}/src/signature.h +0 -0
  124. {pygit2-1.17.0 → pygit2-1.18.0}/src/stash.c +0 -0
  125. {pygit2-1.17.0 → pygit2-1.18.0}/src/tag.c +0 -0
  126. {pygit2-1.17.0 → pygit2-1.18.0}/src/tree.h +0 -0
  127. {pygit2-1.17.0 → pygit2-1.18.0}/src/treebuilder.c +0 -0
  128. {pygit2-1.17.0 → pygit2-1.18.0}/src/treebuilder.h +0 -0
  129. {pygit2-1.17.0 → pygit2-1.18.0}/src/types.h +0 -0
  130. {pygit2-1.17.0 → pygit2-1.18.0}/src/utils.c +0 -0
  131. {pygit2-1.17.0 → pygit2-1.18.0}/src/utils.h +0 -0
  132. {pygit2-1.17.0 → pygit2-1.18.0}/src/walker.c +0 -0
  133. {pygit2-1.17.0 → pygit2-1.18.0}/src/walker.h +0 -0
  134. {pygit2-1.17.0 → pygit2-1.18.0}/src/wildmatch.c +0 -0
  135. {pygit2-1.17.0 → pygit2-1.18.0}/src/wildmatch.h +0 -0
  136. {pygit2-1.17.0 → pygit2-1.18.0}/src/worktree.c +0 -0
  137. {pygit2-1.17.0 → pygit2-1.18.0}/src/worktree.h +0 -0
  138. {pygit2-1.17.0 → pygit2-1.18.0}/test/__init__.py +0 -0
  139. {pygit2-1.17.0 → pygit2-1.18.0}/test/conftest.py +0 -0
  140. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/barerepo.zip +0 -0
  141. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/binaryfilerepo.zip +0 -0
  142. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/blameflagsrepo.zip +0 -0
  143. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/dirtyrepo.zip +0 -0
  144. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/emptyrepo.zip +0 -0
  145. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/encoding.zip +0 -0
  146. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/gpgsigned.zip +0 -0
  147. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/submodulerepo.zip +0 -0
  148. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/testrepo.zip +0 -0
  149. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/testrepoformerging.zip +0 -0
  150. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/testrepopacked.zip +0 -0
  151. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/trailerrepo.zip +0 -0
  152. {pygit2-1.17.0 → pygit2-1.18.0}/test/data/utf8branchrepo.zip +0 -0
  153. {pygit2-1.17.0 → pygit2-1.18.0}/test/keys/pygit2_empty +0 -0
  154. {pygit2-1.17.0 → pygit2-1.18.0}/test/keys/pygit2_empty.pub +0 -0
  155. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_apply_diff.py +0 -0
  156. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_archive.py +0 -0
  157. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_attributes.py +0 -0
  158. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_blame.py +0 -0
  159. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_blob.py +0 -0
  160. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_branch.py +0 -0
  161. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_branch_empty.py +0 -0
  162. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_cherrypick.py +0 -0
  163. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_commit_gpg.py +0 -0
  164. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_commit_trailer.py +0 -0
  165. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_config.py +0 -0
  166. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_describe.py +0 -0
  167. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_diff_binary.py +0 -0
  168. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_filter.py +0 -0
  169. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_index.py +0 -0
  170. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_mailmap.py +0 -0
  171. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_note.py +0 -0
  172. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_odb_backend.py +0 -0
  173. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_options.py +0 -0
  174. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_packbuilder.py +0 -0
  175. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_patch.py +0 -0
  176. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_patch_encoding.py +0 -0
  177. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_refdb_backend.py +0 -0
  178. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_refs.py +0 -0
  179. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_remote_prune.py +0 -0
  180. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_remote_utf8.py +0 -0
  181. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_repository_custom.py +0 -0
  182. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_repository_empty.py +0 -0
  183. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_revparse.py +0 -0
  184. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_revwalk.py +0 -0
  185. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_signature.py +0 -0
  186. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_status.py +0 -0
  187. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_submodule.py +0 -0
  188. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_tag.py +0 -0
  189. {pygit2-1.17.0 → pygit2-1.18.0}/test/test_treebuilder.py +0 -0
@@ -43,14 +43,16 @@ Authors:
43
43
  Chad Dombrova
44
44
  Lukas Fleischer
45
45
  Mathias Leppich
46
+ Mathieu Parent
47
+ Michał Kępień
46
48
  Nicolas Dandrimont
47
49
  Raphael Medaer (Escaux)
50
+ Yaroslav Halchenko
48
51
  Anatoly Techtonik
49
52
  Andrew Olsen
50
53
  Dan Sully
51
54
  David Versmisse
52
55
  Grégory Herrero
53
- Michał Kępień
54
56
  Mikhail Yushkovskiy
55
57
  Robin Stocker
56
58
  Rohit Sanjay
@@ -89,6 +91,7 @@ Authors:
89
91
  Andrey Devyatkin
90
92
  Arno van Lumig
91
93
  Ben Davis
94
+ CJ Steiner
92
95
  Colin Watson
93
96
  Dan Yeaw
94
97
  Dustin Raimondi
@@ -114,7 +117,6 @@ Authors:
114
117
  Kyle Gottfried
115
118
  Marcel Waldvogel
116
119
  Masud Rahman
117
- Mathieu Parent
118
120
  Michael Sondergaard
119
121
  Natanael Arndt
120
122
  Ondřej Nový
@@ -127,6 +129,7 @@ Authors:
127
129
  nikitalita
128
130
  Adam Gausmann
129
131
  Adam Spiers
132
+ Adrien Nader
130
133
  Albin Söderström
131
134
  Alexandru Fikl
132
135
  Andrew Chin
@@ -160,6 +163,7 @@ Authors:
160
163
  David Six
161
164
  Dennis Schwertel
162
165
  Devaev Maxim
166
+ Edmundo Carmona Antoranz
163
167
  Eric Davis
164
168
  Erik Meusel
165
169
  Erik van Zijst
@@ -180,6 +184,7 @@ Authors:
180
184
  Josh Bleecher Snyder
181
185
  Julia Evans
182
186
  Justin Clift
187
+ Karl Malmros
183
188
  Kevin Valk
184
189
  Konstantinos Smanis
185
190
  Kyriakos Oikonomakos
@@ -224,6 +229,7 @@ Authors:
224
229
  Timo Röhling
225
230
  Victor Florea
226
231
  Vladimir Rutsky
232
+ William Schueller
227
233
  Wim Jeantine-Glenn
228
234
  Yu Jianjian
229
235
  buhl
@@ -1,3 +1,61 @@
1
+ # 1.18.0 (2025-04-24)
2
+
3
+ - Upgrade Linux Glibc wheels to `manylinux_2_28`
4
+
5
+ - Add `RemoteCallbacks.push_transfer_progress(...)` callback
6
+ [#1345](https://github.com/libgit2/pygit2/pull/1345)
7
+
8
+ - New `bool(oid)`
9
+ [#1347](https://github.com/libgit2/pygit2/pull/1347)
10
+
11
+ - Now `Repository.merge(...)` accepts a commit or reference object
12
+ [#1348](https://github.com/libgit2/pygit2/pull/1348)
13
+
14
+ - New `threads` optional argument in `Remote.push(...)`
15
+ [#1352](https://github.com/libgit2/pygit2/pull/1352)
16
+
17
+ - New `proxy` optional argument in `clone_repository(...)`
18
+ [#1354](https://github.com/libgit2/pygit2/pull/1354)
19
+
20
+ - New optional arguments `context_lines` and `interhunk_lines` in `Blob.diff(...)` ; and
21
+ now `Repository.diff(...)` honors these two arguments when the objects diffed are blobs.
22
+ [#1360](https://github.com/libgit2/pygit2/pull/1360)
23
+
24
+ - Now `Tree.diff_to_workdir(...)` accepts keyword arguments, not just positional.
25
+
26
+ - Fix when a reference name has non UTF-8 chars
27
+ [#1329](https://github.com/libgit2/pygit2/pull/1329)
28
+
29
+ - Fix condition check in `Repository.remotes.rename(...)`
30
+ [#1342](https://github.com/libgit2/pygit2/pull/1342)
31
+
32
+ - Add codespell workflow, fix a number of typos
33
+ [#1344](https://github.com/libgit2/pygit2/pull/1344)
34
+
35
+ - Documentation and typing
36
+ [#1343](https://github.com/libgit2/pygit2/pull/1343)
37
+ [#1347](https://github.com/libgit2/pygit2/pull/1347)
38
+ [#1356](https://github.com/libgit2/pygit2/pull/1356)
39
+
40
+ - CI: Use ARM runner for tests and wheels
41
+ [#1346](https://github.com/libgit2/pygit2/pull/1346)
42
+
43
+ - Build and CI updates
44
+ [#1363](https://github.com/libgit2/pygit2/pull/1363)
45
+ [#1365](https://github.com/libgit2/pygit2/pull/1365)
46
+
47
+ Deprecations:
48
+
49
+ - Passing str to `Repository.merge(...)` is deprecated,
50
+ instead pass an oid object (or a commit, or a reference)
51
+ [#1349](https://github.com/libgit2/pygit2/pull/1349)
52
+
53
+ Breaking changes:
54
+
55
+ - Keyword argument `flag` has been renamed to `flags` in `Blob.diff(...)` and
56
+ `Blob.diff_to_buffer(...)`
57
+
58
+
1
59
  # 1.17.0 (2025-01-08)
2
60
 
3
61
  - Upgrade to libgit2 1.9
@@ -259,7 +317,7 @@ Deprecations:
259
317
  - New `keep_all` and `paths` optional arguments for
260
318
  `Repository.stash(...)`
261
319
  [#1202](https://github.com/libgit2/pygit2/pull/1202)
262
- - New `Respository.state()`
320
+ - New `Repository.state()`
263
321
  [#1204](https://github.com/libgit2/pygit2/pull/1204)
264
322
  - Improve `Repository.write_archive(...)` performance
265
323
  [#1183](https://github.com/libgit2/pygit2/pull/1183)
@@ -439,7 +497,7 @@ Breaking changes:
439
497
 
440
498
  Breaking changes:
441
499
 
442
- - Remove deprecated `GIT_CREDTYPE_XXX` contants, use
500
+ - Remove deprecated `GIT_CREDTYPE_XXX` constants, use
443
501
  `GIT_CREDENTIAL_XXX` instead.
444
502
  - Remove deprecated `Patch.patch` getter, use `Patch.text` instead.
445
503
 
@@ -536,7 +594,7 @@ Deprecations:
536
594
 
537
595
  - Deprecate `Repository.create_remote(...)`, use instead
538
596
  `Repository.remotes.create(...)`
539
- - Deprecate `GIT_CREDTYPE_XXX` contants, use `GIT_CREDENTIAL_XXX`
597
+ - Deprecate `GIT_CREDTYPE_XXX` constants, use `GIT_CREDENTIAL_XXX`
540
598
  instead.
541
599
 
542
600
  # 1.2.0 (2020-04-05)
@@ -657,7 +715,7 @@ Breaking changes:
657
715
 
658
716
  Breaking changes:
659
717
 
660
- - Now the Repository has a new attribue `odb` for object database:
718
+ - Now the Repository has a new attribute `odb` for object database:
661
719
 
662
720
  # Before
663
721
  repository.read(...)
@@ -862,7 +920,7 @@ Other changes:
862
920
  [#610](https://github.com/libgit2/pygit2/issues/610)
863
921
  - Fix tests failing in some cases
864
922
  [#795](https://github.com/libgit2/pygit2/issues/795)
865
- - Automatize wheels upload to pypi
923
+ - Automate wheels upload to pypi
866
924
  [#563](https://github.com/libgit2/pygit2/issues/563)
867
925
 
868
926
  # 0.27.0 (2018-03-30)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: pygit2
3
- Version: 1.17.0
3
+ Version: 1.18.0
4
4
  Summary: Python bindings for libgit2.
5
5
  Home-page: https://github.com/libgit2/pygit2
6
6
  Maintainer: J. David Ibáñez
@@ -27,6 +27,19 @@ Description-Content-Type: text/markdown
27
27
  License-File: COPYING
28
28
  License-File: AUTHORS.md
29
29
  Requires-Dist: cffi>=1.17.0
30
+ Dynamic: classifier
31
+ Dynamic: description
32
+ Dynamic: description-content-type
33
+ Dynamic: home-page
34
+ Dynamic: keywords
35
+ Dynamic: license
36
+ Dynamic: license-file
37
+ Dynamic: maintainer
38
+ Dynamic: maintainer-email
39
+ Dynamic: project-url
40
+ Dynamic: requires-dist
41
+ Dynamic: requires-python
42
+ Dynamic: summary
30
43
 
31
44
  # pygit2 - libgit2 bindings in Python
32
45
 
@@ -69,6 +69,7 @@ if [ "$CIBUILDWHEEL" = "1" ]; then
69
69
  yum install openssl-devel -y
70
70
  else
71
71
  yum install perl-IPC-Cmd -y
72
+ yum install perl-Pod-Html -y
72
73
  fi
73
74
  elif [ -f /sbin/apk ]; then
74
75
  apk add wget
@@ -1,4 +1,5 @@
1
- import platform, sys
1
+ import platform
2
+ import sys
2
3
 
3
4
  py = {'CPython': 'cp', 'PyPy': 'pp'}[platform.python_implementation()]
4
5
  print(f'{py}{sys.version_info.major}{sys.version_info.minor}')
@@ -23,9 +23,11 @@
23
23
  # the Free Software Foundation, 51 Franklin Street, Fifth Floor,
24
24
  # Boston, MA 02110-1301, USA.
25
25
 
26
+ # ruff: noqa: F401 F403 F405
27
+
26
28
  # Standard Library
27
29
  import functools
28
- from os import PathLike
30
+ import os
29
31
  import typing
30
32
 
31
33
  # Low level API
@@ -38,7 +40,12 @@ from ._build import __version__
38
40
  from .blame import Blame, BlameHunk
39
41
  from .blob import BlobIO
40
42
  from .callbacks import Payload, RemoteCallbacks, CheckoutCallbacks, StashApplyCallbacks
41
- from .callbacks import git_clone_options, git_fetch_options, get_credentials
43
+ from .callbacks import (
44
+ git_clone_options,
45
+ git_fetch_options,
46
+ git_proxy_options,
47
+ get_credentials,
48
+ )
42
49
  from .config import Config
43
50
  from .credentials import *
44
51
  from .errors import check_error, Passthrough
@@ -66,7 +73,7 @@ _cache_enums()
66
73
 
67
74
 
68
75
  def init_repository(
69
- path: typing.Union[str, bytes, PathLike, None],
76
+ path: typing.Union[str, bytes, os.PathLike, None],
70
77
  bare: bool = False,
71
78
  flags: enums.RepositoryInitFlag = enums.RepositoryInitFlag.MKPATH,
72
79
  mode: typing.Union[
@@ -86,7 +93,7 @@ def init_repository(
86
93
 
87
94
  The *flags* may be a combination of enums.RepositoryInitFlag constants:
88
95
 
89
- - BARE (overriden by the *bare* parameter)
96
+ - BARE (overridden by the *bare* parameter)
90
97
  - NO_REINIT
91
98
  - NO_DOTGIT_DIR
92
99
  - MKDIR
@@ -99,6 +106,10 @@ def init_repository(
99
106
  The *workdir_path*, *description*, *template_path*, *initial_head* and
100
107
  *origin_url* are all strings.
101
108
 
109
+ If a repository already exists at *path*, it may be opened successfully but
110
+ you must not rely on that behavior and should use the Repository
111
+ constructor directly instead.
112
+
102
113
  See libgit2's documentation on git_repository_init_ext for further details.
103
114
  """
104
115
  # Pre-process input parameters
@@ -144,14 +155,15 @@ def init_repository(
144
155
 
145
156
 
146
157
  def clone_repository(
147
- url,
148
- path,
149
- bare=False,
150
- repository=None,
151
- remote=None,
152
- checkout_branch=None,
153
- callbacks=None,
154
- depth=0,
158
+ url: str,
159
+ path: str,
160
+ bare: bool = False,
161
+ repository: typing.Callable | None = None,
162
+ remote: typing.Callable | None = None,
163
+ checkout_branch: str | None = None,
164
+ callbacks: RemoteCallbacks | None = None,
165
+ depth: int = 0,
166
+ proxy: None | bool | str = None,
155
167
  ):
156
168
  """
157
169
  Clones a new Git repository from *url* in the given *path*.
@@ -192,6 +204,12 @@ def clone_repository(
192
204
  If greater than 0, creates a shallow clone with a history truncated to
193
205
  the specified number of commits.
194
206
  The default is 0 (full commit history).
207
+ proxy : None or True or str
208
+ Proxy configuration. Can be one of:
209
+
210
+ * `None` (the default) to disable proxy usage
211
+ * `True` to enable automatic proxy detection
212
+ * an url to a proxy (`http://proxy.example.org:3128/`)
195
213
  """
196
214
 
197
215
  if callbacks is None:
@@ -212,9 +230,10 @@ def clone_repository(
212
230
  opts.checkout_branch = checkout_branch_ref
213
231
 
214
232
  with git_fetch_options(payload, opts=opts.fetch_opts):
215
- crepo = ffi.new('git_repository **')
216
- err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
217
- payload.check_error(err)
233
+ with git_proxy_options(payload, opts.fetch_opts.proxy_opts, proxy):
234
+ crepo = ffi.new('git_repository **')
235
+ err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
236
+ payload.check_error(err)
218
237
 
219
238
  # Ok
220
239
  return Repository._from_c(crepo[0], owned=True)
@@ -34,11 +34,11 @@ from pathlib import Path
34
34
  #
35
35
  # The version number of pygit2
36
36
  #
37
- __version__ = '1.17.0'
37
+ __version__ = '1.18.0'
38
38
 
39
39
 
40
40
  #
41
- # Utility functions to get the paths required for bulding extensions
41
+ # Utility functions to get the paths required for building extensions
42
42
  #
43
43
  def _get_libgit2_path():
44
44
  # LIBGIT2 environment variable takes precedence
@@ -262,7 +262,6 @@ class OdbBackendPack(OdbBackend):
262
262
  def __init__(self, *args, **kwargs) -> None: ...
263
263
 
264
264
  class Oid:
265
- hex: str
266
265
  raw: bytes
267
266
  def __init__(self, raw: bytes = ..., hex: str = ...) -> None: ...
268
267
  def __eq__(self, other) -> bool: ...
@@ -272,6 +271,7 @@ class Oid:
272
271
  def __le__(self, other) -> bool: ...
273
272
  def __lt__(self, other) -> bool: ...
274
273
  def __ne__(self, other) -> bool: ...
274
+ def __bool__(self) -> bool: ...
275
275
 
276
276
  class Patch:
277
277
  data: bytes
@@ -82,12 +82,12 @@ from .utils import maybe_string, to_bytes, ptr_to_bytes, StrArray
82
82
 
83
83
 
84
84
  class Payload:
85
- def __init__(self, **kw):
85
+ def __init__(self, **kw: object):
86
86
  for key, value in kw.items():
87
87
  setattr(self, key, value)
88
88
  self._stored_exception = None
89
89
 
90
- def check_error(self, error_code):
90
+ def check_error(self, error_code: int) -> None:
91
91
  if error_code == C.GIT_EUSER:
92
92
  assert self._stored_exception is not None
93
93
  raise self._stored_exception
@@ -120,7 +120,7 @@ class RemoteCallbacks(Payload):
120
120
  if certificate_check is not None:
121
121
  self.certificate_check = certificate_check
122
122
 
123
- def sideband_progress(self, string):
123
+ def sideband_progress(self, string: str) -> None:
124
124
  """
125
125
  Progress output callback. Override this function with your own
126
126
  progress reporting function
@@ -159,7 +159,7 @@ class RemoteCallbacks(Payload):
159
159
  """
160
160
  raise Passthrough
161
161
 
162
- def certificate_check(self, certificate, valid, host):
162
+ def certificate_check(self, certificate: None, valid: bool, host: str) -> bool:
163
163
  """
164
164
  Certificate callback. Override with your own function to determine
165
165
  whether to accept the server's certificate.
@@ -183,8 +183,10 @@ class RemoteCallbacks(Payload):
183
183
 
184
184
  def transfer_progress(self, stats):
185
185
  """
186
- Transfer progress callback. Override with your own function to report
187
- transfer progress.
186
+ During the download of new data, this will be regularly called with
187
+ the indexer's progress.
188
+
189
+ Override with your own function to report transfer progress.
188
190
 
189
191
  Parameters:
190
192
 
@@ -192,6 +194,19 @@ class RemoteCallbacks(Payload):
192
194
  The progress up to now.
193
195
  """
194
196
 
197
+ def push_transfer_progress(
198
+ self, objects_pushed: int, total_objects: int, bytes_pushed: int
199
+ ):
200
+ """
201
+ During the upload portion of a push, this will be regularly called
202
+ with progress information.
203
+
204
+ Be aware that this is called inline with pack building operations,
205
+ so performance may be affected.
206
+
207
+ Override with your own function to report push transfer progress.
208
+ """
209
+
195
210
  def update_tips(self, refname, old, new):
196
211
  """
197
212
  Update tips callback. Override with your own function to report
@@ -355,6 +370,29 @@ def git_fetch_options(payload, opts=None):
355
370
  yield payload
356
371
 
357
372
 
373
+ @contextmanager
374
+ def git_proxy_options(
375
+ payload: object,
376
+ opts: object | None = None,
377
+ proxy: None | bool | str = None,
378
+ ):
379
+ if opts is None:
380
+ opts = ffi.new('git_proxy_options *')
381
+ C.git_proxy_options_init(opts, C.GIT_PROXY_OPTIONS_VERSION)
382
+ if proxy is None:
383
+ opts.type = C.GIT_PROXY_NONE
384
+ elif proxy is True:
385
+ opts.type = C.GIT_PROXY_AUTO
386
+ elif type(proxy) is str:
387
+ opts.type = C.GIT_PROXY_SPECIFIED
388
+ # Keep url in memory, otherwise memory is freed and bad things happen
389
+ payload.__proxy_url = ffi.new('char[]', to_bytes(proxy))
390
+ opts.url = payload.__proxy_url
391
+ else:
392
+ raise TypeError('Proxy must be None, True, or a string')
393
+ yield opts
394
+
395
+
358
396
  @contextmanager
359
397
  def git_push_options(payload, opts=None):
360
398
  if payload is None:
@@ -370,6 +408,13 @@ def git_push_options(payload, opts=None):
370
408
  opts.callbacks.credentials = C._credentials_cb
371
409
  opts.callbacks.certificate_check = C._certificate_check_cb
372
410
  opts.callbacks.push_update_reference = C._push_update_reference_cb
411
+ # Per libgit2 sources, push_transfer_progress may incur a performance hit.
412
+ # So, set it only if the user has overridden the no-op stub.
413
+ if (
414
+ type(payload).push_transfer_progress
415
+ is not RemoteCallbacks.push_transfer_progress
416
+ ):
417
+ opts.callbacks.push_transfer_progress = C._push_transfer_progress_cb
373
418
  # Payload
374
419
  handle = ffi.new_handle(payload)
375
420
  opts.callbacks.payload = handle
@@ -405,10 +450,10 @@ def git_remote_callbacks(payload):
405
450
  #
406
451
  # C callbacks
407
452
  #
408
- # These functions are called by libgit2. They cannot raise execptions, since
453
+ # These functions are called by libgit2. They cannot raise exceptions, since
409
454
  # they return to libgit2, they can only send back error codes.
410
455
  #
411
- # They cannot be overriden, but sometimes the only thing these functions do is
456
+ # They cannot be overridden, but sometimes the only thing these functions do is
412
457
  # to proxy the call to a user defined function. If user defined functions
413
458
  # raises an exception, the callback must store it somewhere and return
414
459
  # GIT_EUSER to libgit2, then the outer Python code will be able to reraise the
@@ -554,6 +599,16 @@ def _transfer_progress_cb(stats_ptr, data):
554
599
  return 0
555
600
 
556
601
 
602
+ @libgit2_callback
603
+ def _push_transfer_progress_cb(current, total, bytes_pushed, payload):
604
+ push_transfer_progress = getattr(payload, 'push_transfer_progress', None)
605
+ if not push_transfer_progress:
606
+ return 0
607
+
608
+ push_transfer_progress(current, total, bytes_pushed)
609
+ return 0
610
+
611
+
557
612
  @libgit2_callback
558
613
  def _update_tips_cb(refname, a, b, data):
559
614
  update_tips = getattr(data, 'update_tips', None)
@@ -304,7 +304,7 @@ class Config:
304
304
 
305
305
 
306
306
  class ConfigEntry:
307
- """An entry in a configuation object."""
307
+ """An entry in a configuration object."""
308
308
 
309
309
  @classmethod
310
310
  def _from_c(cls, ptr, iterator=None):
@@ -321,7 +321,7 @@ class ConfigEntry:
321
321
  # git_config_iterator_free when we've deleted all ConfigEntry objects.
322
322
  # But it's not, to reproduce the error comment the lines below and run
323
323
  # the script in https://github.com/libgit2/pygit2/issues/970
324
- # So instead we load the Python object immmediately. Ideally we should
324
+ # So instead we load the Python object immediately. Ideally we should
325
325
  # investigate libgit2 source code.
326
326
  if iterator is not None:
327
327
  entry.raw_name = entry.raw_name
@@ -23,11 +23,17 @@
23
23
  # the Free Software Foundation, 51 Franklin Street, Fifth Floor,
24
24
  # Boston, MA 02110-1301, USA.
25
25
 
26
- from .ffi import C
26
+ from __future__ import annotations
27
+
28
+ from typing import TYPE_CHECKING
27
29
 
28
30
  from .enums import CredentialType
29
31
 
30
32
 
33
+ if TYPE_CHECKING:
34
+ from pathlib import Path
35
+
36
+
31
37
  class Username:
32
38
  """Username credentials
33
39
 
@@ -35,7 +41,7 @@ class Username:
35
41
  callback and for returning from said callback.
36
42
  """
37
43
 
38
- def __init__(self, username):
44
+ def __init__(self, username: str):
39
45
  self._username = username
40
46
 
41
47
  @property
@@ -46,7 +52,9 @@ class Username:
46
52
  def credential_tuple(self):
47
53
  return (self._username,)
48
54
 
49
- def __call__(self, _url, _username, _allowed):
55
+ def __call__(
56
+ self, _url: str, _username: str | None, _allowed: CredentialType
57
+ ) -> Username:
50
58
  return self
51
59
 
52
60
 
@@ -57,7 +65,7 @@ class UserPass:
57
65
  callback and for returning from said callback.
58
66
  """
59
67
 
60
- def __init__(self, username, password):
68
+ def __init__(self, username: str, password: str):
61
69
  self._username = username
62
70
  self._password = password
63
71
 
@@ -69,7 +77,9 @@ class UserPass:
69
77
  def credential_tuple(self):
70
78
  return (self._username, self._password)
71
79
 
72
- def __call__(self, _url, _username, _allowed):
80
+ def __call__(
81
+ self, _url: str, _username: str | None, _allowed: CredentialType
82
+ ) -> UserPass:
73
83
  return self
74
84
 
75
85
 
@@ -96,7 +106,9 @@ class Keypair:
96
106
  no passphrase is required.
97
107
  """
98
108
 
99
- def __init__(self, username, pubkey, privkey, passphrase):
109
+ def __init__(
110
+ self, username: str, pubkey: str | Path, privkey: str | Path, passphrase: str
111
+ ):
100
112
  self._username = username
101
113
  self._pubkey = pubkey
102
114
  self._privkey = privkey
@@ -110,12 +122,14 @@ class Keypair:
110
122
  def credential_tuple(self):
111
123
  return (self._username, self._pubkey, self._privkey, self._passphrase)
112
124
 
113
- def __call__(self, _url, _username, _allowed):
125
+ def __call__(
126
+ self, _url: str, _username: str | None, _allowed: CredentialType
127
+ ) -> Keypair:
114
128
  return self
115
129
 
116
130
 
117
131
  class KeypairFromAgent(Keypair):
118
- def __init__(self, username):
132
+ def __init__(self, username: str):
119
133
  super().__init__(username, None, None, None)
120
134
 
121
135
 
@@ -38,6 +38,12 @@ extern "Python" int _transfer_progress_cb(
38
38
  const git_indexer_progress *stats,
39
39
  void *payload);
40
40
 
41
+ extern "Python" int _push_transfer_progress_cb(
42
+ unsigned int objects_pushed,
43
+ unsigned int total_objects,
44
+ size_t bytes_pushed,
45
+ void *payload);
46
+
41
47
  extern "Python" int _update_tips_cb(
42
48
  const char *refname,
43
49
  const git_oid *a,
@@ -13,4 +13,9 @@ int git_annotated_commit_lookup(
13
13
  git_repository *repo,
14
14
  const git_oid *id);
15
15
 
16
+ int git_annotated_commit_from_ref(
17
+ git_annotated_commit **out,
18
+ git_repository *repo,
19
+ const struct git_reference *ref);
20
+
16
21
  void git_annotated_commit_free(git_annotated_commit *commit);
@@ -81,7 +81,7 @@ int git_repository_set_head(
81
81
 
82
82
  int git_repository_set_head_detached(
83
83
  git_repository* repo,
84
- const git_oid* commitish);
84
+ const git_oid* committish);
85
85
 
86
86
  int git_repository_hashfile(git_oid *out, git_repository *repo, const char *path, git_object_t type, const char *as_path);
87
87
  int git_repository_ident(const char **name, const char **email, const git_repository *repo);
@@ -42,7 +42,7 @@ def check_error(err, io=False):
42
42
  # Error message
43
43
  giterr = C.git_error_last()
44
44
  if giterr != ffi.NULL:
45
- message = ffi.string(giterr.message).decode('utf8')
45
+ message = ffi.string(giterr.message).decode('utf8', errors='surrogateescape')
46
46
  else:
47
47
  message = f'err {err} (no message provided)'
48
48
 
@@ -24,4 +24,4 @@
24
24
  # Boston, MA 02110-1301, USA.
25
25
 
26
26
  # Import from pygit2
27
- from ._libgit2 import ffi, lib as C
27
+ from ._libgit2 import ffi, lib as C # noqa: F401
@@ -43,7 +43,7 @@ class Refspec:
43
43
 
44
44
  @property
45
45
  def dst(self):
46
- """Destinaton or rhs of the refspec"""
46
+ """Destination or rhs of the refspec"""
47
47
  return ffi.string(C.git_refspec_dst(self._refspec)).decode('utf-8')
48
48
 
49
49
  @property