mirror of
https://github.com/arcan1s/ahriman.git
synced 2026-01-26 07:59:47 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 799dc73d8a | |||
| 4e79cbf71a | |||
| 4fa5d55317 | |||
| a7fa3b90e4 | |||
| ce07cda8ab | |||
| 00c4f32294 | |||
| 49cf91ea52 | |||
| 4a8430dc67 | |||
| 46af782db2 | |||
| 6443e02352 | |||
| 999ad39d6f | |||
| dfab5f56b2 | |||
| 10798b9ba3 | |||
| 358e3dc4d2 | |||
| c13cd029bc | |||
| ae32cc8fbb | |||
| dff5b775a9 | |||
| db3f20546e | |||
| 53368468a4 | |||
| 228c2cce51 | |||
| f5aec4e5c1 | |||
| 9217c8c759 | |||
| 6392520e06 | |||
| c6306631e6 | |||
| 97b906c536 | |||
| 435375721d | |||
| 4c5caba6b7 | |||
| b83df9d2c5 | |||
| f2ea76aab9 | |||
| 471b1c1331 | |||
| bd770aac2f | |||
| 6abe35ef8c | |||
| fdc27a9ebf | |||
| b729096a25 | |||
| 390b9da29e | |||
| 256376df85 | |||
| 939a94d889 |
1
.github/workflows/docker.yml
vendored
1
.github/workflows/docker.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
tags:
|
||||
- '*'
|
||||
- '!*rc*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -215,6 +215,7 @@ Again, the most checks can be performed by `tox` command, though some additional
|
||||
* It is allowed to change web API to add new fields or remove optional ones. However, in case of model changes, new API version must be introduced.
|
||||
* On the other hand, it is allowed to change method signatures, however, it is recommended to add new parameters as optional if possible. Deprecated API can be dropped during major release.
|
||||
* Enumerations (`Enum` classes) are allowed and recommended. However, it is recommended to use `StrEnum` class if there are from/to string conversions and `IntEnum` otherwise.
|
||||
* `Generator` return type is not allowed. Generator functions must return generic `Iterator` object. Documentation should be described as `Yields`, however, because of pylint checks. Unfortunately, `Iterable` return type is not available for generators also, because of specific `contextlib.contextmanager` case.
|
||||
|
||||
### Other checks
|
||||
|
||||
|
||||
@@ -100,6 +100,14 @@ ahriman.application.handlers.rebuild module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.reload module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.application.handlers.reload
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.remove module
|
||||
------------------------------------------
|
||||
|
||||
|
||||
21
docs/ahriman.core.housekeeping.rst
Normal file
21
docs/ahriman.core.housekeeping.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
ahriman.core.housekeeping package
|
||||
=================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.core.housekeeping.logs\_rotation\_trigger module
|
||||
--------------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.housekeeping.logs_rotation_trigger
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.core.housekeeping
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -15,6 +15,7 @@ Subpackages
|
||||
ahriman.core.distributed
|
||||
ahriman.core.formatters
|
||||
ahriman.core.gitremote
|
||||
ahriman.core.housekeeping
|
||||
ahriman.core.http
|
||||
ahriman.core.log
|
||||
ahriman.core.report
|
||||
|
||||
@@ -44,6 +44,14 @@ ahriman.web.schemas.changes\_schema module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.configuration\_schema module
|
||||
------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.configuration_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.counters\_schema module
|
||||
-------------------------------------------
|
||||
|
||||
@@ -140,6 +148,14 @@ ahriman.web.schemas.logs\_schema module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.logs\_search\_schema module
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.logs_search_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.oauth2\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
|
||||
@@ -12,6 +12,14 @@ ahriman.web.views.v1.service.add module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.config module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.config
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.logs module
|
||||
----------------------------------------
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ This package contains everything required for the most of application actions an
|
||||
* ``ahriman.core.distributed`` package with triggers and helpers for distributed build system.
|
||||
* ``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.housekeeping`` package provides few triggers for removing old data.
|
||||
* ``ahriman.core.http`` package provides HTTP clients which can be used later by other classes.
|
||||
* ``ahriman.core.log`` is a log utils package. It includes logger loader class, custom HTTP based logger and some wrappers.
|
||||
* ``ahriman.core.report`` is a package with reporting triggers. Should not be called directly.
|
||||
|
||||
@@ -65,6 +65,8 @@ will try to read value from ``SECRET`` environment variable. In case if the requ
|
||||
|
||||
will eventually lead ``key`` option in section ``section1`` to be set to the value of ``HOME`` environment variable (if available).
|
||||
|
||||
Moreover, configuration can be read from environment variables directly by following the same naming convention, e.g. in the example above, one can have environment variable named ``section1:key`` (e.g. ``section1:key=$HOME``) and it will be substituted to the configuration with the highest priority.
|
||||
|
||||
There is also additional subcommand which will allow to validate configuration and print found errors. In order to do so, run ``service-config-validate`` subcommand, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
@@ -81,7 +83,6 @@ Base configuration settings.
|
||||
* ``apply_migrations`` - perform database migrations on the application start, boolean, optional, default ``yes``. Useful if you are using git version. Note, however, that this option must be changed only if you know what to do and going to handle migrations manually.
|
||||
* ``database`` - path to the application SQLite database, string, required.
|
||||
* ``include`` - path to directory with configuration files overrides, string, optional. Files will be read in alphabetical order.
|
||||
* ``keep_last_logs`` - amount of build logs to be kept for each package, integer, optional ,default ``0``. Logs will be cleared at the end of each process.
|
||||
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
|
||||
|
||||
``alpm:*`` groups
|
||||
@@ -168,6 +169,7 @@ Reporting to web service related settings. In most cases there is fallback to we
|
||||
Web server settings. This feature requires ``aiohttp`` libraries to be installed.
|
||||
|
||||
* ``address`` - optional address in form ``proto://host:port`` (``port`` can be omitted in case of default ``proto`` ports), will be used instead of ``http://{host}:{port}`` in case if set, string, optional. This option is required in case if ``OAuth`` provider is used.
|
||||
* ``autorefresh_intervals`` - enable page auto refresh options, space separated list of integers, optional. The first defined interval will be used as default. If no intervals set, the auto refresh buttons will be disabled. If first element of the list equals ``0``, auto refresh will be disabled by default.
|
||||
* ``enable_archive_upload`` - allow to upload packages via HTTP (i.e. call of ``/api/v1/service/upload`` uri), boolean, optional, default ``no``.
|
||||
* ``host`` - host to bind, string, optional.
|
||||
* ``index_url`` - full URL of the repository index page, string, optional.
|
||||
@@ -181,7 +183,7 @@ Web server settings. This feature requires ``aiohttp`` libraries to be installed
|
||||
* ``wait_timeout`` - wait timeout in seconds, maximum amount of time to be waited before lock will be free, integer, optional.
|
||||
|
||||
``keyring`` group
|
||||
--------------------
|
||||
-----------------
|
||||
|
||||
Keyring package generator plugin.
|
||||
|
||||
@@ -199,6 +201,13 @@ Keyring generator plugin
|
||||
* ``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.
|
||||
|
||||
``housekeeping`` group
|
||||
----------------------
|
||||
|
||||
This section describes settings for the ``ahriman.core.housekeeping.LogsRotationTrigger`` plugin.
|
||||
|
||||
* ``keep_last_logs`` - amount of build logs to be kept for each package, integer, optional ,default ``0``. Logs will be cleared at the end of each process.
|
||||
|
||||
``mirrorlist`` group
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
pkgbase='ahriman'
|
||||
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
||||
pkgver=2.19.3
|
||||
pkgver=2.19.0
|
||||
pkgrel=1
|
||||
pkgdesc="ArcH linux ReposItory MANager"
|
||||
arch=('any')
|
||||
@@ -40,6 +40,7 @@ package_ahriman-core() {
|
||||
'rsync: sync by using rsync')
|
||||
install="$pkgbase.install"
|
||||
backup=('etc/ahriman.ini'
|
||||
'etc/ahriman.ini.d/00-housekeeping.ini'
|
||||
'etc/ahriman.ini.d/logging.ini')
|
||||
|
||||
cd "$pkgbase-$pkgver"
|
||||
@@ -49,6 +50,7 @@ package_ahriman-core() {
|
||||
|
||||
# keep usr/share configs as reference and copy them to /etc
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini.d/00-housekeeping.ini" "$pkgdir/etc/ahriman.ini.d/00-housekeeping.ini"
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgbase/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
|
||||
|
||||
install -Dm644 "$srcdir/$pkgbase.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgbase.conf"
|
||||
|
||||
@@ -5,6 +5,7 @@ After=network.target
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/ahriman web
|
||||
ExecReload=/usr/bin/ahriman web-reload
|
||||
User=ahriman
|
||||
Group=ahriman
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ logging = ahriman.ini.d/logging.ini
|
||||
;apply_migrations = yes
|
||||
; Path to the application SQLite database.
|
||||
database = ${repository:root}/ahriman.db
|
||||
; Keep last build logs for each package
|
||||
keep_last_logs = 5
|
||||
|
||||
[alpm]
|
||||
; Path to pacman system database cache.
|
||||
@@ -45,9 +43,11 @@ triggers[] = ahriman.core.gitremote.RemotePullTrigger
|
||||
triggers[] = ahriman.core.report.ReportTrigger
|
||||
triggers[] = ahriman.core.upload.UploadTrigger
|
||||
triggers[] = ahriman.core.gitremote.RemotePushTrigger
|
||||
triggers[] = ahriman.core.housekeeping.LogsRotationTrigger
|
||||
; List of well-known triggers. Used only for configuration purposes.
|
||||
triggers_known[] = ahriman.core.gitremote.RemotePullTrigger
|
||||
triggers_known[] = ahriman.core.gitremote.RemotePushTrigger
|
||||
triggers_known[] = ahriman.core.housekeeping.LogsRotationTrigger
|
||||
triggers_known[] = ahriman.core.report.ReportTrigger
|
||||
triggers_known[] = ahriman.core.upload.UploadTrigger
|
||||
; Maximal age in seconds of the VCS packages before their version will be updated with its remote source.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[logs-rotation]
|
||||
; Keep last build logs for each package
|
||||
keep_last_logs = 5
|
||||
@@ -28,6 +28,10 @@ allow_read_only = yes
|
||||
; External address of the web service. Will be used for some features like OAuth. If none set will be generated as
|
||||
; address = http://${web:host}:${web:port}
|
||||
;address = http://${web:host}:${web:port}
|
||||
; Enable page auto refresh. Intervals are given in seconds. Default interval is always the first element of the list.
|
||||
; If no intervals set, auto refresh will be disabled. 0 can only be the first element and will disable auto refresh
|
||||
; by default.
|
||||
autorefresh_intervals = 5 1 10 30 60
|
||||
; Enable file upload endpoint used by some triggers.
|
||||
;enable_archive_upload = no
|
||||
; Address to bind the server.
|
||||
|
||||
@@ -80,10 +80,28 @@
|
||||
<button type="button" class="btn btn-secondary" onclick="reload()">
|
||||
<i class="bi bi-arrow-clockwise"></i><span class="d-none d-sm-inline"> reload</span>
|
||||
</button>
|
||||
|
||||
{% if autorefresh_intervals %}
|
||||
<div class="btn-group">
|
||||
<input id="table-autoreload-button" type="checkbox" class="btn-check" autocomplete="off" onclick="toggleTableAutoReload()" checked>
|
||||
<label for="table-autoreload-button" class="btn btn-outline-secondary" title="toggle auto reload"><i class="bi bi-clock"></i></label>
|
||||
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="visually-hidden">select interval</span>
|
||||
</button>
|
||||
<ul id="table-autoreload-input" class="dropdown-menu">
|
||||
{% for interval in autorefresh_intervals %}
|
||||
<li><a class="dropdown-item {{ "active" if interval.is_active }}" onclick="toggleTableAutoReload({{ interval.interval }})" data-interval="{{ interval.interval }}">{{ interval.text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<table id="packages"
|
||||
data-classes="table table-hover"
|
||||
data-cookie="true"
|
||||
data-cookie-id-table="ahriman-packages"
|
||||
data-cookie-storage="localStorage"
|
||||
data-export-options='{"fileName": "packages"}'
|
||||
data-filter-control="true"
|
||||
data-filter-control-visible="false"
|
||||
@@ -102,8 +120,8 @@
|
||||
data-sortable="true"
|
||||
data-sort-name="base"
|
||||
data-sort-order="asc"
|
||||
data-toggle="table"
|
||||
data-toolbar="#toolbar">
|
||||
data-toolbar="#toolbar"
|
||||
data-unique-id="id">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-checkbox="true"></th>
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
function createAlert(title, message, clz, action, id) {
|
||||
id ??= md5(title + message); // MD5 id from the content
|
||||
if (alertPlaceholder.querySelector(`#alert-${id}`)) return; // check if there are duplicates
|
||||
if (alertPlaceholder.querySelector(`#alert-${id}`)) {
|
||||
return; // check if there are duplicates
|
||||
}
|
||||
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.id = `alert-${id}`;
|
||||
|
||||
@@ -51,6 +51,87 @@
|
||||
const dashboardPackagesCountChartCanvas = document.getElementById("dashboard-packages-count-chart");
|
||||
let dashboardPackagesCountChart = null;
|
||||
|
||||
function statusLoad() {
|
||||
const badgeClass = status => {
|
||||
if (status === "pending") return "btn-outline-warning";
|
||||
if (status === "building") return "btn-outline-warning";
|
||||
if (status === "failed") return "btn-outline-danger";
|
||||
if (status === "success") return "btn-outline-success";
|
||||
return "btn-outline-secondary";
|
||||
};
|
||||
|
||||
makeRequest(
|
||||
"/api/v1/status",
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
versionBadge.innerHTML = `<i class="bi bi-github"></i> ahriman ${safe(data.version)}`;
|
||||
|
||||
dashboardButton.classList.remove(...dashboardButton.classList);
|
||||
dashboardButton.classList.add("btn");
|
||||
dashboardButton.classList.add(badgeClass(data.status.status));
|
||||
|
||||
dashboardModalHeader.classList.remove(...dashboardModalHeader.classList);
|
||||
dashboardModalHeader.classList.add("modal-header");
|
||||
headerClass(data.status.status).forEach(clz => dashboardModalHeader.classList.add(clz));
|
||||
|
||||
dashboardName.textContent = data.repository;
|
||||
dashboardArchitecture.textContent = data.architecture;
|
||||
dashboardStatus.textContent = data.status.status;
|
||||
dashboardStatusTimestamp.textContent = new Date(1000 * data.status.timestamp).toISOStringShort();
|
||||
|
||||
if (dashboardPackagesStatusesChart) {
|
||||
const labels = [
|
||||
"unknown",
|
||||
"pending",
|
||||
"building",
|
||||
"failed",
|
||||
"success",
|
||||
];
|
||||
dashboardPackagesStatusesChart.config.data = {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: "packages in status",
|
||||
data: labels.map(label => data.packages[label]),
|
||||
backgroundColor: [
|
||||
"rgb(55, 58, 60)",
|
||||
"rgb(255, 117, 24)",
|
||||
"rgb(255, 117, 24)",
|
||||
"rgb(255, 0, 57)",
|
||||
"rgb(63, 182, 24)", // copy-paste from current style
|
||||
],
|
||||
}],
|
||||
};
|
||||
dashboardPackagesStatusesChart.update();
|
||||
}
|
||||
|
||||
if (dashboardPackagesCountChart) {
|
||||
dashboardPackagesCountChart.config.data = {
|
||||
labels: ["packages"],
|
||||
datasets: [
|
||||
{
|
||||
label: "archives",
|
||||
data: [data.stats.packages],
|
||||
},
|
||||
{
|
||||
label: "bases",
|
||||
data: [data.stats.bases],
|
||||
},
|
||||
],
|
||||
};
|
||||
dashboardPackagesCountChart.update();
|
||||
}
|
||||
|
||||
dashboardCanvas.hidden = data.status.total > 0;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
ready(_ => {
|
||||
dashboardPackagesStatusesChart = new Chart(dashboardPackagesStatusesChartCanvas, {
|
||||
type: "pie",
|
||||
|
||||
@@ -148,8 +148,19 @@
|
||||
|
||||
packageAddInput.addEventListener("keyup", _ => {
|
||||
clearTimeout(packageAddInput.requestTimeout);
|
||||
|
||||
// do not update datalist if search string didn't change yet
|
||||
const value = packageAddInput.value;
|
||||
const previousValue = packageAddInput.dataset.previousValue;
|
||||
if (value === previousValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
// store current search string in attributes
|
||||
packageAddInput.dataset.previousValue = value;
|
||||
|
||||
// perform data list update
|
||||
packageAddInput.requestTimeout = setTimeout(_ => {
|
||||
const value = packageAddInput.value;
|
||||
|
||||
if (value.length >= 3) {
|
||||
makeRequest(
|
||||
|
||||
@@ -80,8 +80,7 @@
|
||||
data-classes="table table-hover"
|
||||
data-sortable="true"
|
||||
data-sort-name="timestamp"
|
||||
data-sort-order="desc"
|
||||
data-toggle="table">
|
||||
data-sort-order="desc">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-align="right" data-field="timestamp">date</th>
|
||||
@@ -98,10 +97,24 @@
|
||||
<input id="package-info-refresh-input" type="checkbox" class="form-check-input" value="" checked>
|
||||
<label for="package-info-refresh-input" class="form-check-label">update pacman databases</label>
|
||||
|
||||
<button id="package-info-update-button" type="submit" class="btn btn-success" onclick="packageInfoUpdate()" data-bs-dismiss="modal"><i class="bi bi-play"></i><span class="d-none d-sm-inline"> update</span></button>
|
||||
<button id="package-info-update-button" type="submit" class="btn btn-success" onclick="packageInfoUpdate()"><i class="bi bi-play"></i><span class="d-none d-sm-inline"> update</span></button>
|
||||
<button id="package-info-remove-button" type="submit" class="btn btn-danger" onclick="packageInfoRemove()" data-bs-dismiss="modal"><i class="bi bi-trash"></i><span class="d-none d-sm-inline"> remove</span></button>
|
||||
{% endif %}
|
||||
<button type="button" class="btn btn-secondary" onclick="showPackageInfo()"><i class="bi bi-arrow-clockwise"></i><span class="d-none d-sm-inline"> reload</span></button>
|
||||
{% if autorefresh_intervals %}
|
||||
<button type="button" class="btn btn-secondary" onclick="showPackageInfo()"><i class="bi bi-arrow-clockwise"></i><span class="d-none d-sm-inline"> reload</span></button>
|
||||
<div class="btn-group dropup">
|
||||
<input id="package-info-autoreload-button" type="checkbox" class="btn-check" autocomplete="off" onclick="togglePackageInfoAutoReload()" checked>
|
||||
<label for="package-info-autoreload-button" class="btn btn-outline-secondary" title="toggle auto reload"><i class="bi bi-clock"></i></label>
|
||||
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="visually-hidden">select interval</span>
|
||||
</button>
|
||||
<ul id="package-info-autoreload-input" class="dropdown-menu">
|
||||
{% for interval in autorefresh_intervals %}
|
||||
<li><a class="dropdown-item {{ "active" if interval.is_active }}" onclick="togglePackageInfoAutoReload({{ interval.interval }})" data-interval="{{ interval.interval }}">{{ interval.text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i><span class="d-none d-sm-inline"> close</span></button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,6 +153,10 @@
|
||||
|
||||
const packageInfoRefreshInput = document.getElementById("package-info-refresh-input");
|
||||
|
||||
const packageInfoAutoReloadButton = document.getElementById("package-info-autoreload-button");
|
||||
const packageInfoAutoReloadInput = document.getElementById("package-info-autoreload-input");
|
||||
let packageInfoAutoReloadTask = null;
|
||||
|
||||
function clearChart() {
|
||||
packageInfoEventsUpdateChartCanvas.hidden = true;
|
||||
if (packageInfoEventsUpdateChart) {
|
||||
@@ -148,6 +165,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function convertLogs(data, filter) {
|
||||
return data
|
||||
.filter((filter || Boolean))
|
||||
.map(log_record => `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
async function copyChanges() {
|
||||
const changes = packageInfoChangesInput.textContent;
|
||||
await copyToClipboard(changes, packageInfoChangesCopyButton);
|
||||
@@ -291,6 +315,69 @@
|
||||
}
|
||||
|
||||
function loadLogs(packageBase, onFailure) {
|
||||
const sortFn = (left, right) => left.process_id.localeCompare(right.process_id) || left.version.localeCompare(right.version);
|
||||
const compareFn = (left, right) => left.process_id === right.process_id && left.version === right.version;
|
||||
|
||||
makeRequest(
|
||||
`/api/v2/packages/${packageBase}/logs`,
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
head: true,
|
||||
repository: repository.repository,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
const currentVersions = Array.from(packageInfoLogsVersions.children)
|
||||
.map(el => {
|
||||
return {
|
||||
process_id: el.dataset.processId,
|
||||
version: el.dataset.version,
|
||||
};
|
||||
})
|
||||
.sort(sortFn);
|
||||
const newVersions = data
|
||||
.map(el => {
|
||||
return {
|
||||
process_id: el.process_id,
|
||||
version: el.version,
|
||||
};
|
||||
})
|
||||
.sort(sortFn);
|
||||
|
||||
if (currentVersions.equals(newVersions, compareFn))
|
||||
loadLogsActive(packageBase);
|
||||
else
|
||||
loadLogsAll(packageBase, onFailure);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
function loadLogsActive(packageBase) {
|
||||
const activeLogSelector = packageInfoLogsVersions.querySelector(".active");
|
||||
|
||||
if (activeLogSelector) {
|
||||
makeRequest(
|
||||
`/api/v2/packages/${packageBase}/logs`,
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
version: activeLogSelector.dataset.version,
|
||||
process_id: activeLogSelector.dataset.processId,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
activeLogSelector.dataset.logs = convertLogs(data);
|
||||
activeLogSelector.click();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function loadLogsAll(packageBase, onFailure) {
|
||||
makeRequest(
|
||||
`/api/v2/packages/${packageBase}/logs`,
|
||||
{
|
||||
@@ -319,15 +406,19 @@
|
||||
const link = document.createElement("a");
|
||||
link.classList.add("dropdown-item");
|
||||
|
||||
link.dataset.version = version.version;
|
||||
link.dataset.processId = version.process_id;
|
||||
link.dataset.logs = convertLogs(data, log_record => log_record.version === version.version && log_record.process_id === version.process_id);
|
||||
|
||||
link.textContent = new Date(1000 * version.created).toISOStringShort();
|
||||
link.href = "#";
|
||||
link.onclick = _ => {
|
||||
const logs = data
|
||||
.filter(log_record => log_record.version === version.version && log_record.process_id === version.process_id)
|
||||
.map(log_record => `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`);
|
||||
|
||||
packageInfoLogsInput.textContent = logs.join("\n");
|
||||
// check if we are at the bottom of the code block
|
||||
const isScrolledToBottom = packageInfoLogsInput.scrollTop + packageInfoLogsInput.clientHeight >= packageInfoLogsInput.scrollHeight;
|
||||
packageInfoLogsInput.textContent = link.dataset.logs;
|
||||
highlight(packageInfoLogsInput);
|
||||
if (isScrolledToBottom)
|
||||
packageInfoLogsInput.scrollTop = packageInfoLogsInput.scrollHeight; // scroll to the new end
|
||||
|
||||
Array.from(packageInfoLogsVersions.children).forEach(el => el.classList.remove("active"));
|
||||
link.classList.add("active");
|
||||
@@ -403,12 +494,12 @@
|
||||
}
|
||||
|
||||
function packageInfoRemove() {
|
||||
const packageBase = packageInfoModal.package;
|
||||
const packageBase = packageInfoModal.dataset.package;
|
||||
packagesRemove([packageBase]);
|
||||
}
|
||||
|
||||
function packageInfoUpdate() {
|
||||
const packageBase = packageInfoModal.package;
|
||||
const packageBase = packageInfoModal.dataset.package;
|
||||
packagesAdd(packageBase, [], repository, {refresh: packageInfoRefreshInput.checked});
|
||||
}
|
||||
|
||||
@@ -416,10 +507,10 @@
|
||||
const isPackageBaseSet = packageBase !== undefined;
|
||||
if (isPackageBaseSet) {
|
||||
// set package base as currently used
|
||||
packageInfoModal.package = packageBase;
|
||||
packageInfoModal.dataset.package = packageBase;
|
||||
} else {
|
||||
// read package base from the current window attribute
|
||||
packageBase = packageInfoModal.package;
|
||||
packageBase = packageInfoModal.dataset.package;
|
||||
}
|
||||
|
||||
const onFailure = error => {
|
||||
@@ -438,10 +529,27 @@
|
||||
|
||||
if (isPackageBaseSet) {
|
||||
bootstrap.Modal.getOrCreateInstance(packageInfoModal).show();
|
||||
{% if autorefresh_intervals %}
|
||||
togglePackageInfoAutoReload();
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
|
||||
function togglePackageInfoAutoReload(interval) {
|
||||
clearInterval(packageInfoAutoReloadTask);
|
||||
packageInfoAutoReloadTask = toggleAutoReload(packageInfoAutoReloadButton, interval, packageInfoAutoReloadInput, _ => {
|
||||
if (!hasActiveSelection()) {
|
||||
const packageBase = packageInfoModal.dataset.package;
|
||||
// we only poll status and logs here
|
||||
loadPackage(packageBase);
|
||||
loadLogs(packageBase);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ready(_ => {
|
||||
packageInfoEventsTable.bootstrapTable({});
|
||||
|
||||
packageInfoEventsUpdateChart = new Chart(packageInfoEventsUpdateChartCanvas, {
|
||||
type: "line",
|
||||
data: {},
|
||||
@@ -468,6 +576,11 @@
|
||||
packageInfoChangesInput.textContent = "";
|
||||
packageInfoEventsTable.bootstrapTable("load", []);
|
||||
clearChart();
|
||||
|
||||
clearInterval(packageInfoAutoReloadTask);
|
||||
packageInfoAutoReloadTask = null; // not really required (?) but lets clear everything
|
||||
});
|
||||
|
||||
restoreAutoReloadSettings(packageInfoAutoReloadButton, packageInfoAutoReloadInput);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
const dashboardButton = document.getElementById("dashboard-button");
|
||||
const versionBadge = document.getElementById("badge-version");
|
||||
|
||||
const tableAutoReloadButton = document.getElementById("table-autoreload-button");
|
||||
const tableAutoReloadInput = document.getElementById("table-autoreload-input");
|
||||
let tableAutoReloadTask = null;
|
||||
|
||||
function doPackageAction(uri, packages, repository, successText, failureText, data) {
|
||||
makeRequest(
|
||||
uri,
|
||||
@@ -55,6 +59,41 @@
|
||||
return table.bootstrapTable("getSelections").map(row => row.id);
|
||||
}
|
||||
|
||||
function packagesLoad(onFailure) {
|
||||
makeRequest(
|
||||
"/api/v1/packages",
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
const payload = data
|
||||
.map(description => {
|
||||
const package_base = description.package.base;
|
||||
const web_url = description.package.remote.web_url;
|
||||
return {
|
||||
id: package_base,
|
||||
base: web_url ? safeLink(web_url, package_base, package_base).outerHTML : safe(package_base),
|
||||
version: safe(description.package.version),
|
||||
packager: description.package.packager ? safe(description.package.packager) : "",
|
||||
packages: listToTable(Object.keys(description.package.packages)),
|
||||
groups: listToTable(extractListProperties(description.package, "groups")),
|
||||
licenses: listToTable(extractListProperties(description.package, "licenses")),
|
||||
timestamp: new Date(1000 * description.status.timestamp).toISOStringShort(),
|
||||
status: description.status.status,
|
||||
};
|
||||
});
|
||||
|
||||
updateTable(table, payload);
|
||||
table.bootstrapTable("hideLoading");
|
||||
},
|
||||
onFailure,
|
||||
);
|
||||
}
|
||||
|
||||
function packagesRemove(packages) {
|
||||
packages = packages ?? getSelection();
|
||||
const onSuccess = update => `Packages ${update} have been removed`;
|
||||
@@ -88,130 +127,22 @@
|
||||
|
||||
function reload() {
|
||||
table.bootstrapTable("showLoading");
|
||||
|
||||
const badgeClass = status => {
|
||||
if (status === "pending") return "btn-outline-warning";
|
||||
if (status === "building") return "btn-outline-warning";
|
||||
if (status === "failed") return "btn-outline-danger";
|
||||
if (status === "success") return "btn-outline-success";
|
||||
return "btn-outline-secondary";
|
||||
const onFailure = error => {
|
||||
if ((error.status === 401) || (error.status === 403)) {
|
||||
// authorization error
|
||||
const text = "In order to see statuses you must login first.";
|
||||
table.find("tr.unauthorized").remove();
|
||||
table.find("tbody").append(`<tr class="unauthorized"><td colspan="100%">${safe(text)}</td></tr>`);
|
||||
table.bootstrapTable("hideLoading");
|
||||
} else {
|
||||
// other errors
|
||||
const message = details => `Could not load list of packages: ${details}`;
|
||||
showFailure("Load failure", message, error);
|
||||
}
|
||||
};
|
||||
|
||||
makeRequest(
|
||||
"/api/v1/packages",
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
const payload = data.map(description => {
|
||||
const package_base = description.package.base;
|
||||
const web_url = description.package.remote.web_url;
|
||||
return {
|
||||
id: package_base,
|
||||
base: web_url ? safeLink(web_url, package_base, package_base).outerHTML : safe(package_base),
|
||||
version: safe(description.package.version),
|
||||
packager: description.package.packager ? safe(description.package.packager) : "",
|
||||
packages: listToTable(Object.keys(description.package.packages)),
|
||||
groups: listToTable(extractListProperties(description.package, "groups")),
|
||||
licenses: listToTable(extractListProperties(description.package, "licenses")),
|
||||
timestamp: new Date(1000 * description.status.timestamp).toISOStringShort(),
|
||||
status: description.status.status,
|
||||
};
|
||||
});
|
||||
|
||||
table.bootstrapTable("load", payload);
|
||||
table.bootstrapTable("uncheckAll");
|
||||
table.bootstrapTable("hideLoading");
|
||||
},
|
||||
error => {
|
||||
if ((error.status === 401) || (error.status === 403)) {
|
||||
// authorization error
|
||||
const text = "In order to see statuses you must login first.";
|
||||
table.find("tr.unauthorized").remove();
|
||||
table.find("tbody").append(`<tr class="unauthorized"><td colspan="100%">${safe(text)}</td></tr>`);
|
||||
table.bootstrapTable("hideLoading");
|
||||
} else {
|
||||
// other errors
|
||||
const message = details => `Could not load list of packages: ${details}`;
|
||||
showFailure("Load failure", message, error);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
makeRequest(
|
||||
"/api/v1/status",
|
||||
{
|
||||
query: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
convert: response => response.json(),
|
||||
},
|
||||
data => {
|
||||
versionBadge.innerHTML = `<i class="bi bi-github"></i> ahriman ${safe(data.version)}`;
|
||||
|
||||
dashboardButton.classList.remove(...dashboardButton.classList);
|
||||
dashboardButton.classList.add("btn");
|
||||
dashboardButton.classList.add(badgeClass(data.status.status));
|
||||
|
||||
dashboardModalHeader.classList.remove(...dashboardModalHeader.classList);
|
||||
dashboardModalHeader.classList.add("modal-header");
|
||||
headerClass(data.status.status).forEach(clz => dashboardModalHeader.classList.add(clz));
|
||||
|
||||
dashboardName.textContent = data.repository;
|
||||
dashboardArchitecture.textContent = data.architecture;
|
||||
dashboardStatus.textContent = data.status.status;
|
||||
dashboardStatusTimestamp.textContent = new Date(1000 * data.status.timestamp).toISOStringShort();
|
||||
|
||||
if (dashboardPackagesStatusesChart) {
|
||||
const labels = [
|
||||
"unknown",
|
||||
"pending",
|
||||
"building",
|
||||
"failed",
|
||||
"success",
|
||||
];
|
||||
dashboardPackagesStatusesChart.config.data = {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
label: "packages in status",
|
||||
data: labels.map(label => data.packages[label]),
|
||||
backgroundColor: [
|
||||
"rgb(55, 58, 60)",
|
||||
"rgb(255, 117, 24)",
|
||||
"rgb(255, 117, 24)",
|
||||
"rgb(255, 0, 57)",
|
||||
"rgb(63, 182, 24)", // copy-paste from current style
|
||||
],
|
||||
}],
|
||||
};
|
||||
dashboardPackagesStatusesChart.update();
|
||||
}
|
||||
|
||||
if (dashboardPackagesCountChart) {
|
||||
dashboardPackagesCountChart.config.data = {
|
||||
labels: ["packages"],
|
||||
datasets: [
|
||||
{
|
||||
label: "archives",
|
||||
data: [data.stats.packages],
|
||||
},
|
||||
{
|
||||
label: "bases",
|
||||
data: [data.stats.bases],
|
||||
},
|
||||
],
|
||||
};
|
||||
dashboardPackagesCountChart.update();
|
||||
}
|
||||
|
||||
dashboardCanvas.hidden = data.status.total > 0;
|
||||
},
|
||||
);
|
||||
packagesLoad(onFailure);
|
||||
statusLoad();
|
||||
}
|
||||
|
||||
function selectRepository() {
|
||||
@@ -230,7 +161,24 @@
|
||||
return {classes: cellClass(value)};
|
||||
}
|
||||
|
||||
function toggleTableAutoReload(interval) {
|
||||
clearInterval(tableAutoReloadTask);
|
||||
tableAutoReloadTask = toggleAutoReload(tableAutoReloadButton, interval, tableAutoReloadInput, _ => {
|
||||
if (!hasActiveModal() &&
|
||||
!hasActiveDropdown()) {
|
||||
packagesLoad();
|
||||
statusLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ready(_ => {
|
||||
const onCheckFunction = function () {
|
||||
if (packageRemoveButton) {
|
||||
packageRemoveButton.disabled = !getSelection().length;
|
||||
}
|
||||
};
|
||||
|
||||
document.querySelectorAll("#repositories a").forEach(element => {
|
||||
element.onclick = _ => {
|
||||
repository = {
|
||||
@@ -245,49 +193,55 @@
|
||||
};
|
||||
});
|
||||
|
||||
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", _ => {
|
||||
if (packageRemoveButton) {
|
||||
packageRemoveButton.disabled = !table.bootstrapTable("getSelections").length;
|
||||
}
|
||||
});
|
||||
table.on("click-row.bs.table", (self, data, row, cell) => {
|
||||
if (0 === cell || "base" === cell) {
|
||||
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
|
||||
table.bootstrapTable(method, {field: "id", values: [data.id]});
|
||||
} else showPackageInfo(data.id);
|
||||
});
|
||||
table.on("created-controls.bs.table", _ => {
|
||||
new easepick.create({
|
||||
element: document.querySelector(".bootstrap-table-filter-control-timestamp"),
|
||||
css: [
|
||||
"https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css",
|
||||
],
|
||||
grid: 2,
|
||||
calendars: 2,
|
||||
autoApply: false,
|
||||
locale: {
|
||||
cancel: "Clear",
|
||||
},
|
||||
RangePlugin: {
|
||||
tooltip: false,
|
||||
},
|
||||
plugins: [
|
||||
"RangePlugin",
|
||||
],
|
||||
setup: picker => {
|
||||
picker.on("select", _ => { table.bootstrapTable("triggerSearch"); });
|
||||
// replace "Cancel" behaviour to "Clear"
|
||||
picker.onClickCancelButton = element => {
|
||||
if (picker.isCancelButton(element)) {
|
||||
picker.clear();
|
||||
picker.hide();
|
||||
table.bootstrapTable("triggerSearch");
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
table.bootstrapTable({
|
||||
onCheck: onCheckFunction,
|
||||
onCheckAll: onCheckFunction,
|
||||
onClickRow: (data, row, cell) => {
|
||||
if (0 === cell || "base" === cell) {
|
||||
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
|
||||
table.bootstrapTable(method, {field: "id", values: [data.id]});
|
||||
} else showPackageInfo(data.id);
|
||||
},
|
||||
onCreatedControls: _ => {
|
||||
new easepick.create({
|
||||
element: document.querySelector(".bootstrap-table-filter-control-timestamp"),
|
||||
css: [
|
||||
"https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css",
|
||||
],
|
||||
grid: 2,
|
||||
calendars: 2,
|
||||
autoApply: false,
|
||||
locale: {
|
||||
cancel: "Clear",
|
||||
},
|
||||
RangePlugin: {
|
||||
tooltip: false,
|
||||
},
|
||||
plugins: [
|
||||
"RangePlugin",
|
||||
],
|
||||
setup: picker => {
|
||||
picker.on("select", _ => { table.bootstrapTable("triggerSearch"); });
|
||||
// replace "Cancel" behaviour to "Clear"
|
||||
picker.onClickCancelButton = element => {
|
||||
if (picker.isCancelButton(element)) {
|
||||
picker.clear();
|
||||
picker.hide();
|
||||
table.bootstrapTable("triggerSearch");
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
onUncheck: onCheckFunction,
|
||||
onUncheckAll: onCheckFunction,
|
||||
});
|
||||
|
||||
restoreAutoReloadSettings(tableAutoReloadButton, tableAutoReloadInput);
|
||||
|
||||
selectRepository();
|
||||
{% if autorefresh_intervals %}
|
||||
toggleTableAutoReload();
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -53,8 +53,7 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
|
||||
data-show-search-clear-button="true"
|
||||
data-sortable="true"
|
||||
data-sort-name="base"
|
||||
data-sort-order="asc"
|
||||
data-toggle="table">
|
||||
data-sort-order="asc">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-sortable="true" data-switchable="false" data-field="name" data-filter-control="input" data-filter-control-placeholder="(any package)">package</th>
|
||||
@@ -128,36 +127,38 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
|
||||
}
|
||||
|
||||
ready(_ => {
|
||||
table.on("created-controls.bs.table", _ => {
|
||||
new easepick.create({
|
||||
element: document.querySelector(".bootstrap-table-filter-control-timestamp"),
|
||||
css: [
|
||||
"https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css",
|
||||
],
|
||||
grid: 2,
|
||||
calendars: 2,
|
||||
autoApply: false,
|
||||
locale: {
|
||||
cancel: "Clear",
|
||||
},
|
||||
RangePlugin: {
|
||||
tooltip: false,
|
||||
},
|
||||
plugins: [
|
||||
"RangePlugin",
|
||||
],
|
||||
setup: picker => {
|
||||
picker.on("select", _ => { table.bootstrapTable("triggerSearch"); });
|
||||
// replace "Cancel" behaviour to "Clear"
|
||||
picker.onClickCancelButton = element => {
|
||||
if (picker.isCancelButton(element)) {
|
||||
picker.clear();
|
||||
picker.hide();
|
||||
table.bootstrapTable("triggerSearch");
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
table.bootstrapTable({
|
||||
onCreatedControls: _ => {
|
||||
new easepick.create({
|
||||
element: document.querySelector(".bootstrap-table-filter-control-timestamp"),
|
||||
css: [
|
||||
"https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css",
|
||||
],
|
||||
grid: 2,
|
||||
calendars: 2,
|
||||
autoApply: false,
|
||||
locale: {
|
||||
cancel: "Clear",
|
||||
},
|
||||
RangePlugin: {
|
||||
tooltip: false,
|
||||
},
|
||||
plugins: [
|
||||
"RangePlugin",
|
||||
],
|
||||
setup: picker => {
|
||||
picker.on("select", _ => { table.bootstrapTable("triggerSearch"); });
|
||||
// replace "Cancel" behaviour to "Clear"
|
||||
picker.onClickCancelButton = element => {
|
||||
if (picker.isCancelButton(element)) {
|
||||
picker.clear();
|
||||
picker.hide();
|
||||
table.bootstrapTable("triggerSearch");
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/js-md5@0.8.3/src/md5.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.30.0/tableExport.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.33.0/tableExport.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.2/dist/bootstrap-table.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/bootstrap-table.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.2/dist/extensions/export/bootstrap-table-export.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.2/dist/extensions/resizable/bootstrap-table-resizable.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.2/dist/extensions/filter-control/bootstrap-table-filter-control.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/export/bootstrap-table-export.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/resizable/bootstrap-table-resizable.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/filter-control/bootstrap-table-filter-control.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/cookie/bootstrap-table-cookie.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.umd.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.10.0/build/highlight.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/highlight.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.0/dist/chart.umd.min.js" crossorigin="anonymous" type="application/javascript"></script>
|
||||
|
||||
<script>
|
||||
async function copyToClipboard(text, button) {
|
||||
@@ -58,6 +59,20 @@
|
||||
return value.includes(dataList[index].toLowerCase());
|
||||
}
|
||||
|
||||
function hasActiveSelection() {
|
||||
return !document.getSelection().isCollapsed; // not sure if it is a valid way, but I guess so
|
||||
}
|
||||
|
||||
function hasActiveDropdown() {
|
||||
return Array.from(document.querySelectorAll(".dropdown-menu"))
|
||||
.some(el => el.classList.contains("show"));
|
||||
}
|
||||
|
||||
function hasActiveModal() {
|
||||
return Array.from(document.querySelectorAll(".modal"))
|
||||
.some(el => el.classList.contains("show"));
|
||||
}
|
||||
|
||||
function headerClass(status) {
|
||||
if (status === "pending") return ["bg-warning"];
|
||||
if (status === "building") return ["bg-warning"];
|
||||
@@ -106,6 +121,12 @@
|
||||
.catch(error => onFailure && onFailure(error));
|
||||
}
|
||||
|
||||
function readOptional(extractor, callback) {
|
||||
for (let value = extractor(); !!value; value = null) {
|
||||
callback(value);
|
||||
}
|
||||
}
|
||||
|
||||
function ready(fn) {
|
||||
if (document.readyState === "complete" || document.readyState === "interactive") {
|
||||
setTimeout(fn, 1);
|
||||
@@ -114,6 +135,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
function restoreAutoReloadSettings(toggle, intervalSelector) {
|
||||
readOptional(() => localStorage.getItem(`ahriman-${toggle.id}-refresh-enabled`), value => toggle.checked = value === "true");
|
||||
readOptional(() => localStorage.getItem(`ahriman-${toggle.id}-refresh-interval`), value => toggleActiveElement(intervalSelector, "interval", value));
|
||||
}
|
||||
|
||||
function safe(string) {
|
||||
return String(string)
|
||||
.replace(/&/g, "&")
|
||||
@@ -133,7 +159,86 @@
|
||||
return element;
|
||||
}
|
||||
|
||||
Date.prototype.toISOStringShort = function() {
|
||||
function toggleActiveElement(selector, dataType, value) {
|
||||
const targetElement = selector.querySelector(`a[data-${dataType}="${value}"]`);
|
||||
if (targetElement?.classList?.contains("active")) {
|
||||
return; // element is already active, skip processing
|
||||
}
|
||||
|
||||
Array.from(selector.children).forEach(il => {
|
||||
Array.from(il.children).forEach(el => el.classList.remove("active"));
|
||||
});
|
||||
targetElement?.classList?.add("active");
|
||||
}
|
||||
|
||||
function toggleAutoReload(toggle, interval, intervalSelector, callback) {
|
||||
if (interval) {
|
||||
toggle.checked = true; // toggle reload
|
||||
} else {
|
||||
interval = intervalSelector.querySelector(".active")?.dataset?.interval; // find active element
|
||||
}
|
||||
|
||||
let intervalId = null;
|
||||
if (interval) {
|
||||
if (toggle.checked) {
|
||||
// refresh UI
|
||||
toggleActiveElement(intervalSelector, "interval", interval);
|
||||
// finally create timer task
|
||||
intervalId = setInterval(callback, interval);
|
||||
}
|
||||
} else {
|
||||
toggle.checked = false; // no active interval found, disable toggle
|
||||
}
|
||||
|
||||
localStorage.setItem(`ahriman-${toggle.id}-refresh-enabled`, toggle.checked);
|
||||
localStorage.setItem(`ahriman-${toggle.id}-refresh-interval`, interval);
|
||||
return intervalId;
|
||||
}
|
||||
|
||||
function updateTable(table, rows) {
|
||||
// instead of using load method here, we just update rows manually to avoid table reinitialization
|
||||
const currentData = table.bootstrapTable("getData").reduce((accumulator, row) => {
|
||||
accumulator[row.id] = row["0"];
|
||||
return accumulator;
|
||||
}, {});
|
||||
// insert or update rows
|
||||
rows.forEach(row => {
|
||||
if (Object.hasOwn(currentData, row.id)) {
|
||||
row["0"] = currentData[row.id]; // copy checkbox state
|
||||
table.bootstrapTable("updateByUniqueId", {
|
||||
id: row.id,
|
||||
row: row,
|
||||
replace: true,
|
||||
});
|
||||
} else {
|
||||
table.bootstrapTable("insertRow", {index: 0, row: row});
|
||||
}
|
||||
});
|
||||
// remove old rows
|
||||
const newData = rows.map(value => value.id);
|
||||
Object.keys(currentData).forEach(id => {
|
||||
if (!newData.includes(id)) {
|
||||
table.bootstrapTable("removeByUniqueId", id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Array.prototype.equals = function (right, comparator) {
|
||||
let index = this.length;
|
||||
if (index !== right.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (index--) {
|
||||
if (!comparator(this[index], right[index])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Date.prototype.toISOStringShort = function () {
|
||||
const pad = number => String(number).padStart(2, "0");
|
||||
return `${this.getFullYear()}-${pad(this.getMonth() + 1)}-${pad(this.getDate())} ${pad(this.getHours())}:${pad(this.getMinutes())}:${pad(this.getSeconds())}`;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.css" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.2/dist/bootstrap-table.min.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/bootstrap-table.min.css" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.23.2/dist/extensions/filter-control/bootstrap-table-filter-control.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/filter-control/bootstrap-table-filter-control.css" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.3/dist/cosmo/bootstrap.min.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.7/dist/cosmo/bootstrap.min.css" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.10.0/build/styles/github.min.css" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/styles/github.min.css" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<style>
|
||||
.pre-scrollable {
|
||||
|
||||
@@ -674,7 +674,6 @@ _shtab_ahriman() {
|
||||
|
||||
if [[ "$current_action_nargs" != "*" ]] && \
|
||||
[[ "$current_action_nargs" != "+" ]] && \
|
||||
[[ "$current_action_nargs" != "?" ]] && \
|
||||
[[ "$current_action_nargs" != *"..." ]] && \
|
||||
(( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
|
||||
$current_action_nargs )); then
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH AHRIMAN "1" "2026\-01\-25" "ahriman 2.19.3" "ArcH linux ReposItory MANager"
|
||||
.TH AHRIMAN "1" "2025\-06\-29" "ahriman 2.19.0" "ArcH linux ReposItory MANager"
|
||||
.SH NAME
|
||||
ahriman \- ArcH linux ReposItory MANager
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -99,9 +99,6 @@ _shtab_ahriman_options=(
|
||||
"--wait-timeout[wait for lock to be free. Negative value will lead to immediate application run even if there is lock file. In case of zero value, the application will wait infinitely (default\: -1)]:wait_timeout:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_defaults_added=0
|
||||
|
||||
_shtab_ahriman_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||
@@ -116,9 +113,6 @@ _shtab_ahriman_add_options=(
|
||||
"(*):package source (base name, path to local files, remote URL):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_add_defaults_added=0
|
||||
|
||||
_shtab_ahriman_aur_search_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
@@ -127,9 +121,6 @@ _shtab_ahriman_aur_search_options=(
|
||||
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_aur_search_defaults_added=0
|
||||
|
||||
_shtab_ahriman_check_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||
@@ -140,9 +131,6 @@ _shtab_ahriman_check_options=(
|
||||
"(*)::filter check by package base (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_check_defaults_added=0
|
||||
|
||||
_shtab_ahriman_clean_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
||||
@@ -152,9 +140,6 @@ _shtab_ahriman_clean_options=(
|
||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_clean_defaults_added=0
|
||||
|
||||
_shtab_ahriman_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||
@@ -163,17 +148,11 @@ _shtab_ahriman_config_options=(
|
||||
":filter settings by key (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_config_defaults_added=0
|
||||
|
||||
_shtab_ahriman_config_validate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_config_validate_defaults_added=0
|
||||
|
||||
_shtab_ahriman_copy_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
@@ -182,9 +161,6 @@ _shtab_ahriman_copy_options=(
|
||||
"(*):package base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_copy_defaults_added=0
|
||||
|
||||
_shtab_ahriman_daemon_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-i,--interval}"[interval between runs in seconds (default\: 43200)]:interval:"
|
||||
@@ -202,40 +178,25 @@ _shtab_ahriman_daemon_options=(
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_daemon_defaults_added=0
|
||||
|
||||
_shtab_ahriman_help_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
":show help message for specific command (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_help_defaults_added=0
|
||||
|
||||
_shtab_ahriman_help_commands_unsafe_options=(
|
||||
"(- : *)"{-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 (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_help_commands_unsafe_defaults_added=0
|
||||
|
||||
_shtab_ahriman_help_updates_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit code if updates available (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_help_updates_defaults_added=0
|
||||
|
||||
_shtab_ahriman_help_version_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_help_version_defaults_added=0
|
||||
|
||||
_shtab_ahriman_init_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
@@ -252,18 +213,12 @@ _shtab_ahriman_init_options=(
|
||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_init_defaults_added=0
|
||||
|
||||
_shtab_ahriman_key_import_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--key-server[key server for key import (default\: keyserver.ubuntu.com)]:key_server:"
|
||||
":PGP key to import from public server:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_key_import_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||
@@ -278,26 +233,17 @@ _shtab_ahriman_package_add_options=(
|
||||
"(*):package source (base name, path to local files, remote URL):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_add_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_changes_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
":package base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_changes_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_changes_remove_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
":package base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_changes_remove_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_copy_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
@@ -306,17 +252,11 @@ _shtab_ahriman_package_copy_options=(
|
||||
"(*):package base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_copy_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_remove_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*):package name or base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_remove_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_status_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--ahriman[get service status itself (default\: False)]"
|
||||
@@ -326,26 +266,17 @@ _shtab_ahriman_package_status_options=(
|
||||
"(*)::filter status by package base (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_status_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_status_remove_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*):remove specified packages from status page:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_status_remove_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_status_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
||||
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_status_update_defaults_added=0
|
||||
|
||||
_shtab_ahriman_package_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||
@@ -360,9 +291,6 @@ _shtab_ahriman_package_update_options=(
|
||||
"(*):package source (base name, path to local files, remote URL):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_package_update_defaults_added=0
|
||||
|
||||
_shtab_ahriman_patch_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
":package base:"
|
||||
@@ -370,9 +298,6 @@ _shtab_ahriman_patch_add_options=(
|
||||
":path to file which contains function or variable value. If not set, the value will be read from stdin (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_patch_add_defaults_added=0
|
||||
|
||||
_shtab_ahriman_patch_list_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
@@ -380,27 +305,18 @@ _shtab_ahriman_patch_list_options=(
|
||||
":package base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_patch_list_defaults_added=0
|
||||
|
||||
_shtab_ahriman_patch_remove_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"*"{-v,--variable}"[should be used for single-function patches in case if you wold like to remove only specified PKGBUILD variables. In case if not set, it will remove all patches related to the package (default\: None)]:variable:"
|
||||
":package base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_patch_remove_defaults_added=0
|
||||
|
||||
_shtab_ahriman_patch_set_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"*"{-t,--track}"[files which has to be tracked (default\: \[\'\*.diff\', \'\*.patch\'\])]:track:"
|
||||
":path to directory with changed files for patch addition\/update:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_patch_set_add_defaults_added=0
|
||||
|
||||
_shtab_ahriman_rebuild_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"*--depends-on[only rebuild packages that depend on specified packages (default\: None)]:depends_on:"
|
||||
@@ -412,33 +328,21 @@ _shtab_ahriman_rebuild_options=(
|
||||
{-u,--username}"[build as user (default\: None)]:username:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_rebuild_defaults_added=0
|
||||
|
||||
_shtab_ahriman_remove_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*):package name or base:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_remove_defaults_added=0
|
||||
|
||||
_shtab_ahriman_remove_unknown_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--dry-run[just perform check for packages without removal (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_remove_unknown_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_backup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
":path of the output archive:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_backup_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_check_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||
@@ -449,9 +353,6 @@ _shtab_ahriman_repo_check_options=(
|
||||
"(*)::filter check by package base (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_check_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_clean_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
||||
@@ -461,9 +362,6 @@ _shtab_ahriman_repo_clean_options=(
|
||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_clean_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||
@@ -472,31 +370,19 @@ _shtab_ahriman_repo_config_options=(
|
||||
":filter settings by key (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_config_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_config_validate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_config_validate_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_create_keyring_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_create_keyring_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_create_mirrorlist_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_create_mirrorlist_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_daemon_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-i,--interval}"[interval between runs in seconds (default\: 43200)]:interval:"
|
||||
@@ -514,9 +400,6 @@ _shtab_ahriman_repo_daemon_options=(
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_daemon_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_init_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
@@ -533,9 +416,6 @@ _shtab_ahriman_repo_init_options=(
|
||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_init_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_rebuild_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"*--depends-on[only rebuild packages that depend on specified packages (default\: None)]:depends_on:"
|
||||
@@ -547,33 +427,21 @@ _shtab_ahriman_repo_rebuild_options=(
|
||||
{-u,--username}"[build as user (default\: None)]:username:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_rebuild_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_remove_unknown_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--dry-run[just perform check for packages without removal (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_remove_unknown_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_report_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_report_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_restore_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-o,--output}"[root path of the extracted files (default\: \/)]:output:"
|
||||
":path of the input archive:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_restore_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
@@ -590,17 +458,11 @@ _shtab_ahriman_repo_setup_options=(
|
||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_setup_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_sign_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*)::sign only specified packages (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_sign_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_statistics_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--chart[create updates chart and save it to the specified path (default\: None)]:chart:"
|
||||
@@ -612,40 +474,25 @@ _shtab_ahriman_repo_statistics_options=(
|
||||
":fetch only events for the specified package (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_statistics_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_status_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-s,--status}"[new status (default\: success)]:status:(unknown pending building failed success)"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_status_update_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_sync_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_sync_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_tree_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-p,--partitions}"[also divide packages by independent partitions (default\: 1)]:partitions:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_tree_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_triggers_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*)::instead of running all triggers as set by configuration, just process specified ones in order of mention (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_triggers_defaults_added=0
|
||||
|
||||
_shtab_ahriman_repo_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: True)]:aur:"
|
||||
@@ -663,24 +510,15 @@ _shtab_ahriman_repo_update_options=(
|
||||
"(*)::filter check by package base (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_repo_update_defaults_added=0
|
||||
|
||||
_shtab_ahriman_report_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_report_defaults_added=0
|
||||
|
||||
_shtab_ahriman_run_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_run_defaults_added=0
|
||||
|
||||
_shtab_ahriman_search_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
@@ -689,9 +527,6 @@ _shtab_ahriman_search_options=(
|
||||
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_search_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_clean_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
||||
@@ -701,9 +536,6 @@ _shtab_ahriman_service_clean_options=(
|
||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_clean_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||
@@ -712,42 +544,27 @@ _shtab_ahriman_service_config_options=(
|
||||
":filter settings by key (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_config_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_config_validate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_config_validate_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_key_import_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--key-server[key server for key import (default\: keyserver.ubuntu.com)]:key_server:"
|
||||
":PGP key to import from public server:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_key_import_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_repositories_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--id-only,--no-id-only}"[show machine readable identifier instead (default\: False)]:id_only:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_repositories_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_run_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_run_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
@@ -764,25 +581,16 @@ _shtab_ahriman_service_setup_options=(
|
||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_setup_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_shell_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_shell_defaults_added=0
|
||||
|
||||
_shtab_ahriman_service_tree_migrate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_service_tree_migrate_defaults_added=0
|
||||
|
||||
_shtab_ahriman_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
@@ -799,26 +607,17 @@ _shtab_ahriman_setup_options=(
|
||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_setup_defaults_added=0
|
||||
|
||||
_shtab_ahriman_shell_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_shell_defaults_added=0
|
||||
|
||||
_shtab_ahriman_sign_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"(*)::sign only specified packages (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_sign_defaults_added=0
|
||||
|
||||
_shtab_ahriman_status_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--ahriman[get service status itself (default\: False)]"
|
||||
@@ -828,25 +627,16 @@ _shtab_ahriman_status_options=(
|
||||
"(*)::filter status by package base (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_status_defaults_added=0
|
||||
|
||||
_shtab_ahriman_status_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
||||
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_status_update_defaults_added=0
|
||||
|
||||
_shtab_ahriman_sync_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_sync_defaults_added=0
|
||||
|
||||
_shtab_ahriman_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: True)]:aur:"
|
||||
@@ -864,9 +654,6 @@ _shtab_ahriman_update_options=(
|
||||
"(*)::filter check by package base (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_update_defaults_added=0
|
||||
|
||||
_shtab_ahriman_user_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--key[optional PGP key used by this user. The private key must be imported (default\: None)]:key:"
|
||||
@@ -876,9 +663,6 @@ _shtab_ahriman_user_add_options=(
|
||||
":username for web service:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_user_add_defaults_added=0
|
||||
|
||||
_shtab_ahriman_user_list_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
@@ -886,41 +670,25 @@ _shtab_ahriman_user_list_options=(
|
||||
":filter users by username (default\: None):"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_user_list_defaults_added=0
|
||||
|
||||
_shtab_ahriman_user_remove_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
":username for web service:"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_user_remove_defaults_added=0
|
||||
|
||||
_shtab_ahriman_version_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_version_defaults_added=0
|
||||
|
||||
_shtab_ahriman_web_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
# guard to ensure default positional specs are added only once per session
|
||||
_shtab_ahriman_web_defaults_added=0
|
||||
|
||||
|
||||
_shtab_ahriman() {
|
||||
local context state line curcontext="$curcontext" one_or_more='(*)' remainder='(-)*' default='*::: :->ahriman'
|
||||
local context state line curcontext="$curcontext" one_or_more='(-)*' remainder='(*)'
|
||||
|
||||
# Add default positional/remainder specs only if none exist, and only once per session
|
||||
if (( ! _shtab_ahriman_defaults_added )); then
|
||||
if (( ${_shtab_ahriman_options[(I)${(q)one_or_more}*]} + ${_shtab_ahriman_options[(I)${(q)remainder}*]} + ${_shtab_ahriman_options[(I)${(q)default}]} == 0 )); then
|
||||
_shtab_ahriman_options+=(': :_shtab_ahriman_commands' '*::: :->ahriman')
|
||||
fi
|
||||
_shtab_ahriman_defaults_added=1
|
||||
if ((${_shtab_ahriman_options[(I)${(q)one_or_more}*]} + ${_shtab_ahriman_options[(I)${(q)remainder}*]} == 0)); then # noqa: E501
|
||||
_shtab_ahriman_options+=(': :_shtab_ahriman_commands' '*::: :->ahriman')
|
||||
fi
|
||||
_arguments -C -s $_shtab_ahriman_options
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -17,4 +17,4 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
__version__ = "2.19.3"
|
||||
__version__ = "2.19.0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
70
src/ahriman/application/handlers/reload.py
Normal file
70
src/ahriman/application/handlers/reload.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# Copyright (c) 2021-2026 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/>.
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Reload(Handler):
|
||||
"""
|
||||
web server reload handler
|
||||
"""
|
||||
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(repository_id, configuration, report=True)
|
||||
client = application.repository.reporter
|
||||
client.configuration_reload()
|
||||
|
||||
@staticmethod
|
||||
def _set_web_reload_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for web reload subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("web-reload", help="reload configuration",
|
||||
description="reload web server configuration",
|
||||
epilog="This method forces the web server to reload its configuration. "
|
||||
"Note, however, that this method does not apply all configuration changes "
|
||||
"(like ports, authentication, etc)")
|
||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_web_reload_parser]
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -28,6 +28,7 @@ from ahriman.core.alpm.remote import AUR, Official
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import OptionError
|
||||
from ahriman.core.formatters import AurPrinter
|
||||
from ahriman.core.types import Comparable
|
||||
from ahriman.models.aur_package import AURPackage
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
@@ -115,7 +116,7 @@ class Search(Handler):
|
||||
raise OptionError(sort_by)
|
||||
# always sort by package name at the last
|
||||
# well technically it is not a string, but we can deal with it
|
||||
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
||||
comparator: Callable[[AURPackage], Comparable] = \
|
||||
lambda package: (getattr(package, sort_by), package.name)
|
||||
return sorted(packages, key=comparator)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -25,6 +25,7 @@ from ahriman.application.application import Application
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import PackagePrinter, StatusPrinter
|
||||
from ahriman.core.types import Comparable
|
||||
from ahriman.core.utils import enum_values
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
from ahriman.models.package import Package
|
||||
@@ -64,7 +65,7 @@ class Status(Handler):
|
||||
|
||||
Status.check_status(args.exit_code, packages)
|
||||
|
||||
comparator: Callable[[tuple[Package, BuildStatus]], str] = lambda item: item[0].base
|
||||
comparator: Callable[[tuple[Package, BuildStatus]], Comparable] = lambda item: item[0].base
|
||||
filter_fn: Callable[[tuple[Package, BuildStatus]], bool] =\
|
||||
lambda item: args.status is None or item[1].status == args.status
|
||||
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -21,7 +21,7 @@ import argparse
|
||||
import re
|
||||
import sys
|
||||
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Iterator
|
||||
from importlib import metadata
|
||||
from typing import ClassVar
|
||||
|
||||
@@ -77,7 +77,7 @@ class Versions(Handler):
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
||||
def package_dependencies(root: str) -> Iterator[tuple[str, str]]:
|
||||
"""
|
||||
extract list of ahriman package dependencies installed into system with their versions
|
||||
|
||||
@@ -87,7 +87,7 @@ class Versions(Handler):
|
||||
Yields:
|
||||
tuple[str, str]: map of installed dependency to its version
|
||||
"""
|
||||
def dependencies_by_key(key: str) -> Generator[str, None, None]:
|
||||
def dependencies_by_key(key: str) -> Iterator[str]:
|
||||
# in importlib it returns requires in the following format
|
||||
# ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]
|
||||
try:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||
@@ -86,7 +86,7 @@ class Web(Handler):
|
||||
return parser
|
||||
|
||||
@staticmethod
|
||||
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Generator[str, None, None]:
|
||||
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Iterator[str]:
|
||||
"""
|
||||
extract list of arguments used for current command, except for command specific ones
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -21,7 +21,7 @@ import itertools
|
||||
import shutil
|
||||
import tarfile
|
||||
|
||||
from collections.abc import Generator, Iterable
|
||||
from collections.abc import Iterable, Iterator
|
||||
from functools import cached_property
|
||||
from pathlib import Path
|
||||
from pyalpm import DB, Handle, Package, SIG_DATABASE_OPTIONAL, SIG_PACKAGE_OPTIONAL # type: ignore[import-not-found]
|
||||
@@ -188,7 +188,7 @@ class Pacman(LazyLogging):
|
||||
Returns:
|
||||
dict[str, set[str]]: map of package name to its list of files
|
||||
"""
|
||||
def extract(tar: tarfile.TarFile, versions: dict[str, str]) -> Generator[tuple[str, set[str]], None, None]:
|
||||
def extract(tar: tarfile.TarFile, versions: dict[str, str]) -> Iterator[tuple[str, set[str]]]:
|
||||
for package_name, version in versions.items():
|
||||
path = Path(f"{package_name}-{version}") / "files"
|
||||
try:
|
||||
@@ -223,7 +223,7 @@ class Pacman(LazyLogging):
|
||||
|
||||
return result
|
||||
|
||||
def package(self, package_name: str) -> Generator[Package, None, None]:
|
||||
def package(self, package_name: str) -> Iterator[Package]:
|
||||
"""
|
||||
retrieve list of the packages from the repository by name
|
||||
|
||||
@@ -256,7 +256,7 @@ class Pacman(LazyLogging):
|
||||
|
||||
return result
|
||||
|
||||
def provided_by(self, package_name: str) -> Generator[Package, None, None]:
|
||||
def provided_by(self, package_name: str) -> Iterator[Package]:
|
||||
"""
|
||||
search through databases and emit packages which provides the ``package_name``
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -21,7 +21,7 @@ import itertools
|
||||
import re
|
||||
import shlex
|
||||
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Iterator
|
||||
from enum import StrEnum
|
||||
from typing import IO
|
||||
|
||||
@@ -209,7 +209,7 @@ class PkgbuildParser(shlex.shlex):
|
||||
Raises:
|
||||
PkgbuildParserError: if array is not closed
|
||||
"""
|
||||
def extract() -> Generator[str, None, None]:
|
||||
def extract() -> Iterator[str]:
|
||||
while token := self.get_token():
|
||||
match token:
|
||||
case _ if self._is_escaped():
|
||||
@@ -276,7 +276,7 @@ class PkgbuildParser(shlex.shlex):
|
||||
|
||||
return content
|
||||
|
||||
def _parse_token(self, token: str) -> Generator[PkgbuildPatch, None, None]:
|
||||
def _parse_token(self, token: str) -> Iterator[PkgbuildPatch]:
|
||||
"""
|
||||
parse single token to the PKGBUILD field
|
||||
|
||||
@@ -360,7 +360,7 @@ class PkgbuildParser(shlex.shlex):
|
||||
|
||||
raise PkgbuildParserError("reached starting position, no valid symbols found")
|
||||
|
||||
def parse(self) -> Generator[PkgbuildPatch, None, None]:
|
||||
def parse(self) -> Iterator[PkgbuildPatch]:
|
||||
"""
|
||||
parse source stream and yield parsed entries
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -44,7 +44,7 @@ class AUR(Remote):
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
Args
|
||||
Args:
|
||||
package_base(str): package base
|
||||
repository(str): repository name
|
||||
|
||||
@@ -58,7 +58,7 @@ class AUR(Remote):
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
Args
|
||||
Args:
|
||||
package_base(str): package base
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -46,7 +46,7 @@ class Official(Remote):
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
Args
|
||||
Args:
|
||||
package_base(str): package base
|
||||
repository(str): repository name
|
||||
|
||||
@@ -60,7 +60,7 @@ class Official(Remote):
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
Args
|
||||
Args:
|
||||
package_base(str): package base
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -94,6 +94,15 @@ class Remote(SyncHttpClient):
|
||||
for package in portion
|
||||
if package.name in packages or not packages
|
||||
}
|
||||
|
||||
# simple check for duplicates. This method will remove all packages under base if there is
|
||||
# a package named exactly as its base
|
||||
packages = {
|
||||
package.name: package
|
||||
for package in packages.values()
|
||||
if package.package_base not in packages or package.package_base == package.name
|
||||
}
|
||||
|
||||
return list(packages.values())
|
||||
|
||||
@classmethod
|
||||
@@ -101,7 +110,7 @@ class Remote(SyncHttpClient):
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
Args
|
||||
Args:
|
||||
package_base(str): package base
|
||||
repository(str): repository name
|
||||
|
||||
@@ -118,7 +127,7 @@ class Remote(SyncHttpClient):
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
Args
|
||||
Args:
|
||||
package_base(str): package base
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -19,7 +19,7 @@
|
||||
#
|
||||
import shutil
|
||||
|
||||
from collections.abc import Generator
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from typing import ClassVar
|
||||
|
||||
@@ -347,7 +347,7 @@ class Sources(LazyLogging):
|
||||
"""
|
||||
gitconfig = gitconfig or {}
|
||||
|
||||
def configuration_flags() -> Generator[str, None, None]:
|
||||
def configuration_flags() -> Iterator[str]:
|
||||
for option, value in (self.GITCONFIG | gitconfig).items():
|
||||
yield "-c"
|
||||
yield f"{option}=\"{value}\""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2025 ahriman team.
|
||||
# Copyright (c) 2021-2026 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@@ -17,7 +17,7 @@
|
||||
# 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 collections.abc import Generator
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
@@ -77,7 +77,7 @@ class Task(LazyLogging):
|
||||
Returns:
|
||||
list[Path]: list of file paths which looks like freshly generated archives
|
||||
"""
|
||||
def files() -> Generator[Path, None, None]:
|
||||
def files() -> Iterator[Path]:
|
||||
for filepath in sources_dir.iterdir():
|
||||
if filepath in source_files:
|
||||
continue # skip files which were already there
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user