pkgsrc-WIP-changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
py-mfusepy: Cherry-pick upstream PRs
Module Name: pkgsrc-wip
Committed By: Greg Troxel <gdt%lexort.com@localhost>
Pushed By: gdt
Date: Wed Sep 30 10:15:30 2026 -0400
Changeset: c2bcdd3accae399dd23662956c943c035ba16f04
Modified Files:
py-mfusepy/Makefile
py-mfusepy/TODO
py-mfusepy/distinfo
py-mfusepy/patches/patch-mfusepy.py
Added Files:
py-mfusepy/patches/patch-tests_test__examples.py
py-mfusepy/patches/patch-tests_test__struct__layout.py
Log Message:
py-mfusepy: Cherry-pick upstream PRs
This commit moves to a new version of "support librefuse", and adds a
version of "avoid ioctl_opt".
To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=c2bcdd3accae399dd23662956c943c035ba16f04
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
diffstat:
py-mfusepy/Makefile | 9 ++
py-mfusepy/TODO | 6 +-
py-mfusepy/distinfo | 4 +-
py-mfusepy/patches/patch-mfusepy.py | 163 +++++++++++++++++++--
py-mfusepy/patches/patch-tests_test__examples.py | 30 ++++
.../patches/patch-tests_test__struct__layout.py | 38 +++++
6 files changed, 234 insertions(+), 16 deletions(-)
diffs:
diff --git a/py-mfusepy/Makefile b/py-mfusepy/Makefile
index ebd39a8e9e..a8b6e5cb86 100644
--- a/py-mfusepy/Makefile
+++ b/py-mfusepy/Makefile
@@ -2,6 +2,7 @@
DISTNAME= mfusepy-3.1.1
PKGNAME= ${PYPKGPREFIX}-${DISTNAME}
+PKGREVISION= 1
CATEGORIES= filesystems python
MASTER_SITES= ${MASTER_SITE_PYPI:=m/mfusepy/}
@@ -12,6 +13,14 @@ LICENSE= isc
USE_LANGUAGES= # none
+TOOL_DEPENDS+= ${PYPKGPREFIX}-setuptools>=77:../../devel/py-setuptools
+
+# Upstream has many test dependencies, not expressed in pyproject.toml.
+# At least:
+# loopback
+# memory
+# https://github.com/mxmlnkn/mfusepy/issues/61
+
.include "../../lang/python/wheel.mk"
.include "../../mk/fuse.buildlink3.mk"
.include "../../mk/bsd.pkg.mk"
diff --git a/py-mfusepy/TODO b/py-mfusepy/TODO
index 16158f56fe..24066003ad 100644
--- a/py-mfusepy/TODO
+++ b/py-mfusepy/TODO
@@ -1,3 +1,5 @@
- prepare COMMIT_MSG
- - resolve ioctl test failure
- - test more
+ - some patches are from upstream pending PRs; address them upstream.
+ - add missing test dependencies
+ - run tests
+
diff --git a/py-mfusepy/distinfo b/py-mfusepy/distinfo
index 6447d6058d..e88b625c51 100644
--- a/py-mfusepy/distinfo
+++ b/py-mfusepy/distinfo
@@ -3,4 +3,6 @@ $NetBSD$
BLAKE2s (mfusepy-3.1.1.tar.gz) = a72506eb624ee8750863452c0c8c493f9ce40ddb0c27f2a196270d6f7953eece
SHA512 (mfusepy-3.1.1.tar.gz) = 3d2b2d7531998bccd2b218e31983efd0b1d0854c9f4af3a88922fb89a55cd5c4e6972fa50031cae29f553b599686ad9dd1cb84134989fb876a9fa3b34f64547f
Size (mfusepy-3.1.1.tar.gz) = 34549 bytes
-SHA1 (patch-mfusepy.py) = 35cb85c125ea95264e8fbabf88409870e6901d3d
+SHA1 (patch-mfusepy.py) = 4069b5c6efd150a116d182a7251dd2aa79675bc3
+SHA1 (patch-tests_test__examples.py) = 3ce125d03050c7d152d6f764de9eb071e9381c69
+SHA1 (patch-tests_test__struct__layout.py) = b982f1593550c9cff006f01a88313a77c94c404e
diff --git a/py-mfusepy/patches/patch-mfusepy.py b/py-mfusepy/patches/patch-mfusepy.py
index d4eb5fc980..34512a6c95 100644
--- a/py-mfusepy/patches/patch-mfusepy.py
+++ b/py-mfusepy/patches/patch-mfusepy.py
@@ -1,27 +1,36 @@
$NetBSD$
-From upstream pending PR:
+From upstream pending PR, less CI hunk and hunk for code added
+since 3.1.1:
- https://github.com/mxmlnkn/mfusepy/pull/42
-
-with additional debugging/kludging of the refuse path. Hence this is in wip :-)
+ https://github.com/mxmlnkn/mfusepy/pull/59
--- mfusepy.py.orig 2026-03-13 00:36:12.000000000 +0000
+++ mfusepy.py
-@@ -99,6 +99,12 @@ if not _libfuse_path:
+@@ -99,6 +99,11 @@ if not _libfuse_path:
_libfuse_path = (
find_library('fuse4x') or find_library('osxfuse') or find_library('fuse') or find_library('fuse-t')
)
+ elif _system == 'NetBSD':
-+ # On NetBSD 10+ librefuse implements FUSE 3, targetting 3.10 compatibility.
-+ _libfuse_path = find_library('refuse')
-+ print(f"_libfuse_path 001 is {_libfuse_path}")
-+ _libfuse_path = 'librefuse.so.2'
-+ print(f"_libfuse_path 002 is {_libfuse_path}")
++ # On NetBSD 10+ librefuse implements FUSE 3, targeting 3.10 compatibility.
++ # On NetBSD, find_library only works if a C compiler or ld is in PATH (and e.g. not within pkgsrc builds,
++ # where the compiler wrappers drop -lrefuse), so fall back to the soname of the base system library.
++ _libfuse_path = find_library('refuse') or 'librefuse.so.2'
elif _system == 'Windows':
# pytype: disable=module-attr
try:
-@@ -155,7 +161,7 @@ if fuse_version_major == 2 and fuse_vers
+@@ -139,6 +144,10 @@ _libfuse = ctypes.CDLL(_libfuse_path)
+ if _system == 'Darwin' and hasattr(_libfuse, 'macfuse_version'):
+ _system = 'Darwin-MacFuse'
+
++# NetBSD's librefuse is a FUSE reimplementation on top of puffs (no perfused daemon needed).
++# Its struct layouts differ from libfuse and are fixed, i.e. independent of the FUSE API version.
++_librefuse = _system == 'NetBSD' and hasattr(_libfuse, '__fuse_main')
++
+
+ def get_fuse_version(libfuse):
+ version = libfuse.fuse_version()
+@@ -155,7 +164,7 @@ if fuse_version_major == 2 and fuse_vers
f"Found library {_libfuse_path} is too old: {fuse_version_major}.{fuse_version_minor}. "
"There have been several ABI breaks in each version. Libfuse < 2.6 is not supported!"
)
@@ -30,7 +39,135 @@ with additional debugging/kludging of the refuse path. Hence this is in wip :-)
raise AttributeError(
f"Found library {_libfuse_path} has wrong major version: {fuse_version_major}. Expected FUSE 2!"
)
-@@ -1379,7 +1385,8 @@ class FUSE:
+@@ -747,56 +756,25 @@ _fuse_int32 = ctypes.c_int32 if (fuse_ve
+ _fuse_uint32 = ctypes.c_uint32 if (fuse_version_major, fuse_version_minor) >= (3, 17) else ctypes.c_uint
+ _fuse_file_info_fields_: list[FieldsEntry] = []
+ _fuse_file_info_fields_bitfield: list[BitFieldsEntry] = []
+-# Bogus check. It fixes the struct for NetBSD, but it makes the examples not run anymore!
+-if _system == 'NetBSD_False':
+- # NetBSD has its own FUSE library reimplementation with mismatching struct layouts!
+- # writepage is a bitfield (as in libFUSE 3.x), but the fh_old member still exists and the reported version is 2.9!
+- # https://www.netbsd.org/docs/puffs/
++if _librefuse:
++ # librefuse has one fuse_file_info layout for all API versions: fh_old still exists (removed in FUSE 3),
++ # writepage is a bitfield and poll_events exists (both as in FUSE 3).
+ # https://github.com/NetBSD/src/blob/netbsd-11/lib/librefuse/fuse.h#L100-L129
+- # https://github.com/NetBSD/src/blob/netbsd-10/lib/librefuse/fuse.h#L100-L129
+- # - fuse_file_info is unchanged between 10 and 11
+- # - FUSE_USE_VERSION is not set, but is set to _REFUSE_VERSION_ (3.10) with a warning if not set!
+- # - However, the CI prints FUSE version 2.9?!
+- # - Seems there is no sane way to get the correct compiled version! This is again an absolute shit show!
+- # https://github.com/NetBSD/src/blob/netbsd-9/lib/librefuse/fuse.h#L51-L61
+- # - fuse_file_info looks quite different and version is specified as 2.6!
+- # - #define FUSE_USE_VERSION 26
+- fuse_version = (fuse_version_major, fuse_version_minor)
+ _fuse_file_info_fields_ = [
+ ('flags', ctypes.c_int32),
+ ('fh_old', ctypes.c_uint32),
+- ]
+-
+- if fuse_version >= (2, 9):
+- _fuse_file_info_fields_bitfield += [('writepage', ctypes.c_int32, 1)]
+- else:
+- _fuse_file_info_fields_ += [('writepage', ctypes.c_int32)]
+-
+- _fuse_file_info_fields_bitfield += [
+- ('direct_io', ctypes.c_uint32, 1), # Introduced in FUSE 2.4
+- ('keep_cache', ctypes.c_uint32, 1), # Introduced in FUSE 2.4
+- ('flush', ctypes.c_uint32, 1), # Introduced in FUSE 2.6
+- ]
+- if fuse_version >= (2, 9):
+- _fuse_file_info_fields_bitfield += [
+- ('nonseekable', ctypes.c_uint, 1), # Introduced in FUSE 2.8
+- ('flock_release', ctypes.c_uint, 1), # Introduced in FUSE 2.9
+- ('cache_readdir', ctypes.c_uint, 1), # Introduced in FUSE 3.5
+- ]
+-
+- _fuse_file_info_flag_count = sum(x[2] for x in _fuse_file_info_fields_bitfield)
+- assert _fuse_file_info_flag_count < ctypes.sizeof(_fuse_uint32) * 8
+-
+- _fuse_file_info_fields_ += _fuse_file_info_fields_bitfield
+- _fuse_file_info_fields_ += [
+- ('padding', _fuse_uint32, ctypes.sizeof(_fuse_uint32) * 8 - _fuse_file_info_flag_count),
++ ('writepage', ctypes.c_uint32, 1),
++ ('direct_io', ctypes.c_uint32, 1),
++ ('keep_cache', ctypes.c_uint32, 1),
++ ('flush', ctypes.c_uint32, 1),
++ ('nonseekable', ctypes.c_uint32, 1),
++ ('flock_release', ctypes.c_uint32, 1),
++ ('cache_readdir', ctypes.c_uint32, 1),
++ ('padding', ctypes.c_uint32, 25),
+ ('fh', ctypes.c_uint64),
+ ('lock_owner', ctypes.c_uint64),
++ ('poll_events', ctypes.c_uint32),
+ ]
+-
+- if fuse_version >= (2, 9):
+- _fuse_file_info_fields_ += [('poll_events', ctypes.c_uint32)]
+-
+ elif fuse_version_major == 2:
+ _fh_old_type = ctypes.c_uint if _system == 'OpenBSD' else ctypes.c_ulong
+ _fuse_file_info_fields_ = [
+@@ -937,14 +915,12 @@ _fuse_conn_info_fields: list[FieldsEntry
+ ('proto_major', ctypes.c_uint),
+ ('proto_minor', ctypes.c_uint),
+ ]
+-# For some reason, NetBSD return 2.9 even though the API is 3.10!
+-# The correct version is important for the struct layout!
+-# https://github.com/NetBSD/src/blob/netbsd-10/lib/librefuse/fuse.h#L58-L59
+-# However, the fuse_operations layout probably fits the advertised version because I had segfaults from utimens!
+-if fuse_version_major == 2 or _system == 'NetBSD': # No idea why NetBSD did not remove it -.-
++# librefuse has one fuse_conn_info layout for all API versions, containing the FUSE 2 and FUSE 3 members.
++# https://github.com/NetBSD/src/blob/netbsd-11/lib/librefuse/fuse.h
++if fuse_version_major == 2 or _librefuse:
+ _fuse_conn_info_fields += [('async_read', _fuse_uint32)]
+ _fuse_conn_info_fields += [('max_write', _fuse_uint32)]
+-if fuse_version_major == 3 or _system == 'NetBSD':
++if fuse_version_major == 3 or _librefuse:
+ _fuse_conn_info_fields += [('max_read', _fuse_uint32)]
+ _fuse_conn_info_fields += [('max_readahead', _fuse_uint32)]
+ if _system == 'Darwin':
+@@ -955,11 +931,11 @@ _fuse_conn_info_fields += [
+ ('max_background', _fuse_uint32), # Added in 2.9
+ ('congestion_threshold', _fuse_uint32), # Added in 2.9
+ ]
+-if fuse_version_major == 2 and _system != 'NetBSD':
++if fuse_version_major == 2 and not _librefuse:
+ _fuse_conn_info_fields += [('reserved', _fuse_uint32 * (22 if _system == 'Darwin' else 23))]
+-elif fuse_version_major == 3 or _system == 'NetBSD':
++elif fuse_version_major == 3 or _librefuse:
+ _fuse_conn_info_fields += [('time_gran', _fuse_uint32)]
+- if fuse_version_minor < 17 or _system == 'NetBSD':
++ if fuse_version_minor < 17 or _librefuse:
+ _fuse_conn_info_fields += [('reserved', _fuse_uint32 * 22)]
+ else:
+ _fuse_conn_info_fields += [
+@@ -1037,7 +1013,7 @@ if fuse_version_major == 3:
+ if fuse_version_minor >= 15 and fuse_version_minor < 17:
+ _fuse_config_fields_ += [('parallel_direct_writes', ctypes.c_int)]
+
+- if _system != 'NetBSD':
++ if not _librefuse:
+ _fuse_config_fields_ += [
+ ('show_help', _fuse_int32),
+ ('modules', ctypes.c_char_p),
+@@ -1243,6 +1219,15 @@ if _system == "OpenBSD":
+ def fuse_main_real(argc, argv, fuse_ops_v, sizeof_fuse_ops, ctx_p):
+ return _libfuse.fuse_main(argc, argv, fuse_ops_v, ctx_p)
+
++elif _librefuse:
++ # librefuse's fuse_main_real is only a shim for binaries built against FUSE 2.6: it always interprets
++ # the operations as struct fuse_operations_v26. __fuse_main takes the layout version instead of the size.
++ # The FUSE 3 fuse_operations defined above is struct fuse_operations_v38 (used for FUSE_USE_VERSION 38..310).
++ _REFUSE_OP_VERSION = 38
++
++ def fuse_main_real(argc, argv, fuse_ops_v, sizeof_fuse_ops, ctx_p):
++ return getattr(_libfuse, '__fuse_main')(argc, argv, fuse_ops_v, _REFUSE_OP_VERSION, ctx_p)
++
+ else:
+ fuse_main_real = _libfuse.fuse_main_real
+
+@@ -1379,7 +1364,8 @@ class FUSE:
}
argsb = [arg.encode(encoding, self.errors) for arg in args]
@@ -40,7 +177,7 @@ with additional debugging/kludging of the refuse path. Hence this is in wip :-)
alternative_callbacks = {
"readdir": ["readdir_with_offset"],
-@@ -1443,7 +1450,7 @@ class FUSE:
+@@ -1443,7 +1429,7 @@ class FUSE:
except ValueError:
old_handler = SIG_DFL
diff --git a/py-mfusepy/patches/patch-tests_test__examples.py b/py-mfusepy/patches/patch-tests_test__examples.py
new file mode 100644
index 0000000000..bd09193db9
--- /dev/null
+++ b/py-mfusepy/patches/patch-tests_test__examples.py
@@ -0,0 +1,30 @@
+$NetBSD$
+
+Tests depend on ioctl_opt, not documented:
+ https://github.com/mxmlnkn/mfusepy/issues/48
+ https://github.com/mxmlnkn/mfusepy/pull/60
+
+Reimplementation of PR patch, less continuing to run the tests on
+Linux. Filed upstream as a comment in the PR.
+
+--- tests/test_examples.py.orig 2026-09-30 13:47:39.350361831 +0000
++++ tests/test_examples.py
+@@ -19,7 +19,8 @@ from types import ModuleType
+ from typing import Optional
+
+ import pytest
+-from ioctl_opt import IOWR
++#from ioctl_opt import IOWR
++ioctl_opt=None
+
+ pwd: Optional[ModuleType]
+ try:
+@@ -248,7 +249,7 @@ def test_read_write_file_system(cli, tmp
+ with open(path, 'rb') as file:
+ # Test a simple ioctl command that returns the argument incremented by one.
+ argument = 123
+- iowr_m = IOWR(ord('M'), 1, ctypes.c_uint32)
++ iowr_m = ioctl_opt.IOWR(ord('M'), 1, ctypes.c_uint32)
+ result = fcntl.ioctl(file, iowr_m, struct.pack('I', argument))
+ assert struct.unpack('I', result)[0] == argument + 1
+
diff --git a/py-mfusepy/patches/patch-tests_test__struct__layout.py b/py-mfusepy/patches/patch-tests_test__struct__layout.py
new file mode 100644
index 0000000000..e856af22d6
--- /dev/null
+++ b/py-mfusepy/patches/patch-tests_test__struct__layout.py
@@ -0,0 +1,38 @@
+$NetBSD$
+
+Logically part of mfusepy.py patch.
+
+--- tests/test_struct_layout.py.orig 2026-03-13 00:36:12.000000000 +0000
++++ tests/test_struct_layout.py
+@@ -1,6 +1,5 @@
+ import ctypes
+ import os
+-import platform
+ import pprint
+ import shutil
+ import subprocess
+@@ -82,8 +81,7 @@ STRUCT_NAMES = {
+ ],
+ }
+
+-if platform.system() != 'NetBSD':
+- STRUCT_NAMES['fuse_file_info'] = ['flags', 'fh', 'lock_owner']
++STRUCT_NAMES['fuse_file_info'] = ['flags', 'fh', 'lock_owner']
+
+ if mfusepy.fuse_version_major == 3:
+ STRUCT_NAMES['fuse_config'] = [
+@@ -188,10 +186,12 @@ def c_run(name: str, source: str) -> str
+ f'-DFUSE_USE_VERSION={mfusepy.fuse_version_major}{mfusepy.fuse_version_minor}',
+ '-D_FILE_OFFSET_BITS=64',
+ ]
+- cflags += [f'-I{path}' for path in include_paths if os.path.exists(path)]
++ # librefuse's fuse.h is in the default include path, do not pick up the headers of a libfuse package.
++ if not mfusepy._librefuse:
++ cflags += [f'-I{path}' for path in include_paths if os.path.exists(path)]
+
+ # Add possible pkg-config flags if available
+- for fuse_lib in ("fuse", "fuse3"):
++ for fuse_lib in () if mfusepy._librefuse else ("fuse", "fuse3"):
+ try:
+ pkg_config_flags = subprocess.check_output(['pkg-config', '--cflags', fuse_lib], text=True).split()
+ cflags.extend(pkg_config_flags)
Home |
Main Index |
Thread Index |
Old Index