Compare commits

..

1 Commits

Author SHA1 Message Date
aac3ccfc30 migration to pkgctl 2023-05-09 15:31:50 +03:00
225 changed files with 5319 additions and 9356 deletions

View File

@ -10,7 +10,7 @@ echo -e '[arcanisrepo]\nServer = http://repo.arcanis.me/$arch\nSigLevel = Never'
# refresh the image # refresh the image
pacman --noconfirm -Syu pacman --noconfirm -Syu
# main dependencies # main dependencies
pacman --noconfirm -Sy base-devel devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd sudo pacman --noconfirm -Sy base-devel devtools-git-poc git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo sudo
# make dependencies # make dependencies
pacman --noconfirm -Sy python-build python-installer python-wheel pacman --noconfirm -Sy python-build python-installer python-wheel
# optional dependencies # optional dependencies
@ -52,9 +52,9 @@ if [[ -z $MINIMAL_INSTALL ]]; then
fi fi
# add the first package # add the first package
# the build itself does not really work in the container # the build itself does not really work in the container
sudo -u ahriman -- ahriman package-add --now yay sudo -u ahriman -- ahriman package-add --now ahriman
# check if package was actually installed # check if package was actually installed
test -n "$(find "/var/lib/ahriman/repository/x86_64" -name "yay*pkg*")" test -n "$(find "/var/lib/ahriman/repository/x86_64" -name "ahriman*pkg*")"
# run package check # run package check
sudo -u ahriman -- ahriman repo-update sudo -u ahriman -- ahriman repo-update
# stop web service lol # stop web service lol

View File

@ -6,7 +6,7 @@ formats:
build: build:
os: ubuntu-20.04 os: ubuntu-20.04
tools: tools:
python: "3.11" python: "3.10"
sphinx: sphinx:
builder: html builder: html

View File

@ -34,7 +34,7 @@ Again, the most checks can be performed by `make check` command, though some add
do foo. With very very very long do foo. With very very very long
docstring docstring
Notes: Note:
Very important note about this function Very important note about this function
Args: Args:
@ -102,9 +102,6 @@ Again, the most checks can be performed by `make check` command, though some add
@property @property
def property(self) -> Any: ... def property(self) -> Any: ...
@cached_property
def property_cached(self) -> Any: ... # cached property has to be treated as normal one
@classmethod @classmethod
def class_method(cls) -> Self: ... def class_method(cls) -> Self: ...

View File

@ -6,7 +6,7 @@ ENV AHRIMAN_DEBUG=""
ENV AHRIMAN_FORCE_ROOT="" ENV AHRIMAN_FORCE_ROOT=""
ENV AHRIMAN_HOST="0.0.0.0" ENV AHRIMAN_HOST="0.0.0.0"
ENV AHRIMAN_MULTILIB="yes" ENV AHRIMAN_MULTILIB="yes"
ENV AHRIMAN_OUTPUT="" ENV AHRIMAN_OUTPUT="syslog"
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>" ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
ENV AHRIMAN_PACMAN_MIRROR="" ENV AHRIMAN_PACMAN_MIRROR=""
ENV AHRIMAN_PORT="" ENV AHRIMAN_PORT=""
@ -28,12 +28,15 @@ RUN useradd -m -d "/home/build" -s "/usr/bin/nologin" build && \
COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package" COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
## install package dependencies ## install package dependencies
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size ## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \ RUN pacman --noconfirm -Sy devtools-git-poc git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \
pacman -Sy --noconfirm --asdeps python-build python-installer python-wheel && \ pacman --noconfirm -Sy python-build python-installer python-wheel && \
pacman -Sy --noconfirm --asdeps breezy mercurial python-aiohttp python-aiohttp-cors python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \ pacman --noconfirm -Sy breezy mercurial python-aiohttp python-aiohttp-cors python-boto3 python-cryptography python-jinja python-requests-unixsocket rsync subversion && \
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-jinja2 \ runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-jinja2 \
python-aiohttp-debugtoolbar python-aiohttp-session python-aiohttp-security python-aiohttp-debugtoolbar python-aiohttp-session python-aiohttp-security
# cleanup unused
RUN find "/var/cache/pacman/pkg" -type f -delete
# install ahriman # install ahriman
## copy tree ## copy tree
COPY --chown=build . "/home/build/ahriman" COPY --chown=build . "/home/build/ahriman"
@ -45,10 +48,6 @@ RUN cd "/home/build/ahriman" && \
runuser -u build -- makepkg --noconfirm --install --skipchecksums && \ runuser -u build -- makepkg --noconfirm --install --skipchecksums && \
cd / && rm -r "/home/build/ahriman" cd / && rm -r "/home/build/ahriman"
# cleanup unused
RUN find "/var/cache/pacman/pkg" -type f -delete
RUN pacman -Qdtq | pacman -Rscn --noconfirm -
VOLUME ["/var/lib/ahriman"] VOLUME ["/var/lib/ahriman"]
# minimal runtime ahriman setup # minimal runtime ahriman setup

View File

@ -16,7 +16,7 @@ Wrapper for managing custom repository inspired by [repo-scripts](https://github
* VCS packages support. * VCS packages support.
* Official repository support. * Official repository support.
* Ability to patch AUR packages and even create package from local PKGBUILDs. * Ability to patch AUR packages and even create package from local PKGBUILDs.
* Sign support with gpg (repository, package), multiple packagers support. * Sign support with gpg (repository, package, per package settings).
* Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram). * Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram).
* Repository status interface with optional authorization and control options: * Repository status interface with optional authorization and control options:

View File

@ -15,10 +15,15 @@ database = $AHRIMAN_REPOSITORY_ROOT/ahriman.db
host = $AHRIMAN_HOST host = $AHRIMAN_HOST
EOF EOF
sed -i "s|handlers = syslog_handler|handlers = ${AHRIMAN_OUTPUT}_handler|g" "/etc/ahriman.ini.d/logging.ini"
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE") AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
if [ -n "$AHRIMAN_OUTPUT" ]; then if [[ "$AHRIMAN_OUTPUT" == "syslog" ]]; then
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT") if [ ! -e "/dev/log" ]; then
# by default ahriman uses syslog which is not available inside container
# to make noise less we force quiet mode in case if /dev/log was not mounted
AHRIMAN_DEFAULT_ARGS+=("--quiet")
fi
fi fi
# create repository root inside the [[mounted]] directory and set correct ownership # create repository root inside the [[mounted]] directory and set correct ownership
@ -31,7 +36,6 @@ AHRIMAN_GNUPG_HOME="$(getent passwd "$AHRIMAN_USER" | cut -d : -f 6)/.gnupg"
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_GNUPG_HOME" chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_GNUPG_HOME"
# run built-in setup command # run built-in setup command
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER") AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER")
AHRIMAN_SETUP_ARGS+=("--repository" "$AHRIMAN_REPOSITORY") AHRIMAN_SETUP_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
if [ -z "$AHRIMAN_MULTILIB" ]; then if [ -z "$AHRIMAN_MULTILIB" ]; then
@ -58,7 +62,7 @@ systemd-machine-id-setup &> /dev/null
# otherwise we prepend executable by sudo command # otherwise we prepend executable by sudo command
if [ -n "$AHRIMAN_FORCE_ROOT" ]; then if [ -n "$AHRIMAN_FORCE_ROOT" ]; then
AHRIMAN_EXECUTABLE=("ahriman") AHRIMAN_EXECUTABLE=("ahriman")
elif ahriman help-commands-unsafe -- "$@" &> /dev/null; then elif ahriman help-commands-unsafe --command="$*" &> /dev/null; then
AHRIMAN_EXECUTABLE=("sudo" "-u" "$AHRIMAN_USER" "--" "ahriman") AHRIMAN_EXECUTABLE=("sudo" "-u" "$AHRIMAN_USER" "--" "ahriman")
else else
AHRIMAN_EXECUTABLE=("ahriman") AHRIMAN_EXECUTABLE=("ahriman")

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 812 KiB

After

Width:  |  Height:  |  Size: 750 KiB

View File

@ -1,9 +1,9 @@
.TH AHRIMAN "1" "2023\-07\-22" "ahriman" "Generated Python Manual" .TH AHRIMAN "1" "2023\-04\-09" "ahriman" "Generated Python Manual"
.SH NAME .SH NAME
ahriman ahriman
.SH SYNOPSIS .SH SYNOPSIS
.B ahriman .B ahriman
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ... [-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
.SH DESCRIPTION .SH DESCRIPTION
ArcH linux ReposItory MANager ArcH linux ReposItory MANager
@ -24,13 +24,9 @@ force run, remove file lock
\fB\-l\fR \fI\,LOCK\/\fR, \fB\-\-lock\fR \fI\,LOCK\/\fR \fB\-l\fR \fI\,LOCK\/\fR, \fB\-\-lock\fR \fI\,LOCK\/\fR
lock file lock file
.TP
\fB\-\-log\-handler\fR \fI\,{console,syslog,journald}\/\fR
explicit log handler specification. If none set, the handler will be guessed from environment
.TP .TP
\fB\-\-report\fR, \fB\-\-no\-report\fR \fB\-\-report\fR, \fB\-\-no\-report\fR
force enable or disable reporting to web service force enable or disable reporting to web service (default: True)
.TP .TP
\fB\-q\fR, \fB\-\-quiet\fR \fB\-q\fR, \fB\-\-quiet\fR
@ -95,12 +91,6 @@ backup repository data
\fBahriman\fR \fI\,repo\-check\/\fR \fBahriman\fR \fI\,repo\-check\/\fR
check for updates check for updates
.TP .TP
\fBahriman\fR \fI\,repo\-create\-keyring\/\fR
create keyring package
.TP
\fBahriman\fR \fI\,repo\-create\-mirrorlist\/\fR
create mirrorlist package
.TP
\fBahriman\fR \fI\,repo\-daemon\/\fR \fBahriman\fR \fI\,repo\-daemon\/\fR
run application as daemon run application as daemon
.TP .TP
@ -182,7 +172,7 @@ return non\-zero exit status if result is empty
.TP .TP
\fB\-\-info\fR, \fB\-\-no\-info\fR \fB\-\-info\fR, \fB\-\-no\-info\fR
show additional package information show additional package information (default: False)
.TP .TP
\fB\-\-sort\-by\fR \fI\,{description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,submitter,url,url_path,version}\/\fR \fB\-\-sort\-by\fR \fI\,{description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,submitter,url,url_path,version}\/\fR
@ -199,12 +189,13 @@ show help message for application or command and exit
show help message for specific command show help message for specific command
.SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR .SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR
usage: ahriman help\-commands\-unsafe [\-h] [command ...] usage: ahriman help\-commands\-unsafe [\-h] [\-\-command COMMAND]
list unsafe commands as defined in default args list unsafe commands as defined in default args
.SH OPTIONS \fI\,'ahriman help\-commands\-unsafe'\/\fR
.TP .TP
\fBcommand\fR \fB\-\-command\fR \fI\,COMMAND\/\fR
instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1
otherwise otherwise
@ -225,7 +216,7 @@ print application and its dependencies versions
.SH COMMAND \fI\,'ahriman package\-add'\/\fR .SH COMMAND \fI\,'ahriman package\-add'\/\fR
usage: ahriman package\-add [\-h] [\-\-dependencies | \-\-no\-dependencies] [\-e] [\-n] [\-y] usage: ahriman package\-add [\-h] [\-\-dependencies | \-\-no\-dependencies] [\-e] [\-n] [\-y]
[\-s {auto,archive,aur,directory,local,remote,repository}] [\-u USERNAME] [\-s {auto,archive,aur,directory,local,remote,repository}]
package [package ...] package [package ...]
add existing or new package to the build queue add existing or new package to the build queue
@ -237,7 +228,7 @@ package source (base name, path to local files, remote URL)
.SH OPTIONS \fI\,'ahriman package\-add'\/\fR .SH OPTIONS \fI\,'ahriman package\-add'\/\fR
.TP .TP
\fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR \fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR
process missing package dependencies process missing package dependencies (default: True)
.TP .TP
\fB\-e\fR, \fB\-\-exit\-code\fR \fB\-e\fR, \fB\-\-exit\-code\fR
@ -255,10 +246,6 @@ download fresh package databases from the mirror before actions, \-yy to force r
\fB\-s\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR, \fB\-\-source\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR \fB\-s\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR, \fB\-\-source\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR
explicitly specify the package source for this command explicitly specify the package source for this command
.TP
\fB\-u\fR \fI\,USERNAME\/\fR, \fB\-\-username\fR \fI\,USERNAME\/\fR
build as user
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR .SH COMMAND \fI\,'ahriman package\-remove'\/\fR
usage: ahriman package\-remove [\-h] package [package ...] usage: ahriman package\-remove [\-h] package [package ...]
@ -289,7 +276,7 @@ return non\-zero exit status if result is empty
.TP .TP
\fB\-\-info\fR, \fB\-\-no\-info\fR \fB\-\-info\fR, \fB\-\-no\-info\fR
show additional package information show additional package information (default: False)
.TP .TP
\fB\-s\fR \fI\,{unknown,pending,building,failed,success}\/\fR, \fB\-\-status\fR \fI\,{unknown,pending,building,failed,success}\/\fR \fB\-s\fR \fI\,{unknown,pending,building,failed,success}\/\fR, \fB\-\-status\fR \fI\,{unknown,pending,building,failed,success}\/\fR
@ -407,22 +394,12 @@ return non\-zero exit status if result is empty
.TP .TP
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR \fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
fetch actual version of VCS packages fetch actual version of VCS packages (default: True)
.TP .TP
\fB\-y\fR, \fB\-\-refresh\fR \fB\-y\fR, \fB\-\-refresh\fR
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
.SH COMMAND \fI\,'ahriman repo\-create\-keyring'\/\fR
usage: ahriman repo\-create\-keyring [\-h]
create package which contains list of trusted keys as set by configuration. Note, that this action will only create package, the package itself has to be built manually
.SH COMMAND \fI\,'ahriman repo\-create\-mirrorlist'\/\fR
usage: ahriman repo\-create\-mirrorlist [\-h]
create package which contains list of available mirrors as set by configuration. Note, that this action will only create package, the package itself has to be built manually
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR .SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-dependencies | \-\-no\-dependencies] usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-dependencies | \-\-no\-dependencies]
[\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-\-vcs | \-\-no\-vcs] [\-y] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-\-vcs | \-\-no\-vcs] [\-y]
@ -436,23 +413,23 @@ interval between runs in seconds
.TP .TP
\fB\-\-aur\fR, \fB\-\-no\-aur\fR \fB\-\-aur\fR, \fB\-\-no\-aur\fR
enable or disable checking for AUR updates enable or disable checking for AUR updates (default: True)
.TP .TP
\fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR \fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR
process missing package dependencies process missing package dependencies (default: True)
.TP .TP
\fB\-\-local\fR, \fB\-\-no\-local\fR \fB\-\-local\fR, \fB\-\-no\-local\fR
enable or disable checking of local packages for updates enable or disable checking of local packages for updates (default: True)
.TP .TP
\fB\-\-manual\fR, \fB\-\-no\-manual\fR \fB\-\-manual\fR, \fB\-\-no\-manual\fR
include or exclude manual updates include or exclude manual updates (default: True)
.TP .TP
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR \fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
fetch actual version of VCS packages fetch actual version of VCS packages (default: True)
.TP .TP
\fB\-y\fR, \fB\-\-refresh\fR \fB\-y\fR, \fB\-\-refresh\fR
@ -460,7 +437,6 @@ download fresh package databases from the mirror before actions, \-yy to force r
.SH COMMAND \fI\,'ahriman repo\-rebuild'\/\fR .SH COMMAND \fI\,'ahriman repo\-rebuild'\/\fR
usage: ahriman repo\-rebuild [\-h] [\-\-depends\-on DEPENDS_ON] [\-\-dry\-run] [\-\-from\-database] [\-e] usage: ahriman repo\-rebuild [\-h] [\-\-depends\-on DEPENDS_ON] [\-\-dry\-run] [\-\-from\-database] [\-e]
[\-s {unknown,pending,building,failed,success}] [\-u USERNAME]
force rebuild whole repository force rebuild whole repository
@ -483,14 +459,6 @@ original ahriman instance run with web service and have run repo\-update at leas
\fB\-e\fR, \fB\-\-exit\-code\fR \fB\-e\fR, \fB\-\-exit\-code\fR
return non\-zero exit status if result is empty return non\-zero exit status if result is empty
.TP
\fB\-s\fR \fI\,{unknown,pending,building,failed,success}\/\fR, \fB\-\-status\fR \fI\,{unknown,pending,building,failed,success}\/\fR
filter packages by status. Requires \-\-from\-database to be set
.TP
\fB\-u\fR \fI\,USERNAME\/\fR, \fB\-\-username\fR \fI\,USERNAME\/\fR
build as user
.SH COMMAND \fI\,'ahriman repo\-remove\-unknown'\/\fR .SH COMMAND \fI\,'ahriman repo\-remove\-unknown'\/\fR
usage: ahriman repo\-remove\-unknown [\-h] [\-\-dry\-run] usage: ahriman repo\-remove\-unknown [\-h] [\-\-dry\-run]
@ -560,7 +528,7 @@ instead of running all triggers as set by configuration, just process specified
.SH COMMAND \fI\,'ahriman repo\-update'\/\fR .SH COMMAND \fI\,'ahriman repo\-update'\/\fR
usage: ahriman repo\-update [\-h] [\-\-aur | \-\-no\-aur] [\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-e] usage: ahriman repo\-update [\-h] [\-\-aur | \-\-no\-aur] [\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-e]
[\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-u USERNAME] [\-\-vcs | \-\-no\-vcs] [\-y] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-\-vcs | \-\-no\-vcs] [\-y]
[package ...] [package ...]
check for packages updates and run build process if requested check for packages updates and run build process if requested
@ -572,11 +540,11 @@ filter check by package base
.SH OPTIONS \fI\,'ahriman repo\-update'\/\fR .SH OPTIONS \fI\,'ahriman repo\-update'\/\fR
.TP .TP
\fB\-\-aur\fR, \fB\-\-no\-aur\fR \fB\-\-aur\fR, \fB\-\-no\-aur\fR
enable or disable checking for AUR updates enable or disable checking for AUR updates (default: True)
.TP .TP
\fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR \fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR
process missing package dependencies process missing package dependencies (default: True)
.TP .TP
\fB\-\-dry\-run\fR \fB\-\-dry\-run\fR
@ -588,19 +556,15 @@ return non\-zero exit status if result is empty
.TP .TP
\fB\-\-local\fR, \fB\-\-no\-local\fR \fB\-\-local\fR, \fB\-\-no\-local\fR
enable or disable checking of local packages for updates enable or disable checking of local packages for updates (default: True)
.TP .TP
\fB\-\-manual\fR, \fB\-\-no\-manual\fR \fB\-\-manual\fR, \fB\-\-no\-manual\fR
include or exclude manual updates include or exclude manual updates (default: True)
.TP
\fB\-u\fR \fI\,USERNAME\/\fR, \fB\-\-username\fR \fI\,USERNAME\/\fR
build as user
.TP .TP
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR \fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
fetch actual version of VCS packages fetch actual version of VCS packages (default: True)
.TP .TP
\fB\-y\fR, \fB\-\-refresh\fR \fB\-y\fR, \fB\-\-refresh\fR
@ -615,23 +579,23 @@ remove local caches
.SH OPTIONS \fI\,'ahriman service\-clean'\/\fR .SH OPTIONS \fI\,'ahriman service\-clean'\/\fR
.TP .TP
\fB\-\-cache\fR, \fB\-\-no\-cache\fR \fB\-\-cache\fR, \fB\-\-no\-cache\fR
clear directory with package caches clear directory with package caches (default: False)
.TP .TP
\fB\-\-chroot\fR, \fB\-\-no\-chroot\fR \fB\-\-chroot\fR, \fB\-\-no\-chroot\fR
clear build chroot clear build chroot (default: False)
.TP .TP
\fB\-\-manual\fR, \fB\-\-no\-manual\fR \fB\-\-manual\fR, \fB\-\-no\-manual\fR
clear manually added packages queue clear manually added packages queue (default: False)
.TP .TP
\fB\-\-packages\fR, \fB\-\-no\-packages\fR \fB\-\-packages\fR, \fB\-\-no\-packages\fR
clear directory with built packages clear directory with built packages (default: False)
.TP .TP
\fB\-\-pacman\fR, \fB\-\-no\-pacman\fR \fB\-\-pacman\fR, \fB\-\-no\-pacman\fR
clear directory with pacman local database cache clear directory with pacman local database cache (default: False)
.SH COMMAND \fI\,'ahriman service\-config'\/\fR .SH COMMAND \fI\,'ahriman service\-config'\/\fR
usage: ahriman service\-config [\-h] [\-\-secure | \-\-no\-secure] usage: ahriman service\-config [\-h] [\-\-secure | \-\-no\-secure]
@ -641,7 +605,7 @@ dump configuration for the specified architecture
.SH OPTIONS \fI\,'ahriman service\-config'\/\fR .SH OPTIONS \fI\,'ahriman service\-config'\/\fR
.TP .TP
\fB\-\-secure\fR, \fB\-\-no\-secure\fR \fB\-\-secure\fR, \fB\-\-no\-secure\fR
hide passwords and secrets from output hide passwords and secrets from output (default: True)
.SH COMMAND \fI\,'ahriman service\-config\-validate'\/\fR .SH COMMAND \fI\,'ahriman service\-config\-validate'\/\fR
usage: ahriman service\-config\-validate [\-h] [\-e] usage: ahriman service\-config\-validate [\-h] [\-e]
@ -669,10 +633,9 @@ key server for key import
.SH COMMAND \fI\,'ahriman service\-setup'\/\fR .SH COMMAND \fI\,'ahriman service\-setup'\/\fR
usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-build\-command BUILD_COMMAND] usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-build\-command BUILD_COMMAND]
[\-\-from\-configuration FROM_CONFIGURATION] [\-\-generate\-salt | \-\-no\-generate\-salt] [\-\-from\-configuration FROM_CONFIGURATION] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
[\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs] [\-\-mirror MIRROR] [\-\-multilib | \-\-no\-multilib] [\-\-mirror MIRROR] [\-\-multilib | \-\-no\-multilib] \-\-packager PACKAGER \-\-repository REPOSITORY
\-\-packager PACKAGER \-\-repository REPOSITORY [\-\-sign\-key SIGN_KEY] [\-\-sign\-key SIGN_KEY] [\-\-sign\-target {disabled,packages,repository}] [\-\-web\-port WEB_PORT]
[\-\-sign\-target {disabled,packages,repository}] [\-\-web\-port WEB_PORT]
[\-\-web\-unix\-socket WEB_UNIX_SOCKET] [\-\-web\-unix\-socket WEB_UNIX_SOCKET]
create initial service configuration, requires root create initial service configuration, requires root
@ -690,13 +653,9 @@ build command prefix
\fB\-\-from\-configuration\fR \fI\,FROM_CONFIGURATION\/\fR \fB\-\-from\-configuration\fR \fI\,FROM_CONFIGURATION\/\fR
path to default devtools pacman configuration path to default devtools pacman configuration
.TP
\fB\-\-generate\-salt\fR, \fB\-\-no\-generate\-salt\fR
generate salt for user passwords
.TP .TP
\fB\-\-makeflags\-jobs\fR, \fB\-\-no\-makeflags\-jobs\fR \fB\-\-makeflags\-jobs\fR, \fB\-\-no\-makeflags\-jobs\fR
append MAKEFLAGS variable with parallelism set to number of cores append MAKEFLAGS variable with parallelism set to number of cores (default: True)
.TP .TP
\fB\-\-mirror\fR \fI\,MIRROR\/\fR \fB\-\-mirror\fR \fI\,MIRROR\/\fR
@ -704,7 +663,7 @@ use the specified explicitly mirror instead of including mirrorlist
.TP .TP
\fB\-\-multilib\fR, \fB\-\-no\-multilib\fR \fB\-\-multilib\fR, \fB\-\-no\-multilib\fR
add or do not multilib repository add or do not multilib repository (default: True)
.TP .TP
\fB\-\-packager\fR \fI\,PACKAGER\/\fR \fB\-\-packager\fR \fI\,PACKAGER\/\fR
@ -740,8 +699,7 @@ drop into python shell while having created application
instead of dropping into shell, just execute the specified code instead of dropping into shell, just execute the specified code
.SH COMMAND \fI\,'ahriman user\-add'\/\fR .SH COMMAND \fI\,'ahriman user\-add'\/\fR
usage: ahriman user\-add [\-h] [\-\-key KEY] [\-\-packager PACKAGER] [\-p PASSWORD] [\-r {unauthorized,read,reporter,full}] usage: ahriman user\-add [\-h] [\-p PASSWORD] [\-r {unauthorized,read,reporter,full}] [\-s] username
username
update user for web services with the given password and role. In case if password was not entered it will be asked interactively update user for web services with the given password and role. In case if password was not entered it will be asked interactively
@ -750,14 +708,6 @@ update user for web services with the given password and role. In case if passwo
username for web service username for web service
.SH OPTIONS \fI\,'ahriman user\-add'\/\fR .SH OPTIONS \fI\,'ahriman user\-add'\/\fR
.TP
\fB\-\-key\fR \fI\,KEY\/\fR
optional PGP key used by this user. The private key must be imported
.TP
\fB\-\-packager\fR \fI\,PACKAGER\/\fR
optional packager id used for build process in form of `Name Surname <mail@example.com>`
.TP .TP
\fB\-p\fR \fI\,PASSWORD\/\fR, \fB\-\-password\fR \fI\,PASSWORD\/\fR \fB\-p\fR \fI\,PASSWORD\/\fR, \fB\-\-password\fR \fI\,PASSWORD\/\fR
user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2 user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2
@ -767,6 +717,10 @@ authorization type.
\fB\-r\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR \fB\-r\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
user access level user access level
.TP
\fB\-s\fR, \fB\-\-secure\fR
set file permissions to user\-only
.SH COMMAND \fI\,'ahriman user\-list'\/\fR .SH COMMAND \fI\,'ahriman user\-list'\/\fR
usage: ahriman user\-list [\-h] [\-e] [\-r {unauthorized,read,reporter,full}] [username] usage: ahriman user\-list [\-h] [\-e] [\-r {unauthorized,read,reporter,full}] [username]
@ -802,7 +756,7 @@ start web server
.SH COMMENTS .SH COMMENTS
Argument list can also be read from file by using @ prefix. Argument list can also be read from file by using @ prefix.
.SH AUTHOR .SH AUTHORS
.nf .nf
ahriman team ahriman team
.fi .fi

