mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-05-04 20:23:49 +00:00
Compare commits
6 Commits
63a2fc791a
...
b4a03fe8c1
Author | SHA1 | Date | |
---|---|---|---|
b4a03fe8c1 | |||
f01f35238d | |||
d30d512eb6 | |||
0437f90e5a | |||
3cab65855a | |||
ecfb615f97 |
7
.github/workflows/setup.sh
vendored
7
.github/workflows/setup.sh
vendored
@ -12,7 +12,7 @@ pacman -Syu --noconfirm
|
|||||||
# main dependencies
|
# main dependencies
|
||||||
pacman -Sy --noconfirm devtools git pyalpm python-cerberus python-inflection python-passlib python-pyelftools python-requests python-srcinfo python-systemd sudo
|
pacman -Sy --noconfirm devtools git pyalpm python-cerberus python-inflection python-passlib python-pyelftools python-requests python-srcinfo python-systemd sudo
|
||||||
# make dependencies
|
# make dependencies
|
||||||
pacman -Sy --noconfirm python-build python-flit python-installer python-tox python-wheel
|
pacman -Sy --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
|
||||||
# optional dependencies
|
# optional dependencies
|
||||||
if [[ -z $MINIMAL_INSTALL ]]; then
|
if [[ -z $MINIMAL_INSTALL ]]; then
|
||||||
# VCS support
|
# VCS support
|
||||||
@ -36,6 +36,9 @@ sudo -u nobody -- makepkg --packagelist | grep -v -- -debug- | pacman -U --nocon
|
|||||||
# create machine-id which is required by build tools
|
# create machine-id which is required by build tools
|
||||||
systemd-machine-id-setup
|
systemd-machine-id-setup
|
||||||
|
|
||||||
|
# remove unused dependencies
|
||||||
|
pacman -Qdtq | pacman -Rscn --noconfirm -
|
||||||
|
|
||||||
# initial setup command as root
|
# initial setup command as root
|
||||||
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
|
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
|
||||||
ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}"
|
ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}"
|
||||||
@ -50,7 +53,7 @@ if [[ -z $MINIMAL_INSTALL ]]; then
|
|||||||
WEB_PID=$!
|
WEB_PID=$!
|
||||||
fi
|
fi
|
||||||
# add the first package
|
# add the first package
|
||||||
sudo -u ahriman -- ahriman package-add --now ahriman
|
sudo -u ahriman -- ahriman --log-handler console package-add --now ahriman
|
||||||
# check if package was actually installed
|
# check if package was actually installed
|
||||||
test -n "$(find "/var/lib/ahriman/repository/github/x86_64" -name "ahriman*pkg*")"
|
test -n "$(find "/var/lib/ahriman/repository/github/x86_64" -name "ahriman*pkg*")"
|
||||||
# run package check
|
# run package check
|
||||||
|
@ -33,9 +33,9 @@ COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
|
|||||||
## install package dependencies
|
## install package dependencies
|
||||||
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
|
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
|
||||||
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-pyelftools python-requests python-srcinfo && \
|
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-pyelftools python-requests python-srcinfo && \
|
||||||
pacman -Sy --noconfirm --asdeps python-build python-flit python-installer python-wheel && \
|
pacman -Sy --noconfirm --asdeps base-devel python-build python-flit python-installer python-wheel && \
|
||||||
pacman -Sy --noconfirm --asdeps breezy git mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \
|
pacman -Sy --noconfirm --asdeps breezy git mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \
|
||||||
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-cors \
|
runuser -u build -- install-aur-package python-aioauth-client python-webargs python-aiohttp-apispec-git python-aiohttp-cors \
|
||||||
python-aiohttp-jinja2 python-aiohttp-session python-aiohttp-security
|
python-aiohttp-jinja2 python-aiohttp-session python-aiohttp-security
|
||||||
|
|
||||||
## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
|
## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
|
||||||
|
@ -6,7 +6,7 @@ for PACKAGE in "$@"; do
|
|||||||
BUILD_DIR="$(mktemp -d)"
|
BUILD_DIR="$(mktemp -d)"
|
||||||
git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR"
|
git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR"
|
||||||
cd "$BUILD_DIR"
|
cd "$BUILD_DIR"
|
||||||
makepkg --noconfirm --install --rmdeps --syncdeps
|
makepkg --nocheck --noconfirm --install --rmdeps --syncdeps
|
||||||
cd /
|
cd /
|
||||||
rm -r "$BUILD_DIR"
|
rm -r "$BUILD_DIR"
|
||||||
done
|
done
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
<!-- Generated by graphviz version 9.0.0 (0)
|
<!-- Generated by graphviz version 10.0.1 (0)
|
||||||
-->
|
-->
|
||||||
<!-- Title: G Pages: 1 -->
|
<!-- Title: G Pages: 1 -->
|
||||||
<svg width="28664pt" height="4176pt"
|
<svg width="28664pt" height="4176pt"
|
||||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
@ -1,7 +1,7 @@
|
|||||||
# Maintainer: Evgeniy Alekseev
|
# Maintainer: Evgeniy Alekseev
|
||||||
|
|
||||||
pkgname='ahriman'
|
pkgname='ahriman'
|
||||||
pkgver=2.13.4
|
pkgver=2.13.5
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="ArcH linux ReposItory MANager"
|
pkgdesc="ArcH linux ReposItory MANager"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
|
@ -38,10 +38,6 @@
|
|||||||
<script>
|
<script>
|
||||||
const keyImportModal = $("#key-import-modal");
|
const keyImportModal = $("#key-import-modal");
|
||||||
const keyImportForm = $("#key-import-form");
|
const keyImportForm = $("#key-import-form");
|
||||||
keyImportModal.on("hidden.bs.modal", () => {
|
|
||||||
keyImportBodyInput.text("");
|
|
||||||
keyImportForm.trigger("reset");
|
|
||||||
});
|
|
||||||
|
|
||||||
const keyImportBodyInput = $("#key-import-body-input");
|
const keyImportBodyInput = $("#key-import-body-input");
|
||||||
const keyImportCopyButton = $("#key-import-copy-button");
|
const keyImportCopyButton = $("#key-import-copy-button");
|
||||||
@ -90,4 +86,11 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
keyImportModal.on("hidden.bs.modal", () => {
|
||||||
|
keyImportBodyInput.text("");
|
||||||
|
keyImportForm.trigger("reset");
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -36,9 +36,6 @@
|
|||||||
<script>
|
<script>
|
||||||
const loginModal = $("#login-modal");
|
const loginModal = $("#login-modal");
|
||||||
const loginForm = $("#login-form");
|
const loginForm = $("#login-form");
|
||||||
loginModal.on("hidden.bs.modal", () => {
|
|
||||||
loginForm.trigger("reset");
|
|
||||||
});
|
|
||||||
|
|
||||||
const loginPasswordInput = $("#login-password");
|
const loginPasswordInput = $("#login-password");
|
||||||
const loginUsernameInput = $("#login-username");
|
const loginUsernameInput = $("#login-username");
|
||||||
@ -77,4 +74,10 @@
|
|||||||
showHidePasswordButton.addClass("bi-eye");
|
showHidePasswordButton.addClass("bi-eye");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
loginModal.on("hidden.bs.modal", () => {
|
||||||
|
loginForm.trigger("reset");
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -43,41 +43,10 @@
|
|||||||
<script>
|
<script>
|
||||||
const packageAddModal = $("#package-add-modal");
|
const packageAddModal = $("#package-add-modal");
|
||||||
const packageAddForm = $("#package-add-form");
|
const packageAddForm = $("#package-add-form");
|
||||||
packageAddModal.on("shown.bs.modal", () => {
|
|
||||||
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
|
|
||||||
});
|
|
||||||
packageAddModal.on("hidden.bs.modal", () => {
|
|
||||||
packageAddVariablesDiv.empty();
|
|
||||||
packageAddForm.trigger("reset");
|
|
||||||
});
|
|
||||||
|
|
||||||
const packageAddInput = $("#package-add-input");
|
const packageAddInput = $("#package-add-input");
|
||||||
const packageAddRepositoryInput = $("#package-add-repository-input");
|
const packageAddRepositoryInput = $("#package-add-repository-input");
|
||||||
const packageAddKnownPackagesList = $("#package-add-known-packages-dlist");
|
const packageAddKnownPackagesList = $("#package-add-known-packages-dlist");
|
||||||
packageAddInput.keyup(() => {
|
|
||||||
clearTimeout(packageAddInput.data("timeout"));
|
|
||||||
packageAddInput.data("timeout", setTimeout($.proxy(() => {
|
|
||||||
const value = packageAddInput.val();
|
|
||||||
|
|
||||||
if (value.length >= 3) {
|
|
||||||
$.ajax({
|
|
||||||
url: "/api/v1/service/search",
|
|
||||||
data: {"for": value},
|
|
||||||
type: "GET",
|
|
||||||
dataType: "json",
|
|
||||||
success: response => {
|
|
||||||
const options = response.map(pkg => {
|
|
||||||
const option = document.createElement("option");
|
|
||||||
option.value = pkg.package;
|
|
||||||
option.innerText = `${pkg.package} (${pkg.description})`;
|
|
||||||
return option;
|
|
||||||
});
|
|
||||||
packageAddKnownPackagesList.empty().append(options);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, this), 500));
|
|
||||||
});
|
|
||||||
|
|
||||||
const packageAddVariablesDiv = $("#package-add-variables-div");
|
const packageAddVariablesDiv = $("#package-add-variables-div");
|
||||||
|
|
||||||
@ -156,4 +125,39 @@
|
|||||||
doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure, patches);
|
doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure, patches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
packageAddModal.on("shown.bs.modal", () => {
|
||||||
|
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
|
||||||
|
});
|
||||||
|
packageAddModal.on("hidden.bs.modal", () => {
|
||||||
|
packageAddVariablesDiv.empty();
|
||||||
|
packageAddForm.trigger("reset");
|
||||||
|
});
|
||||||
|
|
||||||
|
packageAddInput.keyup(() => {
|
||||||
|
clearTimeout(packageAddInput.data("timeout"));
|
||||||
|
packageAddInput.data("timeout", setTimeout($.proxy(() => {
|
||||||
|
const value = packageAddInput.val();
|
||||||
|
|
||||||
|
if (value.length >= 3) {
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/v1/service/search",
|
||||||
|
data: {"for": value},
|
||||||
|
type: "GET",
|
||||||
|
dataType: "json",
|
||||||
|
success: response => {
|
||||||
|
const options = response.map(pkg => {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.value = pkg.package;
|
||||||
|
option.innerText = `${pkg.package} (${pkg.description})`;
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
packageAddKnownPackagesList.empty().append(options);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, this), 500));
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -72,26 +72,6 @@
|
|||||||
const packageInfoModal = $("#package-info-modal");
|
const packageInfoModal = $("#package-info-modal");
|
||||||
const packageInfoModalHeader = $("#package-info-modal-header");
|
const packageInfoModalHeader = $("#package-info-modal-header");
|
||||||
const packageInfo = $("#package-info");
|
const packageInfo = $("#package-info");
|
||||||
packageInfoModal.on("hidden.bs.modal", () => {
|
|
||||||
packageInfoAurUrl.empty();
|
|
||||||
packageInfoDepends.empty();
|
|
||||||
packageInfoGroups.empty();
|
|
||||||
packageInfoLicenses.empty();
|
|
||||||
packageInfoPackager.empty();
|
|
||||||
packageInfoPackages.empty();
|
|
||||||
packageInfoUpstreamUrl.empty();
|
|
||||||
packageInfoVersion.empty();
|
|
||||||
|
|
||||||
packageInfoVariablesBlock.attr("hidden", true);
|
|
||||||
packageInfoVariablesDiv.empty();
|
|
||||||
|
|
||||||
packageInfoLogsInput.empty();
|
|
||||||
packageInfoChangesInput.empty();
|
|
||||||
|
|
||||||
packageInfoModal.trigger("reset");
|
|
||||||
|
|
||||||
hideInfoControls(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
const packageInfoLogsInput = $("#package-info-logs-input");
|
const packageInfoLogsInput = $("#package-info-logs-input");
|
||||||
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
|
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
|
||||||
@ -309,4 +289,27 @@
|
|||||||
|
|
||||||
if (isPackageBaseSet) packageInfoModal.modal("show");
|
if (isPackageBaseSet) packageInfoModal.modal("show");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
packageInfoModal.on("hidden.bs.modal", () => {
|
||||||
|
packageInfoAurUrl.empty();
|
||||||
|
packageInfoDepends.empty();
|
||||||
|
packageInfoGroups.empty();
|
||||||
|
packageInfoLicenses.empty();
|
||||||
|
packageInfoPackager.empty();
|
||||||
|
packageInfoPackages.empty();
|
||||||
|
packageInfoUpstreamUrl.empty();
|
||||||
|
packageInfoVersion.empty();
|
||||||
|
|
||||||
|
packageInfoVariablesBlock.attr("hidden", true);
|
||||||
|
packageInfoVariablesDiv.empty();
|
||||||
|
|
||||||
|
packageInfoLogsInput.empty();
|
||||||
|
packageInfoChangesInput.empty();
|
||||||
|
|
||||||
|
packageInfoModal.trigger("reset");
|
||||||
|
|
||||||
|
hideInfoControls(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -35,11 +35,6 @@
|
|||||||
<script>
|
<script>
|
||||||
const packageRebuildModal = $("#package-rebuild-modal");
|
const packageRebuildModal = $("#package-rebuild-modal");
|
||||||
const packageRebuildForm = $("#package-rebuild-form");
|
const packageRebuildForm = $("#package-rebuild-form");
|
||||||
packageRebuildModal.on("shown.bs.modal", () => {
|
|
||||||
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
|
|
||||||
|
|
||||||
});
|
|
||||||
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
|
|
||||||
|
|
||||||
const packageRebuildDependencyInput = $("#package-rebuild-dependency-input");
|
const packageRebuildDependencyInput = $("#package-rebuild-dependency-input");
|
||||||
const packageRebuildRepositoryInput = $("#package-rebuild-repository-input");
|
const packageRebuildRepositoryInput = $("#package-rebuild-repository-input");
|
||||||
@ -54,4 +49,12 @@
|
|||||||
doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure);
|
doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
packageRebuildModal.on("shown.bs.modal", () => {
|
||||||
|
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
|
||||||
|
|
||||||
|
});
|
||||||
|
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -9,46 +9,8 @@
|
|||||||
const packageInfoUpdateButton = $("#package-info-update-button");
|
const packageInfoUpdateButton = $("#package-info-update-button");
|
||||||
|
|
||||||
let repository = null;
|
let repository = null;
|
||||||
$("#repositories a").on("click", (event) => {
|
|
||||||
const element = event.target;
|
|
||||||
repository = {
|
|
||||||
architecture: element.dataset.architecture,
|
|
||||||
repository: element.dataset.repository,
|
|
||||||
};
|
|
||||||
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
|
|
||||||
$(`#${element.id}`).tab("show");
|
|
||||||
reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
const table = $("#packages");
|
const table = $("#packages");
|
||||||
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
|
|
||||||
packageRemoveButton.prop("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", () => {
|
|
||||||
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
|
|
||||||
pickerInput.daterangepicker({
|
|
||||||
autoUpdateInput: false,
|
|
||||||
locale: {
|
|
||||||
cancelLabel: "Clear",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
pickerInput.on("apply.daterangepicker", (event, picker) => {
|
|
||||||
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
|
|
||||||
table.bootstrapTable("triggerSearch");
|
|
||||||
});
|
|
||||||
|
|
||||||
pickerInput.on("cancel.daterangepicker", () => {
|
|
||||||
pickerInput.val("");
|
|
||||||
table.bootstrapTable("triggerSearch");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const statusBadge = $("#badge-status");
|
const statusBadge = $("#badge-status");
|
||||||
const versionBadge = $("#badge-version");
|
const versionBadge = $("#badge-version");
|
||||||
@ -221,6 +183,46 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
|
$("#repositories a").on("click", event => {
|
||||||
|
const element = event.target;
|
||||||
|
repository = {
|
||||||
|
architecture: element.dataset.architecture,
|
||||||
|
repository: element.dataset.repository,
|
||||||
|
};
|
||||||
|
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
|
||||||
|
$(`#${element.id}`).tab("show");
|
||||||
|
reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
|
||||||
|
packageRemoveButton.prop("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", () => {
|
||||||
|
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
|
||||||
|
pickerInput.daterangepicker({
|
||||||
|
autoUpdateInput: false,
|
||||||
|
locale: {
|
||||||
|
cancelLabel: "Clear",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
pickerInput.on("apply.daterangepicker", (event, picker) => {
|
||||||
|
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
|
||||||
|
table.bootstrapTable("triggerSearch");
|
||||||
|
});
|
||||||
|
|
||||||
|
pickerInput.on("cancel.daterangepicker", () => {
|
||||||
|
pickerInput.val("");
|
||||||
|
table.bootstrapTable("triggerSearch");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
table.bootstrapTable({});
|
table.bootstrapTable({});
|
||||||
statusBadge.popover();
|
statusBadge.popover();
|
||||||
selectRepository();
|
selectRepository();
|
||||||
|
@ -102,25 +102,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
const table = $("#packages");
|
const table = $("#packages");
|
||||||
table.on("created-controls.bs.table", () => {
|
|
||||||
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
|
|
||||||
pickerInput.daterangepicker({
|
|
||||||
autoUpdateInput: false,
|
|
||||||
locale: {
|
|
||||||
cancelLabel: "Clear",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
pickerInput.on("apply.daterangepicker", (event, picker) => {
|
|
||||||
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
|
|
||||||
table.bootstrapTable("triggerSearch");
|
|
||||||
});
|
|
||||||
|
|
||||||
pickerInput.on("cancel.daterangepicker", () => {
|
|
||||||
pickerInput.val("");
|
|
||||||
table.bootstrapTable("triggerSearch");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const pacmanConf = $("#pacman-conf");
|
const pacmanConf = $("#pacman-conf");
|
||||||
const pacmanConfCopyButton = $("#copy-btn");
|
const pacmanConfCopyButton = $("#copy-btn");
|
||||||
@ -141,6 +122,28 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
|
|||||||
function filterListLicenses() {
|
function filterListLicenses() {
|
||||||
return extractDataList(table.bootstrapTable("getData"), "licenses");
|
return extractDataList(table.bootstrapTable("getData"), "licenses");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(() => {
|
||||||
|
table.on("created-controls.bs.table", () => {
|
||||||
|
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
|
||||||
|
pickerInput.daterangepicker({
|
||||||
|
autoUpdateInput: false,
|
||||||
|
locale: {
|
||||||
|
cancelLabel: "Clear",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
pickerInput.on("apply.daterangepicker", (event, picker) => {
|
||||||
|
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
|
||||||
|
table.bootstrapTable("triggerSearch");
|
||||||
|
});
|
||||||
|
|
||||||
|
pickerInput.on("cancel.daterangepicker", () => {
|
||||||
|
pickerInput.val("");
|
||||||
|
table.bootstrapTable("triggerSearch");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -596,7 +596,7 @@ _set_new_action() {
|
|||||||
current_action_nargs=1
|
current_action_nargs=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
current_action_args_start_index=$(( $word_index + 1 ))
|
current_action_args_start_index=$(( $word_index + 1 - $pos_only ))
|
||||||
|
|
||||||
current_action_is_positional=$2
|
current_action_is_positional=$2
|
||||||
}
|
}
|
||||||
@ -623,6 +623,7 @@ _shtab_ahriman() {
|
|||||||
|
|
||||||
local prefix=_shtab_ahriman
|
local prefix=_shtab_ahriman
|
||||||
local word_index=0
|
local word_index=0
|
||||||
|
local pos_only=0 # "--" delimeter not encountered yet
|
||||||
_set_parser_defaults
|
_set_parser_defaults
|
||||||
word_index=1
|
word_index=1
|
||||||
|
|
||||||
@ -631,26 +632,30 @@ _shtab_ahriman() {
|
|||||||
while [ $word_index -ne $COMP_CWORD ]; do
|
while [ $word_index -ne $COMP_CWORD ]; do
|
||||||
local this_word="${COMP_WORDS[$word_index]}"
|
local this_word="${COMP_WORDS[$word_index]}"
|
||||||
|
|
||||||
if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then
|
if [[ $pos_only = 1 || " $this_word " != " -- " ]]; then
|
||||||
# valid subcommand: add it to the prefix & reset the current action
|
if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then
|
||||||
prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
|
# valid subcommand: add it to the prefix & reset the current action
|
||||||
_set_parser_defaults
|
prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
|
||||||
fi
|
_set_parser_defaults
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then
|
if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then
|
||||||
# a new action should be acquired (due to recognised option string or
|
# a new action should be acquired (due to recognised option string or
|
||||||
# no more input expected from current action);
|
# no more input expected from current action);
|
||||||
# the next positional action can fill in here
|
# the next positional action can fill in here
|
||||||
_set_new_action $this_word false
|
_set_new_action $this_word false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$current_action_nargs" != "*" ]] && \
|
if [[ "$current_action_nargs" != "*" ]] && \
|
||||||
[[ "$current_action_nargs" != "+" ]] && \
|
[[ "$current_action_nargs" != "+" ]] && \
|
||||||
[[ "$current_action_nargs" != *"..." ]] && \
|
[[ "$current_action_nargs" != *"..." ]] && \
|
||||||
(( $word_index + 1 - $current_action_args_start_index >= \
|
(( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
|
||||||
$current_action_nargs )); then
|
$current_action_nargs )); then
|
||||||
$current_action_is_positional && let "completed_positional_actions += 1"
|
$current_action_is_positional && let "completed_positional_actions += 1"
|
||||||
_set_new_action "pos_${completed_positional_actions}" true
|
_set_new_action "pos_${completed_positional_actions}" true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pos_only=1 # "--" delimeter encountered
|
||||||
fi
|
fi
|
||||||
|
|
||||||
let "word_index+=1"
|
let "word_index+=1"
|
||||||
@ -658,7 +663,7 @@ _shtab_ahriman() {
|
|||||||
|
|
||||||
# Generate the completions
|
# Generate the completions
|
||||||
|
|
||||||
if [[ "${completing_word}" == -* ]]; then
|
if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
|
||||||
# optional argument started: use option strings
|
# optional argument started: use option strings
|
||||||
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
|
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
|
||||||
else
|
else
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH AHRIMAN "1" "2024\-02\-10" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2024\-04\-04" "ahriman" "Generated Python Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman
|
ahriman
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -742,4 +742,12 @@ _shtab_ahriman() {
|
|||||||
|
|
||||||
|
|
||||||
typeset -A opt_args
|
typeset -A opt_args
|
||||||
_shtab_ahriman "$@"
|
|
||||||
|
if [[ $zsh_eval_context[-1] == eval ]]; then
|
||||||
|
# eval/source/. command, register function for later
|
||||||
|
compdef _shtab_ahriman -N ahriman
|
||||||
|
else
|
||||||
|
# autoload from fpath, call function directly
|
||||||
|
_shtab_ahriman "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
@ -17,4 +17,4 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
__version__ = "2.13.4"
|
__version__ = "2.13.5"
|
||||||
|
@ -68,7 +68,7 @@ class Repo(LazyLogging):
|
|||||||
path(Path): path to archive to add
|
path(Path): path to archive to add
|
||||||
"""
|
"""
|
||||||
check_output(
|
check_output(
|
||||||
"repo-add", *self.sign_args, "-R", str(self.repo_path), str(path),
|
"repo-add", *self.sign_args, "--remove", str(self.repo_path), str(path),
|
||||||
exception=BuildError.from_process(path.name),
|
exception=BuildError.from_process(path.name),
|
||||||
cwd=self.paths.repository,
|
cwd=self.paths.repository,
|
||||||
logger=self.logger,
|
logger=self.logger,
|
||||||
@ -78,8 +78,13 @@ class Repo(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
create empty repository database. It just calls add with empty arguments
|
create empty repository database. It just calls add with empty arguments
|
||||||
"""
|
"""
|
||||||
check_output("repo-add", *self.sign_args, str(self.repo_path),
|
# since pacman-6.1.0 repo-add doesn't create empty database in case if no packages supplied
|
||||||
cwd=self.paths.repository, logger=self.logger, user=self.uid)
|
# this code creates empty files instead
|
||||||
|
if self.repo_path.exists():
|
||||||
|
return # database is already created, skip this part
|
||||||
|
|
||||||
|
self.repo_path.touch(exist_ok=True)
|
||||||
|
(self.paths.repository / f"{self.name}.db").symlink_to(self.repo_path)
|
||||||
|
|
||||||
def remove(self, package: str, filename: Path) -> None:
|
def remove(self, package: str, filename: Path) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from elftools.elf.dynamic import DynamicSection # type: ignore[import-untyped]
|
from elftools.elf.dynamic import DynamicSection
|
||||||
from elftools.elf.elffile import ELFFile # type: ignore[import-untyped]
|
from elftools.elf.elffile import ELFFile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import IO
|
from typing import IO
|
||||||
|
|
||||||
@ -57,13 +57,19 @@ class PackageArchive:
|
|||||||
if not PackageArchive.is_elf(binary_file):
|
if not PackageArchive.is_elf(binary_file):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
elf_file = ELFFile(binary_file)
|
elf_file = ELFFile(binary_file) # type: ignore[no-untyped-call]
|
||||||
dynamic_section = next(
|
dynamic_section = next(
|
||||||
(section for section in elf_file.iter_sections() if isinstance(section, DynamicSection)), None)
|
(section for section in elf_file.iter_sections() # type: ignore[no-untyped-call]
|
||||||
|
if isinstance(section, DynamicSection)),
|
||||||
|
None)
|
||||||
if dynamic_section is None:
|
if dynamic_section is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
return [tag.needed for tag in dynamic_section.iter_tags() if tag.entry.d_tag == "DT_NEEDED"]
|
return [
|
||||||
|
tag.needed
|
||||||
|
for tag in dynamic_section.iter_tags() # type: ignore[no-untyped-call]
|
||||||
|
if tag.entry.d_tag == "DT_NEEDED"
|
||||||
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_elf(content: IO[bytes]) -> bool:
|
def is_elf(content: IO[bytes]) -> bool:
|
||||||
|
@ -26,13 +26,28 @@ def test_repo_add(repo: Repo, mocker: MockerFixture) -> None:
|
|||||||
|
|
||||||
def test_repo_init(repo: Repo, mocker: MockerFixture) -> None:
|
def test_repo_init(repo: Repo, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must call repo-add with empty package list on repo initializing
|
must create empty database files
|
||||||
"""
|
"""
|
||||||
check_output_mock = mocker.patch("ahriman.core.alpm.repo.check_output")
|
mocker.patch("pathlib.Path.exists", return_value=False)
|
||||||
|
touch_mock = mocker.patch("pathlib.Path.touch")
|
||||||
|
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
|
||||||
|
|
||||||
repo.init()
|
repo.init()
|
||||||
check_output_mock.assert_called_once() # it will be checked later
|
touch_mock.assert_called_once_with(exist_ok=True)
|
||||||
assert check_output_mock.call_args[0][0] == "repo-add"
|
symlink_mock.assert_called_once_with(repo.repo_path)
|
||||||
|
|
||||||
|
|
||||||
|
def test_repo_init_skip(repo: Repo, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must do not create files if database already exists
|
||||||
|
"""
|
||||||
|
mocker.patch("pathlib.Path.exists", return_value=True)
|
||||||
|
touch_mock = mocker.patch("pathlib.Path.touch")
|
||||||
|
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
|
||||||
|
|
||||||
|
repo.init()
|
||||||
|
touch_mock.assert_not_called()
|
||||||
|
symlink_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_repo_remove(repo: Repo, mocker: MockerFixture) -> None:
|
def test_repo_remove(repo: Repo, mocker: MockerFixture) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user