Compare commits

..
2 Commits
Author SHA1 Message Date
arcanis 4537969d5d fix: handle is_held flag in all update processes
Previos implementation has ignored this flag in dependencies checks,
local package update and so on
2026-10-14 13:44:37 +03:00
arcanis 47c39f93b7 feat: align tables vertically in center 2026-10-13 13:22:00 +03:00
4 changed files with 90 additions and 3 deletions

No files matched your search

@@ -36,6 +36,17 @@ class UpdateHandler(PackageInfo, Cleaner):
trait to get package update list trait to get package update list
""" """
def _updates_ignored(self) -> set[str]:
"""
collect package bases excluded from automatic updates
Returns:
set[str]: held and configured ignored package bases
"""
return set(self._ignore_list) | {
package.base for package, status in self.reporter.package_get(None) if status.is_held
}
def updates_aur(self, filter_packages: Iterable[str], *, vcs: bool) -> list[Package]: def updates_aur(self, filter_packages: Iterable[str], *, vcs: bool) -> list[Package]:
""" """
check AUR for updates check AUR for updates
@@ -58,9 +69,7 @@ class UpdateHandler(PackageInfo, Cleaner):
continue continue
raise UnknownPackageError(package.base) raise UnknownPackageError(package.base)
ignore_list = self._ignore_list + [ ignore_list = self._updates_ignored()
package.base for package, status in self.reporter.package_get(None) if status.is_held
]
result: list[Package] = [] result: list[Package] = []
for local in self.packages(filter_packages): for local in self.packages(filter_packages):
@@ -106,8 +115,13 @@ class UpdateHandler(PackageInfo, Cleaner):
return files return files
ignore_list = self._updates_ignored()
result: list[Package] = [] result: list[Package] = []
for local in self.packages(filter_packages): for local in self.packages(filter_packages):
if local.base in ignore_list:
self.logger.info("package %s is held, skip update check", local.base)
continue
dependencies = self.reporter.package_dependencies_get(local.base) dependencies = self.reporter.package_dependencies_get(local.base)
if not dependencies.paths: if not dependencies.paths:
continue # skip check if no package dependencies found continue # skip check if no package dependencies found
@@ -141,9 +155,13 @@ class UpdateHandler(PackageInfo, Cleaner):
""" """
packages = {local.base: local for local in self.packages()} packages = {local.base: local for local in self.packages()}
local_versions = {package_base: package.version for package_base, package in packages.items()} local_versions = {package_base: package.version for package_base, package in packages.items()}
ignore_list = self._updates_ignored()
result: list[Package] = [] result: list[Package] = []
for cache_dir in self.paths.cache.iterdir(): for cache_dir in self.paths.cache.iterdir():
if cache_dir.name in ignore_list:
self.logger.info("package %s is held, skip update check", cache_dir.name)
continue
with self.in_package_context(cache_dir.name, local_versions.get(cache_dir.name)): with self.in_package_context(cache_dir.name, local_versions.get(cache_dir.name)):
try: try:
source = RemoteSource( source = RemoteSource(
@@ -162,6 +180,9 @@ class UpdateHandler(PackageInfo, Cleaner):
continue # we don't add packages automatically continue # we don't add packages automatically
if local.remote.is_remote: if local.remote.is_remote:
continue # avoid checking AUR packages continue # avoid checking AUR packages
if local.base in ignore_list:
self.logger.info("package %s is held, skip update check", local.base)
continue
if PackageVersion(local).is_outdated(remote, self.configuration, calculate_version=vcs): if PackageVersion(local).is_outdated(remote, self.configuration, calculate_version=vcs):
self.reporter.set_pending(local.base) self.reporter.set_pending(local.base)
@@ -14,6 +14,20 @@ from ahriman.models.package_source import PackageSource
from ahriman.models.remote_source import RemoteSource from ahriman.models.remote_source import RemoteSource
def test_updates_ignored(update_handler: UpdateHandler, package_ahriman: Package,
package_python_schedule: Package, mocker: MockerFixture) -> None:
"""
must combine configured ignored packages and held packages only
"""
update_handler._ignore_list = ["ignored-package"]
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=[
(package_ahriman, BuildStatus(is_held=True)),
(package_python_schedule, BuildStatus(is_held=False)),
])
assert update_handler._updates_ignored() == {"ignored-package", package_ahriman.base}
def test_updates_aur(update_handler: UpdateHandler, package_ahriman: Package, def test_updates_aur(update_handler: UpdateHandler, package_ahriman: Package,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
@@ -194,6 +208,18 @@ def test_updates_dependencies(update_handler: UpdateHandler, package_ahriman: Pa
pytest.helpers.anyvar(str, True)) pytest.helpers.anyvar(str, True))
def test_updates_dependencies_ignore(update_handler: UpdateHandler, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must skip held packages when checking broken dependencies
"""
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, BuildStatus(is_held=True))])
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[package_ahriman])
assert update_handler.updates_dependencies([]) == []
def test_updates_dependencies_skip_unknown(update_handler: UpdateHandler, package_ahriman: Package, def test_updates_dependencies_skip_unknown(update_handler: UpdateHandler, package_ahriman: Package,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
@@ -249,6 +275,19 @@ def test_updates_local(update_handler: UpdateHandler, package_ahriman: Package,
calculate_version=True) calculate_version=True)
def test_updates_local_ignore(update_handler: UpdateHandler, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must skip held packages before fetching local sources
"""
mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
return_value=[(package_ahriman, BuildStatus(is_held=True))])
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[package_ahriman])
mocker.patch("pathlib.Path.iterdir", return_value=[Path(package_ahriman.base)])
assert update_handler.updates_local(vcs=True) == []
def test_updates_local_ignore_vcs(update_handler: UpdateHandler, package_ahriman: Package, def test_updates_local_ignore_vcs(update_handler: UpdateHandler, package_ahriman: Package,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
@@ -306,6 +345,22 @@ def test_updates_local_with_failures(update_handler: UpdateHandler, package_ahri
assert not update_handler.updates_local(vcs=True) assert not update_handler.updates_local(vcs=True)
def test_updates_local_held_metadata(update_handler: UpdateHandler, package_ahriman: Package,
mocker: MockerFixture) -> None:
"""
must respect the held base even when the source directory has a different name
"""
package_ahriman.remote = RemoteSource(source=PackageSource.Local)
mocker.patch.object(update_handler.reporter, "package_get",
return_value=[(package_ahriman, BuildStatus(is_held=True))])
mocker.patch.object(update_handler, "packages", return_value=[package_ahriman])
mocker.patch("pathlib.Path.iterdir", return_value=[Path("different-base")])
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
assert update_handler.updates_local(vcs=True) == []
def test_updates_manual_clear(update_handler: UpdateHandler, mocker: MockerFixture) -> None: def test_updates_manual_clear(update_handler: UpdateHandler, mocker: MockerFixture) -> None:
""" """
requesting manual updates must clear packages directory requesting manual updates must clear packages directory
+2
View File
@@ -257,6 +257,8 @@ There are few ways for packages to be marked as out-of-date and hence requiring
#. In addition to the above, if package is named as VCS (e.g. has suffix ``-git``) and the last update was more than specified threshold ago, the service will also try to fetch sources and check if the revision is newer than the built one. #. In addition to the above, if package is named as VCS (e.g. has suffix ``-git``) and the last update was more than specified threshold ago, the service will also try to fetch sources and check if the revision is newer than the built one.
#. In addition, there is ability to check if the dependencies of the package have been updated (e.g. if linked library has been renamed or the modules directory - e.g. in case of python and ruby packages - has been changed). And if so, the package will be marked as out-of-date as well. #. In addition, there is ability to check if the dependencies of the package have been updated (e.g. if linked library has been renamed or the modules directory - e.g. in case of python and ruby packages - has been changed). And if so, the package will be marked as out-of-date as well.
Held packages and bases listed in ``build.ignore_packages`` are excluded from automatic AUR, official-repository, local-source, and broken-dependency update checks. These checks leave their package status unchanged. Manual updates and explicit rebuilds remain available.
Update packages Update packages
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
+9
View File
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { createTheme, type Theme } from "@mui/material/styles"; import { createTheme, type Theme } from "@mui/material/styles";
import type {} from "@mui/x-data-grid/themeAugmentation";
export function createAppTheme(mode: "light" | "dark"): Theme { export function createAppTheme(mode: "light" | "dark"): Theme {
return createTheme({ return createTheme({
@@ -30,6 +31,14 @@ export function createAppTheme(mode: "light" | "dark"): Theme {
}, },
}, },
}, },
MuiDataGrid: {
styleOverrides: {
cell: {
alignItems: "center",
display: "flex",
},
},
},
MuiDialog: { MuiDialog: {
defaultProps: { defaultProps: {
fullWidth: true, fullWidth: true,