View File

@ -60,22 +60,6 @@ ahriman.core.database.migrations.m006\_packages\_architecture\_required module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.core.database.migrations.m007\_check\_depends module
------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m007_check_depends
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m008\_packagers module
-------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m008_packagers
:members:
:no-undoc-members:
:show-inheritance:
Module contents Module contents
--------------- ---------------

View File

@ -20,14 +20,6 @@ ahriman.core.log.http\_log\_handler module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.core.log.journal\_handler module
----------------------------------------
.. automodule:: ahriman.core.log.journal_handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.log.lazy\_logging module ahriman.core.log.lazy\_logging module
------------------------------------- -------------------------------------

View File

@ -19,7 +19,6 @@ Subpackages
ahriman.core.repository ahriman.core.repository
ahriman.core.sign ahriman.core.sign
ahriman.core.status ahriman.core.status
ahriman.core.support
ahriman.core.triggers ahriman.core.triggers
ahriman.core.upload ahriman.core.upload

View File

@ -1,37 +0,0 @@
ahriman.core.support.pkgbuild package
=====================================
Submodules
----------
ahriman.core.support.pkgbuild.keyring\_generator module
-------------------------------------------------------
.. automodule:: ahriman.core.support.pkgbuild.keyring_generator
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.pkgbuild.mirrorlist\_generator module
----------------------------------------------------------
.. automodule:: ahriman.core.support.pkgbuild.mirrorlist_generator
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.pkgbuild.pkgbuild\_generator module
--------------------------------------------------------
.. automodule:: ahriman.core.support.pkgbuild.pkgbuild_generator
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.support.pkgbuild
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -1,45 +0,0 @@
ahriman.core.support package
============================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.support.pkgbuild
Submodules
----------
ahriman.core.support.keyring\_trigger module
--------------------------------------------
.. automodule:: ahriman.core.support.keyring_trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.mirrorlist\_trigger module
-----------------------------------------------
.. automodule:: ahriman.core.support.mirrorlist_trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.package\_creator module
--------------------------------------------
.. automodule:: ahriman.core.support.package_creator
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.support
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -60,14 +60,6 @@ ahriman.models.internal\_status module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.models.log\_handler module
----------------------------------
.. automodule:: ahriman.models.log_handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.log\_record\_id module ahriman.models.log\_record\_id module
------------------------------------- -------------------------------------
@ -116,22 +108,6 @@ ahriman.models.package\_source module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.models.packagers module
-------------------------------
.. automodule:: ahriman.models.packagers
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.pacman\_synchronization module
---------------------------------------------
.. automodule:: ahriman.models.pacman_synchronization
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.pkgbuild\_patch module ahriman.models.pkgbuild\_patch module
------------------------------------- -------------------------------------

View File

@ -33,7 +33,6 @@ This package contains everything required for the most of application actions an
* ``ahriman.core.alpm`` package controls pacman related functions. It provides wrappers for ``pyalpm`` library and safe calls for repository tools (``repo-add`` and ``repo-remove``). Also this package contains ``ahriman.core.alpm.remote`` package which provides wrapper for remote sources (e.g. AUR RPC and official repositories RPC). * ``ahriman.core.alpm`` package controls pacman related functions. It provides wrappers for ``pyalpm`` library and safe calls for repository tools (``repo-add`` and ``repo-remove``). Also this package contains ``ahriman.core.alpm.remote`` package which provides wrapper for remote sources (e.g. AUR RPC and official repositories RPC).
* ``ahriman.core.auth`` package provides classes for authorization methods used by web mostly. Base class is ``ahriman.core.auth.Auth`` which must be called by ``load`` method. * ``ahriman.core.auth`` package provides classes for authorization methods used by web mostly. Base class is ``ahriman.core.auth.Auth`` which must be called by ``load`` method.
* ``ahriman.core.build_tools`` is a package which provides wrapper for ``devtools`` commands. * ``ahriman.core.build_tools`` is a package which provides wrapper for ``devtools`` commands.
* ``ahriman.core.configuration`` contains extension for standard ``configparser`` library and some validation related classes.
* ``ahriman.core.database`` is everything including data and schema migrations for database. * ``ahriman.core.database`` is everything including data and schema migrations for database.
* ``ahriman.core.formatters`` package provides ``Printer`` sub-classes for printing data (e.g. package properties) to stdout which are used by some handlers. * ``ahriman.core.formatters`` package provides ``Printer`` sub-classes for printing data (e.g. package properties) to stdout which are used by some handlers.
* ``ahriman.core.gitremote`` is a package with remote PKGBUILD triggers. Should not be called directly. * ``ahriman.core.gitremote`` is a package with remote PKGBUILD triggers. Should not be called directly.
@ -42,12 +41,12 @@ This package contains everything required for the most of application actions an
* ``ahriman.core.repository`` contains several traits and base repository (``ahriman.core.repository.Repository`` class) implementation. * ``ahriman.core.repository`` contains several traits and base repository (``ahriman.core.repository.Repository`` class) implementation.
* ``ahriman.core.sign`` package provides sign feature (only gpg calls are available). * ``ahriman.core.sign`` package provides sign feature (only gpg calls are available).
* ``ahriman.core.status`` contains helpers and watcher class which are required for web application. Reporter must be initialized by using ``ahriman.core.status.client.Client.load`` method. * ``ahriman.core.status`` contains helpers and watcher class which are required for web application. Reporter must be initialized by using ``ahriman.core.status.client.Client.load`` method.
* ``ahriman.core.support`` provides plugins for support packages (mirrorlist and keyring) generation.
* ``ahriman.core.triggers`` package contains base trigger classes. Classes from this package must be imported in order to implement user extensions. In fact, ``ahriman.core.report`` and ``ahriman.core.upload`` use this package. * ``ahriman.core.triggers`` package contains base trigger classes. Classes from this package must be imported in order to implement user extensions. In fact, ``ahriman.core.report`` and ``ahriman.core.upload`` use this package.
* ``ahriman.core.upload`` package provides sync feature, should not be called directly. * ``ahriman.core.upload`` package provides sync feature, should not be called directly.
This package also provides some generic functions and classes which may be used by other packages: This package also provides some generic functions and classes which may be used by other packages:
* ``ahriman.core.configuration.Configuration`` is an extension for standard ``configparser`` library.
* ``ahriman.core.exceptions`` provides custom exceptions. * ``ahriman.core.exceptions`` provides custom exceptions.
* ``ahriman.core.spawn.Spawn`` is a tool which can spawn another ``ahriman`` process. This feature is used by web application. * ``ahriman.core.spawn.Spawn`` is a tool which can spawn another ``ahriman`` process. This feature is used by web application.
* ``ahriman.core.tree`` is a dependency tree implementation. * ``ahriman.core.tree`` is a dependency tree implementation.
@ -63,23 +62,20 @@ It provides models for any other part of application. Unlike ``ahriman.core`` pa
Web application. It is important that this package is isolated from any other to allow it to be optional feature (i.e. dependencies which are required by the package are optional). Web application. It is important that this package is isolated from any other to allow it to be optional feature (i.e. dependencies which are required by the package are optional).
* ``ahriman.web.middlewares`` provides middlewares for request handlers. * ``ahriman.web.middlewares`` provides middlewares for request handlers.
* ``ahriman.web.schemas`` provides schemas (actually copy paste from dataclasses) used by swagger documentation.
* ``ahriman.web.views`` contains web views derived from aiohttp view class. * ``ahriman.web.views`` contains web views derived from aiohttp view class.
* ``ahriman.web.apispec`` provides generators for swagger documentation.
* ``ahriman.web.cors`` contains helpers for cross origin resource sharing middlewares.
* ``ahriman.web.routes`` creates routes for web application. * ``ahriman.web.routes`` creates routes for web application.
* ``ahriman.web.web`` provides main web application functions (e.g. start, initialization). * ``ahriman.web.web`` provides main web application functions (e.g. start, initialization).
Application run Application run
--------------- ---------------
#. Parse command line arguments, find command and related handler which is set by parser. * Parse command line arguments, find command and related handler which is set by parser.
#. Call ``Handler.execute`` method. * Call ``Handler.execute`` method.
#. Define list of architectures to run. In case if there is more than one architecture specified run several subprocesses or process in current process otherwise. Class attribute ``ALLOW_MULTI_ARCHITECTURE_RUN`` controls whether application can be run in multiple processes or not - this feature is required for some handlers (e.g. ``Web``) which should be able to spawn child process in daemon mode (it is impossible to do from daemonic processes). * Define list of architectures to run. In case if there is more than one architecture specified run several subprocesses or process in current process otherwise. Class attribute ``ALLOW_MULTI_ARCHITECTURE_RUN`` controls whether application can be run in multiple processes or not - this feature is required for some handlers (e.g. ``Web``) which should be able to spawn child process in daemon mode (it is impossible to do from daemonic processes).
#. In each child process call lock functions. * In each child process call lock functions.
#. After success checks pass control to ``Handler.run`` method defined by specific handler class. * After success checks pass control to ``Handler.run`` method defined by specific handler class.
#. Return result (success or failure) of each subprocess and exit from application. * Return result (success or failure) of each subprocess and exit from application.
#. Some handlers may override their status and throw ``ExitCode`` exception. This exception is just silently suppressed and changes application exit code to ``1``. * Some handlers may override their status and throw ``ExitCode`` exception. This exception is just silently suppressed and changes application exit code to ``1``.
In the most cases handlers spawn god class ``ahriman.application.application.Application`` class and call required methods. In the most cases handlers spawn god class ``ahriman.application.application.Application`` class and call required methods.
@ -118,7 +114,7 @@ Schema and data migrations
The schema migration are applied according to current ``pragma user_info`` values, located at ``ahriman.core.database.migrations`` package and named as ``m000_migration_name.py`` (the preceding ``m`` is required in order to import migration content for tests). Additional class ``ahriman.core.database.migrations.Migrations`` reads all migrations automatically and applies them in alphabetical order. The schema migration are applied according to current ``pragma user_info`` values, located at ``ahriman.core.database.migrations`` package and named as ``m000_migration_name.py`` (the preceding ``m`` is required in order to import migration content for tests). Additional class ``ahriman.core.database.migrations.Migrations`` reads all migrations automatically and applies them in alphabetical order.
These migrations can also contain data migrations. Though the recommended way is to migrate data directly from SQL requests, sometimes it is required to have external data (like packages list) in order to set correct data. To do so, special method `migrate_data` is used. These migrations also contain data migrations. Though the recommended way is to migrate data directly from SQL requests, sometimes it is required to have external data (like packages list) in order to set correct data. To do so, special method `migrate_data` is used.
Type conversions Type conversions
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@ -130,12 +126,6 @@ By default, it parses rows into python dictionary. In addition, the following ps
Basic flows Basic flows
----------- -----------
By default package build operations are performed with ``PACKAGER`` which is specified in ``makepkg.conf``, however, it is possible to override this variable from command line; in this case service performs lookup in the following way:
* If packager is not set, it reads environment variables (e.g. ``SUDO_USER`` and ``USER``), otherwise it uses value from command line.
* It checks users for the specified username and tries to extract packager variable from it.
* If packager value has been found, it will be passed as ``PACKAGER`` system variable (sudo configuration required).
Add new packages or rebuild existing Add new packages or rebuild existing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -150,7 +140,7 @@ This logic can be overwritten by specifying the ``source`` parameter, which is p
Rebuild packages Rebuild packages
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
Same as add function for every package in repository. Optional filters by reverse dependency or build status can be supplied. Same as add function for every package in repository. Optional filter by reverse dependency can be supplied.
Remove packages Remove packages
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
@ -234,7 +224,7 @@ OAuth provider uses library definitions (``aioauth-client``) in order *authentic
OAuth's implementation also allows authenticating users via username + password (in the same way as mapping does) though it is not recommended for end-users and password must be left blank. In particular this feature can be used by service reporting (aka robots). OAuth's implementation also allows authenticating users via username + password (in the same way as mapping does) though it is not recommended for end-users and password must be left blank. In particular this feature can be used by service reporting (aka robots).
In addition, web service checks the source socket used. In case if it belongs to ``socket.AF_UNIX`` family, it will skip any further checks considering the request to be performed in safe environment (e.g. on the same physical machine). This feature, in particular is being used by the reporter instances in case if socket address is set in configuration. In addition, web service checks the source socket used. In case if it belongs to ``socket.AF_UNIX`` family, it will skip any furher checks considering the request to be performed in safe environment (e.g. on the same physical machine). This feature, in particular is being used by the reporter instances in case if socket address is set in configuration.
In order to configure users there are special commands. In order to configure users there are special commands.
@ -329,5 +319,3 @@ External calls
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
Web application provides external calls to control main service. It spawns child process with specific arguments and waits for its termination. This feature must be used either with authorization or in safe (i.e. when status page is not available world-wide) environment. Web application provides external calls to control main service. It spawns child process with specific arguments and waits for its termination. This feature must be used either with authorization or in safe (i.e. when status page is not available world-wide) environment.
For most actions it also extracts user from authentication (if provided) and passes it to underlying process.

View File

@ -1,18 +1,18 @@
# AUTOMATICALLY GENERATED by `shtab` # AUTOMATICALLY GENERATED by `shtab`
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web') _shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '--report' '--no-report' '-q' '--quiet' '--unsafe' '-V' '--version') _shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--report' '--no-report' '-q' '--quiet' '--unsafe' '-V' '--version')
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by') _shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by') _shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
_shtab_ahriman_help_option_strings=('-h' '--help') _shtab_ahriman_help_option_strings=('-h' '--help')
_shtab_ahriman_help_commands_unsafe_option_strings=('-h' '--help') _shtab_ahriman_help_commands_unsafe_option_strings=('-h' '--help' '--command')
_shtab_ahriman_help_updates_option_strings=('-h' '--help' '-e' '--exit-code') _shtab_ahriman_help_updates_option_strings=('-h' '--help' '-e' '--exit-code')
_shtab_ahriman_help_version_option_strings=('-h' '--help') _shtab_ahriman_help_version_option_strings=('-h' '--help')
_shtab_ahriman_version_option_strings=('-h' '--help') _shtab_ahriman_version_option_strings=('-h' '--help')
_shtab_ahriman_package_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username') _shtab_ahriman_package_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source')
_shtab_ahriman_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username') _shtab_ahriman_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source')
_shtab_ahriman_package_update_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username') _shtab_ahriman_package_update_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source')
_shtab_ahriman_package_remove_option_strings=('-h' '--help') _shtab_ahriman_package_remove_option_strings=('-h' '--help')
_shtab_ahriman_remove_option_strings=('-h' '--help') _shtab_ahriman_remove_option_strings=('-h' '--help')
_shtab_ahriman_package_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status') _shtab_ahriman_package_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status')
@ -27,12 +27,10 @@ _shtab_ahriman_patch_set_add_option_strings=('-h' '--help' '-t' '--track')
_shtab_ahriman_repo_backup_option_strings=('-h' '--help') _shtab_ahriman_repo_backup_option_strings=('-h' '--help')
_shtab_ahriman_repo_check_option_strings=('-h' '--help' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_repo_check_option_strings=('-h' '--help' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_check_option_strings=('-h' '--help' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_check_option_strings=('-h' '--help' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_repo_create_keyring_option_strings=('-h' '--help')
_shtab_ahriman_repo_create_mirrorlist_option_strings=('-h' '--help')
_shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '-e' '--exit-code' '-s' '--status' '-u' '--username') _shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '-e' '--exit-code')
_shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '-e' '--exit-code' '-s' '--status' '-u' '--username') _shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '-e' '--exit-code')
_shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run') _shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run')
_shtab_ahriman_remove_unknown_option_strings=('-h' '--help' '--dry-run') _shtab_ahriman_remove_unknown_option_strings=('-h' '--help' '--dry-run')
_shtab_ahriman_repo_report_option_strings=('-h' '--help') _shtab_ahriman_repo_report_option_strings=('-h' '--help')
@ -45,8 +43,8 @@ _shtab_ahriman_repo_sync_option_strings=('-h' '--help')
_shtab_ahriman_sync_option_strings=('-h' '--help') _shtab_ahriman_sync_option_strings=('-h' '--help')
_shtab_ahriman_repo_tree_option_strings=('-h' '--help') _shtab_ahriman_repo_tree_option_strings=('-h' '--help')
_shtab_ahriman_repo_triggers_option_strings=('-h' '--help') _shtab_ahriman_repo_triggers_option_strings=('-h' '--help')
_shtab_ahriman_repo_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--dry-run' '-e' '--exit-code' '--local' '--no-local' '--manual' '--no-manual' '-u' '--username' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_repo_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--dry-run' '-e' '--exit-code' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--dry-run' '-e' '--exit-code' '--local' '--no-local' '--manual' '--no-manual' '-u' '--username' '--vcs' '--no-vcs' '-y' '--refresh') _shtab_ahriman_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--dry-run' '-e' '--exit-code' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
_shtab_ahriman_service_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman') _shtab_ahriman_service_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
_shtab_ahriman_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman') _shtab_ahriman_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
_shtab_ahriman_repo_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman') _shtab_ahriman_repo_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
@ -58,22 +56,21 @@ _shtab_ahriman_config_validate_option_strings=('-h' '--help' '-e' '--exit-code')
_shtab_ahriman_repo_config_validate_option_strings=('-h' '--help' '-e' '--exit-code') _shtab_ahriman_repo_config_validate_option_strings=('-h' '--help' '-e' '--exit-code')
_shtab_ahriman_service_key_import_option_strings=('-h' '--help' '--key-server') _shtab_ahriman_service_key_import_option_strings=('-h' '--help' '--key-server')
_shtab_ahriman_key_import_option_strings=('-h' '--help' '--key-server') _shtab_ahriman_key_import_option_strings=('-h' '--help' '--key-server')
_shtab_ahriman_service_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket') _shtab_ahriman_service_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
_shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket') _shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket') _shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
_shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket') _shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket') _shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
_shtab_ahriman_service_shell_option_strings=('-h' '--help') _shtab_ahriman_service_shell_option_strings=('-h' '--help')
_shtab_ahriman_shell_option_strings=('-h' '--help') _shtab_ahriman_shell_option_strings=('-h' '--help')
_shtab_ahriman_user_add_option_strings=('-h' '--help' '--key' '--packager' '-p' '--password' '-r' '--role') _shtab_ahriman_user_add_option_strings=('-h' '--help' '-p' '--password' '-r' '--role' '-s' '--secure')
_shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-r' '--role') _shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-r' '--role')
_shtab_ahriman_user_remove_option_strings=('-h' '--help') _shtab_ahriman_user_remove_option_strings=('-h' '--help')
_shtab_ahriman_web_option_strings=('-h' '--help') _shtab_ahriman_web_option_strings=('-h' '--help')
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web') _shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version') _shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version') _shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
_shtab_ahriman_package_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository') _shtab_ahriman_package_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
@ -90,10 +87,6 @@ _shtab_ahriman_package_status_update__s_choices=('unknown' 'pending' 'building'
_shtab_ahriman_package_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success') _shtab_ahriman_package_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_status_update__s_choices=('unknown' 'pending' 'building' 'failed' 'success') _shtab_ahriman_status_update__s_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success') _shtab_ahriman_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_repo_rebuild__s_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_repo_rebuild___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_rebuild__s_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_rebuild___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_repo_status_update__s_choices=('unknown' 'pending' 'building' 'failed' 'success') _shtab_ahriman_repo_status_update__s_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_repo_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success') _shtab_ahriman_repo_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
_shtab_ahriman_service_setup___sign_target_choices=('disabled' 'packages' 'repository') _shtab_ahriman_service_setup___sign_target_choices=('disabled' 'packages' 'repository')
@ -133,7 +126,6 @@ _shtab_ahriman_search___info_nargs=0
_shtab_ahriman_search___no_info_nargs=0 _shtab_ahriman_search___no_info_nargs=0
_shtab_ahriman_help__h_nargs=0 _shtab_ahriman_help__h_nargs=0
_shtab_ahriman_help___help_nargs=0 _shtab_ahriman_help___help_nargs=0
_shtab_ahriman_help_commands_unsafe_pos_0_nargs=*
_shtab_ahriman_help_commands_unsafe__h_nargs=0 _shtab_ahriman_help_commands_unsafe__h_nargs=0
_shtab_ahriman_help_commands_unsafe___help_nargs=0 _shtab_ahriman_help_commands_unsafe___help_nargs=0
_shtab_ahriman_help_updates__h_nargs=0 _shtab_ahriman_help_updates__h_nargs=0
@ -238,10 +230,6 @@ _shtab_ahriman_check___vcs_nargs=0
_shtab_ahriman_check___no_vcs_nargs=0 _shtab_ahriman_check___no_vcs_nargs=0
_shtab_ahriman_check__y_nargs=0 _shtab_ahriman_check__y_nargs=0
_shtab_ahriman_check___refresh_nargs=0 _shtab_ahriman_check___refresh_nargs=0
_shtab_ahriman_repo_create_keyring__h_nargs=0
_shtab_ahriman_repo_create_keyring___help_nargs=0
_shtab_ahriman_repo_create_mirrorlist__h_nargs=0
_shtab_ahriman_repo_create_mirrorlist___help_nargs=0
_shtab_ahriman_repo_daemon__h_nargs=0 _shtab_ahriman_repo_daemon__h_nargs=0
_shtab_ahriman_repo_daemon___help_nargs=0 _shtab_ahriman_repo_daemon___help_nargs=0
_shtab_ahriman_repo_daemon___aur_nargs=0 _shtab_ahriman_repo_daemon___aur_nargs=0
@ -413,40 +401,30 @@ _shtab_ahriman_key_import__h_nargs=0
_shtab_ahriman_key_import___help_nargs=0 _shtab_ahriman_key_import___help_nargs=0
_shtab_ahriman_service_setup__h_nargs=0 _shtab_ahriman_service_setup__h_nargs=0
_shtab_ahriman_service_setup___help_nargs=0 _shtab_ahriman_service_setup___help_nargs=0
_shtab_ahriman_service_setup___generate_salt_nargs=0
_shtab_ahriman_service_setup___no_generate_salt_nargs=0
_shtab_ahriman_service_setup___makeflags_jobs_nargs=0 _shtab_ahriman_service_setup___makeflags_jobs_nargs=0
_shtab_ahriman_service_setup___no_makeflags_jobs_nargs=0 _shtab_ahriman_service_setup___no_makeflags_jobs_nargs=0
_shtab_ahriman_service_setup___multilib_nargs=0 _shtab_ahriman_service_setup___multilib_nargs=0
_shtab_ahriman_service_setup___no_multilib_nargs=0 _shtab_ahriman_service_setup___no_multilib_nargs=0
_shtab_ahriman_init__h_nargs=0 _shtab_ahriman_init__h_nargs=0
_shtab_ahriman_init___help_nargs=0 _shtab_ahriman_init___help_nargs=0
_shtab_ahriman_init___generate_salt_nargs=0
_shtab_ahriman_init___no_generate_salt_nargs=0
_shtab_ahriman_init___makeflags_jobs_nargs=0 _shtab_ahriman_init___makeflags_jobs_nargs=0
_shtab_ahriman_init___no_makeflags_jobs_nargs=0 _shtab_ahriman_init___no_makeflags_jobs_nargs=0
_shtab_ahriman_init___multilib_nargs=0 _shtab_ahriman_init___multilib_nargs=0
_shtab_ahriman_init___no_multilib_nargs=0 _shtab_ahriman_init___no_multilib_nargs=0
_shtab_ahriman_repo_init__h_nargs=0 _shtab_ahriman_repo_init__h_nargs=0
_shtab_ahriman_repo_init___help_nargs=0 _shtab_ahriman_repo_init___help_nargs=0
_shtab_ahriman_repo_init___generate_salt_nargs=0
_shtab_ahriman_repo_init___no_generate_salt_nargs=0
_shtab_ahriman_repo_init___makeflags_jobs_nargs=0 _shtab_ahriman_repo_init___makeflags_jobs_nargs=0
_shtab_ahriman_repo_init___no_makeflags_jobs_nargs=0 _shtab_ahriman_repo_init___no_makeflags_jobs_nargs=0
_shtab_ahriman_repo_init___multilib_nargs=0 _shtab_ahriman_repo_init___multilib_nargs=0
_shtab_ahriman_repo_init___no_multilib_nargs=0 _shtab_ahriman_repo_init___no_multilib_nargs=0
_shtab_ahriman_repo_setup__h_nargs=0 _shtab_ahriman_repo_setup__h_nargs=0
_shtab_ahriman_repo_setup___help_nargs=0 _shtab_ahriman_repo_setup___help_nargs=0
_shtab_ahriman_repo_setup___generate_salt_nargs=0
_shtab_ahriman_repo_setup___no_generate_salt_nargs=0
_shtab_ahriman_repo_setup___makeflags_jobs_nargs=0 _shtab_ahriman_repo_setup___makeflags_jobs_nargs=0
_shtab_ahriman_repo_setup___no_makeflags_jobs_nargs=0 _shtab_ahriman_repo_setup___no_makeflags_jobs_nargs=0
_shtab_ahriman_repo_setup___multilib_nargs=0 _shtab_ahriman_repo_setup___multilib_nargs=0
_shtab_ahriman_repo_setup___no_multilib_nargs=0 _shtab_ahriman_repo_setup___no_multilib_nargs=0
_shtab_ahriman_setup__h_nargs=0 _shtab_ahriman_setup__h_nargs=0
_shtab_ahriman_setup___help_nargs=0 _shtab_ahriman_setup___help_nargs=0
_shtab_ahriman_setup___generate_salt_nargs=0
_shtab_ahriman_setup___no_generate_salt_nargs=0
_shtab_ahriman_setup___makeflags_jobs_nargs=0 _shtab_ahriman_setup___makeflags_jobs_nargs=0
_shtab_ahriman_setup___no_makeflags_jobs_nargs=0 _shtab_ahriman_setup___no_makeflags_jobs_nargs=0
_shtab_ahriman_setup___multilib_nargs=0 _shtab_ahriman_setup___multilib_nargs=0
@ -461,6 +439,8 @@ _shtab_ahriman_shell__v_nargs=0
_shtab_ahriman_shell___verbose_nargs=0 _shtab_ahriman_shell___verbose_nargs=0
_shtab_ahriman_user_add__h_nargs=0 _shtab_ahriman_user_add__h_nargs=0
_shtab_ahriman_user_add___help_nargs=0 _shtab_ahriman_user_add___help_nargs=0
_shtab_ahriman_user_add__s_nargs=0
_shtab_ahriman_user_add___secure_nargs=0
_shtab_ahriman_user_list__h_nargs=0 _shtab_ahriman_user_list__h_nargs=0
_shtab_ahriman_user_list___help_nargs=0 _shtab_ahriman_user_list___help_nargs=0
_shtab_ahriman_user_list__e_nargs=0 _shtab_ahriman_user_list__e_nargs=0

