Skip to content

Commit 13dc301

Browse files
committed
Drop (broken) support for GIT_OPT_ADD_SSL_X509_CERT
1 parent 6007f97 commit 13dc301

File tree

4 files changed

+19
-133
lines changed

4 files changed

+19
-133
lines changed

pygit2/options.py

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
307307
Set the maximum number of objects to include in a pack.
308308
"""
309309

310-
# Handle GET options with size_t output
311310
if option_type in (
312311
C.GIT_OPT_GET_MWINDOW_SIZE,
313312
C.GIT_OPT_GET_MWINDOW_MAPPED_LIMIT,
@@ -320,7 +319,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
320319
check_error(err)
321320
return size_ptr[0]
322321

323-
# Handle SET options with size_t input
324322
elif option_type in (
325323
C.GIT_OPT_SET_MWINDOW_SIZE,
326324
C.GIT_OPT_SET_MWINDOW_MAPPED_LIMIT,
@@ -338,7 +336,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
338336
check_error(err)
339337
return None
340338

341-
# Handle GET_SEARCH_PATH
342339
elif option_type == C.GIT_OPT_GET_SEARCH_PATH:
343340
check_args(option_type, arg1, arg2, 1)
344341

@@ -357,7 +354,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
357354

358355
return result
359356

360-
# Handle SET_SEARCH_PATH
361357
elif option_type == C.GIT_OPT_SET_SEARCH_PATH:
362358
check_args(option_type, arg1, arg2, 2)
363359

@@ -375,7 +371,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
375371
check_error(err)
376372
return None
377373

378-
# Handle SET_CACHE_OBJECT_LIMIT
379374
elif option_type == C.GIT_OPT_SET_CACHE_OBJECT_LIMIT:
380375
check_args(option_type, arg1, arg2, 2)
381376

@@ -394,7 +389,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
394389
check_error(err)
395390
return None
396391

397-
# Handle SET_CACHE_MAX_SIZE
398392
elif option_type == C.GIT_OPT_SET_CACHE_MAX_SIZE:
399393
check_args(option_type, arg1, arg2, 1)
400394

@@ -408,7 +402,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
408402
check_error(err)
409403
return None
410404

411-
# Handle GET_CACHED_MEMORY
412405
elif option_type == C.GIT_OPT_GET_CACHED_MEMORY:
413406
check_args(option_type, arg1, arg2, 0)
414407

@@ -418,7 +411,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
418411
check_error(err)
419412
return (current_ptr[0], allowed_ptr[0])
420413

421-
# Handle SET_SSL_CERT_LOCATIONS
422414
elif option_type == C.GIT_OPT_SET_SSL_CERT_LOCATIONS:
423415
check_args(option_type, arg1, arg2, 2)
424416

@@ -465,7 +457,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
465457
check_error(err)
466458
return None
467459

468-
# Handle GET_OWNER_VALIDATION
469460
elif option_type == C.GIT_OPT_GET_OWNER_VALIDATION:
470461
check_args(option_type, arg1, arg2, 0)
471462

@@ -474,7 +465,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
474465
check_error(err)
475466
return bool(enabled_ptr[0])
476467

477-
# Handle GET_TEMPLATE_PATH
478468
elif option_type == C.GIT_OPT_GET_TEMPLATE_PATH:
479469
check_args(option_type, arg1, arg2, 0)
480470

@@ -492,7 +482,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
492482

493483
return result
494484

495-
# Handle SET_TEMPLATE_PATH
496485
elif option_type == C.GIT_OPT_SET_TEMPLATE_PATH:
497486
check_args(option_type, arg1, arg2, 1)
498487

@@ -508,7 +497,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
508497
check_error(err)
509498
return None
510499

511-
# Handle GET_USER_AGENT
512500
elif option_type == C.GIT_OPT_GET_USER_AGENT:
513501
check_args(option_type, arg1, arg2, 0)
514502

@@ -526,7 +514,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
526514

527515
return result
528516

529-
# Handle SET_USER_AGENT
530517
elif option_type == C.GIT_OPT_SET_USER_AGENT:
531518
check_args(option_type, arg1, arg2, 1)
532519

@@ -538,7 +525,6 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
538525
check_error(err)
539526
return None
540527

541-
# Handle SET_SSL_CIPHERS
542528
elif option_type == C.GIT_OPT_SET_SSL_CIPHERS:
543529
check_args(option_type, arg1, arg2, 1)
544530

@@ -800,28 +786,18 @@ def option(option_type: Option, arg1: Any = NOT_PASSED, arg2: Any = NOT_PASSED)
800786
check_error(err)
801787
return None
802788

803-
# Handle ADD_SSL_X509_CERT
789+
# Not implemented - ADD_SSL_X509_CERT requires directly binding with OpenSSL
790+
# as the API works accepts a X509* struct. Use GIT_OPT_SET_SSL_CERT_LOCATIONS
791+
# instead.
804792
elif option_type == C.GIT_OPT_ADD_SSL_X509_CERT:
805-
check_args(option_type, arg1, arg2, 1)
806-
807-
cert = arg1
808-
if isinstance(cert, (str, bytes)):
809-
cert_bytes = to_bytes(cert)
810-
cert_cdata = ffi.new('char[]', cert_bytes)
811-
cert_len = len(cert_bytes)
812-
else:
813-
raise TypeError('certificate must be a string or bytes')
814-
815-
err = C.git_libgit2_opts(option_type, cert_cdata, ffi.cast('size_t', cert_len))
816-
check_error(err)
817-
return None
793+
raise NotImplementedError("Use GIT_OPT_SET_SSL_CERT_LOCATIONS instead")
818794

819795
# Not implemented - SET_ALLOCATOR is not feasible from Python level
820796
# because it requires providing C function pointers for memory management
821797
# (malloc, free, etc.) that must handle raw memory at the C level,
822798
# which cannot be safely implemented in pure Python.
823-
elif option_type in (C.GIT_OPT_SET_ALLOCATOR,):
824-
return NotImplemented
799+
elif option_type == C.GIT_OPT_SET_ALLOCATOR:
800+
raise NotImplementedError("Setting a custom allocator not possible from Python")
825801

826802
else:
827803
raise ValueError(f'Invalid option {option_type}')

pygit2/settings.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,6 @@ def set_ssl_ciphers(self, ciphers: str | bytes) -> None:
248248
"""Set the SSL ciphers to use for HTTPS connections"""
249249
option(Option.SET_SSL_CIPHERS, ciphers)
250250

251-
def add_ssl_x509_cert(self, certificate: str | bytes) -> None:
252-
"""Add a trusted X.509 certificate for SSL/TLS connections"""
253-
option(Option.ADD_SSL_X509_CERT, certificate)
254-
255251
def enable_strict_object_creation(self, value: bool = True) -> None:
256252
"""Enable or disable strict object creation validation"""
257253
option(Option.ENABLE_STRICT_OBJECT_CREATION, value)

test/test_options.py

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
2424
# Boston, MA 02110-1301, USA.
2525

26+
import sys
27+
28+
import pytest
29+
2630
import pygit2
2731
from pygit2 import option
2832
from pygit2.enums import ConfigLevel, ObjectType, Option
@@ -133,31 +137,25 @@ def test_owner_validation() -> None:
133137

134138

135139
def test_template_path() -> None:
136-
# Get the initial template path
137140
original_path = option(Option.GET_TEMPLATE_PATH)
138141

139-
# Set a new template path
140142
test_path = '/tmp/test_templates'
141143
option(Option.SET_TEMPLATE_PATH, test_path)
142144
assert option(Option.GET_TEMPLATE_PATH) == test_path
143145

144-
# Reset to original path
145146
if original_path:
146147
option(Option.SET_TEMPLATE_PATH, original_path)
147148
else:
148149
option(Option.SET_TEMPLATE_PATH, None)
149150

150151

151152
def test_user_agent() -> None:
152-
# Get the initial user agent
153153
original_agent = option(Option.GET_USER_AGENT)
154154

155-
# Set a new user agent
156155
test_agent = 'test-agent/1.0'
157156
option(Option.SET_USER_AGENT, test_agent)
158157
assert option(Option.GET_USER_AGENT) == test_agent
159158

160-
# Reset to original agent
161159
if original_agent:
162160
option(Option.SET_USER_AGENT, original_agent)
163161

@@ -166,142 +164,99 @@ def test_pack_max_objects() -> None:
166164
__option(Option.GET_PACK_MAX_OBJECTS, Option.SET_PACK_MAX_OBJECTS, 100000)
167165

168166

167+
@pytest.mark.skipif(sys.platform != 'win32', reason='Windows-specific feature')
169168
def test_windows_sharemode() -> None:
170-
# This test might not work on non-Windows platforms
171-
try:
172-
__option(Option.GET_WINDOWS_SHAREMODE, Option.SET_WINDOWS_SHAREMODE, 1)
173-
except Exception:
174-
# May fail on non-Windows platforms
175-
pass
169+
__option(Option.GET_WINDOWS_SHAREMODE, Option.SET_WINDOWS_SHAREMODE, 1)
176170

177171

178172
def test_ssl_ciphers() -> None:
179173
# Setting SSL ciphers (no getter available)
180174
try:
181175
option(Option.SET_SSL_CIPHERS, 'DEFAULT')
182176
except pygit2.GitError as e:
183-
# May fail if TLS backend doesn't support custom ciphers
184-
if "TLS backend doesn't support custom ciphers" not in str(e):
185-
raise
177+
if "TLS backend doesn't support custom ciphers" in str(e):
178+
pytest.skip(str(e))
179+
raise
186180

187181

188182
def test_enable_http_expect_continue() -> None:
189-
# Enable and disable HTTP expect continue
190183
option(Option.ENABLE_HTTP_EXPECT_CONTINUE, True)
191184
option(Option.ENABLE_HTTP_EXPECT_CONTINUE, False)
192185

193186

194187
def test_odb_priorities() -> None:
195-
# Set ODB priorities
196188
option(Option.SET_ODB_PACKED_PRIORITY, 1)
197189
option(Option.SET_ODB_LOOSE_PRIORITY, 2)
198190

199191

200192
def test_extensions() -> None:
201-
# Get initial extensions list
202193
original_extensions = option(Option.GET_EXTENSIONS)
203194
assert isinstance(original_extensions, list)
204195

205-
# Set extensions
206196
test_extensions = ['objectformat', 'worktreeconfig']
207197
option(Option.SET_EXTENSIONS, test_extensions, len(test_extensions))
208198

209-
# Verify they were set
210199
new_extensions = option(Option.GET_EXTENSIONS)
211200
assert isinstance(new_extensions, list)
212201

213-
# Check that our extensions are present
214202
# Note: libgit2 may add its own built-in extensions and sort them
215203
for ext in test_extensions:
216204
assert ext in new_extensions, f"Extension '{ext}' not found in {new_extensions}"
217205

218-
# Test with empty list
219206
option(Option.SET_EXTENSIONS, [], 0)
220207
empty_extensions = option(Option.GET_EXTENSIONS)
221208
assert isinstance(empty_extensions, list)
222-
# Even with empty input, libgit2 may have built-in extensions
223209

224-
# Test with a custom extension
225210
custom_extensions = ['myextension', 'objectformat']
226211
option(Option.SET_EXTENSIONS, custom_extensions, len(custom_extensions))
227212
custom_result = option(Option.GET_EXTENSIONS)
228213
assert 'myextension' in custom_result
229214
assert 'objectformat' in custom_result
230215

231-
# Restore original extensions
232216
if original_extensions:
233217
option(Option.SET_EXTENSIONS, original_extensions, len(original_extensions))
234218
else:
235-
# Reset to empty list if there were no extensions
236219
option(Option.SET_EXTENSIONS, [], 0)
237220

238-
# Verify restoration
239221
final_extensions = option(Option.GET_EXTENSIONS)
240222
assert set(final_extensions) == set(original_extensions)
241223

242224

243225
def test_homedir() -> None:
244-
# Get the initial home directory
245226
original_homedir = option(Option.GET_HOMEDIR)
246227

247-
# Set a new home directory
248228
test_homedir = '/tmp/test_home'
249229
option(Option.SET_HOMEDIR, test_homedir)
250230
assert option(Option.GET_HOMEDIR) == test_homedir
251231

252-
# Reset to original home directory
253232
if original_homedir:
254233
option(Option.SET_HOMEDIR, original_homedir)
255234
else:
256235
option(Option.SET_HOMEDIR, None)
257236

258237

259238
def test_server_timeouts() -> None:
260-
# Test connect timeout
261239
original_connect = option(Option.GET_SERVER_CONNECT_TIMEOUT)
262240
option(Option.SET_SERVER_CONNECT_TIMEOUT, 5000)
263241
assert option(Option.GET_SERVER_CONNECT_TIMEOUT) == 5000
264242
option(Option.SET_SERVER_CONNECT_TIMEOUT, original_connect)
265243

266-
# Test server timeout
267244
original_timeout = option(Option.GET_SERVER_TIMEOUT)
268245
option(Option.SET_SERVER_TIMEOUT, 10000)
269246
assert option(Option.GET_SERVER_TIMEOUT) == 10000
270247
option(Option.SET_SERVER_TIMEOUT, original_timeout)
271248

272249

273250
def test_user_agent_product() -> None:
274-
# Get the initial user agent product
275251
original_product = option(Option.GET_USER_AGENT_PRODUCT)
276252

277-
# Set a new user agent product
278253
test_product = 'test-product'
279254
option(Option.SET_USER_AGENT_PRODUCT, test_product)
280255
assert option(Option.GET_USER_AGENT_PRODUCT) == test_product
281256

282-
# Reset to original product
283257
if original_product:
284258
option(Option.SET_USER_AGENT_PRODUCT, original_product)
285259

286260

287-
def test_add_ssl_x509_cert() -> None:
288-
# Test adding an SSL certificate
289-
# This is a minimal test certificate (not valid, but tests the API)
290-
test_cert = '-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----'
291-
292-
try:
293-
option(Option.ADD_SSL_X509_CERT, test_cert)
294-
except pygit2.GitError as e:
295-
# May fail if TLS backend doesn't support adding raw certs
296-
# or if the certificate format is invalid
297-
msg = str(e).lower()
298-
if (
299-
"tls backend doesn't support" not in msg
300-
and 'invalid' not in msg
301-
and 'failed to add raw x509 certificate' not in msg
302-
):
303-
raise
304-
305-
306261
def test_mwindow_file_limit() -> None:
307262
__option(Option.GET_MWINDOW_FILE_LIMIT, Option.SET_MWINDOW_FILE_LIMIT, 100)

0 commit comments

Comments
 (0)