Compare commits

...

3 commits

Author SHA1 Message Date
57180e3596
jw.pkg.lib.Uri: Add unit test
All checks were successful
CI / Packaging - Kali Linux (pull_request) Successful in 4m9s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m5s
CI / Packaging test (pull_request) Successful in 0s

The Uri class provides URL parsing and manipulation utilities used throughout jw-pkg. Add a unit test covering URL parsing, credential handling, path manipulation, and safe string formatting.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-06-25 18:12:45 +02:00
8c093733f4
test/ .. /help: Fail over missing toplevel "make all"

The help integration test currently only succeeds because CI doesn't run "make all" before "make test". That way, the checked out repository lacks the generated __init__.py files needed for some modular subcommands to be fully loaded, and hence, the test should have failed. The entire machinery only worked because the subcommands in question are not not essential to building jw-pkg itself: "secrets" and "posix"

The fix is to

1. Change CI to run "make all" before "make test" (not here) 2. Fix the test in jw-pkg

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-06-25 18:12:45 +02:00
e739b8f0b8
python-tools.sh: Next attempt to satisfy formatter
Some checks failed
CI / Packaging - Kali Linux (pull_request) Failing after 3m41s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Failing after 3m59s
CI / Packaging test (pull_request) Failing after 0s

Commit 55060486 does not satisfy yapf in all places of the source code, so have another attempt at it.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-06-25 18:12:41 +02:00
8 changed files with 239 additions and 3 deletions

View file