View File

@ -36,8 +36,6 @@ _shtab_ahriman_commands() {
"repo-clean:remove local caches" "repo-clean:remove local caches"
"repo-config:dump configuration for the specified architecture" "repo-config:dump configuration for the specified architecture"
"repo-config-validate:validate configuration and print found errors" "repo-config-validate:validate configuration and print found errors"
"repo-create-keyring:create package which contains list of trusted keys as set by configuration. Note, that this action will only create package, the package itself has to be built manually"
"repo-create-mirrorlist:create package which contains list of available mirrors as set by configuration. Note, that this action will only create package, the package itself has to be built manually"
"repo-daemon:start process which periodically will run update process" "repo-daemon:start process which periodically will run update process"
"repo-init:create initial service configuration, requires root" "repo-init:create initial service configuration, requires root"
"repo-rebuild:force rebuild whole repository" "repo-rebuild:force rebuild whole repository"
@ -81,8 +79,7 @@ _shtab_ahriman_options=(
{-c,--configuration}"[configuration path]:configuration:" {-c,--configuration}"[configuration path]:configuration:"
"--force[force run, remove file lock]" "--force[force run, remove file lock]"
{-l,--lock}"[lock file]:lock:" {-l,--lock}"[lock file]:lock:"
"--log-handler[explicit log handler specification. If none set, the handler will be guessed from environment]:log_handler:(console syslog journald)" {--report,--no-report}"[force enable or disable reporting to web service (default\: \%(default)s)]:report:"
{--report,--no-report}"[force enable or disable reporting to web service]:report:"
{-q,--quiet}"[force disable any logging]" {-q,--quiet}"[force disable any logging]"
"--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable]" "--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable]"
"(- : *)"{-V,--version}"[show program\'s version number and exit]" "(- : *)"{-V,--version}"[show program\'s version number and exit]"
@ -90,19 +87,18 @@ _shtab_ahriman_options=(
_shtab_ahriman_add_options=( _shtab_ahriman_add_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{-n,--now}"[run update function after]" {-n,--now}"[run update function after]"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
{-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)" {-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)"
{-u,--username}"[build as user]:username:"
"(*):package source (base name, path to local files, remote URL):" "(*):package source (base name, path to local files, remote URL):"
) )
_shtab_ahriman_aur_search_options=( _shtab_ahriman_aur_search_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--info,--no-info}"[show additional package information]:info:" {--info,--no-info}"[show additional package information (default\: \%(default)s)]:info:"
"--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository submitter url url_path version)" "--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository submitter url url_path version)"
"(*):search terms, can be specified multiple times, the result will match all terms:" "(*):search terms, can be specified multiple times, the result will match all terms:"
) )
@ -110,23 +106,23 @@ _shtab_ahriman_aur_search_options=(
_shtab_ahriman_check_options=( _shtab_ahriman_check_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--vcs,--no-vcs}"[fetch actual version of VCS packages]:vcs:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
"(*)::filter check by package base:" "(*)::filter check by package base:"
) )
_shtab_ahriman_clean_options=( _shtab_ahriman_clean_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--cache,--no-cache}"[clear directory with package caches]:cache:" {--cache,--no-cache}"[clear directory with package caches (default\: \%(default)s)]:cache:"
{--chroot,--no-chroot}"[clear build chroot]:chroot:" {--chroot,--no-chroot}"[clear build chroot (default\: \%(default)s)]:chroot:"
{--manual,--no-manual}"[clear manually added packages queue]:manual:" {--manual,--no-manual}"[clear manually added packages queue (default\: \%(default)s)]:manual:"
{--packages,--no-packages}"[clear directory with built packages]:packages:" {--packages,--no-packages}"[clear directory with built packages (default\: \%(default)s)]:packages:"
{--pacman,--no-pacman}"[clear directory with pacman local database cache]:pacman:" {--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: \%(default)s)]:pacman:"
) )
_shtab_ahriman_config_options=( _shtab_ahriman_config_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--secure,--no-secure}"[hide passwords and secrets from output]:secure:" {--secure,--no-secure}"[hide passwords and secrets from output (default\: \%(default)s)]:secure:"
) )
_shtab_ahriman_config_validate_options=( _shtab_ahriman_config_validate_options=(
@ -137,11 +133,11 @@ _shtab_ahriman_config_validate_options=(
_shtab_ahriman_daemon_options=( _shtab_ahriman_daemon_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{-i,--interval}"[interval between runs in seconds]:interval:" {-i,--interval}"[interval between runs in seconds]:interval:"
{--aur,--no-aur}"[enable or disable checking for AUR updates]:aur:" {--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
{--local,--no-local}"[enable or disable checking of local packages for updates]:local:" {--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
{--manual,--no-manual}"[include or exclude manual updates]:manual:" {--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
{--vcs,--no-vcs}"[fetch actual version of VCS packages]:vcs:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
) )
@ -152,7 +148,7 @@ _shtab_ahriman_help_options=(
_shtab_ahriman_help_commands_unsafe_options=( _shtab_ahriman_help_commands_unsafe_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
"(*)::instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 otherwise:" "--command[instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 otherwise]:command:"
) )
_shtab_ahriman_help_updates_options=( _shtab_ahriman_help_updates_options=(
@ -169,10 +165,9 @@ _shtab_ahriman_init_options=(
"--build-as-user[force makepkg user to the specific one]:build_as_user:" "--build-as-user[force makepkg user to the specific one]:build_as_user:"
"--build-command[build command prefix]:build_command:" "--build-command[build command prefix]:build_command:"
"--from-configuration[path to default devtools pacman configuration]:from_configuration:" "--from-configuration[path to default devtools pacman configuration]:from_configuration:"
{--generate-salt,--no-generate-salt}"[generate salt for user passwords]:generate_salt:" {--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores]:makeflags_jobs:"
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:" "--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
{--multilib,--no-multilib}"[add or do not multilib repository]:multilib:" {--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
"--packager[packager name and email]:packager:" "--packager[packager name and email]:packager:"
"--repository[repository name]:repository:" "--repository[repository name]:repository:"
"--sign-key[sign key id]:sign_key:" "--sign-key[sign key id]:sign_key:"
@ -189,12 +184,11 @@ _shtab_ahriman_key_import_options=(
_shtab_ahriman_package_add_options=( _shtab_ahriman_package_add_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{-n,--now}"[run update function after]" {-n,--now}"[run update function after]"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
{-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)" {-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)"
{-u,--username}"[build as user]:username:"
"(*):package source (base name, path to local files, remote URL):" "(*):package source (base name, path to local files, remote URL):"
) )
@ -207,7 +201,7 @@ _shtab_ahriman_package_status_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
"--ahriman[get service status itself]" "--ahriman[get service status itself]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--info,--no-info}"[show additional package information]:info:" {--info,--no-info}"[show additional package information (default\: \%(default)s)]:info:"
{-s,--status}"[filter packages by status]:status:(unknown pending building failed success)" {-s,--status}"[filter packages by status]:status:(unknown pending building failed success)"
"(*)::filter status by package base:" "(*)::filter status by package base:"
) )
@ -225,12 +219,11 @@ _shtab_ahriman_package_status_update_options=(
_shtab_ahriman_package_update_options=( _shtab_ahriman_package_update_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{-n,--now}"[run update function after]" {-n,--now}"[run update function after]"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
{-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)" {-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)"
{-u,--username}"[build as user]:username:"
"(*):package source (base name, path to local files, remote URL):" "(*):package source (base name, path to local files, remote URL):"
) )
@ -266,8 +259,6 @@ _shtab_ahriman_rebuild_options=(
"--dry-run[just perform check for packages without rebuild process itself]" "--dry-run[just perform check for packages without rebuild process itself]"
"--from-database[read packages from database instead of filesystem. This feature in particular is required in case if you would like to restore repository from another repository instance. Note, however, that in order to restore packages you need to have original ahriman instance run with web service and have run repo-update at least once.]" "--from-database[read packages from database instead of filesystem. This feature in particular is required in case if you would like to restore repository from another repository instance. Note, however, that in order to restore packages you need to have original ahriman instance run with web service and have run repo-update at least once.]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{-s,--status}"[filter packages by status. Requires --from-database to be set]:status:(unknown pending building failed success)"
{-u,--username}"[build as user]:username:"
) )
_shtab_ahriman_remove_options=( _shtab_ahriman_remove_options=(
@ -288,23 +279,23 @@ _shtab_ahriman_repo_backup_options=(
_shtab_ahriman_repo_check_options=( _shtab_ahriman_repo_check_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--vcs,--no-vcs}"[fetch actual version of VCS packages]:vcs:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
"(*)::filter check by package base:" "(*)::filter check by package base:"
) )
_shtab_ahriman_repo_clean_options=( _shtab_ahriman_repo_clean_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--cache,--no-cache}"[clear directory with package caches]:cache:" {--cache,--no-cache}"[clear directory with package caches (default\: \%(default)s)]:cache:"
{--chroot,--no-chroot}"[clear build chroot]:chroot:" {--chroot,--no-chroot}"[clear build chroot (default\: \%(default)s)]:chroot:"
{--manual,--no-manual}"[clear manually added packages queue]:manual:" {--manual,--no-manual}"[clear manually added packages queue (default\: \%(default)s)]:manual:"
{--packages,--no-packages}"[clear directory with built packages]:packages:" {--packages,--no-packages}"[clear directory with built packages (default\: \%(default)s)]:packages:"
{--pacman,--no-pacman}"[clear directory with pacman local database cache]:pacman:" {--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: \%(default)s)]:pacman:"
) )
_shtab_ahriman_repo_config_options=( _shtab_ahriman_repo_config_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--secure,--no-secure}"[hide passwords and secrets from output]:secure:" {--secure,--no-secure}"[hide passwords and secrets from output (default\: \%(default)s)]:secure:"
) )
_shtab_ahriman_repo_config_validate_options=( _shtab_ahriman_repo_config_validate_options=(
@ -312,22 +303,14 @@ _shtab_ahriman_repo_config_validate_options=(
{-e,--exit-code}"[return non-zero exit status if configuration is invalid]" {-e,--exit-code}"[return non-zero exit status if configuration is invalid]"
) )
_shtab_ahriman_repo_create_keyring_options=(
"(- : *)"{-h,--help}"[show this help message and exit]"
)
_shtab_ahriman_repo_create_mirrorlist_options=(
"(- : *)"{-h,--help}"[show this help message and exit]"
)
_shtab_ahriman_repo_daemon_options=( _shtab_ahriman_repo_daemon_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{-i,--interval}"[interval between runs in seconds]:interval:" {-i,--interval}"[interval between runs in seconds]:interval:"
{--aur,--no-aur}"[enable or disable checking for AUR updates]:aur:" {--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
{--local,--no-local}"[enable or disable checking of local packages for updates]:local:" {--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
{--manual,--no-manual}"[include or exclude manual updates]:manual:" {--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
{--vcs,--no-vcs}"[fetch actual version of VCS packages]:vcs:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
) )
@ -336,10 +319,9 @@ _shtab_ahriman_repo_init_options=(
"--build-as-user[force makepkg user to the specific one]:build_as_user:" "--build-as-user[force makepkg user to the specific one]:build_as_user:"
"--build-command[build command prefix]:build_command:" "--build-command[build command prefix]:build_command:"
"--from-configuration[path to default devtools pacman configuration]:from_configuration:" "--from-configuration[path to default devtools pacman configuration]:from_configuration:"
{--generate-salt,--no-generate-salt}"[generate salt for user passwords]:generate_salt:" {--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores]:makeflags_jobs:"
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:" "--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
{--multilib,--no-multilib}"[add or do not multilib repository]:multilib:" {--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
"--packager[packager name and email]:packager:" "--packager[packager name and email]:packager:"
"--repository[repository name]:repository:" "--repository[repository name]:repository:"
"--sign-key[sign key id]:sign_key:" "--sign-key[sign key id]:sign_key:"
@ -354,8 +336,6 @@ _shtab_ahriman_repo_rebuild_options=(
"--dry-run[just perform check for packages without rebuild process itself]" "--dry-run[just perform check for packages without rebuild process itself]"
"--from-database[read packages from database instead of filesystem. This feature in particular is required in case if you would like to restore repository from another repository instance. Note, however, that in order to restore packages you need to have original ahriman instance run with web service and have run repo-update at least once.]" "--from-database[read packages from database instead of filesystem. This feature in particular is required in case if you would like to restore repository from another repository instance. Note, however, that in order to restore packages you need to have original ahriman instance run with web service and have run repo-update at least once.]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{-s,--status}"[filter packages by status. Requires --from-database to be set]:status:(unknown pending building failed success)"
{-u,--username}"[build as user]:username:"
) )
_shtab_ahriman_repo_remove_unknown_options=( _shtab_ahriman_repo_remove_unknown_options=(
@ -378,10 +358,9 @@ _shtab_ahriman_repo_setup_options=(
"--build-as-user[force makepkg user to the specific one]:build_as_user:" "--build-as-user[force makepkg user to the specific one]:build_as_user:"
"--build-command[build command prefix]:build_command:" "--build-command[build command prefix]:build_command:"
"--from-configuration[path to default devtools pacman configuration]:from_configuration:" "--from-configuration[path to default devtools pacman configuration]:from_configuration:"
{--generate-salt,--no-generate-salt}"[generate salt for user passwords]:generate_salt:" {--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores]:makeflags_jobs:"
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:" "--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
{--multilib,--no-multilib}"[add or do not multilib repository]:multilib:" {--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
"--packager[packager name and email]:packager:" "--packager[packager name and email]:packager:"
"--repository[repository name]:repository:" "--repository[repository name]:repository:"
"--sign-key[sign key id]:sign_key:" "--sign-key[sign key id]:sign_key:"
@ -415,14 +394,13 @@ _shtab_ahriman_repo_triggers_options=(
_shtab_ahriman_repo_update_options=( _shtab_ahriman_repo_update_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--aur,--no-aur}"[enable or disable checking for AUR updates]:aur:" {--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
"--dry-run[just perform check for updates, same as check command]" "--dry-run[just perform check for updates, same as check command]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--local,--no-local}"[enable or disable checking of local packages for updates]:local:" {--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
{--manual,--no-manual}"[include or exclude manual updates]:manual:" {--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
{-u,--username}"[build as user]:username:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
{--vcs,--no-vcs}"[fetch actual version of VCS packages]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
"(*)::filter check by package base:" "(*)::filter check by package base:"
) )
@ -434,23 +412,23 @@ _shtab_ahriman_report_options=(
_shtab_ahriman_search_options=( _shtab_ahriman_search_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--info,--no-info}"[show additional package information]:info:" {--info,--no-info}"[show additional package information (default\: \%(default)s)]:info:"
"--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository submitter url url_path version)" "--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository submitter url url_path version)"
"(*):search terms, can be specified multiple times, the result will match all terms:" "(*):search terms, can be specified multiple times, the result will match all terms:"
) )
_shtab_ahriman_service_clean_options=( _shtab_ahriman_service_clean_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--cache,--no-cache}"[clear directory with package caches]:cache:" {--cache,--no-cache}"[clear directory with package caches (default\: \%(default)s)]:cache:"
{--chroot,--no-chroot}"[clear build chroot]:chroot:" {--chroot,--no-chroot}"[clear build chroot (default\: \%(default)s)]:chroot:"
{--manual,--no-manual}"[clear manually added packages queue]:manual:" {--manual,--no-manual}"[clear manually added packages queue (default\: \%(default)s)]:manual:"
{--packages,--no-packages}"[clear directory with built packages]:packages:" {--packages,--no-packages}"[clear directory with built packages (default\: \%(default)s)]:packages:"
{--pacman,--no-pacman}"[clear directory with pacman local database cache]:pacman:" {--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: \%(default)s)]:pacman:"
) )
_shtab_ahriman_service_config_options=( _shtab_ahriman_service_config_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--secure,--no-secure}"[hide passwords and secrets from output]:secure:" {--secure,--no-secure}"[hide passwords and secrets from output (default\: \%(default)s)]:secure:"
) )
_shtab_ahriman_service_config_validate_options=( _shtab_ahriman_service_config_validate_options=(
@ -469,10 +447,9 @@ _shtab_ahriman_service_setup_options=(
"--build-as-user[force makepkg user to the specific one]:build_as_user:" "--build-as-user[force makepkg user to the specific one]:build_as_user:"
"--build-command[build command prefix]:build_command:" "--build-command[build command prefix]:build_command:"
"--from-configuration[path to default devtools pacman configuration]:from_configuration:" "--from-configuration[path to default devtools pacman configuration]:from_configuration:"
{--generate-salt,--no-generate-salt}"[generate salt for user passwords]:generate_salt:" {--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores]:makeflags_jobs:"
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:" "--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
{--multilib,--no-multilib}"[add or do not multilib repository]:multilib:" {--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
"--packager[packager name and email]:packager:" "--packager[packager name and email]:packager:"
"--repository[repository name]:repository:" "--repository[repository name]:repository:"
"--sign-key[sign key id]:sign_key:" "--sign-key[sign key id]:sign_key:"
@ -491,10 +468,9 @@ _shtab_ahriman_setup_options=(
"--build-as-user[force makepkg user to the specific one]:build_as_user:" "--build-as-user[force makepkg user to the specific one]:build_as_user:"
"--build-command[build command prefix]:build_command:" "--build-command[build command prefix]:build_command:"
"--from-configuration[path to default devtools pacman configuration]:from_configuration:" "--from-configuration[path to default devtools pacman configuration]:from_configuration:"
{--generate-salt,--no-generate-salt}"[generate salt for user passwords]:generate_salt:" {--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores]:makeflags_jobs:"
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:" "--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
{--multilib,--no-multilib}"[add or do not multilib repository]:multilib:" {--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
"--packager[packager name and email]:packager:" "--packager[packager name and email]:packager:"
"--repository[repository name]:repository:" "--repository[repository name]:repository:"
"--sign-key[sign key id]:sign_key:" "--sign-key[sign key id]:sign_key:"
@ -517,7 +493,7 @@ _shtab_ahriman_status_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
"--ahriman[get service status itself]" "--ahriman[get service status itself]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--info,--no-info}"[show additional package information]:info:" {--info,--no-info}"[show additional package information (default\: \%(default)s)]:info:"
{-s,--status}"[filter packages by status]:status:(unknown pending building failed success)" {-s,--status}"[filter packages by status]:status:(unknown pending building failed success)"
"(*)::filter status by package base:" "(*)::filter status by package base:"
) )
@ -534,24 +510,22 @@ _shtab_ahriman_sync_options=(
_shtab_ahriman_update_options=( _shtab_ahriman_update_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
{--aur,--no-aur}"[enable or disable checking for AUR updates]:aur:" {--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
{--dependencies,--no-dependencies}"[process missing package dependencies]:dependencies:" {--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
"--dry-run[just perform check for updates, same as check command]" "--dry-run[just perform check for updates, same as check command]"
{-e,--exit-code}"[return non-zero exit status if result is empty]" {-e,--exit-code}"[return non-zero exit status if result is empty]"
{--local,--no-local}"[enable or disable checking of local packages for updates]:local:" {--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
{--manual,--no-manual}"[include or exclude manual updates]:manual:" {--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
{-u,--username}"[build as user]:username:" {--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
{--vcs,--no-vcs}"[fetch actual version of VCS packages]:vcs:"
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]" "*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
"(*)::filter check by package base:" "(*)::filter check by package base:"
) )
_shtab_ahriman_user_add_options=( _shtab_ahriman_user_add_options=(
"(- : *)"{-h,--help}"[show this help message and exit]" "(- : *)"{-h,--help}"[show this help message and exit]"
"--key[optional PGP key used by this user. The private key must be imported]:key:"
"--packager[optional packager id used for build process in form of \`Name Surname \<mail\@example.com\>\`]:packager:"
{-p,--password}"[user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2 authorization type.]:password:" {-p,--password}"[user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2 authorization type.]:password:"
{-r,--role}"[user access level]:role:(unauthorized read reporter full)" {-r,--role}"[user access level]:role:(unauthorized read reporter full)"
{-s,--secure}"[set file permissions to user-only]"
":username for web service:" ":username for web service:"
) )
@ -621,8 +595,6 @@ _shtab_ahriman() {
repo-clean) _arguments -C $_shtab_ahriman_repo_clean_options ;; repo-clean) _arguments -C $_shtab_ahriman_repo_clean_options ;;
repo-config) _arguments -C $_shtab_ahriman_repo_config_options ;; repo-config) _arguments -C $_shtab_ahriman_repo_config_options ;;
repo-config-validate) _arguments -C $_shtab_ahriman_repo_config_validate_options ;; repo-config-validate) _arguments -C $_shtab_ahriman_repo_config_validate_options ;;
repo-create-keyring) _arguments -C $_shtab_ahriman_repo_create_keyring_options ;;
repo-create-mirrorlist) _arguments -C $_shtab_ahriman_repo_create_mirrorlist_options ;;
repo-daemon) _arguments -C $_shtab_ahriman_repo_daemon_options ;; repo-daemon) _arguments -C $_shtab_ahriman_repo_daemon_options ;;
repo-init) _arguments -C $_shtab_ahriman_repo_init_options ;; repo-init) _arguments -C $_shtab_ahriman_repo_init_options ;;
repo-rebuild) _arguments -C $_shtab_ahriman_repo_rebuild_options ;; repo-rebuild) _arguments -C $_shtab_ahriman_repo_rebuild_options ;;

View File

@ -14,6 +14,7 @@ import os
import sys import sys
from pathlib import Path from pathlib import Path
from unittest import mock
from ahriman.version import __version__ from ahriman.version import __version__
@ -23,6 +24,13 @@ sys.path.insert(0, str(basedir))
on_rtd = os.environ.get("READTHEDOCS", None) == "True" on_rtd = os.environ.get("READTHEDOCS", None) == "True"
for module in (
"pyalpm",
):
if module in sys.modules:
continue
sys.modules[module] = mock.Mock()
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
@ -84,8 +92,6 @@ autoclass_content = "both"
autodoc_member_order = "groupwise" autodoc_member_order = "groupwise"
autodoc_mock_imports = ["pyalpm"]
autodoc_default_options = { autodoc_default_options = {
"no-undoc-members": True, "no-undoc-members": True,
} }

View File

