Changelog
Changelog
All notable changes to this project are documented here. The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
Unreleased
0.1.2 - 2026-08-16
Changed
- The
duhodependency is now>=0.5.0,<0.6. 0.1.1 capped it at<0.4to stay installable; the commands are now declared against duho's current argument model instead, so the cap is gone and pkgforge tracks the supported duho line again. install'ssourceis declared as alist[Path]rather than aUnion[list[Path], Path]. duho resolves a union by composing its members' scalar converters, so a collection member has no way to keep its own argparse action and the parser refused to build. The command still accepts a barePathfrom the Python API; only the annotation narrowed.--excludeoninstall,scananddbdumpis declared withduho.Append, making it a repeatable single-value option.
Fixed
--excludeworks through the command line again. It previously combined a greedynargswith an append action, soinstall --exclude=Pproduced a list of lists (AttributeError: 'list' object has no attribute 'pattern') and the bare-X P SRC DSTform swallowed the positionals. Both forms now parse to a flat statement list; the multi-source regression test drives the option through argv rather than assigning it directly.
Notes
-x/--decompressstill takes an optional argument and therefore still consumes the following token, soinstall -x SRC DSTreadsSRCas the compression kind. That is argparse's own behavior for this shape and the 0.1.1 guard rejecting a path-shaped kind remains in place and necessary.- The suite also passes against duho 0.4.x, but 0.5 is the series exercised and therefore the one declared. CI now runs one job pinned to the declared floor so it is verified rather than assumed.
0.1.1 - 2026-08-16
Added
py.typedmarker, so theTyping :: Typedclassifier is honored by type checkers (PEP 561).
Changed
- The
duhodependency is now>=0.3.2,<0.4. It was unbounded, so a fresh install of 0.1.0 resolved a duho the parser cannot build against and everypkgforgeinvocation failed. sniff_format()reads only the 16 bytes it inspects instead of the whole file.
Fixed
--excludewith an absolute pattern now works for every source of a multi-sourceinstall. The parsed statements were rewritten in place when bound to a source root, so the second source re-prefixed an already-rebased pattern (/a/**->/src2/src1/a/**) and silently excluded nothing.- An exclude statement that does not apply no longer vetoes the statements
after it. A directory that failed a recursive (
**) pattern returned a definite "keep" instead of falling through, making the outcome depend on statement order (-X '**/*.pyc' -X '(?type:directory)**/tmp'never reached the second statement). install -xwith a stdin source (-) raises a clearcannot infer compression from stdin; pass -x TYPEinstead of anAttributeError.install -xgiven a path as its kind is rejected with an explanation.-xtakes an optional argument, soinstall -x SRC DSTparsesSRCas the compression kind; with further sources the positionals silently shifted along by one and the source path was then run as a decompressor command.
Notes
- duho 0.4 and newer are not supported. From 0.4.0 the argument model rejects
Install.source'sUnion[List[Path], Path]and the parser fails to build, so the cap above is what makes this release installable; supporting 0.4+ requires re-declaringsourceandexcludeagainst that model. - On the supported duho range,
--excludepassed through the command line parses to a nested list andinstallthen fails; the exclude fixes above are reachable through the Python API.
0.1.0 - 2026-07-18
First release. pkgforge stages files into a build root, records their intended install metadata in a file DB, and renders that DB into RPM/Debian packaging manifests. Built on the duho declarative CLI framework; Python 3.9+, Linux runtime.
Added
- Commands:
install(stage a source and record its entry — files, directories, symlinks, decompression, hardlinks,--exclude,--chown,--remove-source),scan(walk a tree and record entries;--missingfills gaps),dbdump(render the DB to a packaging manifest),initdb, andcompact(collapse an append-log DB to one record per live path). - Dump formats:
rpmspecfiles(RPM%fileslines with%attr/%dirand ameta.rpmprefix) anddebian(install+permissionsartifacts). The format registry supports multi-artifact formats. - Pluggable file-DB backends behind one
DbProviderinterface:jsonl(append-only JSON Lines, the default),yaml(append-only YAML), andsqlite(a real SQLite store, upserted in place). Every command behaves identically across all three. The backend is inferred from the--dbsuffix (.jsonl/.ndjson,.yaml/.yml,.db/.sqlite/.sqlite3);--db-format/PKGFORGE_DB_FORMAToverrides it, and reading auto-detects a file's actual format.register_provider()lets a third-party package add its own backend;DbProvider,open_db, andregister_providerare exported from the package. - Environment-driven configuration for unattended builds (
PKGFORGE_ROOT,PKGFORGE_DB,PKGFORGE_DB_FORMAT),--version, and shell completion. - Tar-family archives extract via stdlib
tarfile(safedatafilter where supported);bsdtaris only a fallback for other formats (e.g..iso). - Documentation site (mkdocs-material) with a guide + API reference, a
benchmarks/runner, an end-to-end example, and CI (test.yml/release.yml).
Notes
- File-DB entries store
modeas an octal permission string; two sentinels (-= OS default,--= resolve from disk) defer a field to the staged file. - Hardlink install uses
os.linkfor portability across Python 3.9–3.13 (Path.link_towas removed in 3.12;Path.hardlink_toonly exists from 3.10).