@ -81,12 +81,12 @@ cmd_create_init()
echo "import `module_path $f` as $f" echo "import `module_path $f` as $f"
__add_seen $f __add_seen $f
done done
echo
fi fi
if [ ${#seen[@]} -eq 0 ]; then if [ ${#seen[@]} -eq 0 ]; then
echo "__all__ = []" echo "__all__ = []"
else else
echo
echo "__all__ = [" echo "__all__ = ["
for dst_type in ${!seen[@]}; do for dst_type in ${!seen[@]}; do
echo " \"$dst_type\"," echo " \"$dst_type\","

View file

@ -1,4 +1,6 @@
TOPDIR = .. TOPDIR = ..
ORDERED_SUBDIRS = unit integration
include $(TOPDIR)/make/proj.mk include $(TOPDIR)/make/proj.mk
include $(JWBDIR)/make/dirs.mk include $(JWBDIR)/make/dirs.mk

View file

@ -163,12 +163,55 @@ options:
%{codename}, %{gnu-triplet}, %{os-cascade}, %{os-release}, %{codename}, %{gnu-triplet}, %{os-cascade}, %{os-release},
%{pkg-ext} (default: %{cascade}) %{pkg-ext} (default: %{cascade})
============= Running: jw-pkg.py --log-level info posix --help ============= Running: jw-pkg.py --log-level info posix --help
usage: jw-pkg.py posix [-h] usage: jw-pkg.py posix [-h] ...
Perform various operations on a distro through its POSIX utility interface Perform various operations on a distro through its POSIX utility interface
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit
Available subcommands of posix:
copy Copy files
tar Handle tar archives
============= Running: jw-pkg.py --log-level info posix copy --help
usage: jw-pkg.py posix copy [-h] [-o OWNER] [-g GROUP] [-m MODE] [-F] src dst
Copy files
positional arguments:
src Source file URI
dst Destination file URI
options:
-h, --help show this help message and exit
-o, --owner OWNER Destination file owner (default: None)
-g, --group GROUP Destination file group (default: None)
-m, --mode MODE Destination file mode (default: None)
-F, --fixed-strings Don't expand macros in <src> and <dst> (default: False)
============= Running: jw-pkg.py --log-level info posix tar --help
usage: jw-pkg.py posix tar [-h] ...
Handle tar archives
options:
-h, --help show this help message and exit
Available subcommands of tar:
x Extract a tar archive
============= Running: jw-pkg.py --log-level info posix tar x --help
usage: jw-pkg.py posix tar x [-h] -f ARCHIVE_PATH dst
Extract a tar archive
positional arguments:
dst Destination root URI
options:
-h, --help show this help message and exit
-f, --archive-path ARCHIVE_PATH
Archive path
============= Running: jw-pkg.py --log-level info projects --help ============= Running: jw-pkg.py --log-level info projects --help
usage: jw-pkg.py projects [-h] ... usage: jw-pkg.py projects [-h] ...
@ -689,9 +732,93 @@ positional arguments:
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit
============= Running: jw-pkg.py --log-level info secrets --help ============= Running: jw-pkg.py --log-level info secrets --help
usage: jw-pkg.py secrets [-h] usage: jw-pkg.py secrets [-h] ...
Manage package secrets Manage package secrets
options:
-h, --help show this help message and exit
Available subcommands of secrets:
compile-templates Compile package template files
install Install secrets from various sources as static secrets
onto the target
list-compilation-output
List package compilation output files
list-secrets List package secret files
list-templates List package template files
rm-compilation-output
Remove package compilation output files
============= Running: jw-pkg.py --log-level info secrets compile-templates --help
usage: jw-pkg.py secrets compile-templates [-h] [--owner OWNER]
[--group GROUP] [--mode MODE]
[packages ...]
Compile package template files
positional arguments:
packages Package names (default: None)
options:
-h, --help show this help message and exit
--owner, -o OWNER Default output file owner (default: None)
--group, -g GROUP Default output file group (default: None)
--mode, -m MODE Default output file mode (default: None)
============= Running: jw-pkg.py --log-level info secrets install --help
usage: jw-pkg.py secrets install [-h] [--only-missing] src [packages ...]
Install secrets from various sources as static secrets onto the target
positional arguments:
src URI of secret source
packages Package names (default: None)
options:
-h, --help show this help message and exit
--only-missing Install only secrets not already on the target (default:
False)
============= Running: jw-pkg.py --log-level info secrets list-compilation-output --help
usage: jw-pkg.py secrets list-compilation-output [-h] [--all] [packages ...]
List package compilation output files
positional arguments:
packages Package names (default: None)
options:
-h, --help show this help message and exit
--all Show all output targets, including non-existent files (default:
False)
============= Running: jw-pkg.py --log-level info secrets list-secrets --help
usage: jw-pkg.py secrets list-secrets [-h] [--all] [packages ...]
List package secret files
positional arguments:
packages Package names (default: None)
options:
-h, --help show this help message and exit
--all Show all secret paths, including non-existent files (default:
False)
============= Running: jw-pkg.py --log-level info secrets list-templates --help
usage: jw-pkg.py secrets list-templates [-h] [packages ...]
List package template files
positional arguments:
packages Package names (default: None)
options:
-h, --help show this help message and exit
============= Running: jw-pkg.py --log-level info secrets rm-compilation-output --help
usage: jw-pkg.py secrets rm-compilation-output [-h] [packages ...]
Remove package compilation output files
positional arguments:
packages Package names (default: None)
options: options:
-h, --help show this help message and exit -h, --help show this help message and exit

4
test/unit/Makefile Normal file
View file

@ -0,0 +1,4 @@
TOPDIR = ../..
include $(TOPDIR)/make/proj.mk
include $(JWBDIR)/make/dirs.mk

View file

@ -0,0 +1,4 @@
TOPDIR = ../../..
include $(TOPDIR)/make/proj.mk
include $(JWBDIR)/make/dirs.mk

View file

@ -0,0 +1,4 @@
TOPDIR = ../../../..
include $(TOPDIR)/make/proj.mk
include $(JWBDIR)/make/dirs.mk

View file

@ -0,0 +1,7 @@
TOPDIR = ../../../../../
include $(TOPDIR)/make/proj.mk
include $(JWBDIR)/make/py-run.mk
all:
test: run

View file

@ -0,0 +1,88 @@
import sys, os
# Mirror the source tree structure so imports resolve correctly
src_root = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'src', 'python')
sys.path.insert(0, src_root)
from jw.pkg.lib.Uri import Uri
# Basic URL parsing
u = Uri('ssh://john.doe@host:22/path/to/repo')
assert u.protocol == 'ssh'
assert u.hostname == 'host'
assert u.port == 22
assert u.path == '/path/to/repo'
# Username and password
u = Uri('https://user:pass@example.com/repo')
assert u.username == 'user'
assert u.password == 'pass'
# Credentials in output
u = Uri('https://user:secret@example.com/repo')
assert 'secret' in u.full # full shows password
assert '<hidden>' in u.safe_full_with_username # safe version hides password
# Scheme defaults to file
u = Uri('/local/path')
assert u.scheme == 'file://'
assert u.protocol == 'file'
# Pimp returns existing Uri unchanged
u1 = Uri('ssh://host/path')
u2 = Uri.pimp(u1)
assert u2 is u1
# New with path (add)
u = Uri('ssh://host/path')
u2 = u.new_add_path('subdir')
assert u2.to_string == 'ssh://host/path/subdir'
# New with path (replace) - to_string is updated
u3 = u.new_replace_path('/other')
assert u3.to_string == 'ssh://host/other'
# Authority includes credentials
u = Uri('ssh://user:pass@host:22/path')
assert u.authority == 'userpass@host:22'
# Origin excludes credentials
assert u.origin == 'host:22'
# ID and safe version hide password
assert u.id == 'ssh://user:<hidden>@host:22'
assert '<hidden>' in u.safe_full_with_username
# Full includes path and credentials
assert u.full == 'ssh://userpass@host:22/path'
# Simple URLs
u = Uri('https://example.com/repo.git')
assert u.hostname == 'example.com'
assert u.path == '/repo.git'
assert u.basename == 'repo.git'
# Username setter
u = Uri('ssh://host/path')
u.set_username('newuser')
assert u.username == 'newuser'
# Password setter
u = Uri('ssh://host/path')
u.set_password('newpass')
assert u.password == 'newpass'
# No port
u = Uri('ssh://host/path')
assert u.port is None
assert u.port_str is None
# to_string returns original
u = Uri('ssh://user:pass@host:22/path')
assert u.to_string == 'ssh://user:pass@host:22/path'
# String representation hides credentials
u = Uri('https://user:secret@example.com/repo.git')
assert '<hidden>' in str(u)
print('All Uri tests passed')