@ -30,8 +30,8 @@ Base configuration settings.
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference. * ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
* ``suppress_http_log_errors`` - suppress http log errors, boolean, optional, default ``no``. If set to ``yes``, any http log errors (e.g. if web server is not available, but http logging is enabled) will be suppressed. * ``suppress_http_log_errors`` - suppress http log errors, boolean, optional, default ``no``. If set to ``yes``, any http log errors (e.g. if web server is not available, but http logging is enabled) will be suppressed.
``alpm:*`` groups ``alpm`` group
----------------- --------------
libalpm and AUR related configuration. Group name can refer to architecture, e.g. ``alpm:x86_64`` can be used for x86_64 architecture specific settings. libalpm and AUR related configuration. Group name can refer to architecture, e.g. ``alpm:x86_64`` can be used for x86_64 architecture specific settings.
@ -63,13 +63,10 @@ Authorized users are stored inside internal database, if any of external provide
Build related configuration. Group name can refer to architecture, e.g. ``build:x86_64`` can be used for x86_64 architecture specific settings. Build related configuration. Group name can refer to architecture, e.g. ``build:x86_64`` can be used for x86_64 architecture specific settings.
* ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional.
* ``build_command`` - default build command, string, required. * ``build_command`` - default build command, string, required.
* ``build_flags`` - additional ``pkgctl`` flags, space separated list of strings, optional.
* ``ignore_packages`` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional. * ``ignore_packages`` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional.
* ``makepkg_flags`` - additional flags passed to ``makepkg`` command, space separated list of strings, optional.
* ``makechrootpkg_flags`` - additional flags passed to ``makechrootpkg`` command, space separated list of strings, optional.
* ``triggers`` - list of ``ahriman.core.triggers.Trigger`` class implementation (e.g. ``ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger``) which will be loaded and run at the end of processing, space separated list of strings, optional. You can also specify triggers by their paths, e.g. ``/usr/lib/python3.10/site-packages/ahriman/core/report/report.py.ReportTrigger``. Triggers are run in the order of mention. * ``triggers`` - list of ``ahriman.core.triggers.Trigger`` class implementation (e.g. ``ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger``) which will be loaded and run at the end of processing, space separated list of strings, optional. You can also specify triggers by their paths, e.g. ``/usr/lib/python3.10/site-packages/ahriman/core/report/report.py.ReportTrigger``. Triggers are run in the order of mention.
* ``triggers_known`` - optional list of ``ahriman.core.triggers.Trigger`` class implementations which are not run automatically and used only for trigger discovery and configuration validation.
* ``vcs_allowed_age`` - maximal age in seconds of the VCS packages before their version will be updated with its remote source, int, optional, default ``604800``. * ``vcs_allowed_age`` - maximal age in seconds of the VCS packages before their version will be updated with its remote source, int, optional, default ``604800``.
``repository`` group ``repository`` group
@ -87,6 +84,7 @@ Settings for signing packages or repository. Group name can refer to architectur
* ``target`` - configuration flag to enable signing, space separated list of strings, required. Allowed values are ``package`` (sign each package separately), ``repository`` (sign repository database file). * ``target`` - configuration flag to enable signing, space separated list of strings, required. Allowed values are ``package`` (sign each package separately), ``repository`` (sign repository database file).
* ``key`` - default PGP key, string, required. This key will also be used for database signing if enabled. * ``key`` - default PGP key, string, required. This key will also be used for database signing if enabled.
* ``key_*`` settings - PGP key which will be used for specific packages, string, optional. For example, if there is ``key_yay`` option the specified key will be used for yay package and default key for others.
``web:*`` groups ``web:*`` groups
---------------- ----------------
@ -107,41 +105,6 @@ Web server settings. If any of ``host``/``port`` is not set, web integration wil
* ``unix_socket_unsafe`` - set unsafe (o+w) permissions to unix socket, boolean, optional, default ``yes``. This option is enabled by default, because it is supposed that unix socket is created in safe environment (only web service is supposed to be used in unsafe), but it can be disabled by configuration. * ``unix_socket_unsafe`` - set unsafe (o+w) permissions to unix socket, boolean, optional, default ``yes``. This option is enabled by default, because it is supposed that unix socket is created in safe environment (only web service is supposed to be used in unsafe), but it can be disabled by configuration.
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled. * ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
``keyring`` group
--------------------
Keyring package generator plugin.
* ``target`` - list of generator settings sections, space separated list of strings, required. It must point to valid section name.
Keyring generator plugin
^^^^^^^^^^^^^^^^^^^^^^^^
* ``description`` - keyring package description, string, optional, default is ``repo PGP keyring``, where ``repo`` is the repository name.
* ``homepage`` - url to homepage location if any, string, optional.
* ``license`` - list of licenses which are applied to this package, space separated list of strings, optional, default is ``Unlicense``.
* ``package`` - keyring package name, string, optional, default is ``repo-keyring``, where ``repo`` is the repository name.
* ``packagers`` - list of packagers keys, space separated list of strings, optional, if not set, the ``key_*`` options from ``sign`` group will be used.
* ``revoked`` - list of revoked packagers keys, space separated list of strings, optional.
* ``trusted`` - list of master keys, space separated list of strings, optional, if not set, the ``key`` option from ``sign`` group will be used.
``mirrorlist`` group
--------------------
Mirrorlist package generator plugin.
* ``target`` - list of generator settings sections, space separated list of strings, required. It must point to valid section name.
Mirrorlist generator plugin
^^^^^^^^^^^^^^^^^^^^^^^^^^^
* ``description`` - mirrorlist package description, string, optional, default is ``repo mirror list for use by pacman``, where ``repo`` is the repository name.
* ``homepage`` - url to homepage location if any, string, optional.
* ``license`` - list of licenses which are applied to this package, space separated list of strings, optional, default is ``Unlicense``.
* ``package`` - mirrorlist package name, string, optional, default is ``repo-mirrorlist``, where ``repo`` is the repository name.
* ``path`` - absolute path to generated mirrorlist file, string, optional, default is ``/etc/pacman.d/repo-mirrorlist``, where ``repo`` is the repository name.
* ``servers`` - list of repository mirrors, space separated list of strings, required.
``remote-pull`` group ``remote-pull`` group
--------------------- ---------------------

View File

@ -1,3 +1,4 @@
FAQ FAQ
=== ===
@ -196,7 +197,7 @@ Alternatively you can create full-diff patches, which are calculated by using ``
.. code-block:: shell .. code-block:: shell
sudo -u ahriman ahriman patch-set-add /path/to/local/directory/with/PKGBUILD sudo -u ahriman ahriman patch-set-add /path/to/local/directory/with/PKGBUILD
The last command will calculate diff from current tree to the ``HEAD`` and will store it locally. Patches will be applied on any package actions (e.g. it can be used for dependency management). The last command will calculate diff from current tree to the ``HEAD`` and will store it locally. Patches will be applied on any package actions (e.g. it can be used for dependency management).
@ -391,7 +392,7 @@ The following environment variables are supported:
* ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand. * ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand.
* ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``. * ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``.
* ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise. * ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise.
* ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` handler is used you will need to mount ``/dev/log`` inside container because it is not available there. * ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` (the default) handler is used you will need to mount ``/dev/log`` inside container because it is not available there.
* ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``. * ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``.
* ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set. * ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set.
* ``AHRIMAN_PORT`` - HTTP server port if any, default is empty. * ``AHRIMAN_PORT`` - HTTP server port if any, default is empty.
@ -663,7 +664,7 @@ How to report by email
.. code-block:: shell .. code-block:: shell
yay -S --asdeps python-jinja yay -S python-jinja
#. #.
Configure the service: Configure the service:
@ -690,7 +691,7 @@ How to generate index page for S3
.. code-block:: shell .. code-block:: shell
yay -S --asdeps python-jinja yay -S python-jinja
#. #.
Configure the service: Configure the service:
@ -714,7 +715,7 @@ How to post build report to telegram
.. code-block:: shell .. code-block:: shell
yay -S --asdeps python-jinja yay -S python-jinja
#. #.
Register bot in telegram. You can do it by talking with `@BotFather <https://t.me/botfather>`_. For more details please refer to `official documentation <https://core.telegram.org/bots>`_. Register bot in telegram. You can do it by talking with `@BotFather <https://t.me/botfather>`_. For more details please refer to `official documentation <https://core.telegram.org/bots>`_.
@ -753,80 +754,6 @@ If you did everything fine you should receive the message with the next update.
(replace ``${CHAT_ID}`` and ``${API_KEY}`` with the values from configuration). (replace ``${CHAT_ID}`` and ``${API_KEY}`` with the values from configuration).
Maintenance packages
--------------------
Generate keyring package
^^^^^^^^^^^^^^^^^^^^^^^^
The application provides special plugin which generates keyring package. This plugin heavily depends on ``sign`` group settings, however it is possible to override them. The minimal package can be generated in the following way:
#.
Edit configuration:
.. code-block:: ini
[keyring]
target = keyring_generator
By default it will use ``sign.key`` as trusted key and all other keys as packagers ones. For all available options refer to :doc:`configuration <configuration>`.
#.
Create package source files:
.. code-block:: shell
sudo -u ahriman ahriman repo-create-keyring
This command will generate PKGBUILD, revoked and trusted listings and keyring itself and will register the package in database.
#.
Build new package as usual:
.. code-block:: shell
sudo -u ahriman ahriman package-add aur-clone-keyring --source local --now
where ``aur-clone`` is your repository name.
This plugin might have some issues, in case of any of them, kindly create `new issue <https://github.com/arcan1s/ahriman/issues/new/choose>`_.
Generate mirrorlist package
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The application provides special plugin which generates mirrorlist package also. It is possible to distribute this package as usual later. The package can be generated in the following way:
#.
Edit configuration:
.. code-block:: ini
[mirrorlist]
target = mirrorlist_generator
[mirrorlist_generator]
servers = https://repo.example.com/$arch
The ``mirrorlist_generator.servers`` must contain list of available mirrors, the ``$arch`` and ``$repo`` variables are supported. For more options kindly refer to :doc:`configuration <configuration>`.
#.
Create package source files:
.. code-block:: shell
sudo -u ahriman ahriman repo-create-mirrorlist
This command will generate PKGBUILD and mirrorlist file and will register the package in database.
#.
Build new package as usual:
.. code-block:: shell
sudo -u ahriman ahriman package-add aur-clone-mirrorlist --source local --now
where ``aur-clone`` is your repository name.
Web service Web service
----------- -----------
@ -838,7 +765,7 @@ How to setup web service
.. code-block:: shell .. code-block:: shell
yay -S --asdeps python-aiohttp python-aiohttp-jinja2 python-aiohttp-apispec>=3.0.0 python-aiohttp-cors yay -S python-aiohttp python-aiohttp-jinja2
#. #.
Configure service: Configure service:
@ -859,16 +786,15 @@ How to enable basic authorization
.. code-block:: shell .. code-block:: shell
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography yay -S python-aiohttp-security python-aiohttp-session python-cryptography
#. #.
Configure the service to enable authorization (``salt`` can be generated as any random string): Configure the service to enable authorization:
.. code-block:: ini .. code-block:: ini
[auth] [auth]
target = configuration target = configuration
salt = somerandomstring
#. #.
In order to provide access for reporting from application instances you can (recommended way) use unix sockets by configuring the following (note, that it requires ``python-requests-unixsocket`` package to be installed): In order to provide access for reporting from application instances you can (recommended way) use unix sockets by configuring the following (note, that it requires ``python-requests-unixsocket`` package to be installed):
@ -916,7 +842,7 @@ How to enable OAuth authorization
.. code-block:: shell .. code-block:: shell
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography python-aioauth-client yay -S python-aiohttp-security python-aiohttp-session python-cryptography python-aioauth-client
#. #.
Configure the service: Configure the service:
@ -934,7 +860,7 @@ How to enable OAuth authorization
Configure ``oauth_provider`` and ``oauth_scopes`` in case if you would like to use different from Google provider. Scope must grant access to user email. ``web.address`` is required to make callback URL available from internet. Configure ``oauth_provider`` and ``oauth_scopes`` in case if you would like to use different from Google provider. Scope must grant access to user email. ``web.address`` is required to make callback URL available from internet.
#. #.
If you are not going to use unix socket, you also need to create service user (remember to set ``auth.salt`` option before): Create service user:
.. code-block:: shell .. code-block:: shell
@ -1028,11 +954,6 @@ Don't know, haven't tried it. But it lacks of documentation at least.
* ``repoctl`` is able to store old packages. * ``repoctl`` is able to store old packages.
* Ability to host repository from same command in ``repoctl`` vs external services (e.g. nginx) in ``ahriman``. * Ability to host repository from same command in ``repoctl`` vs external services (e.g. nginx) in ``ahriman``.
`repod <https://gitlab.archlinux.org/archlinux/repod>`_
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
Official tool provided by distribution, has clean logic, but it is just a helper for ``repo-add``, e.g. it doesn't work with AUR and all packages builds have to be handled separately.
`repo-scripts <https://github.com/arcan1s/repo-scripts>`_ `repo-scripts <https://github.com/arcan1s/repo-scripts>`_
""""""""""""""""""""""""""""""""""""""""""""""""""""""""" """""""""""""""""""""""""""""""""""""""""""""""""""""""""
@ -1054,17 +975,13 @@ It is automation tools for ``repoctl`` mentioned above. Except for using shell i
How to check service logs How to check service logs
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
By default, the service writes logs to ``journald`` which can be accessed by using ``journalctl`` command (logs are written to the journal of the user under which command is run). In order to retrieve logs for the process you can use the following command: By default, the service writes logs to ``/dev/log`` which can be accessed by using ``journalctl`` command (logs are written to the journal of the user under which command is run).
You can also edit configuration and forward logs to ``stderr``, just change ``handlers`` value, e.g.:
.. code-block:: shell .. code-block:: shell
sudo journalctl SYSLOG_IDENTIFIER=ahriman sed -i 's/handlers = syslog_handler/handlers = console_handler/g' /etc/ahriman.ini.d/logging.ini
You can also ask to forward logs to ``stderr``, just set ``--log-handler`` flag, e.g.:
.. code-block:: shell
ahriman --log-handler console ...
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger). You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).

View File

@ -12,7 +12,7 @@ Features
* VCS packages support. * VCS packages support.
* Official repository support. * Official repository support.
* Ability to patch AUR packages and even create package from local PKGBUILDs. * Ability to patch AUR packages and even create package from local PKGBUILDs.
* Sign support with gpg (repository, package), multiple packagers support. * Sign support with gpg (repository, package, per package settings).
* Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram). * Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram).
* Repository status interface with optional authorization and control options. * Repository status interface with optional authorization and control options.

View File

@ -24,47 +24,32 @@ Initial setup
#. #.
Configure build tools (it is required for correct dependency management system): Configure build tools (it is required for correct dependency management system):
#. #.
Create build command (you can choose any name for command, basically it should be ``{name}-{arch}-build``): Create configuration file ``{repository}.conf``:
.. code-block:: shell .. code-block:: shell
ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build cp /usr/local/share/devtools-git-poc/pacman.conf.d/{extra,aur-clone}.conf
#.
Create configuration file (same as previous ``{name}.conf``):
.. code-block:: shell
cp /usr/share/devtools/pacman.conf.d/{extra,ahriman}.conf
#. #.
Change configuration file, add your own repository, add multilib repository etc: Change configuration file, add your own repository, add multilib repository etc:
.. code-block:: shell .. code-block:: shell
echo '[multilib]' | tee -a /usr/share/devtools/pacman-ahriman.conf echo '[multilib]' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman-ahriman.conf echo '[aur-clone]' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf echo 'SigLevel = Optional TrustAll' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
#.
Set ``build_command`` option to point to your command:
.. code-block:: shell
echo '[build]' | tee -a /etc/ahriman.ini.d/build.ini
echo 'build_command = ahriman-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini
#. #.
Configure ``/etc/sudoers.d/ahriman`` to allow running command without a password: Configure ``/etc/sudoers.d/ahriman`` to allow running devtools command without a password:
.. code-block:: shell .. code-block:: shell
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/ahriman-x86_64-build *' | tee -a /etc/sudoers.d/ahriman echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/bin/pkgctl build *' | tee -a /etc/sudoers.d/ahriman
echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman echo 'ahriman ALL=(ALL) NOPASSWD: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
chmod 400 /etc/sudoers.d/ahriman chmod 400 /etc/sudoers.d/ahriman
This command supports several arguments, kindly refer to its help message. This command supports several arguments, kindly refer to its help message.

View File

@ -31,16 +31,6 @@ This trigger will be called right after build process (``on_result``). It will p
Trigger which can be used for reporting. It implements ``on_result`` method and thus being called on each build update and generates report (e.g. html, telegram etc) according to the current settings. Trigger which can be used for reporting. It implements ``on_result`` method and thus being called on each build update and generates report (e.g. html, telegram etc) according to the current settings.
``ahriman.core.support.KeyringTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Generator for keyring package. This trigger will extract keys from local keychain and pack them into keyring specific format. This trigger will generate sources including PKGBUILD, which can be used later for package building.
``ahriman.core.support.MirrorlistTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Simple generator for mirrorlist package, based on the urls which were set by configuration. This trigger will generate sources including PKGBUILD, which can be used later for package building.
``ahriman.core.upload.UploadTrigger`` ``ahriman.core.upload.UploadTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -83,7 +73,7 @@ The ``context`` also implements collection methods such as ``__iter__`` and ``__
Trigger example Trigger example
--------------- ---------------
Lets consider example of reporting trigger (e.g. `slack <https://slack.com/>`_, which provides easy HTTP API for integration triggers). Lets consider example of reporting trigger (e.g. `slack <https://slack.com/>`_, which provides easy HTTP API for integration triggers).gre
In order to post message to slack we will need a specific trigger url (something like ``https://hooks.slack.com/services/company_id/trigger_id``), channel (e.g. ``#archrepo``) and username (``repo-bot``). In order to post message to slack we will need a specific trigger url (something like ``https://hooks.slack.com/services/company_id/trigger_id``), channel (e.g. ``#archrepo``) and username (``repo-bot``).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,13 +1,13 @@
# Maintainer: Evgeniy Alekseev # Maintainer: Evgeniy Alekseev
pkgname='ahriman' pkgname='ahriman'
pkgver=2.10.0 pkgver=2.8.0
pkgrel=1 pkgrel=1
pkgdesc="ArcH linux ReposItory MANager" pkgdesc="ArcH linux ReposItory MANager"
arch=('any') arch=('any')
url="https://github.com/arcan1s/ahriman" url="https://github.com/arcan1s/ahriman"
license=('GPL3') license=('GPL3')
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests' 'python-srcinfo') depends=('devtools-git-poc' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests' 'python-srcinfo')
makedepends=('python-build' 'python-installer' 'python-wheel') makedepends=('python-build' 'python-installer' 'python-wheel')
optdepends=('breezy: -bzr packages support' optdepends=('breezy: -bzr packages support'
'darcs: -darcs packages support' 'darcs: -darcs packages support'
@ -24,13 +24,11 @@ optdepends=('breezy: -bzr packages support'
'python-cryptography: web server with authorization' 'python-cryptography: web server with authorization'
'python-requests-unixsocket: client report to web server by unix socket' 'python-requests-unixsocket: client report to web server by unix socket'
'python-jinja: html report generation' 'python-jinja: html report generation'
'python-systemd: journal support'
'rsync: sync by using rsync' 'rsync: sync by using rsync'
'subversion: -svn packages support') 'subversion: -svn packages support')
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz" source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz"
'ahriman.sysusers' 'ahriman.sysusers'
'ahriman.tmpfiles') 'ahriman.tmpfiles')
install="$pkgname.install"
backup=('etc/ahriman.ini' backup=('etc/ahriman.ini'
'etc/ahriman.ini.d/logging.ini') 'etc/ahriman.ini.d/logging.ini')
@ -54,6 +52,6 @@ package() {
install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf" install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
} }
sha512sums=('19841842641520b573cdde6cb80a7cfcd69756d323fdfeebc2eee2d264a1325ead4ab2f8383bb369f7896bfc1de59d7358f133f4afeb90a9b9f0695f482a58d0' sha512sums=('112b0d8aac68e5330bbdd2b86a59c8a9af8ab7a7c636489623c8460bb90f1318585851edd2a97a8ce20e2d2ad93b847b522685df707c190aa39d23ab908fa8ef'
'53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131' '53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131'
'62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794') '62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794')

View File

@ -1,25 +0,0 @@
post_upgrade() {
local breakpoints=(
2.9.0-1
)
for v in "${breakpoints[@]}"; do
if [[ $(vercmp "$v" "$2") -eq 1 ]]; then
"_${v//[.-]/_}_changes"
fi
done
}
_2_9_0_1_changes() {
cat << EOF
It was found that you were upgrading from old-devtools package to the new one, which requires manual intervention:
* make sure that devtools are upgraded to the latest release;
* merge service configuration if required;
* run setup command (i.e. sudo ahriman service-setup) with the same arguments as you did before;
* remove build chroot: sudo rm -r /var/lib/ahriman/chroot/ahriman-x86_64/;
* update local databases: sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy;
For more information kindly refer to changelog https://github.com/arcan1s/ahriman/releases/tag/2.9.0
EOF
}

View File

@ -1 +1 @@
u ahriman 643 "ArcH linux ReposItory MANager" /var/lib/ahriman u ahriman 643 "ArcH linux ReposItory MANager" /var/lib/ahriman

View File

@ -1 +1,2 @@
d /var/lib/ahriman 0755 ahriman ahriman d /var/lib/ahriman 0755 ahriman ahriman
d /var/log/ahriman 0755 ahriman ahriman

View File

@ -7,7 +7,7 @@ suppress_http_log_errors = yes
[alpm] [alpm]
database = /var/lib/pacman database = /var/lib/pacman
mirror = https://geo.mirror.pkgbuild.com/$repo/os/$arch mirror = https://geo.mirror.pkgbuild.com/$repo/os/$arch
repositories = core extra multilib repositories = core extra community multilib
root = / root = /
use_ahriman_cache = yes use_ahriman_cache = yes
@ -19,13 +19,10 @@ oauth_scopes = https://www.googleapis.com/auth/userinfo.email
allow_read_only = yes allow_read_only = yes
[build] [build]
archbuild_flags = build_command = pkgctl
build_command = extra-x86_64-build
ignore_packages = ignore_packages =
makechrootpkg_flags = pkgctl_flags =
makepkg_flags = --nocolor --ignorearch
triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger
triggers_known = ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote.RemotePushTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.support.KeyringTrigger ahriman.core.support.MirrorlistTrigger
vcs_allowed_age = 604800 vcs_allowed_age = 604800
[repository] [repository]
@ -35,12 +32,6 @@ root = /var/lib/ahriman
[sign] [sign]
target = target =
[keyring]
target =
[mirrorlist]
target =
[remote-pull] [remote-pull]
target = target =

View File

@ -2,23 +2,17 @@
keys = root,http,stderr,boto3,botocore,nose,s3transfer keys = root,http,stderr,boto3,botocore,nose,s3transfer
[handlers] [handlers]
keys = console_handler,journald_handler,syslog_handler keys = console_handler,syslog_handler
[formatters] [formatters]
keys = generic_format,syslog_format keys = generic_format,syslog_format
[handler_console_handler] [handler_console_handler]
class = logging.StreamHandler class = StreamHandler
level = DEBUG level = DEBUG
formatter = generic_format formatter = generic_format
args = (sys.stderr,) args = (sys.stderr,)
[handler_journald_handler]
class = ahriman.core.log.journal_handler.JournalHandler
level = DEBUG
formatter = syslog_format
kwargs = {"SYSLOG_IDENTIFIER": "ahriman"}
[handler_syslog_handler] [handler_syslog_handler]
class = logging.handlers.SysLogHandler class = logging.handlers.SysLogHandler
level = DEBUG level = DEBUG
@ -27,16 +21,20 @@ args = ("/dev/log",)
[formatter_generic_format] [formatter_generic_format]
format = [%(levelname)s %(asctime)s] [%(name)s]: %(message)s format = [%(levelname)s %(asctime)s] [%(name)s]: %(message)s
datefmt =
[formatter_syslog_format] [formatter_syslog_format]
format = [%(levelname)s] [%(name)s]: %(message)s format = [%(levelname)s] [%(name)s]: %(message)s
datefmt =
[logger_root] [logger_root]
level = DEBUG level = DEBUG
handlers = syslog_handler
qualname = root qualname = root
[logger_http] [logger_http]
level = DEBUG level = DEBUG
handlers = syslog_handler
qualname = http qualname = http
propagate = 0 propagate = 0
@ -47,20 +45,24 @@ qualname = stderr
[logger_boto3] [logger_boto3]
level = INFO level = INFO
handlers = syslog_handler
qualname = boto3 qualname = boto3
propagate = 0 propagate = 0
[logger_botocore] [logger_botocore]
level = INFO level = INFO
handlers = syslog_handler
qualname = botocore qualname = botocore
propagate = 0 propagate = 0
[logger_nose] [logger_nose]
level = INFO level = INFO
handlers = syslog_handler
qualname = nose qualname = nose
propagate = 0 propagate = 0
[logger_s3transfer] [logger_s3transfer]
level = INFO level = INFO
handlers = syslog_handler
qualname = s3transfer qualname = s3transfer
propagate = 0 propagate = 0

View File

@ -63,8 +63,6 @@
<table id="packages" class="table table-striped table-hover" <table id="packages" class="table table-striped table-hover"
data-export-options='{"fileName": "packages"}' data-export-options='{"fileName": "packages"}'
data-filter-control="true"
data-filter-control-visible="false"
data-page-list="[10, 25, 50, 100, all]" data-page-list="[10, 25, 50, 100, all]"
data-page-size="10" data-page-size="10"
data-pagination="true" data-pagination="true"
@ -74,7 +72,6 @@
data-show-columns-search="true" data-show-columns-search="true"
data-show-columns-toggle-all="true" data-show-columns-toggle-all="true"
data-show-export="true" data-show-export="true"
data-show-filter-control-switch="true"
data-show-fullscreen="true" data-show-fullscreen="true"
data-show-search-clear-button="true" data-show-search-clear-button="true"
data-sortable="true" data-sortable="true"
@ -85,14 +82,13 @@
<thead class="table-primary"> <thead class="table-primary">
<tr> <tr>
<th data-checkbox="true"></th> <th data-checkbox="true"></th>
<th data-sortable="true" data-switchable="false" data-field="base" data-filter-control="input" data-filter-control-placeholder="(any base)">package base</th> <th data-sortable="true" data-switchable="false" data-field="base">package base</th>
<th data-sortable="true" data-field="version" data-filter-control="input" data-filter-control-placeholder="(any version)">version</th> <th data-sortable="true" data-field="version">version</th>
<th data-sortable="true" data-field="packages" data-filter-control="input" data-filter-control-placeholder="(any package)">packages</th> <th data-sortable="true" data-field="packages">packages</th>
<th data-sortable="true" data-visible="false" data-field="groups" data-filter-control="select" data-filter-data="func:filterListGroups" data-filter-custom-search="filterList" data-filter-control-placeholder="(any group)">groups</th> <th data-sortable="true" data-visible="false" data-field="groups">groups</th>
<th data-sortable="true" data-visible="false" data-field="licenses" data-filter-control="select" data-filter-data="func:filterListLicenses" data-filter-custom-search="filterList" data-filter-control-placeholder="(any license)">licenses</th> <th data-sortable="true" data-visible="false" data-field="licenses">licenses</th>
<th data-sortable="true" data-visible="false" data-field="packager" data-filter-control="select" data-filter-custom-search="filterContains" data-filter-control-placeholder="(any packager)">packager</th> <th data-sortable="true" data-field="timestamp">last update</th>
<th data-sortable="true" data-field="timestamp" data-filter-control="input" data-filter-custom-search="filterDateRange" data-filter-control-placeholder="(any date)">last update</th> <th data-sortable="true" data-cell-style="statusFormat" data-field="status">status</th>
<th data-sortable="true" data-cell-style="statusFormat" data-field="status" data-filter-control="select" data-filter-control-placeholder="(any status)">status</th>
</tr> </tr>
</thead> </thead>
</table> </table>

View File

@ -84,7 +84,7 @@
showSuccess("Success", `Key ${key} has been imported`); showSuccess("Success", `Key ${key} has been imported`);
}, },
error: (jqXHR, _, errorThrown) => { error: (jqXHR, _, errorThrown) => {
const message = _ => `Could not import key ${key} from ${server}`; const message = _ => { return `Could not import key ${key} from ${server}`; };
showFailure("Action failed", message, jqXHR, errorThrown); showFailure("Action failed", message, jqXHR, errorThrown);
}, },
}); });

View File

