Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 08 Jun 2026 14:56:10 +0000
From:      Michael Gmelin <grembo@FreeBSD.org>
To:        ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org
Subject:   git: 737bf0755ad2 - main - sysutils/iocage: Fix build and runtime issues
Message-ID:  <6a26d80a.19bf0.22084675@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by grembo:

URL: https://cgit.FreeBSD.org/ports/commit/?id=737bf0755ad23e64740989990df7a9d5a1501ade

commit 737bf0755ad23e64740989990df7a9d5a1501ade
Author:     Michael Gmelin <grembo@FreeBSD.org>
AuthorDate: 2026-06-08 14:29:12 +0000
Commit:     Michael Gmelin <grembo@FreeBSD.org>
CommitDate: 2026-06-08 14:55:55 +0000

    sysutils/iocage: Fix build and runtime issues
    
    This switches the build to pyproject.yml and hatchling to avoid
    various setuptools issues.
    
    It adds a workaround for problems with py-click, which
    prevented some command line options from working properly
    (especially formatting output for scripting using '-h').
    
    While there, import small github hosted patch into the tree.
    
    PR:             295084, 295723
    Reported by:    andreas@turriff.net, echoxxzz@gmail.com
---
 sysutils/iocage/Makefile                           | 21 ++-----
 sysutils/iocage/files/iocage.in                    | 44 ---------------
 sysutils/iocage/files/patch-iocage__cli_df.py      | 22 ++++++++
 sysutils/iocage/files/patch-iocage__cli_fstab.py   | 20 +++++++
 sysutils/iocage/files/patch-iocage__cli_get.py     | 22 ++++++++
 sysutils/iocage/files/patch-iocage__cli_list.py    | 41 ++++++++++++++
 .../iocage/files/patch-iocage__cli_snaplist.py     | 23 ++++++++
 .../iocage/files/patch-iocage__lib_ioc__common.py  | 11 ++++
 sysutils/iocage/files/patch-iocage__lib_iocage.py  | 16 ++++++
 sysutils/iocage/files/patch-pyproject.toml         | 65 ++++++++++++++++++++++
 sysutils/iocage/files/patch-rc.d_iocage            | 19 +++++++
 sysutils/iocage/files/patch-setup.py               | 11 ----
 12 files changed, 245 insertions(+), 70 deletions(-)

diff --git a/sysutils/iocage/Makefile b/sysutils/iocage/Makefile
index 563b34888d31..f030606eb112 100644
--- a/sysutils/iocage/Makefile
+++ b/sysutils/iocage/Makefile
@@ -1,14 +1,9 @@
 PORTNAME=	iocage
 PORTVERSION=	1.12
+PORTREVISION=	1
 CATEGORIES=	sysutils python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
-# Pull in PR #61 to unbreak default route detection on CURRENT
-# Pull in PR #107 to unbreak build (man page)
-PATCH_SITES=    https://github.com/freebsd/iocage/commit/
-PATCHFILES=	2120a86d1d4fd3d383a3f0bddfc1e92eb5a7d2e7.patch:-p1 \
-		13c342c37746bffa944b5c397d51ef39cd2eb172.patch:-p1
-
 MAINTAINER=	grembo@FreeBSD.org
 COMMENT=	FreeBSD jail manager written in Python3
 WWW=		https://github.com/freebsd/iocage
@@ -16,6 +11,7 @@ WWW=		https://github.com/freebsd/iocage
 LICENSE=	BSD2CLAUSE
 LICENSE_FILE=	${WRKSRC}/LICENSE
 
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}hatchling>0:devel/py-hatchling@${PY_FLAVOR}
 RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}netifaces>0:net/py-netifaces@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}click>=6.7:devel/py-click@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}six>=1.15.0:devel/py-six@${PY_FLAVOR} \