@ -60,8 +60,8 @@
const packages = packageInput.val(); const packages = packageInput.val();
if (packages) { if (packages) {
packageAddModal.modal("hide"); packageAddModal.modal("hide");
const onSuccess = update => `Packages ${update} have been added`; const onSuccess = update => { return `Packages ${update} have been added`; };
const onFailure = error => `Package addition failed: ${error}`; const onFailure = error => { return `Package addition failed: ${error}`; };
doPackageAction("/api/v1/service/add", [packages], onSuccess, onFailure); doPackageAction("/api/v1/service/add", [packages], onSuccess, onFailure);
} }
} }
@ -70,8 +70,8 @@
const packages = packageInput.val(); const packages = packageInput.val();
if (packages) { if (packages) {
packageAddModal.modal("hide"); packageAddModal.modal("hide");
const onSuccess = update => `Packages ${update} have been requested`; const onSuccess = update => { return `Packages ${update} have been requested`; };
const onFailure = error => `Package request failed: ${error}`; const onFailure = error => { return `Package request failed: ${error}`; };
doPackageAction("/api/v1/service/request", [packages], onSuccess, onFailure); doPackageAction("/api/v1/service/request", [packages], onSuccess, onFailure);
} }
} }

View File

@ -61,7 +61,7 @@
error: (jqXHR, _, errorThrown) => { error: (jqXHR, _, errorThrown) => {
// show failed modal in case if first time loading // show failed modal in case if first time loading
if (isPackageBaseSet) { if (isPackageBaseSet) {
const message = error => `Could not load package ${packageBase} logs: ${error}`; const message = error => { return `Could not load package ${packageBase} logs: ${error}`; };
showFailure("Load failure", message, jqXHR, errorThrown); showFailure("Load failure", message, jqXHR, errorThrown);
} }
}, },

View File

@ -33,8 +33,8 @@
const packages = dependencyInput.val(); const packages = dependencyInput.val();
if (packages) { if (packages) {
packageRebuildModal.modal("hide"); packageRebuildModal.modal("hide");
const onSuccess = update => `Repository rebuild has been run for packages which depend on ${update}`; const onSuccess = update => { return `Repository rebuild has been run for packages which depend on ${update}`; };
const onFailure = error => `Repository rebuild failed: ${error}`; const onFailure = error => { return `Repository rebuild failed: ${error}`; };
doPackageAction("/api/v1/service/rebuild", [packages], onSuccess, onFailure); doPackageAction("/api/v1/service/rebuild", [packages], onSuccess, onFailure);
} }
} }

View File

@ -15,25 +15,6 @@
table.bootstrapTable(method, {field: "id", values: [data.id]}); table.bootstrapTable(method, {field: "id", values: [data.id]});
} else showLogs(data.id); } else showLogs(data.id);
}); });
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const repositoryBadge = $("#badge-repository"); const repositoryBadge = $("#badge-repository");
const statusBadge = $("#badge-status"); const statusBadge = $("#badge-status");
@ -56,21 +37,21 @@
} }
function getSelection() { function getSelection() {
return table.bootstrapTable("getSelections").map(row => row.id); return table.bootstrapTable("getSelections").map(row => { return row.id; });
} }
function removePackages() { function removePackages() {
const onSuccess = update => `Packages ${update} have been removed`; const onSuccess = update => { return `Packages ${update} have been removed`; };
const onFailure = error => `Could not remove packages: ${error}`; const onFailure = error => { return `Could not remove packages: ${error}`; };
doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure); doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure);
} }
function updatePackages() { function updatePackages() {
const currentSelection = getSelection(); const currentSelection = getSelection();
const [url, onSuccess] = currentSelection.length === 0 const [url, onSuccess] = currentSelection.length === 0
? ["/api/v1/service/update", _ => "Repository update has been run"] ? ["/api/v1/service/update", _ => { return "Repository update has been run"; }]
: ["/api/v1/service/add", update => `Run update for packages ${update}`]; : ["/api/v1/service/add", update => { return `Run update for packages ${update}`; }];
const onFailure = error => `Packages update failed: ${error}`; const onFailure = error => { return `Packages update failed: ${error}`; };
doPackageAction(url, currentSelection, onSuccess, onFailure); doPackageAction(url, currentSelection, onSuccess, onFailure);
} }
@ -100,13 +81,13 @@
success: response => { success: response => {
const extractListProperties = (description, property) => { const extractListProperties = (description, property) => {
return Object.values(description.packages) return Object.values(description.packages)
.map(pkg => pkg[property]) .map(pkg => { return pkg[property]; })
.reduce((left, right) => left.concat(right), []); .reduce((left, right) => { return left.concat(right); }, []);
}; };
const listToTable = data => { const listToTable = data => {
return Array.from(new Set(data)) return Array.from(new Set(data))
.sort() .sort()
.map(entry => safe(entry)) .map(entry => { return safe(entry); })
.join("<br>"); .join("<br>");
}; };
@ -117,7 +98,6 @@
id: package_base, id: package_base,
base: web_url ? `<a href="${safe(web_url)}" title="${safe(package_base)}">${safe(package_base)}</a>` : safe(package_base), base: web_url ? `<a href="${safe(web_url)}" title="${safe(package_base)}">${safe(package_base)}</a>` : safe(package_base),
version: safe(description.package.version), version: safe(description.package.version),
packager: description.package.packager ? safe(description.package.packager) : "",
packages: listToTable(Object.keys(description.package.packages)), packages: listToTable(Object.keys(description.package.packages)),
groups: listToTable(extractListProperties(description.package, "groups")), groups: listToTable(extractListProperties(description.package, "groups")),
licenses: listToTable(extractListProperties(description.package, "licenses")), licenses: listToTable(extractListProperties(description.package, "licenses")),
@ -140,8 +120,8 @@
table.bootstrapTable("hideLoading"); table.bootstrapTable("hideLoading");
} else { } else {
// other errors // other errors
const message = error => `Could not load list of packages: ${error}`; const messaga = error => { return `Could not load list of packages: ${error}`; };
showFailure("Load failure", message, jqXHR, errorThrown); showFailure("Load failure", messaga, jqXHR, errorThrown);
} }
hideControls(true); hideControls(true);
}, },
@ -177,18 +157,6 @@
return {classes: cellClass(value)}; return {classes: cellClass(value)};
} }
function filterListGroups() {
return extractDataList(table.bootstrapTable("getData"), "groups");
}
function filterListLicenses() {
return extractDataList(table.bootstrapTable("getData"), "licenses");
}
function filterListPackagers() {
return extractDataList(table.bootstrapTable("getData"), "packager");
}
$(() => { $(() => {
table.bootstrapTable({}); table.bootstrapTable({});
statusBadge.popover(); statusBadge.popover();

View File

@ -31,8 +31,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
<div class="container"> <div class="container">
<table id="packages" class="table table-striped table-hover" <table id="packages" class="table table-striped table-hover"
data-export-options='{"fileName": "packages"}' data-export-options='{"fileName": "packages"}'
data-filter-control="true"
data-filter-control-visible="false"
data-page-list="[10, 25, 50, 100, all]" data-page-list="[10, 25, 50, 100, all]"
data-page-size="10" data-page-size="10"
data-pagination="true" data-pagination="true"
@ -42,7 +40,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
data-show-columns-search="true" data-show-columns-search="true"
data-show-columns-toggle-all="true" data-show-columns-toggle-all="true"
data-show-export="true" data-show-export="true"
data-show-filter-control-switch="true"
data-show-fullscreen="true" data-show-fullscreen="true"
data-show-search-clear-button="true" data-show-search-clear-button="true"
data-sortable="true" data-sortable="true"
@ -51,17 +48,17 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
data-toggle="table"> data-toggle="table">
<thead class="table-primary"> <thead class="table-primary">
<tr> <tr>
<th data-sortable="true" data-switchable="false" data-field="name" data-filter-control="input" data-filter-control-placeholder="(any package)">package</th> <th data-sortable="true" data-switchable="false">package</th>
<th data-sortable="true" data-field="version" data-filter-control="input" data-filter-control-placeholder="(any version)">version</th> <th data-sortable="true">version</th>
<th data-sortable="true" data-visible="false" data-field="architecture" data-filter-control="select" data-filter-control-placeholder="(any arch)">architecture</th> <th data-sortable="true" data-visible="false">architecture</th>
<th data-sortable="true" data-visible="false" data-field="description" data-filter-control="input" data-filter-control-placeholder="(any description)">description</th> <th data-sortable="true" data-visible="false">description</th>
<th data-sortable="true" data-visible="false" data-field="url">upstream url</th> <th data-sortable="true" data-visible="false">upstream url</th>
<th data-sortable="true" data-visible="false" data-field="licenses" data-filter-control="select" data-filter-data="func:filterListLicenses" data-filter-custom-search="filterList" data-filter-control-placeholder="(any license)">licenses</th> <th data-sortable="true" data-visible="false">licenses</th>
<th data-sortable="true" data-visible="false" data-field="groups" data-filter-control="select" data-filter-data="func:filterListGroups" data-filter-custom-search="filterList" data-filter-control-placeholder="(any group)">groups</th> <th data-sortable="true" data-visible="false">groups</th>
<th data-sortable="true" data-visible="false" data-field="depends" data-filter-control="select" data-filter-data="func:filterListDepends" data-filter-custom-search="filterList" data-filter-control-placeholder="(any depends)">depends</th> <th data-sortable="true" data-visible="false">depends</th>
<th data-sortable="true" data-field="archive_size">archive size</th> <th data-sortable="true">archive size</th>
<th data-sortable="true" data-field="installed_size">installed size</th> <th data-sortable="true">installed size</th>
<th data-sortable="true" data-field="timestamp" data-filter-control="input" data-filter-custom-search="filterDateRange" data-filter-control-placeholder="(any date)">build date</th> <th data-sortable="true">build date</th>
</tr> </tr>
</thead> </thead>
@ -99,27 +96,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
</div> </div>
<script> <script>
const table = $("#packages");
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const pacmanConf = $("#pacman-conf"); const pacmanConf = $("#pacman-conf");
const pacmanConfCopyButton = $("#copy-btn"); const pacmanConfCopyButton = $("#copy-btn");
@ -127,18 +103,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
const conf = pacmanConf.text(); const conf = pacmanConf.text();
await copyToClipboard(conf, pacmanConfCopyButton); await copyToClipboard(conf, pacmanConfCopyButton);
} }
function filterListDepends() {
return extractDataList(table.bootstrapTable("getData"), "depends");
}
function filterListGroups() {
return extractDataList(table.bootstrapTable("getData"), "groups");
}
function filterListLicenses() {
return extractDataList(table.bootstrapTable("getData"), "licenses");
}
</script> </script>
</body> </body>

View File

@ -1,21 +1,16 @@
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js" integrity="sha384-NXgwF8Kv9SSAr+jemKKcbvQsz+teULH/a5UNJvZc6kP47hZgl62M1vGnw6gHQhb1" crossorigin="anonymous" type="application/javascript"></script> <script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js" integrity="sha384-8hHkOkbWN1TLWwet/jpbJ0zbx3FJDeYJgQ8dX1mRrv/vfCfHCqFSFZYCgaMML3z9" crossorigin="anonymous" type="application/javascript"></script> <script src="https://unpkg.com/tableexport.jquery.plugin/tableExport.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.min.js" integrity="sha384-u4eJN1VWrTf/FnYYQJo2kqJyVxEQf5UmWY4iUcNAoLenOEtEuCkfwc5bKvZOWBi5" crossorigin="anonymous" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.28.0/tableExport.min.js" integrity="sha384-1Rz4Kz/y1rSWw+ZsjTcxB684XgofbO8iizY+UFIzCwFeQ+QUyhBNWBMh/STOyomI" crossorigin="anonymous" type="application/javascript"></script> <script src="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js" integrity="sha384-IazMVNyYoUNx6357fWJoqtHYUWWCNHIXxFVtbpVgvImQNWuRP2WbHPaIb3QF8j97" crossorigin="anonymous" type="application/javascript"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" integrity="sha384-IDwe1+LCz02ROU9k972gdyvl+AESN10+x7tBKgc9I5HFtuNz0wWnPclzo6p9vxnk" crossorigin="anonymous"></script>
<script src="https://unpkg.com/bootstrap-table@1.21.1/dist/bootstrap-table.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous" type="application/javascript"></script> <script src="https://unpkg.com/bootstrap-table@1.21.1/dist/extensions/export/bootstrap-table-export.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/bootstrap-table.min.js" integrity="sha384-GVLHfbEvuGA/RFiQ3MK2ClEJkWYJXABg55t9LpoDPZFGIsSq8xhFlQydm5poV2jW" crossorigin="anonymous" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/export/bootstrap-table-export.min.js" integrity="sha384-jeldDadm+qM2RwGER3qVqxFgWVpAEJ7Jie+0rlYj8ni3KkQA654T8TSXDtol022X" crossorigin="anonymous" type="application/javascript"></script> <script src="https://unpkg.com/bootstrap-table@1.21.1/dist/extensions/resizable/bootstrap-table-resizable.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/resizable/bootstrap-table-resizable.js" integrity="sha384-wd8Vc6Febikdnsnk9vthRWRvMwffw246vhqiqNO3aSNe1maTEA07Vh3zAQiSyDji" crossorigin="anonymous" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/filter-control/bootstrap-table-filter-control.js" integrity="sha384-B6xNXlSOaOFxjlKo9OW3htbox+9/DcaEcjPPEi1+pTMwH5Tzc/s2wNTYriHz7Tb8" crossorigin="anonymous" type="application/javascript"></script>
<script> <script>
async function copyToClipboard(text, button) { async function copyToClipboard(text, button) {
@ -43,28 +38,4 @@
.replace(/>/g, "&gt;") .replace(/>/g, "&gt;")
.replace(/"/g, "&quot;"); .replace(/"/g, "&quot;");
} }
function extractDataList(data, column) {
const elements = data.flatMap(row => row[column].split("<br>")).filter(v => v); // remove empty elements from array
return Array.from(new Set(elements)).sort();
}
function filterContains(text, value) {
return value.includes(text.toLowerCase().trim());
}
function filterDateRange(text, value) {
const asOfStartOfDay = date => date.setUTCHours(0, 0, 0, 0);
const [minDate, maxDate] = text.split(" - ");
const buildDate = asOfStartOfDay(new Date(value));
return (buildDate >= asOfStartOfDay(new Date(minDate))) && (buildDate <= asOfStartOfDay(new Date(maxDate)));
}
function filterList(index, value, field, data) {
const dataList = extractDataList(data, field);
// the library removes all symbols from string, so it is just string
return value.includes(dataList[index].toLowerCase());
}
</script> </script>

View File

@ -1,15 +1,11 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" type="text/css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.4/font/bootstrap-icons.css" integrity="sha384-LrVLJJYk9OiJmjNDakUBU7kS9qCT8wk1j2OU7ncpsfB3QS37UPdkCuq3ZD1MugNY" crossorigin="anonymous" type="text/css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/bootstrap-table.min.css" integrity="sha384-pTEAhytv7JmEG2D7qiW5gY0lI5EKZ9n3CNmj6Qp+U3qhnmH2qnnN9KJbVwbtMHN0" crossorigin="anonymous" type="text/css"> <link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.21.1/dist/bootstrap-table.min.css" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" integrity="sha384-1sLxvR8mXzjhvFY9f8mzXl97DNLepeZ0PnRiMMdm/rQsKjsrPZPJxYle2wwT2PMg" crossorigin="anonymous" type="text/css"> <link rel="stylesheet" href="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/filter-control/bootstrap-table-filter-control.css" integrity="sha384-4Glx18jZ0Un+yDG6KUpYJ/af8hkssJ02jRASuFv23gfCl0mTXaVMPI9cB4cn3GvE" crossorigin="anonymous" type="text/css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.2.2/dist/cosmo/bootstrap.min.css" integrity="sha256-5t++JZpgVLzo9vF7snO5Qw0y3fA5/NkoJENWB7kpg0E=" crossorigin="anonymous" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.2.3/dist/cosmo/bootstrap.min.css" integrity="sha384-P1PBFVifKf1Ww0gS5B8A0siIeDpcFd4uU7S68LA1XMdE0R+y1WN3DR4HcLc9csRC" crossorigin="anonymous" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.css" integrity="sha384-zLkQsiLfAQqGeIJeKLC+rcCR1YoYaQFLCL7cLDUoKE1ajKJzySpjzWGfYS2vjSG+" crossorigin="anonymous" type="text/css">
<style> <style>
.pre-scrollable { .pre-scrollable {

View File

@ -121,9 +121,6 @@ setup(
"sphinx-rtd-theme>=1.1.1", # https://stackoverflow.com/a/74355734 "sphinx-rtd-theme>=1.1.1", # https://stackoverflow.com/a/74355734
"sphinxcontrib-napoleon", "sphinxcontrib-napoleon",
], ],
"journald": [
"systemd-python",
],
# FIXME technically this dependency is required, but in some cases we do not have access to # FIXME technically this dependency is required, but in some cases we do not have access to
# the libalpm which is required in order to install the package. Thus in case if we do not # the libalpm which is required in order to install the package. Thus in case if we do not
# really need to run the application we can move it to "optional" dependencies # really need to run the application we can move it to "optional" dependencies

View File

@ -27,10 +27,9 @@ from typing import TypeVar
from ahriman import version from ahriman import version
from ahriman.application import handlers from ahriman.application import handlers
from ahriman.core.util import enum_values, extract_user from ahriman.core.util import enum_values
from ahriman.models.action import Action from ahriman.models.action import Action
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.log_handler import LogHandler
from ahriman.models.package_source import PackageSource from ahriman.models.package_source import PackageSource
from ahriman.models.sign_settings import SignSettings from ahriman.models.sign_settings import SignSettings
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
@ -59,7 +58,6 @@ def _formatter(prog: str) -> argparse.HelpFormatter:
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120) return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
# pylint: disable=too-many-statements
def _parser() -> argparse.ArgumentParser: def _parser() -> argparse.ArgumentParser:
""" """
command line parser generator command line parser generator
@ -77,9 +75,6 @@ def _parser() -> argparse.ArgumentParser:
parser.add_argument("--force", help="force run, remove file lock", action="store_true") parser.add_argument("--force", help="force run, remove file lock", action="store_true")
parser.add_argument("-l", "--lock", help="lock file", type=Path, parser.add_argument("-l", "--lock", help="lock file", type=Path,
default=Path(tempfile.gettempdir()) / "ahriman.lock") default=Path(tempfile.gettempdir()) / "ahriman.lock")
parser.add_argument("--log-handler", help="explicit log handler specification. If none set, the handler will be "
"guessed from environment",
type=LogHandler, choices=enum_values(LogHandler))
parser.add_argument("--report", help="force enable or disable reporting to web service", parser.add_argument("--report", help="force enable or disable reporting to web service",
action=argparse.BooleanOptionalAction, default=True) action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true") parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
@ -105,8 +100,6 @@ def _parser() -> argparse.ArgumentParser:
_set_patch_set_add_parser(subparsers) _set_patch_set_add_parser(subparsers)
_set_repo_backup_parser(subparsers) _set_repo_backup_parser(subparsers)
_set_repo_check_parser(subparsers) _set_repo_check_parser(subparsers)
_set_repo_create_keyring_parser(subparsers)
_set_repo_create_mirrorlist_parser(subparsers)
_set_repo_daemon_parser(subparsers) _set_repo_daemon_parser(subparsers)
_set_repo_rebuild_parser(subparsers) _set_repo_rebuild_parser(subparsers)
_set_repo_remove_unknown_parser(subparsers) _set_repo_remove_unknown_parser(subparsers)
@ -187,8 +180,8 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
""" """
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands", parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
description="list unsafe commands as defined in default args", formatter_class=_formatter) description="list unsafe commands as defined in default args", formatter_class=_formatter)
parser.add_argument("command", help="instead of showing commands, just test command line for unsafe subcommand " parser.add_argument("--command", help="instead of showing commands, just test command line for unsafe subcommand "
"and return 0 in case if command is safe and 1 otherwise", nargs="*") "and return 0 in case if command is safe and 1 otherwise")
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, quiet=True, parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, quiet=True,
unsafe=True, parser=_parser) unsafe=True, parser=_parser)
return parser return parser
@ -262,7 +255,6 @@ def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
action="count", default=False) action="count", default=False)
parser.add_argument("-s", "--source", help="explicitly specify the package source for this command", parser.add_argument("-s", "--source", help="explicitly specify the package source for this command",
type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto) type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto)
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
parser.set_defaults(handler=handlers.Add) parser.set_defaults(handler=handlers.Add)
return parser return parser
@ -482,46 +474,7 @@ def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, " parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
"-yy to force refresh even if up to date", "-yy to force refresh even if up to date",
action="count", default=False) action="count", default=False)
parser.set_defaults(handler=handlers.Update, dependencies=False, dry_run=True, aur=True, local=True, manual=False, parser.set_defaults(handler=handlers.Update, dependencies=False, dry_run=True, aur=True, local=True, manual=False)
username=None)
return parser
def _set_repo_create_keyring_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
add parser for create-keyring subcommand
Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-create-keyring", help="create keyring package",
description="create package which contains list of trusted keys as set by "
"configuration. Note, that this action will only create package, the package "
"itself has to be built manually",
formatter_class=_formatter)
parser.set_defaults(handler=handlers.Triggers, trigger=["ahriman.core.support.KeyringTrigger"])
return parser
def _set_repo_create_mirrorlist_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
add parser for create-mirrorlist subcommand
Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("repo-create-mirrorlist", help="create mirrorlist package",
description="create package which contains list of available mirrors as set by "
"configuration. Note, that this action will only create package, the package "
"itself has to be built manually",
formatter_class=_formatter)
parser.set_defaults(handler=handlers.Triggers, trigger=["ahriman.core.support.MirrorlistTrigger"])
return parser return parser
@ -578,9 +531,6 @@ def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
"ahriman instance run with web service and have run repo-update at least once.", "ahriman instance run with web service and have run repo-update at least once.",
action="store_true") action="store_true")
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true") parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.add_argument("-s", "--status", help="filter packages by status. Requires --from-database to be set",
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
parser.set_defaults(handler=handlers.Rebuild) parser.set_defaults(handler=handlers.Rebuild)
return parser return parser
@ -755,7 +705,6 @@ def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
action=argparse.BooleanOptionalAction, default=True) action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("--manual", help="include or exclude manual updates", parser.add_argument("--manual", help="include or exclude manual updates",
action=argparse.BooleanOptionalAction, default=True) action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
parser.add_argument("--vcs", help="fetch actual version of VCS packages", parser.add_argument("--vcs", help="fetch actual version of VCS packages",
action=argparse.BooleanOptionalAction, default=True) action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, " parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
@ -871,12 +820,9 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="create initial service configuration, requires root", description="create initial service configuration, requires root",
epilog="Create _minimal_ configuration for the service according to provided options.", epilog="Create _minimal_ configuration for the service according to provided options.",
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("--build-as-user", help="force makepkg user to the specific one") parser.add_argument("--build-command", help="path to build command", default=Path("/usr") / "bin" / "pkgctl")
parser.add_argument("--build-command", help="build command prefix", default="ahriman") parser.add_argument("--from-configuration", help="path to default devtools pacman configuration", type=Path,
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration", default=Path("/usr") / "local" / "share" / "devtools-git-poc" / "pacman.conf.d" / "extra.conf")
type=Path, default=Path("/usr") / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
parser.add_argument("--generate-salt", help="generate salt for user passwords",
action=argparse.BooleanOptionalAction, default=False)
parser.add_argument("--makeflags-jobs", help="append MAKEFLAGS variable with parallelism set to number of cores", parser.add_argument("--makeflags-jobs", help="append MAKEFLAGS variable with parallelism set to number of cores",
action=argparse.BooleanOptionalAction, default=True) action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("--mirror", help="use the specified explicitly mirror instead of including mirrorlist") parser.add_argument("--mirror", help="use the specified explicitly mirror instead of including mirrorlist")
@ -925,15 +871,15 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser = root.add_parser("user-add", help="create or update user", parser = root.add_parser("user-add", help="create or update user",
description="update user for web services with the given password and role. " description="update user for web services with the given password and role. "
"In case if password was not entered it will be asked interactively", "In case if password was not entered it will be asked interactively",
epilog="In case of first run (i.e. if password salt is not set yet) this action requires "
"root privileges because it performs write to filesystem configuration.",
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("username", help="username for web service") parser.add_argument("username", help="username for web service")
parser.add_argument("--key", help="optional PGP key used by this user. The private key must be imported")
parser.add_argument("--packager", help="optional packager id used for build process in form of "
"`Name Surname <mail@example.com>`")
parser.add_argument("-p", "--password", help="user password. Blank password will be treated as empty password, " parser.add_argument("-p", "--password", help="user password. Blank password will be treated as empty password, "
"which is in particular must be used for OAuth2 authorization type.") "which is in particular must be used for OAuth2 authorization type.")
parser.add_argument("-r", "--role", help="user access level", parser.add_argument("-r", "--role", help="user access level",
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read) type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
parser.add_argument("-s", "--secure", help="set file permissions to user-only", action="store_true")
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False, parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
quiet=True) quiet=True)
return parser return parser
@ -955,8 +901,8 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("username", help="filter users by username", nargs="?") parser.add_argument("username", help="filter users by username", nargs="?")
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true") parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.add_argument("-r", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess)) parser.add_argument("-r", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False, parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False, # nosec
quiet=True, unsafe=True) password="", quiet=True, unsafe=True)
return parser return parser
@ -974,8 +920,8 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="remove user from the user mapping and update the configuration", description="remove user from the user mapping and update the configuration",
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("username", help="username for web service") parser.add_argument("username", help="username for web service")
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False, parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False, # nosec
quiet=True) password="", quiet=True)
return parser return parser

View File

@ -17,12 +17,10 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from collections.abc import Callable, Iterable from collections.abc import Iterable
from ahriman.application.application.application_packages import ApplicationPackages from ahriman.application.application.application_packages import ApplicationPackages
from ahriman.application.application.application_repository import ApplicationRepository from ahriman.application.application.application_repository import ApplicationRepository
from ahriman.core.formatters import UpdatePrinter
from ahriman.core.tree import Tree
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.result import Result from ahriman.models.result import Result
@ -39,12 +37,12 @@ class Application(ApplicationPackages, ApplicationRepository):
>>> from ahriman.models.package_source import PackageSource >>> from ahriman.models.package_source import PackageSource
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> application = Application("x86_64", configuration, report=True) >>> application = Application("x86_64", configuration, report=True, unsafe=False)
>>> # add packages to build queue >>> # add packages to build queue
>>> application.add(["ahriman"], PackageSource.AUR) >>> application.add(["ahriman"], PackageSource.AUR, without_dependencies=False)
>>> >>>
>>> # check for updates >>> # check for updates
>>> updates = application.updates([], aur=True, local=True, manual=True, vcs=True) >>> updates = application.updates([], aur=True, local=True, manual=True, vcs=True, log_fn=print)
>>> # updates for specified packages >>> # updates for specified packages
>>> application.update(updates) >>> application.update(updates)
@ -91,22 +89,6 @@ class Application(ApplicationPackages, ApplicationRepository):
""" """
self.repository.triggers.on_stop() self.repository.triggers.on_stop()
def print_updates(self, packages: list[Package], *, log_fn: Callable[[str], None]) -> None:
"""
print list of packages to be built. This method will build dependency tree and print updates accordingly
Args:
packages(list[Package]): package list to be printed
log_fn(Callable[[str], None]): logger function to log updates
"""
local_versions = {package.base: package.version for package in self.repository.packages()}
tree = Tree.resolve(packages)
for level in tree:
for package in level:
UpdatePrinter(package, local_versions.get(package.base)).print(
verbose=True, log_fn=log_fn, separator=" -> ")
def with_dependencies(self, packages: list[Package], *, process_dependencies: bool) -> list[Package]: def with_dependencies(self, packages: list[Package], *, process_dependencies: bool) -> list[Package]:
""" """
add missing dependencies to list of packages add missing dependencies to list of packages
@ -114,25 +96,21 @@ class Application(ApplicationPackages, ApplicationRepository):
Args: Args:
packages(list[Package]): list of source packages of which dependencies have to be processed packages(list[Package]): list of source packages of which dependencies have to be processed
process_dependencies(bool): if no set, dependencies will not be processed process_dependencies(bool): if no set, dependencies will not be processed
Returns:
list[Package]: updated packages list. Packager for dependencies will be copied from
original package
""" """
def missing_dependencies(source: Iterable[Package]) -> dict[str, str | None]: def missing_dependencies(source: Iterable[Package]) -> set[str]:
# append list of known packages with packages which are in current sources # build initial list of dependencies
satisfied_packages = known_packages | { result = set()
single for package in source:
for package in source result.update(package.depends_build)
for single in package.packages_full
}
return { # remove ones which are already well-known
dependency: package.packager result = result.difference(known_packages)
for package in source
for dependency in package.depends_build # remove ones which are in this list already
if dependency not in satisfied_packages for package in source:
} result = result.difference(package.packages_full)
return result
if not process_dependencies or not packages: if not process_dependencies or not packages:
return packages return packages
@ -141,11 +119,8 @@ class Application(ApplicationPackages, ApplicationRepository):
with_dependencies = {package.base: package for package in packages} with_dependencies = {package.base: package for package in packages}
while missing := missing_dependencies(with_dependencies.values()): while missing := missing_dependencies(with_dependencies.values()):
for package_name, username in missing.items(): for package_name in missing:
package = Package.from_aur(package_name, self.repository.pacman, username) package = Package.from_aur(package_name, self.repository.pacman)
with_dependencies[package.base] = package with_dependencies[package.base] = package
# register package in local database
self.database.remote_update(package)
self.repository.reporter.set_unknown(package)
return list(with_dependencies.values()) return list(with_dependencies.values())

View File

@ -26,7 +26,6 @@ from typing import Any
from ahriman.application.application.application_properties import ApplicationProperties from ahriman.application.application.application_properties import ApplicationProperties
from ahriman.core.build_tools.sources import Sources from ahriman.core.build_tools.sources import Sources
from ahriman.core.exceptions import UnknownPackageError
from ahriman.core.util import package_like from ahriman.core.util import package_like
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource from ahriman.models.package_source import PackageSource
@ -44,26 +43,20 @@ class ApplicationPackages(ApplicationProperties):
Args: Args:
source(str): path to package archive source(str): path to package archive
Raises:
UnknownPackageError: if specified path doesn't exist
""" """
local_path = Path(source) local_path = Path(source)
if not local_path.is_file():
raise UnknownPackageError(source)
dst = self.repository.paths.packages / local_path.name dst = self.repository.paths.packages / local_path.name
shutil.copy(local_path, dst) shutil.copy(local_path, dst)
def _add_aur(self, source: str, username: str | None) -> None: def _add_aur(self, source: str) -> None:
""" """
add package from AUR add package from AUR
Args: Args:
source(str): package base name source(str): package base name
username(str | None): optional override of username for build process
""" """
package = Package.from_aur(source, self.repository.pacman, username) package = Package.from_aur(source, self.repository.pacman)
self.database.build_queue_insert(package) self.database.build_queue_insert(package)
self.database.remote_update(package) self.database.remote_update(package)
@ -75,32 +68,21 @@ class ApplicationPackages(ApplicationProperties):
source(str): path to local directory source(str): path to local directory
""" """
local_dir = Path(source) local_dir = Path(source)
if not local_dir.is_dir():
raise UnknownPackageError(source)
for full_path in filter(package_like, local_dir.iterdir()): for full_path in filter(package_like, local_dir.iterdir()):
self._add_archive(str(full_path)) self._add_archive(str(full_path))
def _add_local(self, source: str, username: str | None) -> None: def _add_local(self, source: str) -> None:
""" """
add package from local PKGBUILDs add package from local PKGBUILDs
Args: Args:
source(str): path to directory with local source files source(str): path to directory with local source files
username(str | None): optional override of username for build process
Raises:
UnknownPackageError: if specified package is unknown or doesn't exist
""" """
if (source_dir := Path(source)).is_dir(): source_dir = Path(source)
package = Package.from_build(source_dir, self.architecture, username) package = Package.from_build(source_dir, self.architecture)
cache_dir = self.repository.paths.cache_for(package.base) cache_dir = self.repository.paths.cache_for(package.base)
shutil.copytree(source_dir, cache_dir) # copy package to store in caches shutil.copytree(source_dir, cache_dir) # copy package to store in caches
Sources.init(cache_dir) # we need to run init command in directory where we do have permissions Sources.init(cache_dir) # we need to run init command in directory where we do have permissions
elif (source_dir := self.repository.paths.cache_for(source)).is_dir():
package = Package.from_build(source_dir, self.architecture, username)
else:
raise UnknownPackageError(source)
self.database.build_queue_insert(package) self.database.build_queue_insert(package)
@ -113,41 +95,36 @@ class ApplicationPackages(ApplicationProperties):
""" """
dst = self.repository.paths.packages / Path(source).name # URL is path, is not it? dst = self.repository.paths.packages / Path(source).name # URL is path, is not it?
# timeout=None to suppress pylint warns. Also suppress bandit warnings # timeout=None to suppress pylint warns. Also suppress bandit warnings
try: response = requests.get(source, stream=True, timeout=None) # nosec
response = requests.get(source, stream=True, timeout=None) # nosec response.raise_for_status()
response.raise_for_status()
except Exception:
raise UnknownPackageError(source)
with dst.open("wb") as local_file: with dst.open("wb") as local_file:
for chunk in response.iter_content(chunk_size=1024): for chunk in response.iter_content(chunk_size=1024):
local_file.write(chunk) local_file.write(chunk)
def _add_repository(self, source: str, username: str | None) -> None: def _add_repository(self, source: str, *_: Any) -> None:
""" """
add package from official repository add package from official repository
Args: Args:
source(str): package base name source(str): package base name
username(str | None): optional override of username for build process
""" """
package = Package.from_official(source, self.repository.pacman, username) package = Package.from_official(source, self.repository.pacman)
self.database.build_queue_insert(package) self.database.build_queue_insert(package)
self.database.remote_update(package) self.database.remote_update(package)
def add(self, names: Iterable[str], source: PackageSource, username: str | None = None) -> None: def add(self, names: Iterable[str], source: PackageSource) -> None:
""" """
add packages for the next build add packages for the next build
Args: Args:
names(Iterable[str]): list of package bases to add names(Iterable[str]): list of package bases to add
source(PackageSource): package source to add source(PackageSource): package source to add
username(str | None, optional): optional override of username for build process (Default value = None)
""" """
for name in names: for name in names:
resolved_source = source.resolve(name) resolved_source = source.resolve(name)
fn = getattr(self, f"_add_{resolved_source.value}") fn = getattr(self, f"_add_{resolved_source.value}")
fn(name, username) fn(name)
def on_result(self, result: Result) -> None: def on_result(self, result: Result) -> None:
""" """

View File

@ -35,7 +35,7 @@ class ApplicationProperties(LazyLogging):
repository(Repository): repository instance repository(Repository): repository instance
""" """
def __init__(self, architecture: str, configuration: Configuration, *, report: bool, def __init__(self, architecture: str, configuration: Configuration, *, report: bool, unsafe: bool,
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> None: refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> None:
""" """
default constructor default constructor
@ -44,11 +44,12 @@ class ApplicationProperties(LazyLogging):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level
(Default value = PacmanSynchronization.Disabled) (Default value = PacmanSynchronization.Disabled)
""" """
self.configuration = configuration self.configuration = configuration
self.architecture = architecture self.architecture = architecture
self.database = SQLite.load(configuration) self.database = SQLite.load(configuration)
self.repository = Repository.load(architecture, configuration, self.database, report=report, self.repository = Repository.load(architecture, configuration, self.database, report=report, unsafe=unsafe,
refresh_pacman_database=refresh_pacman_database) refresh_pacman_database=refresh_pacman_database)

View File

@ -17,14 +17,14 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from collections.abc import Iterable from collections.abc import Callable, Iterable
from pathlib import Path from pathlib import Path
from ahriman.application.application.application_properties import ApplicationProperties from ahriman.application.application.application_properties import ApplicationProperties
from ahriman.core.build_tools.sources import Sources from ahriman.core.build_tools.sources import Sources
from ahriman.core.formatters import UpdatePrinter
from ahriman.core.tree import Tree from ahriman.core.tree import Tree
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result from ahriman.models.result import Result
@ -83,7 +83,7 @@ class ApplicationRepository(ApplicationProperties):
if archive.filepath is None: if archive.filepath is None:
self.logger.warning("filepath is empty for %s", package.base) self.logger.warning("filepath is empty for %s", package.base)
continue # avoid mypy warning continue # avoid mypy warning
self.repository.sign.process_sign_package(archive.filepath, None) self.repository.sign.process_sign_package(archive.filepath, package.base)
# sign repository database if set # sign repository database if set
self.repository.sign.process_sign_repository(self.repository.repo.repo_path) self.repository.sign.process_sign_repository(self.repository.repo.repo_path)
# process triggers # process triggers
@ -104,14 +104,14 @@ class ApplicationRepository(ApplicationProperties):
packages: list[str] = [] packages: list[str] = []
for single in probe.packages: for single in probe.packages:
try: try:
_ = Package.from_aur(single, self.repository.pacman, None) _ = Package.from_aur(single, self.repository.pacman)
except Exception: except Exception:
packages.append(single) packages.append(single)
return packages return packages
def unknown_local(probe: Package) -> list[str]: def unknown_local(probe: Package) -> list[str]:
cache_dir = self.repository.paths.cache_for(probe.base) cache_dir = self.repository.paths.cache_for(probe.base)
local = Package.from_build(cache_dir, self.architecture, None) local = Package.from_build(cache_dir, self.architecture)
packages = set(probe.packages.keys()).difference(local.packages.keys()) packages = set(probe.packages.keys()).difference(local.packages.keys())
return list(packages) return list(packages)
@ -123,14 +123,12 @@ class ApplicationRepository(ApplicationProperties):
result.extend(unknown_aur(package)) # local package not found result.extend(unknown_aur(package)) # local package not found
return result return result
def update(self, updates: Iterable[Package], packagers: Packagers | None = None) -> Result: def update(self, updates: Iterable[Package]) -> Result:
""" """
run package updates run package updates
Args: Args:
updates(Iterable[Package]): list of packages to update updates(Iterable[Package]): list of packages to update
packagers(Packagers | None, optional): optional override of username for build process
(Default value = None)
Returns: Returns:
Result: update result Result: update result
@ -138,7 +136,7 @@ class ApplicationRepository(ApplicationProperties):
def process_update(paths: Iterable[Path], result: Result) -> None: def process_update(paths: Iterable[Path], result: Result) -> None:
if not paths: if not paths:
return # don't need to process if no update supplied return # don't need to process if no update supplied
update_result = self.repository.process_update(paths, packagers) update_result = self.repository.process_update(paths)
self.on_result(result.merge(update_result)) self.on_result(result.merge(update_result))
# process built packages # process built packages
@ -150,14 +148,14 @@ class ApplicationRepository(ApplicationProperties):
tree = Tree.resolve(updates) tree = Tree.resolve(updates)
for num, level in enumerate(tree): for num, level in enumerate(tree):
self.logger.info("processing level #%i %s", num, [package.base for package in level]) self.logger.info("processing level #%i %s", num, [package.base for package in level])
build_result = self.repository.process_build(level, packagers) build_result = self.repository.process_build(level)
packages = self.repository.packages_built() packages = self.repository.packages_built()
process_update(packages, build_result) process_update(packages, build_result)
return build_result return build_result
def updates(self, filter_packages: Iterable[str], *, def updates(self, filter_packages: Iterable[str], *,
aur: bool, local: bool, manual: bool, vcs: bool) -> list[Package]: aur: bool, local: bool, manual: bool, vcs: bool, log_fn: Callable[[str], None]) -> list[Package]:
""" """
get list of packages to run update process get list of packages to run update process
@ -167,6 +165,7 @@ class ApplicationRepository(ApplicationProperties):
local(bool): enable or disable checking of local packages for updates local(bool): enable or disable checking of local packages for updates
manual(bool): include or exclude manual updates manual(bool): include or exclude manual updates
vcs(bool): enable or disable checking of VCS packages vcs(bool): enable or disable checking of VCS packages
log_fn(Callable[[str], None]): logger function to log updates
Returns: Returns:
list[Package]: list of out-of-dated packages list[Package]: list of out-of-dated packages
@ -180,4 +179,14 @@ class ApplicationRepository(ApplicationProperties):
if manual: if manual:
updates.update({package.base: package for package in self.repository.updates_manual()}) updates.update({package.base: package for package in self.repository.updates_manual()})
return [package for _, package in sorted(updates.items())] local_versions = {package.base: package.version for package in self.repository.packages()}
updated_packages = [package for _, package in sorted(updates.items())]
# reorder updates according to the dependency tree
tree = Tree.resolve(updated_packages)
for level in tree:
for package in level:
UpdatePrinter(package, local_versions.get(package.base)).print(
verbose=True, log_fn=log_fn, separator=" -> ")
return updated_packages

View File

@ -22,7 +22,6 @@ import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.packagers import Packagers
class Add(Handler): class Add(Handler):
@ -31,7 +30,8 @@ class Add(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -40,17 +40,17 @@ class Add(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report, refresh_pacman_database=args.refresh) application = Application(architecture, configuration,
report=report, unsafe=unsafe, refresh_pacman_database=args.refresh)
application.on_start() application.on_start()
application.add(args.package, args.source, args.username) application.add(args.package, args.source)
if not args.now: if not args.now:
return return
packages = application.updates(args.package, aur=False, local=False, manual=True, vcs=False) packages = application.updates(args.package, aur=False, local=False, manual=True, vcs=False,
log_fn=application.logger.info)
packages = application.with_dependencies(packages, process_dependencies=args.dependencies) packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
packagers = Packagers(args.username, {package.base: package.packager for package in packages}) result = application.update(packages)
application.print_updates(packages, log_fn=application.logger.info)
result = application.update(packages, packagers)
Add.check_if_empty(args.exit_code, result.is_empty) Add.check_if_empty(args.exit_code, result.is_empty)

View File

@ -36,7 +36,8 @@ class Backup(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -45,6 +46,7 @@ class Backup(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
backup_paths = Backup.get_paths(configuration) backup_paths = Backup.get_paths(configuration)
with TarFile(args.path, mode="w") as archive: # well we don't actually use compression with TarFile(args.path, mode="w") as archive: # well we don't actually use compression

View File

@ -30,7 +30,8 @@ class Clean(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -39,8 +40,9 @@ class Clean(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
application.on_start() application.on_start()
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages, application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
pacman=args.pacman) pacman=args.pacman)

View File

@ -30,7 +30,8 @@ class Daemon(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -39,10 +40,11 @@ class Daemon(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
from ahriman.application.handlers import Update from ahriman.application.handlers import Update
Update.run(args, architecture, configuration, report=report) Update.run(args, architecture, configuration, report=report, unsafe=unsafe)
timer = threading.Timer(args.interval, Daemon.run, args=[args, architecture, configuration], timer = threading.Timer(args.interval, Daemon.run, args=[args, architecture, configuration],
kwargs={"report": report}) kwargs={"report": report, "unsafe": unsafe})
timer.start() timer.start()
timer.join() timer.join()

View File

@ -21,7 +21,7 @@ import argparse
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter from ahriman.core.formatters import ConfigurationPrinter
class Dump(Handler): class Dump(Handler):
@ -32,7 +32,8 @@ class Dump(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -41,13 +42,8 @@ class Dump(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
root, _ = configuration.check_loaded()
ConfigurationPathsPrinter(root, configuration.includes).print(verbose=True, separator=" = ")
# empty line
StringPrinter("").print(verbose=False)
dump = configuration.dump() dump = configuration.dump()
for section, values in sorted(dump.items()): for section, values in sorted(dump.items()):
ConfigurationPrinter(section, values).print(verbose=not args.secure, separator=" = ") ConfigurationPrinter(section, values).print(verbose=not args.secure, separator=" = ")

View File

@ -94,10 +94,9 @@ class Handler:
""" """
try: try:
configuration = Configuration.from_path(args.configuration, architecture) configuration = Configuration.from_path(args.configuration, architecture)
log_handler = Log.handler(args.log_handler) Log.load(configuration, quiet=args.quiet, report=args.report)
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
with Lock(args, architecture, configuration): with Lock(args, architecture, configuration):
cls.run(args, architecture, configuration, report=args.report) cls.run(args, architecture, configuration, report=args.report, unsafe=args.unsafe)
return True return True
except ExitCode: except ExitCode:
return False return False
@ -136,7 +135,8 @@ class Handler:
return 0 if all(result) else 1 return 0 if all(result) else 1
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -145,6 +145,7 @@ class Handler:
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
Raises: Raises:
NotImplementedError: not implemented method NotImplementedError: not implemented method

View File

@ -31,7 +31,8 @@ class Help(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -40,6 +41,7 @@ class Help(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
parser: argparse.ArgumentParser = args.parser() parser: argparse.ArgumentParser = args.parser()
if args.command is None: if args.command is None:

View File

@ -32,7 +32,8 @@ class KeyImport(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -41,6 +42,7 @@ class KeyImport(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
application.repository.sign.key_import(args.key_server, args.key) application.repository.sign.key_import(args.key_server, args.key)

View File

@ -38,7 +38,8 @@ class Patch(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -47,8 +48,9 @@ class Patch(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
application.on_start() application.on_start()
if args.action == Action.Update and args.variable is not None: if args.action == Action.Update and args.variable is not None:
@ -76,7 +78,7 @@ class Patch(Handler):
tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
to current files to current files
""" """
package = Package.from_build(sources_dir, architecture, None) package = Package.from_build(sources_dir, architecture)
patch = Sources.patch_create(sources_dir, *track) patch = Sources.patch_create(sources_dir, *track)
return package.base, PkgbuildPatch(None, patch) return package.base, PkgbuildPatch(None, patch)

View File

@ -22,7 +22,7 @@ import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.build_status import BuildStatusEnum from ahriman.core.formatters import UpdatePrinter
from ahriman.models.package import Package from ahriman.models.package import Package
@ -32,7 +32,8 @@ class Rebuild(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -41,40 +42,35 @@ class Rebuild(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
application.on_start() application.on_start()
packages = Rebuild.extract_packages(application, args.status, from_database=args.from_database) packages = Rebuild.extract_packages(application, from_database=args.from_database)
updates = application.repository.packages_depend_on(packages, args.depends_on or None) updates = application.repository.packages_depend_on(packages, args.depends_on or None)
Rebuild.check_if_empty(args.exit_code, not updates) Rebuild.check_if_empty(args.exit_code, not updates)
if args.dry_run: if args.dry_run:
application.print_updates(updates, log_fn=print) for package in updates:
UpdatePrinter(package, package.version).print(verbose=True)
return return
result = application.update(updates, args.username) result = application.update(updates)
Rebuild.check_if_empty(args.exit_code, result.is_empty) Rebuild.check_if_empty(args.exit_code, result.is_empty)
@staticmethod @staticmethod
def extract_packages(application: Application, status: BuildStatusEnum | None, *, def extract_packages(application: Application, *, from_database: bool) -> list[Package]:
from_database: bool) -> list[Package]:
""" """
extract packages from database file extract packages from database file
Args: Args:
application(Application): application instance application(Application): application instance
status(BuildStatusEnum | None): optional filter by package status
from_database(bool): extract packages from database instead of repository filesystem from_database(bool): extract packages from database instead of repository filesystem
Returns: Returns:
list[Package]: list of packages which were stored in database list[Package]: list of packages which were stored in database
""" """
if from_database: if from_database:
return [ return [package for (package, _) in application.database.packages_get()]
package
for (package, last_status) in application.database.packages_get()
if status is None or last_status.status == status
]
return application.repository.packages() return application.repository.packages()

View File

@ -30,7 +30,8 @@ class Remove(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -39,7 +40,8 @@ class Remove(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
application.on_start() application.on_start()
application.remove(args.package) application.remove(args.package)

View File

@ -31,7 +31,8 @@ class RemoveUnknown(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -40,8 +41,9 @@ class RemoveUnknown(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
application.on_start() application.on_start()
unknown_packages = application.unknown() unknown_packages = application.unknown()

View File

@ -33,7 +33,8 @@ class Restore(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -42,6 +43,7 @@ class Restore(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
with TarFile(args.path) as archive: with TarFile(args.path) as archive:
archive.extractall(path=args.output) archive.extractall(path=args.output)

View File

@ -47,7 +47,8 @@ class Search(Handler):
} }
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -56,8 +57,9 @@ class Search(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
official_packages_list = Official.multisearch(*args.search, pacman=application.repository.pacman) official_packages_list = Official.multisearch(*args.search, pacman=application.repository.pacman)
aur_packages_list = AUR.multisearch(*args.search, pacman=application.repository.pacman) aur_packages_list = AUR.multisearch(*args.search, pacman=application.repository.pacman)

View File

@ -35,7 +35,8 @@ class ServiceUpdates(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -44,10 +45,11 @@ class ServiceUpdates(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
remote = Package.from_aur("ahriman", application.repository.pacman, None) remote = Package.from_aur("ahriman", application.repository.pacman)
release = remote.version.rsplit("-", 1)[-1] # we don't store pkgrel locally, so we just append it release = remote.version.rsplit("-", 1)[-1] # we don't store pkgrel locally, so we just append it
local_version = f"{version.__version__}-{release}" local_version = f"{version.__version__}-{release}"

View File

@ -26,7 +26,6 @@ from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.user import User
class Setup(Handler): class Setup(Handler):
@ -34,19 +33,18 @@ class Setup(Handler):
setup handler setup handler
Attributes: Attributes:
ARCHBUILD_COMMAND_PATH(Path): (class attribute) default devtools command
MIRRORLIST_PATH(Path): (class attribute) path to pacman default mirrorlist (used by multilib repository) MIRRORLIST_PATH(Path): (class attribute) path to pacman default mirrorlist (used by multilib repository)
SUDOERS_DIR_PATH(Path): (class attribute) path to sudoers.d includes directory SUDOERS_DIR_PATH(Path): (class attribute) path to sudoers.d includes directory
""" """
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
ARCHBUILD_COMMAND_PATH = Path("/usr") / "bin" / "archbuild" MIRRORLIST_PATH = Path("/etc/pacman.d/mirrorlist")
MIRRORLIST_PATH = Path("/etc") / "pacman.d" / "mirrorlist" SUDOERS_DIR_PATH = Path("/etc/sudoers.d")
SUDOERS_DIR_PATH = Path("/etc") / "sudoers.d"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -55,37 +53,22 @@ class Setup(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration) Setup.configuration_create_ahriman(args, architecture, args.repository, configuration)
configuration.reload() configuration.reload()
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths) Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths)
Setup.executable_create(application.repository.paths, args.build_command, architecture) Setup.configuration_create_devtools(architecture, args.from_configuration, args.mirror,
Setup.configuration_create_devtools(args.build_command, architecture, args.from_configuration, args.mirror,
args.multilib, args.repository, application.repository.paths) args.multilib, args.repository, application.repository.paths)
Setup.configuration_create_sudo(application.repository.paths, args.build_command, architecture) Setup.configuration_create_sudo(args.build_command)
application.repository.repo.init() application.repository.repo.init()
# lazy database sync # lazy database sync
application.repository.pacman.handle # pylint: disable=pointless-statement application.repository.pacman.handle # pylint: disable=pointless-statement
@staticmethod
def build_command(root: Path, prefix: str, architecture: str) -> Path:
"""
generate build command name
Args:
root(Path): root directory for the build command (must be root of the repository)
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
Returns:
Path: valid devtools command name
"""
return root / f"{prefix}-{architecture}-build"
@staticmethod @staticmethod
def configuration_create_ahriman(args: argparse.Namespace, architecture: str, repository: str, def configuration_create_ahriman(args: argparse.Namespace, architecture: str, repository: str,
root: Configuration) -> None: root: Configuration) -> None:
@ -100,12 +83,10 @@ class Setup(Handler):
""" """
configuration = Configuration() configuration = Configuration()
section = Configuration.section_name("build", architecture)
build_command = Setup.build_command(root.repository_paths.root, args.build_command, architecture)
configuration.set_option(section, "build_command", str(build_command))
configuration.set_option("repository", "name", repository) configuration.set_option("repository", "name", repository)
if args.build_as_user is not None:
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}") section = Configuration.section_name("build", architecture)
configuration.set_option(section, "build_command", str(args.build_command))
section = Configuration.section_name("alpm", architecture) section = Configuration.section_name("alpm", architecture)
if args.mirror is not None: if args.mirror is not None:
@ -125,24 +106,20 @@ class Setup(Handler):
if args.web_unix_socket is not None: if args.web_unix_socket is not None:
configuration.set_option(section, "unix_socket", str(args.web_unix_socket)) configuration.set_option(section, "unix_socket", str(args.web_unix_socket))
if args.generate_salt:
configuration.set_option("auth", "salt", User.generate_password(20))
target = root.include / "00-setup-overrides.ini" target = root.include / "00-setup-overrides.ini"
with target.open("w") as ahriman_configuration: with target.open("w") as ahriman_configuration:
configuration.write(ahriman_configuration) configuration.write(ahriman_configuration)
@staticmethod @staticmethod
def configuration_create_devtools(prefix: str, architecture: str, source: Path, mirror: str | None, def configuration_create_devtools(architecture: str, source: Path, mirror: str | None,
multilib: bool, repository: str, paths: RepositoryPaths) -> None: multilib: bool, repository: str, paths: RepositoryPaths) -> None:
""" """
create configuration for devtools based on ``source`` configuration create configuration for devtools based on ``source`` configuration
Notes: Note:
devtools does not allow to specify the pacman configuration, thus we still have to use configuration in /usr devtools does not allow to specify the pacman configuration, thus we still have to use configuration in /usr
Args: Args:
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture architecture(str): repository architecture
source(Path): path to source configuration file source(Path): path to source configuration file
mirror(str | None): link to package server mirror mirror(str | None): link to package server mirror
@ -177,10 +154,10 @@ class Setup(Handler):
configuration.set_option(section, "Server", mirror) configuration.set_option(section, "Server", mirror)
# add repository itself # add repository itself
configuration.set_option(repository, "SigLevel", "Never") # we don't care configuration.set_option(repository, "SigLevel", "Optional TrustAll") # we don't care
configuration.set_option(repository, "Server", f"file://{paths.repository}") configuration.set_option(repository, "Server", f"file://{paths.repository}")
target = source.parent / f"{prefix}-{architecture}.conf" target = source.parent / f"{repository}.conf"
with target.open("w") as devtools_configuration: with target.open("w") as devtools_configuration:
configuration.write(devtools_configuration) configuration.write(devtools_configuration)
@ -204,31 +181,13 @@ class Setup(Handler):
(home_dir / ".makepkg.conf").write_text(content, encoding="utf8") (home_dir / ".makepkg.conf").write_text(content, encoding="utf8")
@staticmethod @staticmethod
def configuration_create_sudo(paths: RepositoryPaths, prefix: str, architecture: str) -> None: def configuration_create_sudo(build_command: Path) -> None:
""" """
create configuration to run build command with sudo without password create configuration to run build command with sudo without password
Args: Args:
paths(RepositoryPaths): repository paths instance build_command(Path): path to build command
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
""" """
command = Setup.build_command(paths.root, prefix, architecture) sudoers_file = Setup.SUDOERS_DIR_PATH / f"ahriman-{build_command.name}"
sudoers_file = Setup.build_command(Setup.SUDOERS_DIR_PATH, prefix, architecture) sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD: {build_command} build *\n", encoding="utf8")
sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD:SETENV: {command} *\n", encoding="utf8")
sudoers_file.chmod(0o400) # security! sudoers_file.chmod(0o400) # security!
@staticmethod
def executable_create(paths: RepositoryPaths, prefix: str, architecture: str) -> None:
"""
create executable for the service
Args:
paths(RepositoryPaths): repository paths instance
prefix(str): command prefix in {prefix}-{architecture}-build
architecture(str): repository architecture
"""
command = Setup.build_command(paths.root, prefix, architecture)
command.unlink(missing_ok=True)
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
paths.chown(command) # we would like to keep owner inside ahriman's home

View File

@ -37,7 +37,8 @@ class Shell(Handler):
ALLOW_MULTI_ARCHITECTURE_RUN = False ALLOW_MULTI_ARCHITECTURE_RUN = False
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -46,9 +47,10 @@ class Shell(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
# pylint: disable=possibly-unused-variable # pylint: disable=possibly-unused-variable
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
if args.verbose: if args.verbose:
# licensed by https://creativecommons.org/licenses/by-sa/3.0 # licensed by https://creativecommons.org/licenses/by-sa/3.0
path = Path(sys.prefix) / "share" / "ahriman" / "templates" / "shell" path = Path(sys.prefix) / "share" / "ahriman" / "templates" / "shell"

View File

@ -30,7 +30,8 @@ class Sign(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -39,5 +40,6 @@ class Sign(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
Application(architecture, configuration, report=report).sign(args.package) Application(architecture, configuration, report=report, unsafe=unsafe).sign(args.package)

View File

@ -37,7 +37,8 @@ class Status(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -46,9 +47,10 @@ class Status(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
# we are using reporter here # we are using reporter here
client = Application(architecture, configuration, report=True).repository.reporter client = Application(architecture, configuration, report=True, unsafe=unsafe).repository.reporter
if args.ahriman: if args.ahriman:
service_status = client.get_internal() service_status = client.get_internal()
StatusPrinter(service_status.status).print(verbose=args.info) StatusPrinter(service_status.status).print(verbose=args.info)

View File

@ -33,7 +33,8 @@ class StatusUpdate(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -42,9 +43,10 @@ class StatusUpdate(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
# we are using reporter here # we are using reporter here
client = Application(architecture, configuration, report=True).repository.reporter client = Application(architecture, configuration, report=True, unsafe=unsafe).repository.reporter
if args.action == Action.Update and args.package: if args.action == Action.Update and args.package:
# update packages statuses # update packages statuses

View File

@ -34,7 +34,8 @@ class Structure(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -43,8 +44,9 @@ class Structure(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
packages = application.repository.packages() packages = application.repository.packages()
tree = Tree.resolve(packages) tree = Tree.resolve(packages)

View File

@ -31,7 +31,8 @@ class Triggers(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -40,8 +41,9 @@ class Triggers(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report) application = Application(architecture, configuration, report=report, unsafe=unsafe)
if args.trigger: if args.trigger:
loader = application.repository.triggers loader = application.repository.triggers
loader.triggers = [loader.load_trigger(trigger, architecture, configuration) for trigger in args.trigger] loader.triggers = [loader.load_trigger(trigger, architecture, configuration) for trigger in args.trigger]

View File

@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
import argparse import argparse
import shlex
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
@ -32,7 +33,8 @@ class UnsafeCommands(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -41,17 +43,18 @@ class UnsafeCommands(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
parser = args.parser() parser = args.parser()
unsafe_commands = UnsafeCommands.get_unsafe_commands(parser) unsafe_commands = UnsafeCommands.get_unsafe_commands(parser)
if args.command: if args.command is None:
UnsafeCommands.check_unsafe(args.command, unsafe_commands, parser)
else:
for command in unsafe_commands: for command in unsafe_commands:
StringPrinter(command).print(verbose=True) StringPrinter(command).print(verbose=True)
else:
UnsafeCommands.check_unsafe(args.command, unsafe_commands, parser)
@staticmethod @staticmethod
def check_unsafe(command: list[str], unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None: def check_unsafe(command: str, unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
""" """
check if command is unsafe check if command is unsafe
@ -60,7 +63,7 @@ class UnsafeCommands(Handler):
unsafe_commands(list[str]): list of unsafe commands unsafe_commands(list[str]): list of unsafe commands
parser(argparse.ArgumentParser): generated argument parser parser(argparse.ArgumentParser): generated argument parser
""" """
args = parser.parse_args(command) args = parser.parse_args(shlex.split(command))
UnsafeCommands.check_if_empty(True, args.command in unsafe_commands) UnsafeCommands.check_if_empty(True, args.command in unsafe_commands)
@staticmethod @staticmethod
@ -76,6 +79,5 @@ class UnsafeCommands(Handler):
""" """
# should never fail # should never fail
# pylint: disable=protected-access # pylint: disable=protected-access
subparser = next((action for action in parser._actions if isinstance(action, argparse._SubParsersAction)), None) subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))
actions = subparser.choices if subparser is not None else {} return sorted(action_name for action_name, action in subparser.choices.items() if action.get_default("unsafe"))
return sorted(action_name for action_name, action in actions.items() if action.get_default("unsafe"))

View File

@ -24,7 +24,6 @@ from collections.abc import Callable
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.packagers import Packagers
class Update(Handler): class Update(Handler):
@ -33,7 +32,8 @@ class Update(Handler):
""" """
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -42,19 +42,19 @@ class Update(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, report=report, refresh_pacman_database=args.refresh) application = Application(architecture, configuration, report=report, unsafe=unsafe,
refresh_pacman_database=args.refresh)
application.on_start() application.on_start()
packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs) packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs,
log_fn=Update.log_fn(application, args.dry_run))
Update.check_if_empty(args.exit_code, not packages) Update.check_if_empty(args.exit_code, not packages)
if args.dry_run: if args.dry_run:
return return
packages = application.with_dependencies(packages, process_dependencies=args.dependencies) packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
packagers = Packagers(args.username, {package.base: package.packager for package in packages}) result = application.update(packages)
application.print_updates(packages, log_fn=application.logger.info)
result = application.update(packages, packagers)
Update.check_if_empty(args.exit_code, result.is_empty) Update.check_if_empty(args.exit_code, result.is_empty)
@staticmethod @staticmethod

View File

@ -20,6 +20,8 @@
import argparse import argparse
import getpass import getpass
from pathlib import Path
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite from ahriman.core.database import SQLite
@ -37,7 +39,8 @@ class Users(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture" ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -46,13 +49,18 @@ class Users(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
database = SQLite.load(configuration) database = SQLite.load(configuration)
if args.action == Action.Update: if args.action == Action.Update:
old_salt, salt = Users.get_salt(configuration)
user = Users.user_create(args) user = Users.user_create(args)
# if password is left blank we are not going to require salt to be set
salt = configuration.get("auth", "salt") if user.password else "" if old_salt is None:
auth_configuration = Users.configuration_get(configuration.include)
Users.configuration_create(auth_configuration, salt, args.secure)
database.user_update(user.hash_password(salt)) database.user_update(user.hash_password(salt))
elif args.action == Action.List: elif args.action == Action.List:
users = database.user_list(args.username, args.role) users = database.user_list(args.username, args.role)
@ -62,6 +70,70 @@ class Users(Handler):
elif args.action == Action.Remove: elif args.action == Action.Remove:
database.user_remove(args.username) database.user_remove(args.username)
@staticmethod
def configuration_create(configuration: Configuration, salt: str, secure: bool) -> None:
"""
enable configuration if it has been disabled
Args:
configuration(Configuration): configuration instance
salt(str): password hash salt
secure(bool): if true then set file permissions to 0o600
"""
configuration.set_option("auth", "salt", salt)
Users.configuration_write(configuration, secure)
@staticmethod
def configuration_get(include_path: Path) -> Configuration:
"""
create configuration instance
Args:
include_path(Path): path to directory with configuration includes
Returns:
Configuration: configuration instance. In case if there are local settings they will be loaded
"""
target = include_path / "00-auth.ini"
configuration = Configuration()
configuration.load(target)
configuration.architecture = "" # not user anyway
return configuration
@staticmethod
def configuration_write(configuration: Configuration, secure: bool) -> None:
"""
write configuration file
Args:
configuration(Configuration): configuration instance
secure(bool): if true then set file permissions to 0o600
"""
path, _ = configuration.check_loaded()
with path.open("w") as ahriman_configuration:
configuration.write(ahriman_configuration)
if secure:
path.chmod(0o600)
@staticmethod
def get_salt(configuration: Configuration, salt_length: int = 20) -> tuple[str | None, str]:
"""
get salt from configuration or create new string
Args:
configuration(Configuration): configuration instance
salt_length(int, optional): salt length (Default value = 20)
Returns:
tuple[str | None, str]: tuple containing salt from configuration if any and actual salt which must be
used for password hash
"""
if salt := configuration.get("auth", "salt", fallback=None):
return salt, salt
return None, User.generate_password(salt_length)
@staticmethod @staticmethod
def user_create(args: argparse.Namespace) -> User: def user_create(args: argparse.Namespace) -> User:
""" """
@ -84,5 +156,4 @@ class Users(Handler):
if password is None: if password is None:
password = read_password() password = read_password()
return User(username=args.username, password=password, access=args.role, return User(username=args.username, password=password, access=args.role)
packager_id=args.packager, key=args.key)

View File

@ -39,7 +39,8 @@ class Validate(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -48,6 +49,7 @@ class Validate(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
schema = Validate.schema(architecture, configuration) schema = Validate.schema(architecture, configuration)
validator = Validator(configuration=configuration, schema=schema) validator = Validator(configuration=configuration, schema=schema)
@ -76,9 +78,7 @@ class Validate(Handler):
# create trigger loader instance # create trigger loader instance
loader = TriggerLoader() loader = TriggerLoader()
triggers = loader.selected_triggers(configuration) + loader.known_triggers(configuration) for trigger in loader.selected_triggers(configuration):
for trigger in set(triggers):
try: try:
trigger_class = loader.load_trigger_class(trigger) trigger_class = loader.load_trigger_class(trigger)
except ExtensionError: except ExtensionError:

View File

@ -42,7 +42,8 @@ class Versions(Handler):
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+") PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -51,6 +52,7 @@ class Versions(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
VersionPrinter(f"Module version {version.__version__}", VersionPrinter(f"Module version {version.__version__}",
{"Python": sys.version}).print(verbose=False, separator=" ") {"Python": sys.version}).print(verbose=False, separator=" ")

View File

@ -19,8 +19,6 @@
# #
import argparse import argparse
from collections.abc import Generator
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.spawn import Spawn from ahriman.core.spawn import Spawn
@ -33,10 +31,10 @@ class Web(Handler):
ALLOW_AUTO_ARCHITECTURE_RUN = False ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
COMMAND_ARGS_WHITELIST = ["force", "log_handler", ""]
@classmethod @classmethod
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None: def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
""" """
callback for command line callback for command line
@ -45,12 +43,12 @@ class Web(Handler):
architecture(str): repository architecture architecture(str): repository architecture
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
""" """
# we are using local import for optional dependencies # we are using local import for optional dependencies
from ahriman.web.web import run_server, setup_service from ahriman.web.web import run_server, setup_service
spawner_args = Web.extract_arguments(args, architecture, configuration) spawner = Spawn(args.parser(), architecture, configuration)
spawner = Spawn(args.parser(), architecture, list(spawner_args))
spawner.start() spawner.start()
application = setup_service(architecture, configuration, spawner) application = setup_service(architecture, configuration, spawner)
@ -59,33 +57,3 @@ class Web(Handler):
# terminate spawn process at the last # terminate spawn process at the last
spawner.stop() spawner.stop()
spawner.join() spawner.join()
@staticmethod
def extract_arguments(args: argparse.Namespace, architecture: str,
configuration: Configuration) -> Generator[str, None, None]:
"""
extract list of arguments used for current command, except for command specific ones
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
Returns:
Generator[str, None, None]: command line arguments which were used for this specific command
"""
# read architecture from the same argument list
yield from ["--architecture", architecture]
# read configuration path from current settings
if (configuration_path := configuration.path) is not None:
yield from ["--configuration", str(configuration_path)]
# arguments from command line
if args.force:
yield "--force"
if args.log_handler is not None:
yield from ["--log-handler", args.log_handler.value]
if args.quiet:
yield "--quiet"
if args.unsafe:
yield "--unsafe"

View File

@ -86,7 +86,6 @@ class Lock(LazyLogging):
check if current user is actually owner of ahriman root check if current user is actually owner of ahriman root
""" """
check_user(self.paths, unsafe=self.unsafe) check_user(self.paths, unsafe=self.unsafe)
self.paths.tree_create()
def clear(self) -> None: def clear(self) -> None:
""" """
@ -117,7 +116,7 @@ class Lock(LazyLogging):
1. Check user UID 1. Check user UID
2. Check if there is lock file 2. Check if there is lock file
3. Check web status watcher status 3. Check web status watcher status
4. Create lock file and directory tree 4. Create lock file
5. Report to status page if enabled 5. Report to status page if enabled
Returns: Returns:

View File

@ -20,9 +20,9 @@
import shutil import shutil
from collections.abc import Callable, Generator from collections.abc import Callable, Generator
from functools import cached_property
from pathlib import Path from pathlib import Path
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import] from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import]
from typing import Any
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.log import LazyLogging from ahriman.core.log import LazyLogging
@ -34,8 +34,13 @@ from ahriman.models.repository_paths import RepositoryPaths
class Pacman(LazyLogging): class Pacman(LazyLogging):
""" """
alpm wrapper alpm wrapper
Attributes:
handle(Handle): pyalpm root ``Handle``
""" """
handle: Handle
def __init__(self, architecture: str, configuration: Configuration, *, def __init__(self, architecture: str, configuration: Configuration, *,
refresh_database: PacmanSynchronization) -> None: refresh_database: PacmanSynchronization) -> None:
""" """
@ -79,16 +84,6 @@ class Pacman(LazyLogging):
return handle return handle
@cached_property
def handle(self) -> Handle:
"""
pyalpm handle
Returns:
Handle: generated pyalpm handle instance
"""
return self.__create_handle_fn()
def database_copy(self, handle: Handle, database: DB, pacman_root: Path, paths: RepositoryPaths, *, def database_copy(self, handle: Handle, database: DB, pacman_root: Path, paths: RepositoryPaths, *,
use_ahriman_cache: bool) -> None: use_ahriman_cache: bool) -> None:
""" """
@ -189,3 +184,22 @@ class Pacman(LazyLogging):
result.update(trim_package(provides) for provides in package.provides) result.update(trim_package(provides) for provides in package.provides)
return result return result
def __getattr__(self, item: str) -> Any:
"""
pacman handle extractor
Args:
item(str): property name
Returns:
Any: attribute by its name
Raises:
AttributeError: in case if no such attribute found
"""
if item == "handle":
handle = self.__create_handle_fn()
setattr(self, item, handle)
return handle
return super().__getattr__(item) # required for logging attribute

View File

@ -115,11 +115,7 @@ class AUR(Remote):
query[key] = value query[key] = value
try: try:
response = requests.get( response = requests.get(self.DEFAULT_RPC_URL, params=query, timeout=self.DEFAULT_TIMEOUT)
self.DEFAULT_RPC_URL,
params=query,
headers={"User-Agent": self.DEFAULT_USER_AGENT},
timeout=self.DEFAULT_TIMEOUT)
response.raise_for_status() response.raise_for_status()
return self.parse_response(response.json()) return self.parse_response(response.json())
except requests.HTTPError as e: except requests.HTTPError as e:

View File

@ -34,15 +34,13 @@ class Official(Remote):
Attributes: Attributes:
DEFAULT_ARCHLINUX_URL(str): (class attribute) default archlinux url DEFAULT_ARCHLINUX_URL(str): (class attribute) default archlinux url
DEFAULT_ARCHLINUX_GIT_URL(str): (class attribute) default url for git packages
DEFAULT_SEARCH_REPOSITORIES(list[str]): (class attribute) default list of repositories to search DEFAULT_SEARCH_REPOSITORIES(list[str]): (class attribute) default list of repositories to search
DEFAULT_RPC_URL(str): (class attribute) default archlinux repositories RPC url DEFAULT_RPC_URL(str): (class attribute) default archlinux repositories RPC url
DEFAULT_TIMEOUT(int): (class attribute) HTTP request timeout in seconds DEFAULT_TIMEOUT(int): (class attribute) HTTP request timeout in seconds
""" """
DEFAULT_ARCHLINUX_GIT_URL = "https://gitlab.archlinux.org"
DEFAULT_ARCHLINUX_URL = "https://archlinux.org" DEFAULT_ARCHLINUX_URL = "https://archlinux.org"
DEFAULT_SEARCH_REPOSITORIES = ["Core", "Extra", "Multilib"] DEFAULT_SEARCH_REPOSITORIES = ["Core", "Extra", "Multilib", "Community"]
DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json" DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json"
DEFAULT_TIMEOUT = 30 DEFAULT_TIMEOUT = 30
@ -58,7 +56,9 @@ class Official(Remote):
Returns: Returns:
str: git url for the specific base str: git url for the specific base
""" """
return f"{Official.DEFAULT_ARCHLINUX_GIT_URL}/archlinux/packaging/packages/{package_base}.git" if repository.lower() in ("core", "extra", "testing", "kde-unstable"):
return "https://github.com/archlinux/svntogit-packages.git" # hardcoded, ok
return "https://github.com/archlinux/svntogit-community.git"
@classmethod @classmethod
def remote_web_url(cls, package_base: str) -> str: def remote_web_url(cls, package_base: str) -> str:
@ -106,7 +106,6 @@ class Official(Remote):
response = requests.get( response = requests.get(
self.DEFAULT_RPC_URL, self.DEFAULT_RPC_URL,
params={by: args, "repo": self.DEFAULT_SEARCH_REPOSITORIES}, params={by: args, "repo": self.DEFAULT_SEARCH_REPOSITORIES},
headers={"User-Agent": self.DEFAULT_USER_AGENT},
timeout=self.DEFAULT_TIMEOUT) timeout=self.DEFAULT_TIMEOUT)
response.raise_for_status() response.raise_for_status()
return self.parse_response(response.json()) return self.parse_response(response.json())

View File

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from ahriman import version
from ahriman.core.alpm.pacman import Pacman from ahriman.core.alpm.pacman import Pacman
from ahriman.core.log import LazyLogging from ahriman.core.log import LazyLogging
from ahriman.models.aur_package import AURPackage from ahriman.models.aur_package import AURPackage
@ -27,9 +26,6 @@ class Remote(LazyLogging):
""" """
base class for remote package search base class for remote package search
Attributes:
DEFAULT_USER_AGENT(str): (class attribute) default user agent
Examples: Examples:
These classes are designed to be used without instancing. In order to achieve it several class methods are These classes are designed to be used without instancing. In order to achieve it several class methods are
provided: ``info``, ``multisearch`` and ``search``. Thus, the basic flow is the following:: provided: ``info``, ``multisearch`` and ``search``. Thus, the basic flow is the following::
@ -43,8 +39,6 @@ class Remote(LazyLogging):
directly, whereas ``multisearch`` splits search one by one and finds intersection between search results. directly, whereas ``multisearch`` splits search one by one and finds intersection between search results.
""" """
DEFAULT_USER_AGENT = f"ahriman/{version.__version__}"
@classmethod @classmethod
def info(cls, package_name: str, *, pacman: Pacman) -> AURPackage: def info(cls, package_name: str, *, pacman: Pacman) -> AURPackage:
""" """

View File

@ -125,12 +125,6 @@ class Sources(LazyLogging):
Sources._check_output("git", "init", "--initial-branch", instance.DEFAULT_BRANCH, Sources._check_output("git", "init", "--initial-branch", instance.DEFAULT_BRANCH,
cwd=sources_dir, logger=instance.logger) cwd=sources_dir, logger=instance.logger)
# extract local files...
files = ["PKGBUILD", ".SRCINFO"] + [str(path) for path in Package.local_files(sources_dir)]
instance.add(sources_dir, *files)
# ...and commit them
instance.commit(sources_dir, author="ahriman <ahriman@localhost>")
@staticmethod @staticmethod
def load(sources_dir: Path, package: Package, patches: list[PkgbuildPatch], paths: RepositoryPaths) -> None: def load(sources_dir: Path, package: Package, patches: list[PkgbuildPatch], paths: RepositoryPaths) -> None:
""" """

View File

@ -34,6 +34,10 @@ class Task(LazyLogging):
base package build task base package build task
Attributes: Attributes:
architecture(str): repository architecture
build_command(str): build command
build_flags(list[str]): list of additional flags to pkgctl
name(str): repository name
package(Package): package definitions package(Package): package definitions
paths(RepositoryPaths): repository paths instance paths(RepositoryPaths): repository paths instance
uid(int): uid of the repository owner user uid(int): uid of the repository owner user
@ -52,42 +56,35 @@ class Task(LazyLogging):
""" """
self.package = package self.package = package
self.paths = paths self.paths = paths
_, self.architecture = configuration.check_loaded()
self.uid, _ = paths.root_owner self.uid, _ = paths.root_owner
self.name = configuration.get("repository", "name")
self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[])
self.build_command = configuration.get("build", "build_command") self.build_command = configuration.get("build", "build_command")
self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[]) self.build_flags = configuration.getlist("build", "pkgctl_flags", fallback=[])
self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
def build(self, sources_dir: Path, packager: str | None = None) -> list[Path]: def build(self, sources_dir: Path) -> list[Path]:
""" """
run package build run package build
Args: Args:
sources_dir(Path): path to where sources are sources_dir(Path): path to where sources are
packager(str | None, optional): optional packager override (Default value = None)
Returns: Returns:
list[Path]: paths of produced packages list[Path]: paths of produced packages
""" """
command = [self.build_command, "-r", str(self.paths.chroot)] command = [self.build_command, "build"] + self.build_flags
command.extend(self.archbuild_flags) command.extend(["--arch", self.architecture])
command.extend(["--"] + self.makechrootpkg_flags) command.extend(["--repo", self.name])
command.extend(["--"] + self.makepkg_flags)
self.logger.info("using %s for %s", command, self.package.base) self.logger.info("using %s for %s", command, self.package.base)
environment: dict[str, str] = {}
if packager is not None:
environment["PACKAGER"] = packager
self.logger.info("using environment variables %s", environment)
Task._check_output( Task._check_output(
*command, *command,
exception=BuildError(self.package.base), exception=BuildError(self.package.base),
cwd=sources_dir, cwd=sources_dir,
logger=self.logger, logger=self.logger,
user=self.uid, user=self.uid)
environment=environment)
# well it is not actually correct, but we can deal with it # well it is not actually correct, but we can deal with it
packages = Task._check_output( packages = Task._check_output(

View File

@ -38,7 +38,6 @@ class Configuration(configparser.RawConfigParser):
Required by dump and merging functions Required by dump and merging functions
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
architecture(str | None): repository architecture architecture(str | None): repository architecture
includes(list[Path]): list of includes which were read
path(Path | None): path to root configuration file path(Path | None): path to root configuration file
Examples: Examples:
@ -79,7 +78,6 @@ class Configuration(configparser.RawConfigParser):
}) })
self.architecture: str | None = None self.architecture: str | None = None
self.path: Path | None = None self.path: Path | None = None
self.includes: list[Path] = []
@property @property
def include(self) -> Path: def include(self) -> Path:
@ -101,16 +99,6 @@ class Configuration(configparser.RawConfigParser):
""" """
return self.getpath("settings", "logging") return self.getpath("settings", "logging")
@property
def repository_name(self) -> str:
"""
repository name as defined by configuration
Returns:
str: repository name from configuration
"""
return self.get("repository", "name")
@property @property
def repository_paths(self) -> RepositoryPaths: def repository_paths(self) -> RepositoryPaths:
""" """
@ -195,7 +183,7 @@ class Configuration(configparser.RawConfigParser):
} }
# pylint and mypy are too stupid to find these methods # pylint and mypy are too stupid to find these methods
# pylint: disable=missing-function-docstring,unused-argument # pylint: disable=missing-function-docstring,multiple-statements,unused-argument
def getlist(self, *args: Any, **kwargs: Any) -> list[str]: ... # type: ignore[empty-body] def getlist(self, *args: Any, **kwargs: Any) -> list[str]: ... # type: ignore[empty-body]
def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore[empty-body] def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore[empty-body]
@ -245,13 +233,11 @@ class Configuration(configparser.RawConfigParser):
""" """
load configuration includes load configuration includes
""" """
self.includes = [] # reset state
try: try:
for path in sorted(self.include.glob("*.ini")): for path in sorted(self.include.glob("*.ini")):
if path == self.logging_path: if path == self.logging_path:
continue # we don't want to load logging explicitly continue # we don't want to load logging explicitly
self.read(path) self.read(path)
self.includes.append(path)
except (FileNotFoundError, configparser.NoOptionError, configparser.NoSectionError): except (FileNotFoundError, configparser.NoOptionError, configparser.NoSectionError):
pass pass

View File

@ -134,11 +134,6 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"build": { "build": {
"type": "dict", "type": "dict",
"schema": { "schema": {
"archbuild_flags": {
"type": "list",
"coerce": "list",
"schema": {"type": "string"},
},
"build_command": { "build_command": {
"type": "string", "type": "string",
"required": True, "required": True,
@ -148,12 +143,7 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"coerce": "list", "coerce": "list",
"schema": {"type": "string"}, "schema": {"type": "string"},
}, },
"makepkg_flags": { "pkgctl_flags": {
"type": "list",
"coerce": "list",
"schema": {"type": "string"},
},
"makechrootpkg_flags": {
"type": "list", "type": "list",
"coerce": "list", "coerce": "list",
"schema": {"type": "string"}, "schema": {"type": "string"},
@ -163,11 +153,6 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"coerce": "list", "coerce": "list",
"schema": {"type": "string"}, "schema": {"type": "string"},
}, },
"triggers_known": {
"type": "list",
"coerce": "list",
"schema": {"type": "string"},
},
"vcs_allowed_age": { "vcs_allowed_age": {
"type": "integer", "type": "integer",
"coerce": "integer", "coerce": "integer",
@ -191,6 +176,10 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"sign": { "sign": {
"type": "dict", "type": "dict",
"allow_unknown": True, "allow_unknown": True,
"keysrules": {
"type": "string",
"anyof_regex": ["^target$", "^key$", "^key_.*"],
},
"schema": { "schema": {
"target": { "target": {
"type": "list", "type": "list",

View File

@ -144,24 +144,6 @@ class Validator(RootValidator):
if constraint and url.scheme not in constraint: if constraint and url.scheme not in constraint:
self._error(field, f"Url {value} scheme must be one of {constraint}") self._error(field, f"Url {value} scheme must be one of {constraint}")
def _validate_path_is_absolute(self, constraint: bool, field: str, value: Path) -> None:
"""
check if path is absolute or not
Args:
constraint(bool): True in case if path must be absolute and False if it must be relative
field(str): field name to be checked
value(Path): value to be checked
Examples:
The rule's arguments are validated against this schema:
{"type": "boolean"}
"""
if constraint and not value.is_absolute():
self._error(field, f"Path {value} must be absolute")
if not constraint and value.is_absolute():
self._error(field, f"Path {value} must be relative")
def _validate_path_exists(self, constraint: bool, field: str, value: Path) -> None: def _validate_path_exists(self, constraint: bool, field: str, value: Path) -> None:
""" """
check if paths exists check if paths exists
@ -177,5 +159,3 @@ class Validator(RootValidator):
""" """
if constraint and not value.exists(): if constraint and not value.exists():
self._error(field, f"Path {value} must exist") self._error(field, f"Path {value} must exist")
if not constraint and value.exists():
self._error(field, f"Path {value} must not exist")

View File

@ -1,80 +0,0 @@
#
# Copyright (c) 2021-2023 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from sqlite3 import Connection
from ahriman.core.alpm.pacman import Pacman
from ahriman.core.configuration import Configuration
from ahriman.core.util import package_like
from ahriman.models.package import Package
from ahriman.models.pacman_synchronization import PacmanSynchronization
__all__ = ["migrate_data", "steps"]
steps = [
"""
alter table packages add column check_depends json
""",
]
def migrate_data(connection: Connection, configuration: Configuration) -> None:
"""
perform data migration
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
migrate_package_check_depends(connection, configuration)
def migrate_package_check_depends(connection: Connection, configuration: Configuration) -> None:
"""
migrate package check depends fields
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
if not configuration.repository_paths.repository.is_dir():
return
_, architecture = configuration.check_loaded()
pacman = Pacman(architecture, configuration, refresh_database=PacmanSynchronization.Disabled)
package_list = []
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
base = Package.from_archive(full_path, pacman, remote=None)
for package, description in base.packages.items():
package_list.append({
"check_depends": description.check_depends,
"package": package,
})
connection.executemany(
"""
update packages set
check_depends = :check_depends
where package = :package
""",
package_list
)

View File

@ -1,85 +0,0 @@
#
# Copyright (c) 2021-2023 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from sqlite3 import Connection
from ahriman.core.alpm.pacman import Pacman
from ahriman.core.configuration import Configuration
from ahriman.core.util import package_like
from ahriman.models.package import Package
from ahriman.models.pacman_synchronization import PacmanSynchronization
__all__ = ["migrate_data", "steps"]
steps = [
"""
alter table users add column packager_id
""",
"""
alter table users add column key_id
""",
"""
alter table package_bases add column packager
""",
]
def migrate_data(connection: Connection, configuration: Configuration) -> None:
"""
perform data migration
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
migrate_package_base_packager(connection, configuration)
def migrate_package_base_packager(connection: Connection, configuration: Configuration) -> None:
"""
migrate package packager field
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
if not configuration.repository_paths.repository.is_dir():
return
_, architecture = configuration.check_loaded()
pacman = Pacman(architecture, configuration, refresh_database=PacmanSynchronization.Disabled)
package_list = []
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
package = Package.from_archive(full_path, pacman, remote=None)
package_list.append({
"package_base": package.base,
"packager": package.packager,
})
connection.executemany(
"""
update package_bases set
packager = :packager
where package_base = :package_base
""",
package_list
)

View File

@ -57,9 +57,8 @@ class AuthOperations(Operations):
def run(connection: Connection) -> list[User]: def run(connection: Connection) -> list[User]:
return [ return [
User(username=row["username"], password=row["password"], access=UserAccess(row["access"]), User(username=cursor["username"], password=cursor["password"], access=UserAccess(cursor["access"]))
packager_id=row["packager_id"], key=row["key_id"]) for cursor in connection.execute(
for row in connection.execute(
""" """
select * from users select * from users
where (:username is null or username = :username) and (:access is null or access = :access) where (:username is null or username = :username) and (:access is null or access = :access)
@ -92,13 +91,12 @@ class AuthOperations(Operations):
connection.execute( connection.execute(
""" """
insert into users insert into users
(username, access, password, packager_id, key_id) (username, access, password)
values values
(:username, :access, :password, :packager_id, :key_id) (:username, :access, :password)
on conflict (username) do update set on conflict (username) do update set
access = :access, password = :password, packager_id = :packager_id, key_id = :key_id access = :access, password = :password
""", """,
{"username": user.username.lower(), "access": user.access.value, "password": user.password, {"username": user.username.lower(), "access": user.access.value, "password": user.password})
"packager_id": user.packager_id, "key_id": user.key})
self.with_connection(run, commit=True) self.with_connection(run, commit=True)

View File

@ -76,12 +76,11 @@ class PackageOperations(Operations):
connection.execute( connection.execute(
""" """
insert into package_bases insert into package_bases
(package_base, version, source, branch, git_url, path, web_url, packager) (package_base, version, source, branch, git_url, path, web_url)
values values
(:package_base, :version, :source, :branch, :git_url, :path, :web_url, :packager) (:package_base, :version, :source, :branch, :git_url, :path, :web_url)
on conflict (package_base) do update set on conflict (package_base) do update set
version = :version, branch = :branch, git_url = :git_url, path = :path, web_url = :web_url, version = :version, branch = :branch, git_url = :git_url, path = :path, web_url = :web_url, source = :source
source = :source, packager = :packager
""", """,
{ {
"package_base": package.base, "package_base": package.base,
@ -91,7 +90,6 @@ class PackageOperations(Operations):
"path": package.remote.path if package.remote is not None else None, "path": package.remote.path if package.remote is not None else None,
"web_url": package.remote.web_url if package.remote is not None else None, "web_url": package.remote.web_url if package.remote is not None else None,
"source": package.remote.source.value if package.remote is not None else None, "source": package.remote.source.value if package.remote is not None else None,
"packager": package.packager,
} }
) )
@ -115,17 +113,17 @@ class PackageOperations(Operations):
(package, package_base, architecture, archive_size, (package, package_base, architecture, archive_size,
build_date, depends, description, filename, build_date, depends, description, filename,
"groups", installed_size, licenses, provides, "groups", installed_size, licenses, provides,
url, make_depends, opt_depends, check_depends) url, make_depends, opt_depends)
values values
(:package, :package_base, :architecture, :archive_size, (:package, :package_base, :architecture, :archive_size,
:build_date, :depends, :description, :filename, :build_date, :depends, :description, :filename,
:groups, :installed_size, :licenses, :provides, :groups, :installed_size, :licenses, :provides,
:url, :make_depends, :opt_depends, :check_depends) :url, :make_depends, :opt_depends)
on conflict (package, architecture) do update set on conflict (package, architecture) do update set
package_base = :package_base, archive_size = :archive_size, package_base = :package_base, archive_size = :archive_size,
build_date = :build_date, depends = :depends, description = :description, filename = :filename, build_date = :build_date, depends = :depends, description = :description, filename = :filename,
"groups" = :groups, installed_size = :installed_size, licenses = :licenses, provides = :provides, "groups" = :groups, installed_size = :installed_size, licenses = :licenses, provides = :provides,
url = :url, make_depends = :make_depends, opt_depends = :opt_depends, check_depends = :check_depends url = :url, make_depends = :make_depends, opt_depends = :opt_depends
""", """,
package_list) package_list)
@ -165,9 +163,8 @@ class PackageOperations(Operations):
base=row["package_base"], base=row["package_base"],
version=row["version"], version=row["version"],
remote=RemoteSource.from_json(row), remote=RemoteSource.from_json(row),
packages={}, packages={})
packager=row["packager"] or None, for row in connection.execute("""select * from package_bases""")
) for row in connection.execute("""select * from package_bases""")
} }
@staticmethod @staticmethod

View File

@ -77,8 +77,8 @@ class PatchOperations(Operations):
""" """
def run(connection: Connection) -> list[tuple[str, PkgbuildPatch]]: def run(connection: Connection) -> list[tuple[str, PkgbuildPatch]]:
return [ return [
(row["package_base"], PkgbuildPatch(row["variable"], row["patch"])) (cursor["package_base"], PkgbuildPatch(cursor["variable"], cursor["patch"]))
for row in connection.execute( for cursor in connection.execute(
"""select * from patches where :package_base is null or package_base = :package_base""", """select * from patches where :package_base is null or package_base = :package_base""",
{"package_base": package_base}) {"package_base": package_base})
] ]

View File

@ -194,18 +194,6 @@ class PasswordError(ValueError):
ValueError.__init__(self, f"Password error: {details}") ValueError.__init__(self, f"Password error: {details}")
class PkgbuildGeneratorError(RuntimeError):
"""
exception class for support type triggers
"""
def __init__(self) -> None:
"""
default constructor
"""
RuntimeError.__init__(self, "Could not generate package")
class ReportError(RuntimeError): class ReportError(RuntimeError):
""" """
report generation exception report generation exception

View File

@ -22,7 +22,6 @@ from ahriman.core.formatters.string_printer import StringPrinter
from ahriman.core.formatters.aur_printer import AurPrinter from ahriman.core.formatters.aur_printer import AurPrinter
from ahriman.core.formatters.build_printer import BuildPrinter from ahriman.core.formatters.build_printer import BuildPrinter
from ahriman.core.formatters.configuration_paths_printer import ConfigurationPathsPrinter
from ahriman.core.formatters.configuration_printer import ConfigurationPrinter from ahriman.core.formatters.configuration_printer import ConfigurationPrinter
from ahriman.core.formatters.package_printer import PackagePrinter from ahriman.core.formatters.package_printer import PackagePrinter
from ahriman.core.formatters.patch_printer import PatchPrinter from ahriman.core.formatters.patch_printer import PatchPrinter

View File

@ -1,52 +0,0 @@
#
# Copyright (c) 2021-2023 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from pathlib import Path
from ahriman.core.formatters import StringPrinter
from ahriman.models.property import Property
class ConfigurationPathsPrinter(StringPrinter):
"""
print configuration paths
Attributes:
includes(list[Path]): list of include files
"""
def __init__(self, root: Path, includes: list[Path]) -> None:
"""
default constructor
Args:
root(Path): path to root configuration file
includes(list[Path]): list of include files
"""
StringPrinter.__init__(self, str(root))
self.includes = includes
def properties(self) -> list[Property]:
"""
convert content into printable data
Returns:
list[Property]: list of content properties
"""
return [Property("Include", str(path), is_required=True) for path in self.includes]

View File

@ -44,13 +44,13 @@ class RemotePush(LazyLogging):
remote_source(RemoteSource): repository remote source (remote pull url and branch) remote_source(RemoteSource): repository remote source (remote pull url and branch)
""" """
def __init__(self, database: SQLite, configuration: Configuration, section: str) -> None: def __init__(self, configuration: Configuration, database: SQLite, section: str) -> None:
""" """
default constructor default constructor
Args: Args:
database(SQLite): database instance
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
database(SQLite): database instance
section(str): settings section name section(str): settings section name
""" """
self.database = database self.database = database

View File

@ -105,5 +105,5 @@ class RemotePushTrigger(Trigger):
for target in self.targets: for target in self.targets:
section, _ = self.configuration.gettype( section, _ = self.configuration.gettype(
target, self.architecture, fallback=self.CONFIGURATION_SCHEMA_FALLBACK) target, self.architecture, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
runner = RemotePush(database, self.configuration, section) runner = RemotePush(self.configuration, database, section)
runner.run(result) runner.run(result)

View File

@ -1,47 +0,0 @@
#
# Copyright (c) 2021-2023 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from logging import NullHandler
from typing import Any
__all__ = ["JournalHandler"]
class _JournalHandler(NullHandler):
"""
wrapper for unexpected args and kwargs
"""
def __init__(self, *args: Any, **kwargs: Any) -> None:
"""
default constructor
Args:
*args(Any): positional arguments
**kwargs(Any): keyword arguments
"""
NullHandler.__init__(self)
del args, kwargs
try:
from systemd.journal import JournalHandler # type: ignore[import]
except ImportError:
JournalHandler = _JournalHandler

View File

@ -21,24 +21,18 @@ import contextlib
import logging import logging
from collections.abc import Generator from collections.abc import Generator
from functools import cached_property
from typing import Any from typing import Any
class LazyLogging: class LazyLogging:
""" """
wrapper for the logger library inspired by scala lazy logging module wrapper for the logger library inspired by scala lazy logging module
Attributes:
logger(logging.Logger): class logger instance
""" """
@cached_property logger: logging.Logger
def logger(self) -> logging.Logger:
"""
get class logger instance
Returns:
logging.Logger: class logger instance
"""
return logging.getLogger(self.logger_name)
@property @property
def logger_name(self) -> str: def logger_name(self) -> str:
@ -95,3 +89,22 @@ class LazyLogging:
yield yield
finally: finally:
self._package_logger_reset() self._package_logger_reset()
def __getattr__(self, item: str) -> Any:
"""
logger extractor
Args:
item(str): property name
Returns:
Any: attribute by its name
Raises:
AttributeError: in case if no such attribute found
"""
if item == "logger":
logger = logging.getLogger(self.logger_name)
setattr(self, item, logger)
return logger
raise AttributeError(f"'{self.__class__.__qualname__}' object has no attribute '{item}'")

View File

@ -20,11 +20,9 @@
import logging import logging
from logging.config import fileConfig from logging.config import fileConfig
from pathlib import Path
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.log.http_log_handler import HttpLogHandler from ahriman.core.log.http_log_handler import HttpLogHandler
from ahriman.models.log_handler import LogHandler
class Log: class Log:
@ -34,65 +32,24 @@ class Log:
Attributes: Attributes:
DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback) DEFAULT_LOG_FORMAT(str): (class attribute) default log format (in case of fallback)
DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback) DEFAULT_LOG_LEVEL(int): (class attribute) default log level (in case of fallback)
DEFAULT_SYSLOG_DEVICE(Path): (class attribute) default path to syslog device
""" """
DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s" DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s"
DEFAULT_LOG_LEVEL = logging.DEBUG DEFAULT_LOG_LEVEL = logging.DEBUG
DEFAULT_SYSLOG_DEVICE = Path("/dev") / "log"
@staticmethod @staticmethod
def handler(selected: LogHandler | None) -> LogHandler: def load(configuration: Configuration, *, quiet: bool, report: bool) -> None:
"""
try to guess default log handler. In case if ``selected`` is set, it will return specified value with appended
_handler suffix. Otherwise, it will try to import journald handler and returns ``journald_handler`` if library
is available. Otherwise, it will check if there is ``/dev/log`` device and returns ``syslog_handler`` in this
case. And, finally, it will fall back to ``console_handler`` if none were found
Args:
selected(LogHandler | None): user specified handler if any
Returns:
LogHandler: selected log handler
"""
if selected is not None:
return selected
try:
from systemd.journal import JournalHandler # type: ignore[import]
del JournalHandler
return LogHandler.Journald # journald import was found
except ImportError:
if Log.DEFAULT_SYSLOG_DEVICE.exists():
return LogHandler.Syslog
return LogHandler.Console
@staticmethod
def load(configuration: Configuration, handler: LogHandler, *, quiet: bool, report: bool) -> None:
""" """
setup logging settings from configuration setup logging settings from configuration
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
handler(LogHandler): selected default log handler, which will be used if no handlers were set
quiet(bool): force disable any log messages quiet(bool): force disable any log messages
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
""" """
default_handler = f"{handler.value}_handler"
try: try:
log_configuration = Configuration() path = configuration.logging_path
log_configuration.read(configuration.logging_path) fileConfig(path)
# set handlers if they are not set
for section in filter(lambda s: s.startswith("logger_"), log_configuration.sections()):
if "handlers" in log_configuration[section]:
continue
log_configuration.set_option(section, "handlers", default_handler)
# load logging configuration
fileConfig(log_configuration, disable_existing_loggers=True)
logging.debug("using %s logger", default_handler)
except Exception: except Exception:
logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT, logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT,
level=Log.DEFAULT_LOG_LEVEL) level=Log.DEFAULT_LOG_LEVEL)

View File

@ -57,4 +57,4 @@ class HTML(Report, JinjaTemplate):
result(Result): build result result(Result): build result
""" """
html = self.make_html(Result(success=packages), self.template_path) html = self.make_html(Result(success=packages), self.template_path)
self.report_path.write_text(html, encoding="utf8") self.report_path.write_text(html)

View File

@ -75,7 +75,7 @@ class JinjaTemplate:
# base template vars # base template vars
self.homepage = configuration.get(section, "homepage", fallback=None) self.homepage = configuration.get(section, "homepage", fallback=None)
self.name = configuration.repository_name self.name = configuration.get("repository", "name")
self.sign_targets, self.default_pgp_key = GPG.sign_options(configuration) self.sign_targets, self.default_pgp_key = GPG.sign_options(configuration)

View File

@ -28,7 +28,6 @@ from ahriman.core.repository.cleaner import Cleaner
from ahriman.core.util import safe_filename from ahriman.core.util import safe_filename
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.package_description import PackageDescription from ahriman.models.package_description import PackageDescription
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result from ahriman.models.result import Result
@ -64,35 +63,30 @@ class Executor(Cleaner):
""" """
raise NotImplementedError raise NotImplementedError
def process_build(self, updates: Iterable[Package], packagers: Packagers | None = None) -> Result: def process_build(self, updates: Iterable[Package]) -> Result:
""" """
build packages build packages
Args: Args:
updates(Iterable[Package]): list of packages properties to build updates(Iterable[Package]): list of packages properties to build
packagers(Packagers | None, optional): optional override of username for build process
(Default value = None)
Returns: Returns:
Result: build result Result: build result
""" """
def build_single(package: Package, local_path: Path, packager_id: str | None) -> None: def build_single(package: Package, local_path: Path) -> None:
self.reporter.set_building(package.base) self.reporter.set_building(package.base)
task = Task(package, self.configuration, self.paths) task = Task(package, self.configuration, self.paths)
task.init(local_path, self.database) task.init(local_path, self.database)
built = task.build(local_path, packager_id) built = task.build(local_path)
for src in built: for src in built:
dst = self.paths.packages / src.name dst = self.paths.packages / src.name
shutil.move(src, dst) shutil.move(src, dst)
packagers = packagers or Packagers()
result = Result() result = Result()
for single in updates: for single in updates:
with self.in_package_context(single.base), TemporaryDirectory(ignore_cleanup_errors=True) as dir_name: with self.in_package_context(single.base), TemporaryDirectory(ignore_cleanup_errors=True) as dir_name:
try: try:
packager = self.packager(packagers, single.base) build_single(single, Path(dir_name))
build_single(single, Path(dir_name), packager.packager_id)
result.add_success(single) result.add_success(single)
except Exception: except Exception:
self.reporter.set_failed(single.base) self.reporter.set_failed(single.base)
@ -164,14 +158,12 @@ class Executor(Cleaner):
return self.repo.repo_path return self.repo.repo_path
def process_update(self, packages: Iterable[Path], packagers: Packagers | None = None) -> Result: def process_update(self, packages: Iterable[Path]) -> Result:
""" """
sign packages, add them to repository and update repository database sign packages, add them to repository and update repository database
Args: Args:
packages(Iterable[Path]): list of filenames to run packages(Iterable[Path]): list of filenames to run
packagers(Packagers | None, optional): optional override of username for build process
(Default value = None)
Returns: Returns:
Result: path to repository database Result: path to repository database
@ -184,13 +176,13 @@ class Executor(Cleaner):
shutil.move(self.paths.packages / archive.filename, self.paths.packages / safe) shutil.move(self.paths.packages / archive.filename, self.paths.packages / safe)
archive.filename = safe archive.filename = safe
def update_single(name: str | None, package_base: str, packager_key: str | None) -> None: def update_single(name: str | None, package_base: str) -> None:
if name is None: if name is None:
self.logger.warning("received empty package name for base %s", package_base) self.logger.warning("received empty package name for base %s", package_base)
return # suppress type checking, it never can be none actually return # suppress type checking, it never can be none actually
# in theory, it might be NOT packages directory, but we suppose it is # in theory, it might be NOT packages directory, but we suppose it is
full_path = self.paths.packages / name full_path = self.paths.packages / name
files = self.sign.process_sign_package(full_path, packager_key) files = self.sign.process_sign_package(full_path, package_base)
for src in files: for src in files:
dst = self.paths.repository / safe_filename(src.name) dst = self.paths.repository / safe_filename(src.name)
shutil.move(src, dst) shutil.move(src, dst)
@ -200,17 +192,14 @@ class Executor(Cleaner):
current_packages = self.packages() current_packages = self.packages()
removed_packages: list[str] = [] # list of packages which have been removed from the base removed_packages: list[str] = [] # list of packages which have been removed from the base
updates = self.load_archives(packages) updates = self.load_archives(packages)
packagers = packagers or Packagers()
result = Result() result = Result()
for local in updates: for local in updates:
with self.in_package_context(local.base): with self.in_package_context(local.base):
try: try:
packager = self.packager(packagers, local.base)
for description in local.packages.values(): for description in local.packages.values():
rename(description, local.base) rename(description, local.base)
update_single(description.filename, local.base, packager.key) update_single(description.filename, local.base)
self.reporter.set_success(local) self.reporter.set_success(local)
result.add_success(local) result.add_success(local)

View File

@ -47,7 +47,7 @@ class Repository(Executor, UpdateHandler):
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> database = SQLite.load(configuration) >>> database = SQLite.load(configuration)
>>> repository = Repository.load("x86_64", configuration, database, report=True) >>> repository = Repository.load("x86_64", configuration, database, report=True, unsafe=False)
>>> known_packages = repository.packages() >>> known_packages = repository.packages()
>>> >>>
>>> build_result = repository.process_build(known_packages) >>> build_result = repository.process_build(known_packages)
@ -58,7 +58,7 @@ class Repository(Executor, UpdateHandler):
""" """
@classmethod @classmethod
def load(cls, architecture: str, configuration: Configuration, database: SQLite, *, report: bool, def load(cls, architecture: str, configuration: Configuration, database: SQLite, *, report: bool, unsafe: bool,
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> Self: refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> Self:
""" """
load instance from argument list load instance from argument list
@ -68,6 +68,7 @@ class Repository(Executor, UpdateHandler):
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
database(SQLite): database instance database(SQLite): database instance
report(bool): force enable or disable reporting report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level
(Default value = PacmanSynchronization.Disabled) (Default value = PacmanSynchronization.Disabled)
@ -75,7 +76,7 @@ class Repository(Executor, UpdateHandler):
Self: fully loaded repository class instance Self: fully loaded repository class instance
""" """
instance = cls(architecture, configuration, database, instance = cls(architecture, configuration, database,
report=report, refresh_pacman_database=refresh_pacman_database) report=report, unsafe=unsafe, refresh_pacman_database=refresh_pacman_database)
instance._set_context() instance._set_context()
return instance return instance

Some files were not shown because too many files have changed in this diff Show More