@@ -33,19 +29,11 @@ TEST_DEPENDS=	${PYTHON_PKGNAMEPREFIX}libzfs>=1.0.2:filesystems/py-libzfs@${PY_FL
 USES=		python
 USE_GITHUB=	yes
 GH_ACCOUNT=	freebsd
-USE_PYTHON=	autoplist distutils
+USE_PYTHON=	autoplist pep517
 
 CONFLICTS=	py*[0-9]-iocage py*-iocage-devel
 NO_ARCH=	yes
 
-PLIST_FILES=	${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib-${PORTVERSION}-py${PYTHON_VER}.egg-info/PKG-INFO \
-		${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib-${PORTVERSION}-py${PYTHON_VER}.egg-info/SOURCES.txt \
-		${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib-${PORTVERSION}-py${PYTHON_VER}.egg-info/dependency_links.txt \
-		${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib-${PORTVERSION}-py${PYTHON_VER}.egg-info/entry_points.txt \
-		${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib-${PORTVERSION}-py${PYTHON_VER}.egg-info/requires.txt \
-		${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib-${PORTVERSION}-py${PYTHON_VER}.egg-info/top_level.txt \
-		${PYTHONPREFIX_SITELIBDIR}/${PORTNAME}_lib/plugin_manifest.json
-
 OPTIONS_DEFAULT=	GIT
 OPTIONS_RADIO=	GIT_PACKAGE
 OPTIONS_RADIO_GIT_PACKAGE=	GIT GIT_LITE
@@ -56,6 +44,9 @@ GIT_LITE_DESC=	depend on lite flavor of devel/git (bare minimum git experience)
 GIT_RUN_DEPENDS=git:devel/git
 GIT_LITE_RUN_DEPENDS=git:devel/git@lite
 
+post-patch:
+	@${RM} ${WRKSRC}/setup.py
+
 do-test:
 	@cd ${WRKSRC} && ${PYTHON_CMD} -m pytest
 
diff --git a/sysutils/iocage/files/iocage.in b/sysutils/iocage/files/iocage.in
deleted file mode 100644
index b8200077b97a..000000000000
--- a/sysutils/iocage/files/iocage.in
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-
-# PROVIDE: iocage
-# REQUIRE: LOGIN cleanvar sshd ZFS
-# BEFORE:  securelevel
-# KEYWORD: shutdown
-
-# Add the following lines to /etc/rc.conf to enable iocage:
-#
-# iocage_enable="YES"
-#
-#
-
-. /etc/rc.subr
-
-name="iocage"
-rcvar=iocage_enable
-
-# read configuration and set defaults
-load_rc_config "$name"
-: ${iocage_enable="NO"}
-: ${iocage_lang="en_US.UTF-8"}
-
-start_cmd="iocage_start"
-stop_cmd="iocage_stop"
-export LANG=$iocage_lang
-
-iocage_start()
-{
-    if checkyesno ${rcvar}; then
-        echo "* [I|O|C] starting jails... "
-        /usr/local/bin/iocage start --rc
-    fi
-}
-
-iocage_stop()
-{
-    if checkyesno ${rcvar}; then
-        echo "* [I|O|C] stopping jails... "
-        /usr/local/bin/iocage stop --rc
-    fi
-}
-
-run_rc_command "$1"
diff --git a/sysutils/iocage/files/patch-iocage__cli_df.py b/sysutils/iocage/files/patch-iocage__cli_df.py
new file mode 100644
index 000000000000..f0146e39f985
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__cli_df.py
@@ -0,0 +1,22 @@
+--- iocage_cli/df.py.orig	2025-12-12 22:04:57 UTC
++++ iocage_cli/df.py
+@@ -35,8 +35,8 @@ import texttable
+     "-h",
+     "-H",
+     is_flag=True,
+-    default=True,
+-    help="For scripting, use tabs for separators.")
++    default=not ioc.CLICK_WORKAROUND,
++    help="For scripting, no headers and tabs as separators.")
+ @click.option(
+     "--long",
+     "-l",
+@@ -53,6 +53,8 @@ def cli(header, _long, _sort):
+     help="Sorts the list by the given type")
+ def cli(header, _long, _sort):
+     """Allows a user to show resource usage of all jails."""
++    if ioc.CLICK_WORKAROUND:
++        header = not header
+     table = texttable.Texttable(max_width=0)
+     jail_list = ioc.IOCage().df()
+ 
diff --git a/sysutils/iocage/files/patch-iocage__cli_fstab.py b/sysutils/iocage/files/patch-iocage__cli_fstab.py
new file mode 100644
index 000000000000..8ef8c9d9f460
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__cli_fstab.py
@@ -0,0 +1,20 @@
+--- iocage_cli/fstab.py.orig	2026-06-08 13:53:38 UTC
++++ iocage_cli/fstab.py
+@@ -45,13 +45,15 @@ __rootcmd__ = True
+               help="Replace an entry by index number", nargs=1)
+ @click.option("--list", "-l", "action",
+               help="Lists the jails fstab.", flag_value="list")
+-@click.option("--header", "-h", "-H", is_flag=True, default=True,
+-              help="For scripting, use tabs for separators.")
++@click.option("--header", "-h", "-H", is_flag=True, default=not ioc.CLICK_WORKAROUND,
++              help="For scripting, no headers and tabs as separators.")
+ def cli(action, fstab_string, jail, header, replace):
+     """
+     Looks for the jail supplied and passes the uuid, path and configuration
+     location to manipulate the fstab.
+     """
++    if ioc.CLICK_WORKAROUND:
++        header = not header
+     index = None if not replace else replace
+     _index = False
+     add_path = False
diff --git a/sysutils/iocage/files/patch-iocage__cli_get.py b/sysutils/iocage/files/patch-iocage__cli_get.py
new file mode 100644
index 000000000000..28a03a157ff4
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__cli_get.py
@@ -0,0 +1,22 @@
+--- iocage_cli/get.py.orig	2026-06-08 13:53:44 UTC
++++ iocage_cli/get.py
+@@ -33,8 +33,8 @@ import iocage_lib.iocage as ioc
+     max_content_width=400, ), name='get', help='Gets the specified property.')
+ @click.argument('prop', required=True, default='')
+ @click.argument('jail', required=True, default='')
+-@click.option('--header', '-h', '-H', is_flag=True, default=True,
+-              help='For scripting, use tabs for separators.')
++@click.option('--header', '-h', '-H', is_flag=True, default=not ioc.CLICK_WORKAROUND,
++              help='For scripting, no headers and tabs as separators.')
+ @click.option('--recursive', '-r', help='Get the specified property for all '
+                                         'jails.', flag_value='recursive')
+ @click.option('--plugin', '-P',
+@@ -58,6 +58,8 @@ def cli(prop, _type, _pool, jail, recursive, header, p
+ )
+ def cli(prop, _type, _pool, jail, recursive, header, plugin, force):
+     """Get a list of jails and print the property."""
++    if ioc.CLICK_WORKAROUND:
++        header = not header
+     table = texttable.Texttable(max_width=0)
+ 
+     if _type:
diff --git a/sysutils/iocage/files/patch-iocage__cli_list.py b/sysutils/iocage/files/patch-iocage__cli_list.py
new file mode 100644
index 000000000000..4733b9f7d7d2
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__cli_list.py
@@ -0,0 +1,41 @@
+--- iocage_cli/list.py.orig	2025-12-12 22:04:57 UTC
++++ iocage_cli/list.py
+@@ -26,7 +26,6 @@ import iocage_lib.iocage as ioc
+ import iocage_lib.ioc_common as ioc_common
+ import iocage_lib.iocage as ioc
+ 
+-
+ @click.command(
+     name="list",
+     help="List a specified dataset type, by default lists all jails.")
+@@ -36,15 +35,15 @@ import iocage_lib.iocage as ioc
+               flag_value="basejail", help="List all basejails.")
+ @click.option("--template", "-t", "dataset_type", flag_value="template",
+               help="List all templates.")
+-@click.option("--header", "-h", "-H", is_flag=True, default=True,
+-              help="For scripting, use tabs for separators.")
++@click.option("--header", "-h", "-H", is_flag=True, default=not ioc.CLICK_WORKAROUND,
++              help="For scripting, no headers and tabs as separators.")
+ @click.option("--long", "-l", "_long", is_flag=True, default=False,
+               help="Show the full uuid and ip4 address.")
+ @click.option("--remote", "-R", is_flag=True,
+               help="Show remote's available RELEASEs.")
+ @click.option("--plugins", "-P", is_flag=True, help="Show available plugins.")
+-@click.option("--http", default=True, help="Have --remote use HTTP instead.",
+-              is_flag=True)
++@click.option("--http", is_flag=True, default=not ioc.CLICK_WORKAROUND,
++              help="Have --remote not use HTTP.")
+ @click.option("--sort", "-s", "_sort", default="name", nargs=1,
+               help="Sorts the list by the given type")
+ @click.option("--quick", "-q", is_flag=True, default=False,
+@@ -54,6 +53,10 @@ def cli(dataset_type, header, _long, remote, http, plu
+ def cli(dataset_type, header, _long, remote, http, plugins, _sort, quick,
+         official):
+     """This passes the arg and calls the jail_datasets function."""
++
++    if ioc.CLICK_WORKAROUND:
++        header = not header
++        http = not http
+     freebsd_version = ioc_common.checkoutput(["freebsd-version"])
+     iocage = ioc.IOCage(skip_jails=True)
+ 
diff --git a/sysutils/iocage/files/patch-iocage__cli_snaplist.py b/sysutils/iocage/files/patch-iocage__cli_snaplist.py
new file mode 100644
index 000000000000..6621cd997d44
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__cli_snaplist.py
@@ -0,0 +1,23 @@
+--- iocage_cli/snaplist.py.orig	2025-12-12 22:04:57 UTC
++++ iocage_cli/snaplist.py
+@@ -30,8 +30,8 @@ import iocage_lib.iocage as ioc
+ 
+ 
+ @click.command(name="snaplist", help="Show snapshots of a specified jail.")
+-@click.option("--header", "-h", "-H", is_flag=True, default=True,
+-              help="For scripting, use tabs for separators.")
++@click.option("--header", "-h", "-H", is_flag=True, default=not ioc.CLICK_WORKAROUND,
++              help="For scripting, no headers and tabs as separators.")
+ @click.option("--long", "-l", "_long", is_flag=True, default=False,
+               help="Show the full dataset path for snapshot name.")
+ @click.option("--sort", "-s", "_sort", default="created", nargs=1,
+@@ -39,6 +39,9 @@ def cli(header, jail, _long, _sort):
+ @click.argument("jail")
+ def cli(header, jail, _long, _sort):
+     """Allows a user to show resource usage of all jails."""
++
++    if ioc.CLICK_WORKAROUND:
++        header = not header
+     table = texttable.Texttable(max_width=0)
+     snap_list = ioc.IOCage(jail=jail).snap_list(_long, _sort)
+ 
diff --git a/sysutils/iocage/files/patch-iocage__lib_ioc__common.py b/sysutils/iocage/files/patch-iocage__lib_ioc__common.py
new file mode 100644
index 000000000000..257c32d1bb16
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__lib_ioc__common.py
@@ -0,0 +1,11 @@
+--- iocage_lib/ioc_common.py.orig	2025-12-12 22:04:57 UTC
++++ iocage_lib/ioc_common.py
+@@ -1116,7 +1116,7 @@ def get_host_gateways():
+             pass
+         else:
+             default_route = list(filter(
+-                lambda x: x['destination'] == 'default', route_entries)
++                lambda x: x['destination'] in ['default', '0.0.0.0', '::/0'], route_entries)
+             )
+             if default_route and 'gateway' in default_route[0]:
+                 gateways[af_mapping[af]]['gateway'] = \
diff --git a/sysutils/iocage/files/patch-iocage__lib_iocage.py b/sysutils/iocage/files/patch-iocage__lib_iocage.py
new file mode 100644
index 000000000000..2055674c846b
--- /dev/null
+++ b/sysutils/iocage/files/patch-iocage__lib_iocage.py
@@ -0,0 +1,16 @@
+--- iocage_lib/iocage.py.orig	2026-06-08 13:53:06 UTC
++++ iocage_lib/iocage.py
+@@ -53,6 +53,13 @@ from iocage_lib.snapshot import SnapshotListableResour
+ from iocage_lib.snapshot import SnapshotListableResource, Snapshot
+ 
+ 
++# Workaround for click bugs and incompatible changes introduced
++# in 8.2.x. Once we can upgrade to click 8.4.1, this and all
++# its consumers can be removed, but places using the workaround
++# need to be changed to use flag_value=False instead of
++# is_flag=True (and change default to True).
++CLICK_WORKAROUND=True
++
+ class PoolAndDataset:
+ 
+     def get_pool(self):
diff --git a/sysutils/iocage/files/patch-pyproject.toml b/sysutils/iocage/files/patch-pyproject.toml
new file mode 100644
index 000000000000..6611054605aa
--- /dev/null
+++ b/sysutils/iocage/files/patch-pyproject.toml
@@ -0,0 +1,65 @@
+--- pyproject.toml.orig	2026-06-07 07:14:53 UTC
++++ pyproject.toml
+@@ -0,0 +1,62 @@
++[project]
++name = "iocage"
++version = "1.12"
++description = "A jail manager that uses ZFS."
++authors = [
++    {name = "iocage Contributors",email = "ports@FreeBSD.org"},
++]
++keywords = ["freebsd", "jail", "jail manager", "zfs"]
++classifiers = [
++  "Environment :: Console",
++  "Intended Audience :: System Administrators",
++  "Operating System :: POSIX :: BSD :: FreeBSD",
++  "Programming Language :: Python",
++  "Programming Language :: Python :: 3",
++  "Programming Language :: Python :: 3.9",
++  "Programming Language :: Python :: 3.10",
++  "Programming Language :: Python :: 3.11",
++  "Programming Language :: Python :: 3.12",
++  "Programming Language :: Python :: 3.13",
++  "Programming Language :: Python :: 3.14"
++]
++requires-python = ">=3.9"
++readme = "README.md"
++license = "BSD-2-Clause"
++license-files = ["LICENSE"]
++
++dependencies = [
++    "setuptools>=82.0.1",
++    "click>=6.7",
++    "coloredlogs>=9.0",
++    "requests>=2.18.4",
++    "texttable>=1.2.1",
++]
++
++[project.urls]
++Homepage = "https://github.com/freebsd/iocage"
++
++[project.scripts]
++iocage = "iocage_cli:cli"
++
++[build-system]
++requires = ["hatchling"]
++build-backend = "hatchling.build"
++
++[tool.hatch.build.targets.wheel]
++packages = ["iocage_cli", "iocage_lib"]
++exclude = ["*.orig"]
++
++[tool.hatch.build.targets.wheel.shared-data]
++"rc.d/iocage" = "etc/rc.d/iocage"
++"iocage.8" = "share/man/man8/iocage.8"
++"zsh-completion/_iocage" = "share/zsh/site-functions/_iocage"
++
++[tool.hatch.build.targets.sdist]
++include = [
++    "iocage_cli/*.py",
++    "iocage_lib/*.py",
++    "pyproject.toml",
++    "README.md",
++    "LICENSE"
++]
++exclude = ["*.orig"]
diff --git a/sysutils/iocage/files/patch-rc.d_iocage b/sysutils/iocage/files/patch-rc.d_iocage
new file mode 100644
index 000000000000..593e7365ad9b
--- /dev/null
+++ b/sysutils/iocage/files/patch-rc.d_iocage
@@ -0,0 +1,19 @@
+--- rc.d/iocage.orig	2026-06-07 06:57:45 UTC
++++ rc.d/iocage
+@@ -1,7 +1,4 @@
+ #!/bin/sh
+-#
+-# $FreeBSD$
+-#
+ 
+ # PROVIDE: iocage
+ # REQUIRE: LOGIN cleanvar sshd zfs
+@@ -22,7 +19,7 @@ load_rc_config "$name"
+ # read configuration and set defaults
+ load_rc_config "$name"
+ : ${iocage_enable="NO"}
+-: ${iocage_lang="en_US.UTF-8"}
++: ${iocage_lang="C.UTF-8"}
+ 
+ start_cmd="iocage_start"
+ stop_cmd="iocage_stop"
diff --git a/sysutils/iocage/files/patch-setup.py b/sysutils/iocage/files/patch-setup.py
deleted file mode 100644
index ac7f0ebb9dee..000000000000
--- a/sysutils/iocage/files/patch-setup.py
+++ /dev/null
@@ -1,11 +0,0 @@
---- setup.py.orig	2026-04-29 16:39:04 UTC
-+++ setup.py
-@@ -61,7 +61,7 @@ setup(
-     ],
-     entry_points={'console_scripts': ['iocage = iocage_lib:cli']},
-     data_files=_data,
--    tests_require=['pytest', 'pytest-cov', 'pytest-pep8', 'pytest-runner']
-+    tests_require=['pytest', 'pytest-cov', 'pytest-runner']
- )
- 
- setup(


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a26d80a.19bf0.22084675>