mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-04 07:43:42 +00:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			2.15.3
			...
			8f401988bb
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8f401988bb | |||
| f1b6de23fd | |||
| cf8915a457 | |||
| 28bc6edd66 | |||
| e64ada0067 | |||
| d9a2045d32 | |||
| 07eb930bd1 | |||
| e7eccca342 | |||
| 6e232f0cd6 | |||
| 05f87a36d6 | 
							
								
								
									
										4
									
								
								.github/workflows/setup.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/setup.sh
									
									
									
									
										vendored
									
									
								
							@ -10,13 +10,11 @@ echo -e '[arcanisrepo]\nServer = https://repo.arcanis.me/$arch\nSigLevel = Never
 | 
				
			|||||||
# refresh the image
 | 
					# refresh the image
 | 
				
			||||||
pacman -Syu --noconfirm
 | 
					pacman -Syu --noconfirm
 | 
				
			||||||
# main dependencies
 | 
					# main dependencies
 | 
				
			||||||
pacman -Sy --noconfirm devtools git pyalpm python-inflection python-passlib python-pyelftools python-requests python-srcinfo python-systemd sudo
 | 
					pacman -Sy --noconfirm devtools git pyalpm python-inflection python-passlib python-pyelftools python-requests python-systemd sudo
 | 
				
			||||||
# make dependencies
 | 
					# make dependencies
 | 
				
			||||||
pacman -Sy --noconfirm --asdeps base-devel 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
 | 
					 | 
				
			||||||
    pacman -Sy --noconfirm breezy darcs mercurial subversion
 | 
					 | 
				
			||||||
    # web server
 | 
					    # web server
 | 
				
			||||||
    pacman -Sy --noconfirm python-aioauth-client python-aiohttp python-aiohttp-apispec-git python-aiohttp-cors python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
 | 
					    pacman -Sy --noconfirm python-aioauth-client python-aiohttp python-aiohttp-apispec-git python-aiohttp-cors python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
 | 
				
			||||||
    # additional features
 | 
					    # additional features
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,6 @@ RUN useradd -m -d "/home/build" -s "/usr/bin/nologin" build && \
 | 
				
			|||||||
    echo "build ALL=(ALL) NOPASSWD: ALL" > "/etc/sudoers.d/build"
 | 
					    echo "build ALL=(ALL) NOPASSWD: ALL" > "/etc/sudoers.d/build"
 | 
				
			||||||
COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
 | 
					COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
 | 
				
			||||||
## install package dependencies
 | 
					## install package dependencies
 | 
				
			||||||
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
 | 
					 | 
				
			||||||
RUN pacman -Sy --noconfirm --asdeps \
 | 
					RUN pacman -Sy --noconfirm --asdeps \
 | 
				
			||||||
        devtools \
 | 
					        devtools \
 | 
				
			||||||
        git \
 | 
					        git \
 | 
				
			||||||
@ -40,7 +39,6 @@ RUN pacman -Sy --noconfirm --asdeps \
 | 
				
			|||||||
        python-passlib \
 | 
					        python-passlib \
 | 
				
			||||||
        python-pyelftools \
 | 
					        python-pyelftools \
 | 
				
			||||||
        python-requests \
 | 
					        python-requests \
 | 
				
			||||||
        python-srcinfo \
 | 
					 | 
				
			||||||
        && \
 | 
					        && \
 | 
				
			||||||
    pacman -Sy --noconfirm --asdeps \
 | 
					    pacman -Sy --noconfirm --asdeps \
 | 
				
			||||||
        base-devel \
 | 
					        base-devel \
 | 
				
			||||||
@ -50,9 +48,7 @@ RUN pacman -Sy --noconfirm --asdeps \
 | 
				
			|||||||
        python-wheel \
 | 
					        python-wheel \
 | 
				
			||||||
        && \
 | 
					        && \
 | 
				
			||||||
    pacman -Sy --noconfirm --asdeps \
 | 
					    pacman -Sy --noconfirm --asdeps \
 | 
				
			||||||
        breezy \
 | 
					 | 
				
			||||||
        git \
 | 
					        git \
 | 
				
			||||||
        mercurial \
 | 
					 | 
				
			||||||
        python-aiohttp \
 | 
					        python-aiohttp \
 | 
				
			||||||
        python-boto3 \
 | 
					        python-boto3 \
 | 
				
			||||||
        python-cerberus \
 | 
					        python-cerberus \
 | 
				
			||||||
@ -61,7 +57,6 @@ RUN pacman -Sy --noconfirm --asdeps \
 | 
				
			|||||||
        python-matplotlib \
 | 
					        python-matplotlib \
 | 
				
			||||||
        python-systemd \
 | 
					        python-systemd \
 | 
				
			||||||
        rsync \
 | 
					        rsync \
 | 
				
			||||||
        subversion \
 | 
					 | 
				
			||||||
        && \
 | 
					        && \
 | 
				
			||||||
    runuser -u build -- install-aur-package \
 | 
					    runuser -u build -- install-aur-package \
 | 
				
			||||||
        python-aioauth-client \
 | 
					        python-aioauth-client \
 | 
				
			||||||
 | 
				
			|||||||
@ -265,11 +265,7 @@ TL;DR
 | 
				
			|||||||
How to update VCS packages
 | 
					How to update VCS packages
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Normally the service handles VCS packages correctly, however it requires additional dependencies:
 | 
					Normally the service handles VCS packages correctly. The version is updated in clean chroot, no additional actions are required.
 | 
				
			||||||
 | 
					 | 
				
			||||||
.. code-block:: shell
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   pacman -S breezy darcs mercurial subversion
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
How to review changes before build
 | 
					How to review changes before build
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
				
			|||||||
@ -7,12 +7,9 @@ pkgdesc="ArcH linux ReposItory MANager"
 | 
				
			|||||||
arch=('any')
 | 
					arch=('any')
 | 
				
			||||||
url="https://github.com/arcan1s/ahriman"
 | 
					url="https://github.com/arcan1s/ahriman"
 | 
				
			||||||
license=('GPL3')
 | 
					license=('GPL3')
 | 
				
			||||||
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-inflection' 'python-passlib' 'python-pyelftools' 'python-requests' 'python-srcinfo')
 | 
					depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-inflection' 'python-passlib' 'python-pyelftools' 'python-requests')
 | 
				
			||||||
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
 | 
					makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
 | 
				
			||||||
optdepends=('breezy: -bzr packages support'
 | 
					optdepends=('python-aioauth-client: web server with OAuth2 authorization'
 | 
				
			||||||
            'darcs: -darcs packages support'
 | 
					 | 
				
			||||||
            'mercurial: -hg packages support'
 | 
					 | 
				
			||||||
            'python-aioauth-client: web server with OAuth2 authorization'
 | 
					 | 
				
			||||||
            'python-aiohttp: web server'
 | 
					            'python-aiohttp: web server'
 | 
				
			||||||
            'python-aiohttp-apispec>=3.0.0: web server'
 | 
					            'python-aiohttp-apispec>=3.0.0: web server'
 | 
				
			||||||
            'python-aiohttp-cors: web server'
 | 
					            'python-aiohttp-cors: web server'
 | 
				
			||||||
@ -26,8 +23,7 @@ optdepends=('breezy: -bzr packages support'
 | 
				
			|||||||
            'python-requests-unixsocket2: client report to web server by unix socket'
 | 
					            'python-requests-unixsocket2: client report to web server by unix socket'
 | 
				
			||||||
            'python-jinja: html report generation'
 | 
					            'python-jinja: html report generation'
 | 
				
			||||||
            'python-systemd: journal support'
 | 
					            'python-systemd: journal support'
 | 
				
			||||||
            'rsync: sync by using rsync'
 | 
					            'rsync: sync by using rsync')
 | 
				
			||||||
            'subversion: -svn packages support')
 | 
					 | 
				
			||||||
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver.tar.gz"
 | 
					source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver.tar.gz"
 | 
				
			||||||
        'ahriman.sysusers'
 | 
					        'ahriman.sysusers'
 | 
				
			||||||
        'ahriman.tmpfiles')
 | 
					        'ahriman.tmpfiles')
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ dependencies = [
 | 
				
			|||||||
    "passlib",
 | 
					    "passlib",
 | 
				
			||||||
    "pyelftools",
 | 
					    "pyelftools",
 | 
				
			||||||
    "requests",
 | 
					    "requests",
 | 
				
			||||||
    "srcinfo",
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dynamic = ["version"]
 | 
					dynamic = ["version"]
 | 
				
			||||||
 | 
				
			|||||||
@ -17,13 +17,14 @@
 | 
				
			|||||||
# You should have received a copy of the GNU General Public License
 | 
					# You should have received a copy of the GNU General Public License
 | 
				
			||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
					# along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					from collections.abc import Generator
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.build_tools.sources import Sources
 | 
					from ahriman.core.build_tools.sources import Sources
 | 
				
			||||||
from ahriman.core.configuration import Configuration
 | 
					from ahriman.core.configuration import Configuration
 | 
				
			||||||
from ahriman.core.exceptions import BuildError
 | 
					from ahriman.core.exceptions import BuildError
 | 
				
			||||||
from ahriman.core.log import LazyLogging
 | 
					from ahriman.core.log import LazyLogging
 | 
				
			||||||
from ahriman.core.utils import check_output
 | 
					from ahriman.core.utils import check_output, package_like
 | 
				
			||||||
from ahriman.models.package import Package
 | 
					from ahriman.models.package import Package
 | 
				
			||||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
					from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
				
			||||||
from ahriman.models.repository_paths import RepositoryPaths
 | 
					from ahriman.models.repository_paths import RepositoryPaths
 | 
				
			||||||
@ -67,12 +68,43 @@ class Task(LazyLogging):
 | 
				
			|||||||
        self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[])
 | 
					        self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[])
 | 
				
			||||||
        self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
 | 
					        self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def build(self, sources_dir: Path, **kwargs: str | None) -> list[Path]:
 | 
					    def _package_archives(self, sources_dir: Path, source_files: list[Path]) -> list[Path]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        extract package archives from the directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            sources_dir(Path): path to where sources are
 | 
				
			||||||
 | 
					            source_files(list[Path]): list of files which were initially in the directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            list[Path]: list of file paths which looks like freshly generated archives
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        def files() -> Generator[Path, None, None]:
 | 
				
			||||||
 | 
					            for filepath in sources_dir.iterdir():
 | 
				
			||||||
 | 
					                if filepath in source_files:
 | 
				
			||||||
 | 
					                    continue  # skip files which were already there
 | 
				
			||||||
 | 
					                if filepath.suffix == ".log":
 | 
				
			||||||
 | 
					                    continue  # skip log files
 | 
				
			||||||
 | 
					                if not package_like(filepath):
 | 
				
			||||||
 | 
					                    continue  # path doesn't look like a package
 | 
				
			||||||
 | 
					                yield filepath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # debug packages are always formed as package.base-debug
 | 
				
			||||||
 | 
					        # see /usr/share/makepkg/util/pkgbuild.sh for more details
 | 
				
			||||||
 | 
					        debug_package_prefix = f"{self.package.base}-debug-"
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            package
 | 
				
			||||||
 | 
					            for package in files()
 | 
				
			||||||
 | 
					            if self.include_debug_packages or not package.name.startswith(debug_package_prefix)
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def build(self, sources_dir: Path, *, dry_run: bool = False, **kwargs: str | None) -> list[Path]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        run package build
 | 
					        run package build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Args:
 | 
					        Args:
 | 
				
			||||||
            sources_dir(Path): path to where sources are
 | 
					            sources_dir(Path): path to where sources are
 | 
				
			||||||
 | 
					            dry_run(bool, optional): do not perform build itself (Default value = False)
 | 
				
			||||||
            **kwargs(str | None): environment variables to be passed to build processes
 | 
					            **kwargs(str | None): environment variables to be passed to build processes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
@ -82,6 +114,8 @@ class Task(LazyLogging):
 | 
				
			|||||||
        command.extend(self.archbuild_flags)
 | 
					        command.extend(self.archbuild_flags)
 | 
				
			||||||
        command.extend(["--"] + self.makechrootpkg_flags)
 | 
					        command.extend(["--"] + self.makechrootpkg_flags)
 | 
				
			||||||
        command.extend(["--"] + self.makepkg_flags)
 | 
					        command.extend(["--"] + self.makepkg_flags)
 | 
				
			||||||
 | 
					        if dry_run:
 | 
				
			||||||
 | 
					            command.extend(["--nobuild"])
 | 
				
			||||||
        self.logger.info("using %s for %s", command, self.package.base)
 | 
					        self.logger.info("using %s for %s", command, self.package.base)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        environment: dict[str, str] = {
 | 
					        environment: dict[str, str] = {
 | 
				
			||||||
@ -91,6 +125,7 @@ class Task(LazyLogging):
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        self.logger.info("using environment variables %s", environment)
 | 
					        self.logger.info("using environment variables %s", environment)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        source_files = list(sources_dir.iterdir())
 | 
				
			||||||
        check_output(
 | 
					        check_output(
 | 
				
			||||||
            *command,
 | 
					            *command,
 | 
				
			||||||
            exception=BuildError.from_process(self.package.base),
 | 
					            exception=BuildError.from_process(self.package.base),
 | 
				
			||||||
@ -100,20 +135,7 @@ class Task(LazyLogging):
 | 
				
			|||||||
            environment=environment,
 | 
					            environment=environment,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        package_list_command = ["makepkg", "--packagelist"]
 | 
					        return self._package_archives(sources_dir, source_files)
 | 
				
			||||||
        if not self.include_debug_packages:
 | 
					 | 
				
			||||||
            package_list_command.append("OPTIONS=(!debug)")  # disable debug flag manually
 | 
					 | 
				
			||||||
        packages = check_output(
 | 
					 | 
				
			||||||
            *package_list_command,
 | 
					 | 
				
			||||||
            exception=BuildError.from_process(self.package.base),
 | 
					 | 
				
			||||||
            cwd=sources_dir,
 | 
					 | 
				
			||||||
            logger=self.logger,
 | 
					 | 
				
			||||||
            environment=environment,
 | 
					 | 
				
			||||||
        ).splitlines()
 | 
					 | 
				
			||||||
        # some dirty magic here
 | 
					 | 
				
			||||||
        # the filter is applied in order to make sure that result will only contain packages which were actually built
 | 
					 | 
				
			||||||
        # e.g. in some cases packagelist command produces debug packages which were not actually built
 | 
					 | 
				
			||||||
        return list(filter(lambda path: path.is_file(), map(Path, packages)))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def init(self, sources_dir: Path, patches: list[PkgbuildPatch], local_version: str | None) -> str | None:
 | 
					    def init(self, sources_dir: Path, patches: list[PkgbuildPatch], local_version: str | None) -> str | None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ class PackageInfo(RepositoryProperties):
 | 
				
			|||||||
                    # force version to max of them
 | 
					                    # force version to max of them
 | 
				
			||||||
                    self.logger.warning("version of %s differs, found %s and %s",
 | 
					                    self.logger.warning("version of %s differs, found %s and %s",
 | 
				
			||||||
                                        current.base, current.version, local.version)
 | 
					                                        current.base, current.version, local.version)
 | 
				
			||||||
                    if current.is_outdated(local, self.paths, calculate_version=False):
 | 
					                    if current.is_outdated(local, self.configuration, calculate_version=False):
 | 
				
			||||||
                        current.version = local.version
 | 
					                        current.version = local.version
 | 
				
			||||||
                current.packages.update(local.packages)
 | 
					                current.packages.update(local.packages)
 | 
				
			||||||
            except Exception:
 | 
					            except Exception:
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,6 @@ class RepositoryProperties(EventLogger, LazyLogging):
 | 
				
			|||||||
        scan_paths(ScanPaths): scan paths for the implicit dependencies
 | 
					        scan_paths(ScanPaths): scan paths for the implicit dependencies
 | 
				
			||||||
        sign(GPG): GPG wrapper instance
 | 
					        sign(GPG): GPG wrapper instance
 | 
				
			||||||
        triggers(TriggerLoader): triggers holder
 | 
					        triggers(TriggerLoader): triggers holder
 | 
				
			||||||
        vcs_allowed_age(int): maximal age of the VCS packages before they will be checked
 | 
					 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, repository_id: RepositoryId, configuration: Configuration, database: SQLite, *, report: bool,
 | 
					    def __init__(self, repository_id: RepositoryId, configuration: Configuration, database: SQLite, *, report: bool,
 | 
				
			||||||
@ -70,8 +69,6 @@ class RepositoryProperties(EventLogger, LazyLogging):
 | 
				
			|||||||
        self.configuration = configuration
 | 
					        self.configuration = configuration
 | 
				
			||||||
        self.database = database
 | 
					        self.database = database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.vcs_allowed_age = configuration.getint("build", "vcs_allowed_age", fallback=0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.paths: RepositoryPaths = configuration.repository_paths  # additional workaround for pycharm typing
 | 
					        self.paths: RepositoryPaths = configuration.repository_paths  # additional workaround for pycharm typing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.ignore_list = configuration.getlist("build", "ignore_packages", fallback=[])
 | 
					        self.ignore_list = configuration.getlist("build", "ignore_packages", fallback=[])
 | 
				
			||||||
 | 
				
			|||||||
@ -67,10 +67,7 @@ class UpdateHandler(PackageInfo, Cleaner):
 | 
				
			|||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    remote = load_remote(local)
 | 
					                    remote = load_remote(local)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if local.is_outdated(
 | 
					                    if local.is_outdated(remote, self.configuration, calculate_version=vcs):
 | 
				
			||||||
                            remote, self.paths,
 | 
					 | 
				
			||||||
                            vcs_allowed_age=self.vcs_allowed_age,
 | 
					 | 
				
			||||||
                            calculate_version=vcs):
 | 
					 | 
				
			||||||
                        self.reporter.set_pending(local.base)
 | 
					                        self.reporter.set_pending(local.base)
 | 
				
			||||||
                        self.event(local.base, EventType.PackageOutdated, "Remote version is newer than local")
 | 
					                        self.event(local.base, EventType.PackageOutdated, "Remote version is newer than local")
 | 
				
			||||||
                        result.append(remote)
 | 
					                        result.append(remote)
 | 
				
			||||||
@ -154,9 +151,7 @@ class UpdateHandler(PackageInfo, Cleaner):
 | 
				
			|||||||
                    if local is None:
 | 
					                    if local is None:
 | 
				
			||||||
                        continue  # we don't add packages automatically
 | 
					                        continue  # we don't add packages automatically
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if local.is_outdated(remote, self.paths,
 | 
					                    if local.is_outdated(remote, self.configuration, calculate_version=vcs):
 | 
				
			||||||
                                         vcs_allowed_age=self.vcs_allowed_age,
 | 
					 | 
				
			||||||
                                         calculate_version=vcs):
 | 
					 | 
				
			||||||
                        self.reporter.set_pending(local.base)
 | 
					                        self.reporter.set_pending(local.base)
 | 
				
			||||||
                        self.event(local.base, EventType.PackageOutdated, "Locally pulled sources are outdated")
 | 
					                        self.event(local.base, EventType.PackageOutdated, "Locally pulled sources are outdated")
 | 
				
			||||||
                        result.append(remote)
 | 
					                        result.append(remote)
 | 
				
			||||||
 | 
				
			|||||||
@ -199,7 +199,7 @@ class Watcher(LazyLogging):
 | 
				
			|||||||
        proxy methods for reporter client
 | 
					        proxy methods for reporter client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Args:
 | 
					        Args:
 | 
				
			||||||
            item(str): property name:
 | 
					            item(str): property name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
            Any: attribute by its name
 | 
					            Any: attribute by its name
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ import re
 | 
				
			|||||||
import selectors
 | 
					import selectors
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from collections.abc import Callable, Generator, Iterable
 | 
					from collections.abc import Callable, Generator, Iterable, Mapping
 | 
				
			||||||
from dataclasses import asdict
 | 
					from dataclasses import asdict
 | 
				
			||||||
from enum import Enum
 | 
					from enum import Enum
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
@ -407,7 +407,7 @@ def safe_filename(source: str) -> str:
 | 
				
			|||||||
    return re.sub(r"[^A-Za-z\d\-._~:\[\]@]", "-", source)
 | 
					    return re.sub(r"[^A-Za-z\d\-._~:\[\]@]", "-", source)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def srcinfo_property(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[str, Any], *,
 | 
					def srcinfo_property(key: str, srcinfo: Mapping[str, Any], package_srcinfo: Mapping[str, Any], *,
 | 
				
			||||||
                     default: Any = None) -> Any:
 | 
					                     default: Any = None) -> Any:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    extract property from SRCINFO. This method extracts property from package if this property is presented in
 | 
					    extract property from SRCINFO. This method extracts property from package if this property is presented in
 | 
				
			||||||
@ -416,8 +416,8 @@ def srcinfo_property(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[st
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Args:
 | 
					    Args:
 | 
				
			||||||
        key(str): key to extract
 | 
					        key(str): key to extract
 | 
				
			||||||
        srcinfo(dict[str, Any]): root structure of SRCINFO
 | 
					        srcinfo(Mapping[str, Any]): root structure of SRCINFO
 | 
				
			||||||
        package_srcinfo(dict[str, Any]): package specific SRCINFO
 | 
					        package_srcinfo(Mapping[str, Any]): package specific SRCINFO
 | 
				
			||||||
        default(Any, optional): the default value for the specified key (Default value = None)
 | 
					        default(Any, optional): the default value for the specified key (Default value = None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Returns:
 | 
					    Returns:
 | 
				
			||||||
@ -426,7 +426,7 @@ def srcinfo_property(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[st
 | 
				
			|||||||
    return package_srcinfo.get(key) or srcinfo.get(key) or default
 | 
					    return package_srcinfo.get(key) or srcinfo.get(key) or default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def srcinfo_property_list(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[str, Any], *,
 | 
					def srcinfo_property_list(key: str, srcinfo: Mapping[str, Any], package_srcinfo: Mapping[str, Any], *,
 | 
				
			||||||
                          architecture: str | None = None) -> list[Any]:
 | 
					                          architecture: str | None = None) -> list[Any]:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    extract list property from SRCINFO. Unlike :func:`srcinfo_property()` it supposes that default return value is
 | 
					    extract list property from SRCINFO. Unlike :func:`srcinfo_property()` it supposes that default return value is
 | 
				
			||||||
@ -435,8 +435,8 @@ def srcinfo_property_list(key: str, srcinfo: dict[str, Any], package_srcinfo: di
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Args:
 | 
					    Args:
 | 
				
			||||||
        key(str): key to extract
 | 
					        key(str): key to extract
 | 
				
			||||||
        srcinfo(dict[str, Any]): root structure of SRCINFO
 | 
					        srcinfo(Mapping[str, Any]): root structure of SRCINFO
 | 
				
			||||||
        package_srcinfo(dict[str, Any]): package specific SRCINFO
 | 
					        package_srcinfo(Mapping[str, Any]): package specific SRCINFO
 | 
				
			||||||
        architecture(str | None, optional): package architecture if set (Default value = None)
 | 
					        architecture(str | None, optional): package architecture if set (Default value = None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Returns:
 | 
					    Returns:
 | 
				
			||||||
 | 
				
			|||||||
@ -26,19 +26,18 @@ from collections.abc import Callable, Generator, Iterable
 | 
				
			|||||||
from dataclasses import dataclass
 | 
					from dataclasses import dataclass
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from pyalpm import vercmp  # type: ignore[import-not-found]
 | 
					from pyalpm import vercmp  # type: ignore[import-not-found]
 | 
				
			||||||
from srcinfo.parse import parse_srcinfo  # type: ignore[import-untyped]
 | 
					 | 
				
			||||||
from typing import Any, Self
 | 
					from typing import Any, Self
 | 
				
			||||||
from urllib.parse import urlparse
 | 
					from urllib.parse import urlparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.alpm.pacman import Pacman
 | 
					from ahriman.core.alpm.pacman import Pacman
 | 
				
			||||||
from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
 | 
					from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
 | 
				
			||||||
from ahriman.core.exceptions import PackageInfoError
 | 
					from ahriman.core.configuration import Configuration
 | 
				
			||||||
from ahriman.core.log import LazyLogging
 | 
					from ahriman.core.log import LazyLogging
 | 
				
			||||||
from ahriman.core.utils import check_output, dataclass_view, full_version, parse_version, srcinfo_property_list, utcnow
 | 
					from ahriman.core.utils import dataclass_view, full_version, parse_version, srcinfo_property_list, utcnow
 | 
				
			||||||
from ahriman.models.package_description import PackageDescription
 | 
					from ahriman.models.package_description import PackageDescription
 | 
				
			||||||
from ahriman.models.package_source import PackageSource
 | 
					from ahriman.models.package_source import PackageSource
 | 
				
			||||||
 | 
					from ahriman.models.pkgbuild import Pkgbuild
 | 
				
			||||||
from ahriman.models.remote_source import RemoteSource
 | 
					from ahriman.models.remote_source import RemoteSource
 | 
				
			||||||
from ahriman.models.repository_paths import RepositoryPaths
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dataclass(kw_only=True)
 | 
					@dataclass(kw_only=True)
 | 
				
			||||||
@ -255,25 +254,19 @@ class Package(LazyLogging):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
            Self: package properties
 | 
					            Self: package properties
 | 
				
			||||||
 | 
					 | 
				
			||||||
        Raises:
 | 
					 | 
				
			||||||
            PackageInfoError: if there are parsing errors
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        srcinfo_source = check_output("makepkg", "--printsrcinfo", cwd=path)
 | 
					        pkgbuild = Pkgbuild.from_file(path / "PKGBUILD")
 | 
				
			||||||
        srcinfo, errors = parse_srcinfo(srcinfo_source)
 | 
					 | 
				
			||||||
        if errors:
 | 
					 | 
				
			||||||
            raise PackageInfoError(errors)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        packages = {
 | 
					        packages = {
 | 
				
			||||||
            package: PackageDescription(
 | 
					            package: PackageDescription(
 | 
				
			||||||
                depends=srcinfo_property_list("depends", srcinfo, properties, architecture=architecture),
 | 
					                depends=srcinfo_property_list("depends", pkgbuild, properties, architecture=architecture),
 | 
				
			||||||
                make_depends=srcinfo_property_list("makedepends", srcinfo, properties, architecture=architecture),
 | 
					                make_depends=srcinfo_property_list("makedepends", pkgbuild, properties, architecture=architecture),
 | 
				
			||||||
                opt_depends=srcinfo_property_list("optdepends", srcinfo, properties, architecture=architecture),
 | 
					                opt_depends=srcinfo_property_list("optdepends", pkgbuild, properties, architecture=architecture),
 | 
				
			||||||
                check_depends=srcinfo_property_list("checkdepends", srcinfo, properties, architecture=architecture),
 | 
					                check_depends=srcinfo_property_list("checkdepends", pkgbuild, properties, architecture=architecture),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            for package, properties in srcinfo["packages"].items()
 | 
					            for package, properties in pkgbuild.packages().items()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        version = full_version(srcinfo.get("epoch"), srcinfo["pkgver"], srcinfo["pkgrel"])
 | 
					        version = full_version(pkgbuild.get("epoch"), pkgbuild["pkgver"], pkgbuild["pkgrel"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        remote = RemoteSource(
 | 
					        remote = RemoteSource(
 | 
				
			||||||
            source=PackageSource.Local,
 | 
					            source=PackageSource.Local,
 | 
				
			||||||
@ -284,7 +277,7 @@ class Package(LazyLogging):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return cls(
 | 
					        return cls(
 | 
				
			||||||
            base=srcinfo["pkgbase"],
 | 
					            base=pkgbuild["pkgbase"],
 | 
				
			||||||
            version=version,
 | 
					            version=version,
 | 
				
			||||||
            remote=remote,
 | 
					            remote=remote,
 | 
				
			||||||
            packages=packages,
 | 
					            packages=packages,
 | 
				
			||||||
@ -363,16 +356,12 @@ class Package(LazyLogging):
 | 
				
			|||||||
        Raises:
 | 
					        Raises:
 | 
				
			||||||
            PackageInfoError: if there are parsing errors
 | 
					            PackageInfoError: if there are parsing errors
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        srcinfo_source = check_output("makepkg", "--printsrcinfo", cwd=path)
 | 
					        pkgbuild = Pkgbuild.from_file(path / "PKGBUILD")
 | 
				
			||||||
        srcinfo, errors = parse_srcinfo(srcinfo_source)
 | 
					 | 
				
			||||||
        if errors:
 | 
					 | 
				
			||||||
            raise PackageInfoError(errors)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # we could use arch property, but for consistency it is better to call special method
 | 
					        # we could use arch property, but for consistency it is better to call special method
 | 
				
			||||||
        architectures = Package.supported_architectures(path)
 | 
					        architectures = Package.supported_architectures(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for architecture in architectures:
 | 
					        for architecture in architectures:
 | 
				
			||||||
            for source in srcinfo_property_list("source", srcinfo, {}, architecture=architecture):
 | 
					            for source in srcinfo_property_list("source", pkgbuild, {}, architecture=architecture):
 | 
				
			||||||
                if "::" in source:
 | 
					                if "::" in source:
 | 
				
			||||||
                    _, source = source.split("::", 1)  # in case if filename is specified, remove it
 | 
					                    _, source = source.split("::", 1)  # in case if filename is specified, remove it
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -383,7 +372,7 @@ class Package(LazyLogging):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                yield Path(source)
 | 
					                yield Path(source)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (install := srcinfo.get("install", None)) is not None:
 | 
					        if (install := pkgbuild.get("install")) is not None:
 | 
				
			||||||
            yield Path(install)
 | 
					            yield Path(install)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
@ -396,15 +385,9 @@ class Package(LazyLogging):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
            set[str]: list of package supported architectures
 | 
					            set[str]: list of package supported architectures
 | 
				
			||||||
 | 
					 | 
				
			||||||
        Raises:
 | 
					 | 
				
			||||||
            PackageInfoError: if there are parsing errors
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        srcinfo_source = check_output("makepkg", "--printsrcinfo", cwd=path)
 | 
					        pkgbuild = Pkgbuild.from_file(path / "PKGBUILD")
 | 
				
			||||||
        srcinfo, errors = parse_srcinfo(srcinfo_source)
 | 
					        return set(pkgbuild.get("arch", []))
 | 
				
			||||||
        if errors:
 | 
					 | 
				
			||||||
            raise PackageInfoError(errors)
 | 
					 | 
				
			||||||
        return set(srcinfo.get("arch", []))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _package_list_property(self, extractor: Callable[[PackageDescription], list[str]]) -> list[str]:
 | 
					    def _package_list_property(self, extractor: Callable[[PackageDescription], list[str]]) -> list[str]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@ -426,39 +409,39 @@ class Package(LazyLogging):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return sorted(set(generator()))
 | 
					        return sorted(set(generator()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def actual_version(self, paths: RepositoryPaths) -> str:
 | 
					    def actual_version(self, configuration: Configuration) -> str:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        additional method to handle VCS package versions
 | 
					        additional method to handle VCS package versions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Args:
 | 
					        Args:
 | 
				
			||||||
            paths(RepositoryPaths): repository paths instance
 | 
					            configuration(Configuration): configuration instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
            str: package version if package is not VCS and current version according to VCS otherwise
 | 
					            str: package version if package is not VCS and current version according to VCS otherwise
 | 
				
			||||||
 | 
					 | 
				
			||||||
        Raises:
 | 
					 | 
				
			||||||
            PackageInfoError: if there are parsing errors
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if not self.is_vcs:
 | 
					        if not self.is_vcs:
 | 
				
			||||||
            return self.version
 | 
					            return self.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        from ahriman.core.build_tools.sources import Sources
 | 
					        from ahriman.core.build_tools.task import Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Sources.load(paths.cache_for(self.base), self, [], paths)
 | 
					        _, repository_id = configuration.check_loaded()
 | 
				
			||||||
 | 
					        paths = configuration.repository_paths
 | 
				
			||||||
 | 
					        task = Task(self, configuration, repository_id.architecture, paths)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # update pkgver first
 | 
					            # create fresh chroot environment, fetch sources and - automagically - update PKGBUILD
 | 
				
			||||||
            check_output("makepkg", "--nodeps", "--nobuild", cwd=paths.cache_for(self.base), logger=self.logger)
 | 
					            task.init(paths.cache_for(self.base), [], None)
 | 
				
			||||||
            # generate new .SRCINFO and put it to parser
 | 
					            task.build(paths.cache_for(self.base), dry_run=True)
 | 
				
			||||||
            srcinfo_source = check_output("makepkg", "--printsrcinfo",
 | 
					 | 
				
			||||||
                                          cwd=paths.cache_for(self.base), logger=self.logger)
 | 
					 | 
				
			||||||
            srcinfo, errors = parse_srcinfo(srcinfo_source)
 | 
					 | 
				
			||||||
            if errors:
 | 
					 | 
				
			||||||
                raise PackageInfoError(errors)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return full_version(srcinfo.get("epoch"), srcinfo["pkgver"], srcinfo["pkgrel"])
 | 
					            pkgbuild = Pkgbuild.from_file(paths.cache_for(self.base) / "PKGBUILD")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return full_version(pkgbuild.get("epoch"), pkgbuild["pkgver"], pkgbuild["pkgrel"])
 | 
				
			||||||
        except Exception:
 | 
					        except Exception:
 | 
				
			||||||
            self.logger.exception("cannot determine version of VCS package, make sure that VCS tools are installed")
 | 
					            self.logger.exception("cannot determine version of VCS package")
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            # clear log files generated by devtools
 | 
				
			||||||
 | 
					            for log_file in paths.cache_for(self.base).glob("*.log"):
 | 
				
			||||||
 | 
					                log_file.unlink()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self.version
 | 
					        return self.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -513,26 +496,25 @@ class Package(LazyLogging):
 | 
				
			|||||||
            if package.build_date is not None
 | 
					            if package.build_date is not None
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def is_outdated(self, remote: Package, paths: RepositoryPaths, *,
 | 
					    def is_outdated(self, remote: Package, configuration: Configuration, *,
 | 
				
			||||||
                    vcs_allowed_age: float | int = 0,
 | 
					 | 
				
			||||||
                    calculate_version: bool = True) -> bool:
 | 
					                    calculate_version: bool = True) -> bool:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        check if package is out-of-dated
 | 
					        check if package is out-of-dated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Args:
 | 
					        Args:
 | 
				
			||||||
            remote(Package): package properties from remote source
 | 
					            remote(Package): package properties from remote source
 | 
				
			||||||
            paths(RepositoryPaths): repository paths instance. Required for VCS packages cache
 | 
					            configuration(Configuration): configuration instance
 | 
				
			||||||
            vcs_allowed_age(float | int, optional): max age of the built packages before they will be
 | 
					 | 
				
			||||||
                forced to calculate actual version (Default value = 0)
 | 
					 | 
				
			||||||
            calculate_version(bool, optional): expand version to actual value (by calculating git versions)
 | 
					            calculate_version(bool, optional): expand version to actual value (by calculating git versions)
 | 
				
			||||||
                (Default value = True)
 | 
					                (Default value = True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
            bool: ``True`` if the package is out-of-dated and ``False`` otherwise
 | 
					            bool: ``True`` if the package is out-of-dated and ``False`` otherwise
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
					        vcs_allowed_age = configuration.getint("build", "vcs_allowed_age", fallback=0)
 | 
				
			||||||
        min_vcs_build_date = utcnow().timestamp() - vcs_allowed_age
 | 
					        min_vcs_build_date = utcnow().timestamp() - vcs_allowed_age
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if calculate_version and not self.is_newer_than(min_vcs_build_date):
 | 
					        if calculate_version and not self.is_newer_than(min_vcs_build_date):
 | 
				
			||||||
            remote_version = remote.actual_version(paths)
 | 
					            remote_version = remote.actual_version(configuration)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            remote_version = remote.version
 | 
					            remote_version = remote.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										368
									
								
								src/ahriman/models/pkgbuild.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								src/ahriman/models/pkgbuild.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,368 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2021-2024 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 itertools
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import shlex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from collections.abc import Generator, Iterator, Mapping
 | 
				
			||||||
 | 
					from dataclasses import dataclass
 | 
				
			||||||
 | 
					from enum import StrEnum
 | 
				
			||||||
 | 
					from io import StringIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					from typing import Any, IO, Self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PkgbuildToken(StrEnum):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    well-known tokens dictionary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Attributes:
 | 
				
			||||||
 | 
					        ArrayEnds(PkgbuildToken): (class attribute) array ends token
 | 
				
			||||||
 | 
					        ArrayStarts(PkgbuildToken): (class attribute) array starts token
 | 
				
			||||||
 | 
					        Comma(PkgbuildToken): (class attribute) comma token
 | 
				
			||||||
 | 
					        Comment(PkgbuildToken): (class attribute) comment token
 | 
				
			||||||
 | 
					        FunctionDeclaration(PkgbuildToken): (class attribute) function declaration token
 | 
				
			||||||
 | 
					        FunctionEnds(PkgbuildToken): (class attribute) function ends token
 | 
				
			||||||
 | 
					        FunctionStarts(PkgbuildToken): (class attribute) function starts token
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ArrayStarts = "("
 | 
				
			||||||
 | 
					    ArrayEnds = ")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Comma = ","
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Comment = "#"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FunctionDeclaration = "()"
 | 
				
			||||||
 | 
					    FunctionStarts = "{"
 | 
				
			||||||
 | 
					    FunctionEnds = "}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@dataclass(frozen=True)
 | 
				
			||||||
 | 
					class Pkgbuild(Mapping[str, Any]):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    simple pkgbuild reader implementation in pure python, because others sucks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Attributes:
 | 
				
			||||||
 | 
					        fields(dict[str, PkgbuildPatch]): PKGBUILD fields
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fields: dict[str, PkgbuildPatch]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _ARRAY_ASSIGNMENT = re.compile(r"^(?P<key>\w+)=$")
 | 
				
			||||||
 | 
					    _STRING_ASSIGNMENT = re.compile(r"^(?P<key>\w+)=(?P<value>.+)$")
 | 
				
			||||||
 | 
					    # in addition, functions can have dash to usual assignment
 | 
				
			||||||
 | 
					    _FUNCTION_DECLARATION = re.compile(r"^(?P<key>[\w-]+)$")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def variables(self) -> dict[str, str]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        list of variables defined and (maybe) used in this PKGBUILD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            dict[str, str]: map of variable name to its value. The value will be included here in case if it presented
 | 
				
			||||||
 | 
					            in the internal dictionary, it is not a function and the value has string type
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            key: value.value
 | 
				
			||||||
 | 
					            for key, value in self.fields.items()
 | 
				
			||||||
 | 
					            if not value.is_function and isinstance(value.value, str)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def from_file(cls, path: Path) -> Self:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        parse PKGBUILD from the file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            path(Path): path to the PKGBUILD file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            Self: constructed instance of self
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        with path.open() as input_file:
 | 
				
			||||||
 | 
					            return cls.from_io(input_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def from_io(cls, stream: IO[str]) -> Self:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        parse PKGBUILD from input stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            stream: IO[str]: input stream containing PKGBUILD content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            Self: constructed instance of self
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        fields = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parser = shlex.shlex(stream, posix=True, punctuation_chars=True)
 | 
				
			||||||
 | 
					        # ignore substitution and extend bash symbols
 | 
				
			||||||
 | 
					        parser.wordchars += "${}#:+-@"
 | 
				
			||||||
 | 
					        # in case of default behaviour, it will ignore, for example, segment part of url outside of quotes
 | 
				
			||||||
 | 
					        parser.commenters = ""
 | 
				
			||||||
 | 
					        while token := parser.get_token():
 | 
				
			||||||
 | 
					            if (patch := cls._parse_token(token, parser)) is not None:
 | 
				
			||||||
 | 
					                fields[patch.key] = patch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # pkgbase is optional field, the pkgname must be used instead if not set
 | 
				
			||||||
 | 
					        # however, pkgname is not presented is "package()" functions which we are parsing here too,
 | 
				
			||||||
 | 
					        # thus, in our terms, it is optional too
 | 
				
			||||||
 | 
					        if "pkgbase" not in fields and "pkgname" in fields:
 | 
				
			||||||
 | 
					            fields["pkgbase"] = fields["pkgname"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cls({key: value for key, value in fields.items() if key})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def _expand_array(array: list[str]) -> list[str]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        bash array expansion simulator. It takes raw parsed array and tries to expand constructions like
 | 
				
			||||||
 | 
					        ``(first prefix-{mid1,mid2}-suffix last)`` into ``(first, prefix-mid1-suffix prefix-mid2-suffix last)``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            array(list[str]): input array
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            list[str]: either source array or expanded array if possible
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Raises:
 | 
				
			||||||
 | 
					            ValueError: if there are errors in parser
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # we are using comma as marker for expansion (if any)
 | 
				
			||||||
 | 
					        if PkgbuildToken.Comma not in array:
 | 
				
			||||||
 | 
					            return array
 | 
				
			||||||
 | 
					        # again sanity check, for expansion there are at least 3 elements (first, last and comma)
 | 
				
			||||||
 | 
					        if len(array) < 3:
 | 
				
			||||||
 | 
					            return array
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = []
 | 
				
			||||||
 | 
					        buffer, prefix = [], None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for index, (first, second) in enumerate(itertools.pairwise(array)):
 | 
				
			||||||
 | 
					            match (first, second):
 | 
				
			||||||
 | 
					                # in this case we check if expansion should be started
 | 
				
			||||||
 | 
					                # this condition matches "prefix{first", ","
 | 
				
			||||||
 | 
					                case (_, PkgbuildToken.Comma) if PkgbuildToken.FunctionStarts in first:
 | 
				
			||||||
 | 
					                    prefix, part = first.rsplit(PkgbuildToken.FunctionStarts, maxsplit=1)
 | 
				
			||||||
 | 
					                    buffer.append(f"{prefix}{part}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # the last element case, it matches either ",", "last}" or ",", "last}suffix"
 | 
				
			||||||
 | 
					                # in case if there is suffix, it must be appended to all list elements
 | 
				
			||||||
 | 
					                case (PkgbuildToken.Comma, _) if prefix is not None and PkgbuildToken.FunctionEnds in second:
 | 
				
			||||||
 | 
					                    part, suffix = second.rsplit(PkgbuildToken.FunctionEnds, maxsplit=1)
 | 
				
			||||||
 | 
					                    buffer.append(f"{prefix}{part}")
 | 
				
			||||||
 | 
					                    result.extend([f"{part}{suffix}" for part in buffer])
 | 
				
			||||||
 | 
					                    # reset state
 | 
				
			||||||
 | 
					                    buffer, prefix = [], None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # we have already prefix string, so we are in progress of expansion
 | 
				
			||||||
 | 
					                # we always operate the last element, so this matches ",", "next"
 | 
				
			||||||
 | 
					                case (PkgbuildToken.Comma, _) if prefix is not None:
 | 
				
			||||||
 | 
					                    buffer.append(f"{prefix}{second}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # exactly first element of the list
 | 
				
			||||||
 | 
					                case (_, _) if prefix is None and index == 0:
 | 
				
			||||||
 | 
					                    result.append(first)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # any next normal element
 | 
				
			||||||
 | 
					                case (_, _) if prefix is None:
 | 
				
			||||||
 | 
					                    result.append(second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # small sanity check
 | 
				
			||||||
 | 
					        if prefix is not None:
 | 
				
			||||||
 | 
					            raise ValueError(f"Could not expand `{array}` as array")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def _parse_array(parser: shlex.shlex) -> list[str]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        parse array from the PKGBUILD. This method will extract tokens from parser until it matches closing array,
 | 
				
			||||||
 | 
					        modifying source parser state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            parser(shlex.shlex): shell parser instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            list[str]: extracted arrays elements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Raises:
 | 
				
			||||||
 | 
					            ValueError: if array is not closed
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        def extract() -> Generator[str, None, None]:
 | 
				
			||||||
 | 
					            while token := parser.get_token():
 | 
				
			||||||
 | 
					                if token == PkgbuildToken.ArrayEnds:
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					                if token == PkgbuildToken.Comment:
 | 
				
			||||||
 | 
					                    parser.instream.readline()
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                yield token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if token != PkgbuildToken.ArrayEnds:
 | 
				
			||||||
 | 
					                raise ValueError("No closing array bracket found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Pkgbuild._expand_array(list(extract()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def _parse_function(parser: shlex.shlex) -> str:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        parse function from the PKGBUILD. This method will extract tokens from parser until it matches closing function,
 | 
				
			||||||
 | 
					        modifying source parser state. Instead of trying to combine tokens together, it uses positions of the file
 | 
				
			||||||
 | 
					        and read content again in this range
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            parser(shlex.shlex): shell parser instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            str: function body
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Raises:
 | 
				
			||||||
 | 
					            ValueError: if function body wasn't found or parser input stream doesn't support position reading
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        io: IO[str] = parser.instream  # type: ignore[assignment]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # find start and end positions
 | 
				
			||||||
 | 
					        start_position, end_position = -1, -1
 | 
				
			||||||
 | 
					        while token := parser.get_token():
 | 
				
			||||||
 | 
					            match token:
 | 
				
			||||||
 | 
					                case PkgbuildToken.FunctionStarts:
 | 
				
			||||||
 | 
					                    start_position = io.tell() - 1
 | 
				
			||||||
 | 
					                case PkgbuildToken.FunctionEnds:
 | 
				
			||||||
 | 
					                    end_position = io.tell()
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not 0 < start_position < end_position:
 | 
				
			||||||
 | 
					            raise ValueError("Function body wasn't found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # read the specified interval from source stream
 | 
				
			||||||
 | 
					        io.seek(start_position - 1)  # start from the previous symbol
 | 
				
			||||||
 | 
					        content = io.read(end_position - start_position)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def _parse_token(token: str, parser: shlex.shlex) -> PkgbuildPatch | None:  # pylint: disable=too-many-return-statementste
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        parse single token to the PKGBUILD field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            token(str): current token
 | 
				
			||||||
 | 
					            parser(shlex.shlex): shell parser instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            PkgbuildPatch: extracted a PKGBUILD node
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # simple assignment rule
 | 
				
			||||||
 | 
					        if (match := Pkgbuild._STRING_ASSIGNMENT.match(token)) is not None:
 | 
				
			||||||
 | 
					            key = match.group("key")
 | 
				
			||||||
 | 
					            value = match.group("value")
 | 
				
			||||||
 | 
					            return PkgbuildPatch(key, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if token == PkgbuildToken.Comment:
 | 
				
			||||||
 | 
					            parser.instream.readline()
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match parser.get_token():
 | 
				
			||||||
 | 
					            # array processing. Arrays will be sent as "key=", "(", values, ")"
 | 
				
			||||||
 | 
					            case PkgbuildToken.ArrayStarts if (match := Pkgbuild._ARRAY_ASSIGNMENT.match(token)) is not None:
 | 
				
			||||||
 | 
					                key = match.group("key")
 | 
				
			||||||
 | 
					                value = Pkgbuild._parse_array(parser)
 | 
				
			||||||
 | 
					                return PkgbuildPatch(key, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # functions processing. Function will be sent as "name", "()", "{", body, "}"
 | 
				
			||||||
 | 
					            case PkgbuildToken.FunctionDeclaration if Pkgbuild._FUNCTION_DECLARATION.match(token):
 | 
				
			||||||
 | 
					                key = f"{token}{PkgbuildToken.FunctionDeclaration}"
 | 
				
			||||||
 | 
					                value = Pkgbuild._parse_function(parser)
 | 
				
			||||||
 | 
					                return PkgbuildPatch(key, value)  # this is not mistake, assign to token without ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # special function case, where "(" and ")" are separated tokens, e.g. "pkgver ( )"
 | 
				
			||||||
 | 
					            case PkgbuildToken.ArrayStarts if Pkgbuild._FUNCTION_DECLARATION.match(token):
 | 
				
			||||||
 | 
					                next_token = parser.get_token()
 | 
				
			||||||
 | 
					                if next_token == PkgbuildToken.ArrayEnds:  # replace closing bracket with "()"
 | 
				
			||||||
 | 
					                    next_token = PkgbuildToken.FunctionDeclaration
 | 
				
			||||||
 | 
					                parser.push_token(next_token)  # type: ignore[arg-type]
 | 
				
			||||||
 | 
					                return Pkgbuild._parse_token(token, parser)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # some random token received without continuation, lets guess it is empty assignment (i.e. key=)
 | 
				
			||||||
 | 
					            case other if other is not None:
 | 
				
			||||||
 | 
					                return Pkgbuild._parse_token(other, parser)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return None  # basically end of the parser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def packages(self) -> dict[str, Self]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        extract properties from internal package functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            dict[str, Self]: map of package name to its inner properties if defined
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        packages = [self["pkgname"]] if isinstance(self["pkgname"], str) else self["pkgname"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def io(package_name: str) -> IO[str]:
 | 
				
			||||||
 | 
					            # try to read package specific function and fallback to default otherwise
 | 
				
			||||||
 | 
					            content = self.get(f"package_{package_name}") or self["package"]
 | 
				
			||||||
 | 
					            return StringIO(content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {package: self.from_io(io(package)) for package in packages}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __getitem__(self, item: str) -> Any:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        get the field of the PKGBUILD. This method tries to get exact key value if possible; if none found, it tries to
 | 
				
			||||||
 | 
					        fetch function with the same name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            item(str): key name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            Any: substituted value by the key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Raises:
 | 
				
			||||||
 | 
					            KeyError: if key doesn't exist
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        value = self.fields.get(item)
 | 
				
			||||||
 | 
					        # if the key wasn't found and user didn't ask for function explicitly, we can try to get by function name
 | 
				
			||||||
 | 
					        if value is None and not item.endswith(PkgbuildToken.FunctionDeclaration):
 | 
				
			||||||
 | 
					            value = self.fields.get(f"{item}{PkgbuildToken.FunctionDeclaration}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # if we still didn't find anything, we can just raise the exception
 | 
				
			||||||
 | 
					        if value is None:
 | 
				
			||||||
 | 
					            raise KeyError(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return value.substitute(self.variables)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __iter__(self) -> Iterator[str]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        iterate over the fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            Iterator[str]: keys iterator
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return iter(self.fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __len__(self) -> int:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        get length of the mapping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            int: amount of the fields in this PKGBUILD
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return len(self.fields)
 | 
				
			||||||
@ -21,6 +21,7 @@ import shlex
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from dataclasses import dataclass, fields
 | 
					from dataclasses import dataclass, fields
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					from string import Template
 | 
				
			||||||
from typing import Any, Generator, Self
 | 
					from typing import Any, Generator, Self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.utils import dataclass_view, filter_json
 | 
					from ahriman.core.utils import dataclass_view, filter_json
 | 
				
			||||||
@ -167,6 +168,21 @@ class PkgbuildPatch:
 | 
				
			|||||||
            return f"{self.key} {self.value}"  # no quoting enabled here
 | 
					            return f"{self.key} {self.value}"  # no quoting enabled here
 | 
				
			||||||
        return f"""{self.key}={PkgbuildPatch.quote(self.value)}"""
 | 
					        return f"""{self.key}={PkgbuildPatch.quote(self.value)}"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def substitute(self, variables: dict[str, str]) -> str | list[str]:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        substitute variables into the value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Args:
 | 
				
			||||||
 | 
					            variables(dict[str, str]): map of variables available for usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Returns:
 | 
				
			||||||
 | 
					            str | list[str]: substituted value. All unknown variables will remain as links to their values.
 | 
				
			||||||
 | 
					            This function doesn't support recursive substitution
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if isinstance(self.value, str):
 | 
				
			||||||
 | 
					            return Template(self.value).safe_substitute(variables)
 | 
				
			||||||
 | 
					        return [Template(value).safe_substitute(variables) for value in self.value]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def view(self) -> dict[str, Any]:
 | 
					    def view(self) -> dict[str, Any]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        generate json patch view
 | 
					        generate json patch view
 | 
				
			||||||
 | 
				
			|||||||
@ -28,9 +28,9 @@ def test_package_dependencies() -> None:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must extract package dependencies
 | 
					    must extract package dependencies
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    packages = dict(Versions.package_dependencies("srcinfo"))
 | 
					    packages = dict(Versions.package_dependencies("requests"))
 | 
				
			||||||
    assert packages
 | 
					    assert packages
 | 
				
			||||||
    assert packages.get("parse") is not None
 | 
					    assert packages.get("urllib3") is not None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_package_dependencies_missing() -> None:
 | 
					def test_package_dependencies_missing() -> None:
 | 
				
			||||||
 | 
				
			|||||||
@ -2,37 +2,65 @@ import pytest
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from pytest_mock import MockerFixture
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
from unittest.mock import call as MockCall
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.build_tools.task import Task
 | 
					from ahriman.core.build_tools.task import Task
 | 
				
			||||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
					from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_package_archives(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must correctly return list of new files
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.iterdir", return_value=[
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-debug-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path("source.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path("randomfile"),
 | 
				
			||||||
 | 
					        Path("namcap.log"),
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					    assert task_ahriman._package_archives(Path("local"), [Path("source.pkg.tar.xz")]) == [
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-debug-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_package_archives_no_debug(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must correctly return list of new files without debug packages
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    task_ahriman.include_debug_packages = False
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.iterdir", return_value=[
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-debug-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path("source.pkg.tar.xz"),
 | 
				
			||||||
 | 
					        Path("randomfile"),
 | 
				
			||||||
 | 
					        Path("namcap.log"),
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					    assert task_ahriman._package_archives(Path("local"), [Path("source.pkg.tar.xz")]) == [
 | 
				
			||||||
 | 
					        Path(f"{task_ahriman.package.base}-{task_ahriman.package.version}-any.pkg.tar.xz"),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_build(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
					def test_build(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must build package
 | 
					    must build package
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    local = Path("local")
 | 
					    local = Path("local")
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.iterdir", return_value=["file"])
 | 
				
			||||||
    check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
 | 
				
			||||||
 | 
					    archives_mock = mocker.patch("ahriman.core.build_tools.task.Task._package_archives",
 | 
				
			||||||
 | 
					                                 return_value=[task_ahriman.package.base])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    task_ahriman.build(local)
 | 
					    assert task_ahriman.build(local) == [task_ahriman.package.base]
 | 
				
			||||||
    check_output_mock.assert_has_calls([
 | 
					    check_output_mock.assert_called_once_with(
 | 
				
			||||||
        MockCall(
 | 
					        "extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
 | 
				
			||||||
            "extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
 | 
					        exception=pytest.helpers.anyvar(int),
 | 
				
			||||||
            exception=pytest.helpers.anyvar(int),
 | 
					        cwd=local,
 | 
				
			||||||
            cwd=local,
 | 
					        logger=task_ahriman.logger,
 | 
				
			||||||
            logger=task_ahriman.logger,
 | 
					        user=task_ahriman.uid,
 | 
				
			||||||
            user=task_ahriman.uid,
 | 
					        environment={},
 | 
				
			||||||
            environment={},
 | 
					    )
 | 
				
			||||||
        ),
 | 
					    archives_mock.assert_called_once_with(local, ["file"])
 | 
				
			||||||
        MockCall(
 | 
					 | 
				
			||||||
            "makepkg", "--packagelist",
 | 
					 | 
				
			||||||
            exception=pytest.helpers.anyvar(int),
 | 
					 | 
				
			||||||
            cwd=local,
 | 
					 | 
				
			||||||
            logger=task_ahriman.logger,
 | 
					 | 
				
			||||||
            environment={},
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    ])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_build_environment(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
					def test_build_environment(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			||||||
@ -40,55 +68,41 @@ def test_build_environment(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			|||||||
    must build package with environment variables set
 | 
					    must build package with environment variables set
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    local = Path("local")
 | 
					    local = Path("local")
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.iterdir", return_value=["file"])
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.build_tools.task.Task._package_archives", return_value=[task_ahriman.package.base])
 | 
				
			||||||
    check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    environment = {"variable": "value"}
 | 
					    environment = {"variable": "value"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    task_ahriman.build(local, **environment, empty=None)
 | 
					    task_ahriman.build(local, **environment, empty=None)
 | 
				
			||||||
    check_output_mock.assert_has_calls([
 | 
					    check_output_mock.assert_called_once_with(
 | 
				
			||||||
        MockCall(
 | 
					        "extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
 | 
				
			||||||
            "extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
 | 
					        exception=pytest.helpers.anyvar(int),
 | 
				
			||||||
            exception=pytest.helpers.anyvar(int),
 | 
					        cwd=local,
 | 
				
			||||||
            cwd=local,
 | 
					        logger=task_ahriman.logger,
 | 
				
			||||||
            logger=task_ahriman.logger,
 | 
					        user=task_ahriman.uid,
 | 
				
			||||||
            user=task_ahriman.uid,
 | 
					        environment=environment,
 | 
				
			||||||
            environment=environment,
 | 
					    )
 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        MockCall(
 | 
					 | 
				
			||||||
            "makepkg", "--packagelist",
 | 
					 | 
				
			||||||
            exception=pytest.helpers.anyvar(int),
 | 
					 | 
				
			||||||
            cwd=local,
 | 
					 | 
				
			||||||
            logger=task_ahriman.logger,
 | 
					 | 
				
			||||||
            environment=environment,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    ])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_build_no_debug(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
					def test_build_dry_run(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must filter debug packages from result
 | 
					    must run devtools in dry-run mode
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    local = Path("local")
 | 
					    local = Path("local")
 | 
				
			||||||
 | 
					    mocker.patch("pathlib.Path.iterdir", return_value=["file"])
 | 
				
			||||||
 | 
					    mocker.patch("ahriman.core.build_tools.task.Task._package_archives", return_value=[task_ahriman.package.base])
 | 
				
			||||||
    check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
 | 
					    check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
 | 
				
			||||||
    task_ahriman.include_debug_packages = False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    task_ahriman.build(local)
 | 
					    assert task_ahriman.build(local, dry_run=True) == [task_ahriman.package.base]
 | 
				
			||||||
    check_output_mock.assert_has_calls([
 | 
					    check_output_mock.assert_called_once_with(
 | 
				
			||||||
        MockCall(
 | 
					        "extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck", "--nobuild",
 | 
				
			||||||
            "extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
 | 
					        exception=pytest.helpers.anyvar(int),
 | 
				
			||||||
            exception=pytest.helpers.anyvar(int),
 | 
					        cwd=local,
 | 
				
			||||||
            cwd=local,
 | 
					        logger=task_ahriman.logger,
 | 
				
			||||||
            logger=task_ahriman.logger,
 | 
					        user=task_ahriman.uid,
 | 
				
			||||||
            user=task_ahriman.uid,
 | 
					        environment={},
 | 
				
			||||||
            environment={},
 | 
					    )
 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        MockCall(
 | 
					 | 
				
			||||||
            "makepkg", "--packagelist", "OPTIONS=(!debug)",
 | 
					 | 
				
			||||||
            exception=pytest.helpers.anyvar(int),
 | 
					 | 
				
			||||||
            cwd=local,
 | 
					 | 
				
			||||||
            logger=task_ahriman.logger,
 | 
					 | 
				
			||||||
            environment={},
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    ])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_init(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
					def test_init(task_ahriman: Task, mocker: MockerFixture) -> None:
 | 
				
			||||||
 | 
				
			|||||||
@ -31,8 +31,7 @@ def test_updates_aur(update_handler: UpdateHandler, package_ahriman: Package,
 | 
				
			|||||||
    event_mock.assert_called_once_with(package_ahriman.base, EventType.PackageOutdated,
 | 
					    event_mock.assert_called_once_with(package_ahriman.base, EventType.PackageOutdated,
 | 
				
			||||||
                                       pytest.helpers.anyvar(str, True))
 | 
					                                       pytest.helpers.anyvar(str, True))
 | 
				
			||||||
    package_is_outdated_mock.assert_called_once_with(
 | 
					    package_is_outdated_mock.assert_called_once_with(
 | 
				
			||||||
        package_ahriman, update_handler.paths,
 | 
					        package_ahriman, update_handler.configuration,
 | 
				
			||||||
        vcs_allowed_age=update_handler.vcs_allowed_age,
 | 
					 | 
				
			||||||
        calculate_version=True)
 | 
					        calculate_version=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -119,8 +118,7 @@ def test_updates_aur_ignore_vcs(update_handler: UpdateHandler, package_ahriman:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    assert not update_handler.updates_aur([], vcs=False)
 | 
					    assert not update_handler.updates_aur([], vcs=False)
 | 
				
			||||||
    package_is_outdated_mock.assert_called_once_with(
 | 
					    package_is_outdated_mock.assert_called_once_with(
 | 
				
			||||||
        package_ahriman, update_handler.paths,
 | 
					        package_ahriman, update_handler.configuration,
 | 
				
			||||||
        vcs_allowed_age=update_handler.vcs_allowed_age,
 | 
					 | 
				
			||||||
        calculate_version=False)
 | 
					        calculate_version=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -227,8 +225,7 @@ def test_updates_local(update_handler: UpdateHandler, package_ahriman: Package,
 | 
				
			|||||||
    event_mock.assert_called_once_with(package_ahriman.base, EventType.PackageOutdated,
 | 
					    event_mock.assert_called_once_with(package_ahriman.base, EventType.PackageOutdated,
 | 
				
			||||||
                                       pytest.helpers.anyvar(str, True))
 | 
					                                       pytest.helpers.anyvar(str, True))
 | 
				
			||||||
    package_is_outdated_mock.assert_called_once_with(
 | 
					    package_is_outdated_mock.assert_called_once_with(
 | 
				
			||||||
        package_ahriman, update_handler.paths,
 | 
					        package_ahriman, update_handler.configuration,
 | 
				
			||||||
        vcs_allowed_age=update_handler.vcs_allowed_age,
 | 
					 | 
				
			||||||
        calculate_version=True)
 | 
					        calculate_version=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -245,8 +242,7 @@ def test_updates_local_ignore_vcs(update_handler: UpdateHandler, package_ahriman
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    assert not update_handler.updates_local(vcs=False)
 | 
					    assert not update_handler.updates_local(vcs=False)
 | 
				
			||||||
    package_is_outdated_mock.assert_called_once_with(
 | 
					    package_is_outdated_mock.assert_called_once_with(
 | 
				
			||||||
        package_ahriman, update_handler.paths,
 | 
					        package_ahriman, update_handler.configuration,
 | 
				
			||||||
        vcs_allowed_age=update_handler.vcs_allowed_age,
 | 
					 | 
				
			||||||
        calculate_version=False)
 | 
					        calculate_version=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -468,11 +468,11 @@ def test_walk(resource_path_root: Path) -> None:
 | 
				
			|||||||
        resource_path_root / "models" / "package_ahriman_aur",
 | 
					        resource_path_root / "models" / "package_ahriman_aur",
 | 
				
			||||||
        resource_path_root / "models" / "package_akonadi_aur",
 | 
					        resource_path_root / "models" / "package_akonadi_aur",
 | 
				
			||||||
        resource_path_root / "models" / "package_ahriman_files",
 | 
					        resource_path_root / "models" / "package_ahriman_files",
 | 
				
			||||||
        resource_path_root / "models" / "package_ahriman_srcinfo",
 | 
					        resource_path_root / "models" / "package_ahriman_pkgbuild",
 | 
				
			||||||
        resource_path_root / "models" / "package_gcc10_srcinfo",
 | 
					        resource_path_root / "models" / "package_gcc10_pkgbuild",
 | 
				
			||||||
        resource_path_root / "models" / "package_jellyfin-ffmpeg5-bin_srcinfo",
 | 
					        resource_path_root / "models" / "package_jellyfin-ffmpeg6-bin_pkgbuild",
 | 
				
			||||||
        resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo",
 | 
					        resource_path_root / "models" / "package_tpacpi-bat-git_pkgbuild",
 | 
				
			||||||
        resource_path_root / "models" / "package_yay_srcinfo",
 | 
					        resource_path_root / "models" / "package_yay_pkgbuild",
 | 
				
			||||||
        resource_path_root / "web" / "templates" / "build-status" / "alerts.jinja2",
 | 
					        resource_path_root / "web" / "templates" / "build-status" / "alerts.jinja2",
 | 
				
			||||||
        resource_path_root / "web" / "templates" / "build-status" / "key-import-modal.jinja2",
 | 
					        resource_path_root / "web" / "templates" / "build-status" / "key-import-modal.jinja2",
 | 
				
			||||||
        resource_path_root / "web" / "templates" / "build-status" / "login-modal.jinja2",
 | 
					        resource_path_root / "web" / "templates" / "build-status" / "login-modal.jinja2",
 | 
				
			||||||
 | 
				
			|||||||
@ -15,8 +15,8 @@ def test_calculate_hash_small(resource_path_root: Path) -> None:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must calculate checksum for path which is single chunk
 | 
					    must calculate checksum for path which is single chunk
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    path = resource_path_root / "models" / "package_ahriman_srcinfo"
 | 
					    path = resource_path_root / "models" / "package_ahriman_pkgbuild"
 | 
				
			||||||
    assert HttpUpload.calculate_hash(path) == "2635e2898452d594025517cfe529b1f2"
 | 
					    assert HttpUpload.calculate_hash(path) == "7136fc388980dc043f9f869d57c5ce0c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_get_body_get_hashes() -> None:
 | 
					def test_get_body_get_hashes() -> None:
 | 
				
			||||||
 | 
				
			|||||||
@ -49,8 +49,8 @@ def test_calculate_etag_small(resource_path_root: Path) -> None:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must calculate checksum for path which is single chunk
 | 
					    must calculate checksum for path which is single chunk
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    path = resource_path_root / "models" / "package_ahriman_srcinfo"
 | 
					    path = resource_path_root / "models" / "package_ahriman_pkgbuild"
 | 
				
			||||||
    assert S3.calculate_etag(path, _chunk_size) == "2635e2898452d594025517cfe529b1f2"
 | 
					    assert S3.calculate_etag(path, _chunk_size) == "7136fc388980dc043f9f869d57c5ce0c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_files_remove(s3_remote_objects: list[Any]) -> None:
 | 
					def test_files_remove(s3_remote_objects: list[Any]) -> None:
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,16 @@
 | 
				
			|||||||
import pytest
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from pytest_mock import MockerFixture
 | 
					from pytest_mock import MockerFixture
 | 
				
			||||||
from srcinfo.parse import parse_srcinfo
 | 
					 | 
				
			||||||
from unittest.mock import MagicMock
 | 
					from unittest.mock import MagicMock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ahriman.core.alpm.pacman import Pacman
 | 
					from ahriman.core.alpm.pacman import Pacman
 | 
				
			||||||
from ahriman.core.exceptions import PackageInfoError
 | 
					from ahriman.core.configuration import Configuration
 | 
				
			||||||
from ahriman.core.utils import utcnow
 | 
					from ahriman.core.utils import utcnow
 | 
				
			||||||
from ahriman.models.aur_package import AURPackage
 | 
					from ahriman.models.aur_package import AURPackage
 | 
				
			||||||
from ahriman.models.package import Package
 | 
					from ahriman.models.package import Package
 | 
				
			||||||
from ahriman.models.package_description import PackageDescription
 | 
					from ahriman.models.package_description import PackageDescription
 | 
				
			||||||
from ahriman.models.repository_paths import RepositoryPaths
 | 
					from ahriman.models.pkgbuild import Pkgbuild
 | 
				
			||||||
 | 
					from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_depends(package_python_schedule: Package) -> None:
 | 
					def test_depends(package_python_schedule: Package) -> None:
 | 
				
			||||||
@ -52,9 +51,8 @@ def test_depends_build_with_version_and_overlap(mocker: MockerFixture, resource_
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must load correct list of dependencies with version
 | 
					    must load correct list of dependencies with version
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    pkgbuild = resource_path_root / "models" / "package_gcc10_pkgbuild"
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_gcc10_srcinfo").read_text()
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    package_gcc10 = Package.from_build(Path("local"), "x86_64", None)
 | 
					    package_gcc10 = Package.from_build(Path("local"), "x86_64", None)
 | 
				
			||||||
    assert package_gcc10.depends_build == {
 | 
					    assert package_gcc10.depends_build == {
 | 
				
			||||||
@ -179,10 +177,10 @@ def test_from_aur(package_ahriman: Package, aur_package_ahriman: AURPackage, moc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_from_build(package_ahriman: Package, mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
					def test_from_build(package_ahriman: Package, mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must construct package from srcinfo
 | 
					    must construct package from PKGBUILD
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_ahriman_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_ahriman_pkgbuild"
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    package = Package.from_build(Path("path"), "x86_64", "packager")
 | 
					    package = Package.from_build(Path("path"), "x86_64", "packager")
 | 
				
			||||||
    assert package_ahriman.packages.keys() == package.packages.keys()
 | 
					    assert package_ahriman.packages.keys() == package.packages.keys()
 | 
				
			||||||
@ -193,15 +191,15 @@ def test_from_build(package_ahriman: Package, mocker: MockerFixture, resource_pa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_from_build_multiple_packages(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
					def test_from_build_multiple_packages(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must construct package from srcinfo with dependencies per-package overrides
 | 
					    must construct package from PKGBUILD with dependencies per-package overrides
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_gcc10_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_gcc10_pkgbuild"
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    package = Package.from_build(Path("path"), "x86_64", None)
 | 
					    package = Package.from_build(Path("path"), "x86_64", None)
 | 
				
			||||||
    assert package.packages == {
 | 
					    assert package.packages == {
 | 
				
			||||||
        "gcc10": PackageDescription(
 | 
					        "gcc10": PackageDescription(
 | 
				
			||||||
            depends=["gcc10-libs=10.3.0-2", "binutils>=2.28", "libmpc", "zstd"],
 | 
					            depends=["gcc10-libs=10.5.0-2", "binutils>=2.28", "libmpc", "zstd"],
 | 
				
			||||||
            make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
 | 
					            make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
 | 
				
			||||||
            opt_depends=[],
 | 
					            opt_depends=[],
 | 
				
			||||||
            check_depends=["dejagnu", "inetutils"],
 | 
					            check_depends=["dejagnu", "inetutils"],
 | 
				
			||||||
@ -213,7 +211,7 @@ def test_from_build_multiple_packages(mocker: MockerFixture, resource_path_root:
 | 
				
			|||||||
            check_depends=["dejagnu", "inetutils"],
 | 
					            check_depends=["dejagnu", "inetutils"],
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        "gcc10-fortran": PackageDescription(
 | 
					        "gcc10-fortran": PackageDescription(
 | 
				
			||||||
            depends=["gcc10=10.3.0-2"],
 | 
					            depends=["gcc10=10.5.0-2"],
 | 
				
			||||||
            make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
 | 
					            make_depends=["binutils", "doxygen", "git", "libmpc", "python"],
 | 
				
			||||||
            opt_depends=[],
 | 
					            opt_depends=[],
 | 
				
			||||||
            check_depends=["dejagnu", "inetutils"],
 | 
					            check_depends=["dejagnu", "inetutils"],
 | 
				
			||||||
@ -225,12 +223,12 @@ def test_from_build_architecture(mocker: MockerFixture, resource_path_root: Path
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must construct package with architecture specific depends list
 | 
					    must construct package with architecture specific depends list
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_jellyfin-ffmpeg5-bin_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_jellyfin-ffmpeg6-bin_pkgbuild"
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    package = Package.from_build(Path("path"), "x86_64", None)
 | 
					    package = Package.from_build(Path("path"), "x86_64", None)
 | 
				
			||||||
    assert package.packages == {
 | 
					    assert package.packages == {
 | 
				
			||||||
        "jellyfin-ffmpeg5-bin": PackageDescription(
 | 
					        "jellyfin-ffmpeg6-bin": PackageDescription(
 | 
				
			||||||
            depends=["glibc"],
 | 
					            depends=["glibc"],
 | 
				
			||||||
            make_depends=[],
 | 
					            make_depends=[],
 | 
				
			||||||
            opt_depends=[
 | 
					            opt_depends=[
 | 
				
			||||||
@ -249,17 +247,6 @@ def test_from_build_architecture(mocker: MockerFixture, resource_path_root: Path
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_from_build_failed(mocker: MockerFixture) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    must raise exception if there are errors during srcinfo load
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value="")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    with pytest.raises(PackageInfoError):
 | 
					 | 
				
			||||||
        Package.from_build(Path("path"), "x86_64", None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_from_json_view_1(package_ahriman: Package) -> None:
 | 
					def test_from_json_view_1(package_ahriman: Package) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must construct same object from json
 | 
					    must construct same object from json
 | 
				
			||||||
@ -299,11 +286,10 @@ def test_local_files(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must extract local file sources
 | 
					    must extract local file sources
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
 | 
				
			||||||
    parsed_srcinfo, _ = parse_srcinfo(srcinfo)
 | 
					    parsed_pkgbuild = Pkgbuild.from_file(pkgbuild)
 | 
				
			||||||
    parsed_srcinfo["source"] = ["local-file.tar.gz"]
 | 
					    parsed_pkgbuild.fields["source"] = PkgbuildPatch("source", ["local-file.tar.gz"])
 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=(parsed_srcinfo, []))
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=parsed_pkgbuild)
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
					    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert list(Package.local_files(Path("path"))) == [Path("local-file.tar.gz")]
 | 
					    assert list(Package.local_files(Path("path"))) == [Path("local-file.tar.gz")]
 | 
				
			||||||
@ -311,35 +297,23 @@ def test_local_files(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def test_local_files_empty(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
					def test_local_files_empty(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must extract empty local files list when there is no local files
 | 
					    must extract empty local files list when there are no local files
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
					    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert not list(Package.local_files(Path("path")))
 | 
					    assert not list(Package.local_files(Path("path")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_local_files_error(mocker: MockerFixture) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    must raise exception on package parsing for local sources
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value="")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    with pytest.raises(PackageInfoError):
 | 
					 | 
				
			||||||
        list(Package.local_files(Path("path")))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_local_files_schema(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
					def test_local_files_schema(mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must skip local file source when file schema is used
 | 
					    must skip local file source when file schema is used
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
 | 
				
			||||||
    parsed_srcinfo, _ = parse_srcinfo(srcinfo)
 | 
					    parsed_pkgbuild = Pkgbuild.from_file(pkgbuild)
 | 
				
			||||||
    parsed_srcinfo["source"] = ["file:///local-file.tar.gz"]
 | 
					    parsed_pkgbuild.fields["source"] = PkgbuildPatch("source", ["file:///local-file.tar.gz"])
 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=(parsed_srcinfo, []))
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=parsed_pkgbuild)
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value="")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
					    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert not list(Package.local_files(Path("path")))
 | 
					    assert not list(Package.local_files(Path("path")))
 | 
				
			||||||
@ -349,11 +323,10 @@ def test_local_files_with_install(mocker: MockerFixture, resource_path_root: Pat
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must extract local file sources with install file
 | 
					    must extract local file sources with install file
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
 | 
				
			||||||
    parsed_srcinfo, _ = parse_srcinfo(srcinfo)
 | 
					    parsed_pkgbuild = Pkgbuild.from_file(pkgbuild)
 | 
				
			||||||
    parsed_srcinfo["install"] = "install"
 | 
					    parsed_pkgbuild.fields["install"] = PkgbuildPatch("install", "install")
 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=(parsed_srcinfo, []))
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=parsed_pkgbuild)
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value="")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
					    mocker.patch("ahriman.models.package.Package.supported_architectures", return_value=["any"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert list(Package.local_files(Path("path"))) == [Path("install")]
 | 
					    assert list(Package.local_files(Path("path"))) == [Path("install")]
 | 
				
			||||||
@ -363,64 +336,49 @@ def test_supported_architectures(mocker: MockerFixture, resource_path_root: Path
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    must generate list of available architectures
 | 
					    must generate list of available architectures
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_yay_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_yay_pkgbuild"
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
    assert Package.supported_architectures(Path("path")) == \
 | 
					    assert Package.supported_architectures(Path("path")) == \
 | 
				
			||||||
        {"i686", "pentium4", "x86_64", "arm", "armv7h", "armv6h", "aarch64"}
 | 
					        {"i686", "pentium4", "x86_64", "arm", "armv7h", "armv6h", "aarch64", "riscv64"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_supported_architectures_failed(mocker: MockerFixture) -> None:
 | 
					def test_actual_version(package_ahriman: Package, configuration: Configuration) -> None:
 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    must raise exception if there are errors during srcinfo load for architectures
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value="")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    with pytest.raises(PackageInfoError):
 | 
					 | 
				
			||||||
        Package.supported_architectures(Path("path"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_actual_version(package_ahriman: Package, repository_paths: RepositoryPaths) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must return same actual_version as version is
 | 
					    must return same actual_version as version is
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    assert package_ahriman.actual_version(repository_paths) == package_ahriman.version
 | 
					    assert package_ahriman.actual_version(configuration) == package_ahriman.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_actual_version_vcs(package_tpacpi_bat_git: Package, repository_paths: RepositoryPaths,
 | 
					def test_actual_version_vcs(package_tpacpi_bat_git: Package, configuration: Configuration,
 | 
				
			||||||
                            mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
					                            mocker: MockerFixture, resource_path_root: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must return valid actual_version for VCS package
 | 
					    must return valid actual_version for VCS package
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    srcinfo = (resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo").read_text()
 | 
					    pkgbuild = resource_path_root / "models" / "package_tpacpi-bat-git_pkgbuild"
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", return_value=srcinfo)
 | 
					    mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_file", return_value=Pkgbuild.from_file(pkgbuild))
 | 
				
			||||||
    mocker.patch("ahriman.core.build_tools.sources.Sources.load")
 | 
					    mocker.patch("pathlib.Path.glob", return_value=[Path("local")])
 | 
				
			||||||
 | 
					    init_mock = mocker.patch("ahriman.core.build_tools.task.Task.init")
 | 
				
			||||||
 | 
					    build_mock = mocker.patch("ahriman.core.build_tools.task.Task.build")
 | 
				
			||||||
 | 
					    unlink_mock = mocker.patch("pathlib.Path.unlink")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert package_tpacpi_bat_git.actual_version(repository_paths) == "3.1.r13.g4959b52-1"
 | 
					    assert package_tpacpi_bat_git.actual_version(configuration) == "3.1.r13.g4959b52-1"
 | 
				
			||||||
 | 
					    init_mock.assert_called_once_with(configuration.repository_paths.cache_for(package_tpacpi_bat_git.base), [], None)
 | 
				
			||||||
 | 
					    build_mock.assert_called_once_with(configuration.repository_paths.cache_for(package_tpacpi_bat_git.base),
 | 
				
			||||||
 | 
					                                       dry_run=True)
 | 
				
			||||||
 | 
					    unlink_mock.assert_called_once_with()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_actual_version_srcinfo_failed(package_tpacpi_bat_git: Package, repository_paths: RepositoryPaths,
 | 
					def test_actual_version_failed(package_tpacpi_bat_git: Package, configuration: Configuration,
 | 
				
			||||||
                                       mocker: MockerFixture) -> None:
 | 
					                               mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must return same version in case if exception occurred
 | 
					    must return same version in case if exception occurred
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output", side_effect=Exception())
 | 
					    mocker.patch("ahriman.core.build_tools.task.Task.init", side_effect=Exception())
 | 
				
			||||||
    mocker.patch("ahriman.core.build_tools.sources.Sources.load")
 | 
					    mocker.patch("pathlib.Path.glob", return_value=[Path("local")])
 | 
				
			||||||
 | 
					    unlink_mock = mocker.patch("pathlib.Path.unlink")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert package_tpacpi_bat_git.actual_version(repository_paths) == package_tpacpi_bat_git.version
 | 
					    assert package_tpacpi_bat_git.actual_version(configuration) == package_tpacpi_bat_git.version
 | 
				
			||||||
 | 
					    unlink_mock.assert_called_once_with()
 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_actual_version_vcs_failed(package_tpacpi_bat_git: Package, repository_paths: RepositoryPaths,
 | 
					 | 
				
			||||||
                                   mocker: MockerFixture) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    must return same version in case if there are errors during parse
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    mocker.patch("pathlib.Path.read_text", return_value="")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"]))
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.models.package.check_output")
 | 
					 | 
				
			||||||
    mocker.patch("ahriman.core.build_tools.sources.Sources.load")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert package_tpacpi_bat_git.actual_version(repository_paths) == package_tpacpi_bat_git.version
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_full_depends(package_ahriman: Package, package_python_schedule: Package, pyalpm_package_ahriman: MagicMock,
 | 
					def test_full_depends(package_ahriman: Package, package_python_schedule: Package, pyalpm_package_ahriman: MagicMock,
 | 
				
			||||||
@ -461,17 +419,17 @@ def test_is_newer_than(package_ahriman: Package, package_python_schedule: Packag
 | 
				
			|||||||
    assert not package_python_schedule.is_newer_than(min_date)
 | 
					    assert not package_python_schedule.is_newer_than(min_date)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_outdated_false(package_ahriman: Package, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
 | 
					def test_is_outdated_false(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must be not outdated for the same package
 | 
					    must be not outdated for the same package
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version",
 | 
					    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version",
 | 
				
			||||||
                                       return_value=package_ahriman.version)
 | 
					                                       return_value=package_ahriman.version)
 | 
				
			||||||
    assert not package_ahriman.is_outdated(package_ahriman, repository_paths)
 | 
					    assert not package_ahriman.is_outdated(package_ahriman, configuration)
 | 
				
			||||||
    actual_version_mock.assert_called_once_with(repository_paths)
 | 
					    actual_version_mock.assert_called_once_with(configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_outdated_true(package_ahriman: Package, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
 | 
					def test_is_outdated_true(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must be outdated for the new version
 | 
					    must be outdated for the new version
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
@ -479,27 +437,28 @@ def test_is_outdated_true(package_ahriman: Package, repository_paths: Repository
 | 
				
			|||||||
    other.version = other.version.replace("-1", "-2")
 | 
					    other.version = other.version.replace("-1", "-2")
 | 
				
			||||||
    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version", return_value=other.version)
 | 
					    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version", return_value=other.version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert package_ahriman.is_outdated(other, repository_paths)
 | 
					    assert package_ahriman.is_outdated(other, configuration)
 | 
				
			||||||
    actual_version_mock.assert_called_once_with(repository_paths)
 | 
					    actual_version_mock.assert_called_once_with(configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_outdated_no_version_calculation(package_ahriman: Package, repository_paths: RepositoryPaths,
 | 
					def test_is_outdated_no_version_calculation(package_ahriman: Package, configuration: Configuration,
 | 
				
			||||||
                                            mocker: MockerFixture) -> None:
 | 
					                                            mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must not call actual version if calculation is disabled
 | 
					    must not call actual version if calculation is disabled
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version")
 | 
					    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version")
 | 
				
			||||||
    assert not package_ahriman.is_outdated(package_ahriman, repository_paths, calculate_version=False)
 | 
					    assert not package_ahriman.is_outdated(package_ahriman, configuration, calculate_version=False)
 | 
				
			||||||
    actual_version_mock.assert_not_called()
 | 
					    actual_version_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_outdated_fresh_package(package_ahriman: Package, repository_paths: RepositoryPaths,
 | 
					def test_is_outdated_fresh_package(package_ahriman: Package, configuration: Configuration,
 | 
				
			||||||
                                   mocker: MockerFixture) -> None:
 | 
					                                   mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must not call actual version if package is never than specified time
 | 
					    must not call actual version if package is never than specified time
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    configuration.set_option("build", "vcs_allowed_age", str(int(utcnow().timestamp())))
 | 
				
			||||||
    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version")
 | 
					    actual_version_mock = mocker.patch("ahriman.models.package.Package.actual_version")
 | 
				
			||||||
    assert not package_ahriman.is_outdated(package_ahriman, repository_paths, vcs_allowed_age=utcnow().timestamp())
 | 
					    assert not package_ahriman.is_outdated(package_ahriman, configuration)
 | 
				
			||||||
    actual_version_mock.assert_not_called()
 | 
					    actual_version_mock.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										0
									
								
								tests/ahriman/models/test_pkgbuild.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/ahriman/models/test_pkgbuild.py
									
									
									
									
									
										Normal file
									
								
							@ -132,6 +132,14 @@ def test_serialize_list() -> None:
 | 
				
			|||||||
    assert PkgbuildPatch("key", ["val'ue", "val\"ue2"]).serialize() == """key=('val'"'"'ue' 'val"ue2')"""
 | 
					    assert PkgbuildPatch("key", ["val'ue", "val\"ue2"]).serialize() == """key=('val'"'"'ue' 'val"ue2')"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_substitute() -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    must correctly substitute variables
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    assert PkgbuildPatch("key", "$env $value").substitute({"env": "variable"}) == "variable $value"
 | 
				
			||||||
 | 
					    assert PkgbuildPatch("key", ["$env $value"]).substitute({"env": "variable"}) == ["variable $value"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write(mocker: MockerFixture) -> None:
 | 
					def test_write(mocker: MockerFixture) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    must write serialized value to the file
 | 
					    must write serialized value to the file
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										55
									
								
								tests/testresources/models/package_ahriman_pkgbuild
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								tests/testresources/models/package_ahriman_pkgbuild
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					# Maintainer: Evgeniy Alekseev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pkgname='ahriman'
 | 
				
			||||||
 | 
					pkgver=2.6.0
 | 
				
			||||||
 | 
					pkgrel=1
 | 
				
			||||||
 | 
					pkgdesc="ArcH linux ReposItory MANager"
 | 
				
			||||||
 | 
					arch=('any')
 | 
				
			||||||
 | 
					url="https://github.com/arcan1s/ahriman"
 | 
				
			||||||
 | 
					license=('GPL3')
 | 
				
			||||||
 | 
					depends=('devtools' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests' 'python-setuptools' 'python-srcinfo')
 | 
				
			||||||
 | 
					makedepends=('python-build' 'python-installer' 'python-wheel')
 | 
				
			||||||
 | 
					optdepends=('breezy: -bzr packages support'
 | 
				
			||||||
 | 
					            'darcs: -darcs packages support'
 | 
				
			||||||
 | 
					            'mercurial: -hg packages support'
 | 
				
			||||||
 | 
					            'python-aioauth-client: web server with OAuth2 authorization'
 | 
				
			||||||
 | 
					            'python-aiohttp: web server'
 | 
				
			||||||
 | 
					            'python-aiohttp-debugtoolbar: web server with enabled debug panel'
 | 
				
			||||||
 | 
					            'python-aiohttp-jinja2: web server'
 | 
				
			||||||
 | 
					            'python-aiohttp-security: web server with authorization'
 | 
				
			||||||
 | 
					            'python-aiohttp-session: web server with authorization'
 | 
				
			||||||
 | 
					            'python-boto3: sync to s3'
 | 
				
			||||||
 | 
					            'python-cryptography: web server with authorization'
 | 
				
			||||||
 | 
					            'python-requests-unixsocket: client report to web server by unix socket'
 | 
				
			||||||
 | 
					            'python-jinja: html report generation'
 | 
				
			||||||
 | 
					            'rsync: sync by using rsync'
 | 
				
			||||||
 | 
					            'subversion: -svn packages support')
 | 
				
			||||||
 | 
					source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz"
 | 
				
			||||||
 | 
					        'ahriman.sysusers'
 | 
				
			||||||
 | 
					        'ahriman.tmpfiles')
 | 
				
			||||||
 | 
					backup=('etc/ahriman.ini'
 | 
				
			||||||
 | 
					        'etc/ahriman.ini.d/logging.ini')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build() {
 | 
				
			||||||
 | 
					  cd "$pkgname"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  python -m build --wheel --no-isolation
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package() {
 | 
				
			||||||
 | 
					  cd "$pkgname"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # python-installer actually thinks that you cannot just copy files to root
 | 
				
			||||||
 | 
					  # thus we need to copy them manually
 | 
				
			||||||
 | 
					  install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
 | 
				
			||||||
 | 
					  install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  install -Dm644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
 | 
				
			||||||
 | 
					  install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sha512sums=('ec1f64e463455761d72be7f7b8b51b3b4424685c96a2d5eee6afa1c93780c8d7f8a39487a2f2f3bd83d2b58a93279e1392a965a4b905795e58ca686fb21123a1'
 | 
				
			||||||
 | 
					            '53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131'
 | 
				
			||||||
 | 
					            '62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794')
 | 
				
			||||||
@ -1,45 +0,0 @@
 | 
				
			|||||||
pkgbase = ahriman
 | 
					 | 
				
			||||||
	pkgdesc = ArcH linux ReposItory MANager
 | 
					 | 
				
			||||||
	pkgver = 2.6.0
 | 
					 | 
				
			||||||
	pkgrel = 1
 | 
					 | 
				
			||||||
	url = https://github.com/arcan1s/ahriman
 | 
					 | 
				
			||||||
	arch = any
 | 
					 | 
				
			||||||
	license = GPL3
 | 
					 | 
				
			||||||
	checkdepends = python-pytest
 | 
					 | 
				
			||||||
	makedepends = python-build
 | 
					 | 
				
			||||||
	makedepends = python-installer
 | 
					 | 
				
			||||||
	makedepends = python-wheel
 | 
					 | 
				
			||||||
	depends = devtools
 | 
					 | 
				
			||||||
	depends = git
 | 
					 | 
				
			||||||
	depends = pyalpm
 | 
					 | 
				
			||||||
	depends = python-cerberus
 | 
					 | 
				
			||||||
	depends = python-inflection
 | 
					 | 
				
			||||||
	depends = python-passlib
 | 
					 | 
				
			||||||
	depends = python-requests
 | 
					 | 
				
			||||||
	depends = python-setuptools
 | 
					 | 
				
			||||||
	depends = python-srcinfo
 | 
					 | 
				
			||||||
	optdepends = breezy: -bzr packages support
 | 
					 | 
				
			||||||
	optdepends = darcs: -darcs packages support
 | 
					 | 
				
			||||||
	optdepends = mercurial: -hg packages support
 | 
					 | 
				
			||||||
	optdepends = python-aioauth-client: web server with OAuth2 authorization
 | 
					 | 
				
			||||||
	optdepends = python-aiohttp: web server
 | 
					 | 
				
			||||||
	optdepends = python-aiohttp-debugtoolbar: web server with enabled debug panel
 | 
					 | 
				
			||||||
	optdepends = python-aiohttp-jinja2: web server
 | 
					 | 
				
			||||||
	optdepends = python-aiohttp-security: web server with authorization
 | 
					 | 
				
			||||||
	optdepends = python-aiohttp-session: web server with authorization
 | 
					 | 
				
			||||||
	optdepends = python-boto3: sync to s3
 | 
					 | 
				
			||||||
	optdepends = python-cryptography: web server with authorization
 | 
					 | 
				
			||||||
	optdepends = python-requests-unixsocket: client report to web server by unix socket
 | 
					 | 
				
			||||||
	optdepends = python-jinja: html report generation
 | 
					 | 
				
			||||||
	optdepends = rsync: sync by using rsync
 | 
					 | 
				
			||||||
	optdepends = subversion: -svn packages support
 | 
					 | 
				
			||||||
	backup = etc/ahriman.ini
 | 
					 | 
				
			||||||
	backup = etc/ahriman.ini.d/logging.ini
 | 
					 | 
				
			||||||
	source = https://github.com/arcan1s/ahriman/releases/download/2.6.0/ahriman-2.6.0-src.tar.xz
 | 
					 | 
				
			||||||
	source = ahriman.sysusers
 | 
					 | 
				
			||||||
	source = ahriman.tmpfiles
 | 
					 | 
				
			||||||
	sha512sums = ec1f64e463455761d72be7f7b8b51b3b4424685c96a2d5eee6afa1c93780c8d7f8a39487a2f2f3bd83d2b58a93279e1392a965a4b905795e58ca686fb21123a1
 | 
					 | 
				
			||||||
	sha512sums = 53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131
 | 
					 | 
				
			||||||
	sha512sums = 62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = ahriman
 | 
					 | 
				
			||||||
							
								
								
									
										270
									
								
								tests/testresources/models/package_gcc10_pkgbuild
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								tests/testresources/models/package_gcc10_pkgbuild
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,270 @@
 | 
				
			|||||||
 | 
					# Maintainer:  Chris Severance aur.severach aATt spamgourmet dott com
 | 
				
			||||||
 | 
					# Contributor: Jonathon Fernyhough <jonathon+m2x+dev>
 | 
				
			||||||
 | 
					# Contributor: Giancarlo Razzolini <grazzolini@archlinux.org>
 | 
				
			||||||
 | 
					# Contributor: Frederik Schwan <freswa at archlinux dot org>
 | 
				
			||||||
 | 
					# Contributor:  Bartłomiej Piotrowski <bpiotrowski@archlinux.org>
 | 
				
			||||||
 | 
					# Contributor: Allan McRae <allan@archlinux.org>
 | 
				
			||||||
 | 
					# Contributor: Daniel Kozak <kozzi11@gmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -u
 | 
				
			||||||
 | 
					pkgbase='gcc10'
 | 
				
			||||||
 | 
					pkgname=("${pkgbase}"{,-libs,-fortran})
 | 
				
			||||||
 | 
					pkgver='10.5.0'
 | 
				
			||||||
 | 
					_majorver="${pkgver%%.*}"
 | 
				
			||||||
 | 
					_islver='0.24'
 | 
				
			||||||
 | 
					pkgrel='2'
 | 
				
			||||||
 | 
					pkgdesc='The GNU Compiler Collection (10.x.x)'
 | 
				
			||||||
 | 
					arch=('x86_64')
 | 
				
			||||||
 | 
					url='https://gcc.gnu.org'
 | 
				
			||||||
 | 
					license=('GPL-3.0-or-later' 'LGPL-3.0+' 'GFDL-1.3' 'LicenseRef-custom')
 | 
				
			||||||
 | 
					makedepends=('binutils' 'doxygen' 'git' 'libmpc' 'python')
 | 
				
			||||||
 | 
					checkdepends=('dejagnu' 'inetutils')
 | 
				
			||||||
 | 
					options=('!emptydirs' '!lto' '!buildflags')
 | 
				
			||||||
 | 
					source=(
 | 
				
			||||||
 | 
					  "https://sourceware.org/pub/gcc/releases/gcc-${pkgver}/gcc-${pkgver}.tar.xz"{,.sig}
 | 
				
			||||||
 | 
					  "https://sourceware.org/pub/gcc/infrastructure/isl-${_islver}.tar.bz2"
 | 
				
			||||||
 | 
					  'c89'
 | 
				
			||||||
 | 
					  'c99'
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					validpgpkeys=(
 | 
				
			||||||
 | 
					  'F3691687D867B81B51CE07D9BBE43771487328A9'  # bpiotrowski@archlinux.org
 | 
				
			||||||
 | 
					  '86CFFCA918CF3AF47147588051E8B148A9999C34'  # evangelos@foutrelis.com
 | 
				
			||||||
 | 
					  '13975A70E63C361C73AE69EF6EEB81F8981C74C7'  # richard.guenther@gmail.com
 | 
				
			||||||
 | 
					  'D3A93CAD751C2AF4F8C7AD516C35B99309B5FA62'  # Jakub Jelinek <jakub@redhat.com>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					md5sums=('c7d1958570fbd1cd859b015774b9987a'
 | 
				
			||||||
 | 
					         'SKIP'
 | 
				
			||||||
 | 
					         'dd2f7b78e118c25bd96134a52aae7f4d'
 | 
				
			||||||
 | 
					         'd5fd2672deb5f97a2c4bdab486470abe'
 | 
				
			||||||
 | 
					         'd99ba9f4bd860e274f17040ee51cd1bf')
 | 
				
			||||||
 | 
					b2sums=('9b71761f4015649514677784443886e59733ac3845f7dfaa4343f46327d36c08c403c444b9e492b870ac0b3f2e3568f972b7700a0ef05a497fb4066079b3143b'
 | 
				
			||||||
 | 
					        'SKIP'
 | 
				
			||||||
 | 
					        '88a178dad5fe9c33be5ec5fe4ac9abc0e075a86cff9184f75cedb7c47de67ce3be273bd0db72286ba0382f4016e9d74855ead798ad7bccb015b853931731828e'
 | 
				
			||||||
 | 
					        'a76d19c7830b0a141302890522086fc1548c177611501caac7e66d576e541b64ca3f6e977de715268a9872dfdd6368a011b92e01f7944ec0088f899ac0d2a2a5'
 | 
				
			||||||
 | 
					        '02b655b5668f7dea51c3b3e4ff46d5a4aee5a04ed5e26b98a6470f39c2e98ddc0519bffeeedd982c31ef3c171457e4d1beaff32767d1aedd9346837aac4ec3ee')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_CHOST="${CHOST:=}" # https://bbs.archlinux.org/viewtopic.php?pid=2174541
 | 
				
			||||||
 | 
					_MAKEFLAGS="${MAKEFLAGS:=}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_libdir="usr/lib/gcc/${CHOST}/${pkgver%%+*}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					prepare() {
 | 
				
			||||||
 | 
					  set -u
 | 
				
			||||||
 | 
					  if [ ! -d 'gcc' ]; then
 | 
				
			||||||
 | 
					    ln -s "gcc-${pkgver/+/-}" 'gcc'
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					  pushd 'gcc' > /dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # link isl for in-tree build
 | 
				
			||||||
 | 
					  ln -s "../isl-${_islver}" 'isl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Do not run fixincludes
 | 
				
			||||||
 | 
					  sed -e 's@\./fixinc\.sh@-c true@' -i 'gcc/Makefile.in'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Arch Linux installs x86_64 libraries /lib
 | 
				
			||||||
 | 
					  sed -e '/m64=/s/lib64/lib/' -i 'gcc/config/i386/t-linux64'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # hack! - some configure tests for header files using "$CPP $CPPFLAGS"
 | 
				
			||||||
 | 
					  sed -e '/ac_cpp=/s/$CPPFLAGS/$CPPFLAGS -O2/' -i 'gcc/configure'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  popd > /dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rm -rf 'gcc-build'
 | 
				
			||||||
 | 
					  mkdir 'gcc-build'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set +u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build() {
 | 
				
			||||||
 | 
					  set -u
 | 
				
			||||||
 | 
					  export MAKEFLAGS="${_MAKEFLAGS}"
 | 
				
			||||||
 | 
					  export CHOST="${_CHOST}"
 | 
				
			||||||
 | 
					  cd 'gcc-build'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [ ! -s 'Makefile' ]; then
 | 
				
			||||||
 | 
					    # The following options are one per line, mostly sorted so they are easy to diff compare to other gcc packages.
 | 
				
			||||||
 | 
					    local _conf=(
 | 
				
			||||||
 | 
					      --build="${CHOST}"
 | 
				
			||||||
 | 
					      --disable-libssp
 | 
				
			||||||
 | 
					      --disable-libstdcxx-pch
 | 
				
			||||||
 | 
					      --disable-libunwind-exceptions
 | 
				
			||||||
 | 
					      --disable-multilib
 | 
				
			||||||
 | 
					      --disable-werror
 | 
				
			||||||
 | 
					      --enable-__cxa_atexit
 | 
				
			||||||
 | 
					      --enable-cet='auto'
 | 
				
			||||||
 | 
					      --enable-checking='release'
 | 
				
			||||||
 | 
					      --enable-clocale='gnu'
 | 
				
			||||||
 | 
					      --enable-default-pie
 | 
				
			||||||
 | 
					      --enable-default-ssp
 | 
				
			||||||
 | 
					      --enable-gnu-indirect-function
 | 
				
			||||||
 | 
					      --enable-gnu-unique-object
 | 
				
			||||||
 | 
					      --enable-languages='c,c++,fortran,lto'
 | 
				
			||||||
 | 
					      --enable-linker-build-id
 | 
				
			||||||
 | 
					      --enable-lto
 | 
				
			||||||
 | 
					      --enable-plugin
 | 
				
			||||||
 | 
					      --enable-shared
 | 
				
			||||||
 | 
					      --enable-threads='posix'
 | 
				
			||||||
 | 
					      --enable-version-specific-runtime-libs
 | 
				
			||||||
 | 
					      --infodir='/usr/share/info'
 | 
				
			||||||
 | 
					      --libdir='/usr/lib'
 | 
				
			||||||
 | 
					      --libexecdir='/usr/lib'
 | 
				
			||||||
 | 
					      --mandir='/usr/share/man'
 | 
				
			||||||
 | 
					      --program-suffix="-${_majorver}"
 | 
				
			||||||
 | 
					      --with-bugurl='https://bugs.archlinux.org/'
 | 
				
			||||||
 | 
					      --with-isl
 | 
				
			||||||
 | 
					      --with-linker-hash-style='gnu'
 | 
				
			||||||
 | 
					      --with-pkgversion="Arch Linux ${pkgver}-${pkgrel}"
 | 
				
			||||||
 | 
					      --with-system-zlib
 | 
				
			||||||
 | 
					      --prefix='/usr'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    ../gcc/configure "${_conf[@]}"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					  LD_PRELOAD='/usr/lib/libstdc++.so' \
 | 
				
			||||||
 | 
					  nice make -s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set +u; msg 'Compile complete'; set -u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # make documentation
 | 
				
			||||||
 | 
					  make -s -j1 -C "${CHOST}/libstdc++-v3/doc" 'doc-man-doxygen'
 | 
				
			||||||
 | 
					  set +u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check() {
 | 
				
			||||||
 | 
					  set -u
 | 
				
			||||||
 | 
					  cd 'gcc-build'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # disable libphobos test to avoid segfaults and other unfunny ways to waste my time
 | 
				
			||||||
 | 
					  sed -e '/maybe-check-target-libphobos \\/d' -i 'Makefile'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # do not abort on error as some are "expected"
 | 
				
			||||||
 | 
					  make -O -k check || :
 | 
				
			||||||
 | 
					  "${srcdir}/gcc/contrib/test_summary"
 | 
				
			||||||
 | 
					  set +u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package_gcc10-libs() {
 | 
				
			||||||
 | 
					  set -u
 | 
				
			||||||
 | 
					  export MAKEFLAGS="${_MAKEFLAGS}"
 | 
				
			||||||
 | 
					  export CHOST="${_CHOST}"
 | 
				
			||||||
 | 
					  pkgdesc='Runtime libraries shipped by GCC (10.x.x)'
 | 
				
			||||||
 | 
					  depends=('glibc>=2.27')
 | 
				
			||||||
 | 
					  options=('!emptydirs' '!strip')
 | 
				
			||||||
 | 
					  provides=('libgfortran.so' 'libubsan.so' 'libasan.so' 'libtsan.so' 'liblsan.so')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cd 'gcc-build'
 | 
				
			||||||
 | 
					  LD_PRELOAD='/usr/lib/libstdc++.so' \
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libgcc" DESTDIR="${pkgdir}" install-shared
 | 
				
			||||||
 | 
					  mv "${pkgdir}/${_libdir}"/../lib/* "${pkgdir}/${_libdir}"
 | 
				
			||||||
 | 
					  rmdir "${pkgdir}/${_libdir}/../lib"
 | 
				
			||||||
 | 
					  rm -f "${pkgdir}/${_libdir}/libgcc_eh.a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local _lib
 | 
				
			||||||
 | 
					  for _lib in libatomic \
 | 
				
			||||||
 | 
					              libgfortran \
 | 
				
			||||||
 | 
					              libgomp \
 | 
				
			||||||
 | 
					              libitm \
 | 
				
			||||||
 | 
					              libquadmath \
 | 
				
			||||||
 | 
					              libsanitizer/{a,l,ub,t}san \
 | 
				
			||||||
 | 
					              libstdc++-v3/src \
 | 
				
			||||||
 | 
					              libvtv; do
 | 
				
			||||||
 | 
					    make -C "${CHOST}/${_lib}" DESTDIR="${pkgdir}" install-toolexeclibLTLIBRARIES
 | 
				
			||||||
 | 
					  done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libstdc++-v3/po" DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Install Runtime Library Exception
 | 
				
			||||||
 | 
					  install -Dm644 "${srcdir}/gcc/COPYING.RUNTIME" \
 | 
				
			||||||
 | 
					    "${pkgdir}/usr/share/licenses/${pkgname}/RUNTIME.LIBRARY.EXCEPTION"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # remove conflicting files
 | 
				
			||||||
 | 
					  rm -rf "${pkgdir}/usr/share/locale"
 | 
				
			||||||
 | 
					  set +u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package_gcc10() {
 | 
				
			||||||
 | 
					  set -u
 | 
				
			||||||
 | 
					  export MAKEFLAGS="${_MAKEFLAGS}"
 | 
				
			||||||
 | 
					  export CHOST="${_CHOST}"
 | 
				
			||||||
 | 
					  pkgdesc='The GNU Compiler Collection - C and C++ frontends (10.x.x)'
 | 
				
			||||||
 | 
					  depends=("${pkgbase}-libs=${pkgver}-${pkgrel}" 'binutils>=2.28' 'libmpc' 'zstd')
 | 
				
			||||||
 | 
					  options=('!emptydirs' 'staticlibs')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cd 'gcc-build'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C 'gcc' DESTDIR="${pkgdir}" install-driver install-cpp install-gcc-ar \
 | 
				
			||||||
 | 
					    c++.install-common install-headers install-plugin install-lto-wrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  install -m755 -t "${pkgdir}/${_libdir}/" gcc/{cc1,cc1plus,collect2,lto1,gcov{,-tool}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libgcc" DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  rm -rf "${pkgdir}/${_libdir}/../lib"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libstdc++-v3/src" DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libstdc++-v3/include" DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libstdc++-v3/libsupc++" DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libstdc++-v3/python" DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  rm -f "${pkgdir}/${_libdir}"/libstdc++.so*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make DESTDIR="${pkgdir}" install-fixincludes
 | 
				
			||||||
 | 
					  make -C 'gcc' DESTDIR="${pkgdir}" install-mkheaders
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C 'lto-plugin' DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  install -dm755 "${pkgdir}/${_libdir}/bfd-plugins/"
 | 
				
			||||||
 | 
					  ln -s "/${_libdir}/liblto_plugin.so" \
 | 
				
			||||||
 | 
					    "${pkgdir}/${_libdir}/bfd-plugins/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libgomp" DESTDIR="${pkgdir}" install-nodist_{libsubinclude,toolexeclib}HEADERS
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libitm" DESTDIR="${pkgdir}" install-nodist_toolexeclibHEADERS
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libquadmath" DESTDIR="${pkgdir}" install-nodist_libsubincludeHEADERS
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libsanitizer" DESTDIR="${pkgdir}" install-nodist_{saninclude,toolexeclib}HEADERS
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libsanitizer/asan" DESTDIR="${pkgdir}" install-nodist_toolexeclibHEADERS
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libsanitizer/tsan" DESTDIR="${pkgdir}" install-nodist_toolexeclibHEADERS
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libsanitizer/lsan" DESTDIR="${pkgdir}" install-nodist_toolexeclibHEADERS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  make -C 'libcpp' DESTDIR="${pkgdir}" install
 | 
				
			||||||
 | 
					  make -C 'gcc' DESTDIR="${pkgdir}" install-po
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # many packages expect this symlink
 | 
				
			||||||
 | 
					  ln -s "gcc-${_majorver}" "${pkgdir}/usr/bin/cc-${_majorver}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # POSIX conformance launcher scripts for c89 and c99
 | 
				
			||||||
 | 
					  install -Dm755 "${srcdir}/c89" "${pkgdir}/usr/bin/c89-${_majorver}"
 | 
				
			||||||
 | 
					  install -Dm755 "${srcdir}/c99" "${pkgdir}/usr/bin/c99-${_majorver}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # byte-compile python libraries
 | 
				
			||||||
 | 
					  python -m 'compileall' "${pkgdir}/usr/share/gcc-${pkgver%%+*}/"
 | 
				
			||||||
 | 
					  python -O -m 'compileall' "${pkgdir}/usr/share/gcc-${pkgver%%+*}/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Install Runtime Library Exception
 | 
				
			||||||
 | 
					  install -d "${pkgdir}/usr/share/licenses/${pkgname}/"
 | 
				
			||||||
 | 
					  ln -s "/usr/share/licenses/${pkgbase}-libs/RUNTIME.LIBRARY.EXCEPTION" \
 | 
				
			||||||
 | 
					    "${pkgdir}/usr/share/licenses/${pkgname}/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Remove conflicting files
 | 
				
			||||||
 | 
					  rm -rf "${pkgdir}/usr/share/locale"
 | 
				
			||||||
 | 
					  set +u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package_gcc10-fortran() {
 | 
				
			||||||
 | 
					  set -u
 | 
				
			||||||
 | 
					  export MAKEFLAGS="${_MAKEFLAGS}"
 | 
				
			||||||
 | 
					  export CHOST="${_CHOST}"
 | 
				
			||||||
 | 
					  pkgdesc='Fortran front-end for GCC (10.x.x)'
 | 
				
			||||||
 | 
					  depends=("${pkgbase}=${pkgver}-${pkgrel}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cd 'gcc-build'
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libgfortran" DESTDIR="${pkgdir}" install-cafexeclibLTLIBRARIES \
 | 
				
			||||||
 | 
					    install-{toolexeclibDATA,nodist_fincludeHEADERS,gfor_cHEADERS}
 | 
				
			||||||
 | 
					  make -C "${CHOST}/libgomp" DESTDIR="${pkgdir}" install-nodist_fincludeHEADERS
 | 
				
			||||||
 | 
					  make -C 'gcc' DESTDIR="${pkgdir}" fortran.install-common
 | 
				
			||||||
 | 
					  install -Dm755 'gcc/f951' "${pkgdir}/${_libdir}/f951"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ln -s "gfortran-${_majorver}" "${pkgdir}/usr/bin/f95-${_majorver}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Install Runtime Library Exception
 | 
				
			||||||
 | 
					  install -d "${pkgdir}/usr/share/licenses/${pkgname}/"
 | 
				
			||||||
 | 
					  ln -s "/usr/share/licenses/${pkgbase}-libs/RUNTIME.LIBRARY.EXCEPTION" \
 | 
				
			||||||
 | 
					    "${pkgdir}/usr/share/licenses/${pkgname}/"
 | 
				
			||||||
 | 
					  set +u
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					set +u
 | 
				
			||||||
@ -1,57 +0,0 @@
 | 
				
			|||||||
pkgbase = gcc10
 | 
					 | 
				
			||||||
	pkgdesc = The GNU Compiler Collection (10.x.x)
 | 
					 | 
				
			||||||
	pkgver = 10.3.0
 | 
					 | 
				
			||||||
	pkgrel = 2
 | 
					 | 
				
			||||||
	url = https://gcc.gnu.org
 | 
					 | 
				
			||||||
	arch = x86_64
 | 
					 | 
				
			||||||
	license = GPL
 | 
					 | 
				
			||||||
	license = LGPL
 | 
					 | 
				
			||||||
	license = FDL
 | 
					 | 
				
			||||||
	license = custom
 | 
					 | 
				
			||||||
	checkdepends = dejagnu
 | 
					 | 
				
			||||||
	checkdepends = inetutils
 | 
					 | 
				
			||||||
	makedepends = binutils
 | 
					 | 
				
			||||||
	makedepends = doxygen
 | 
					 | 
				
			||||||
	makedepends = git
 | 
					 | 
				
			||||||
	makedepends = libmpc
 | 
					 | 
				
			||||||
	makedepends = python
 | 
					 | 
				
			||||||
	options = !emptydirs
 | 
					 | 
				
			||||||
	options = !lto
 | 
					 | 
				
			||||||
	source = https://sourceware.org/pub/gcc/releases/gcc-10.3.0/gcc-10.3.0.tar.xz
 | 
					 | 
				
			||||||
	source = https://sourceware.org/pub/gcc/releases/gcc-10.3.0/gcc-10.3.0.tar.xz.sig
 | 
					 | 
				
			||||||
	source = https://mirror.sobukus.de/files/src/isl/isl-0.24.tar.xz
 | 
					 | 
				
			||||||
	source = c89
 | 
					 | 
				
			||||||
	source = c99
 | 
					 | 
				
			||||||
	validpgpkeys = F3691687D867B81B51CE07D9BBE43771487328A9
 | 
					 | 
				
			||||||
	validpgpkeys = 86CFFCA918CF3AF47147588051E8B148A9999C34
 | 
					 | 
				
			||||||
	validpgpkeys = 13975A70E63C361C73AE69EF6EEB81F8981C74C7
 | 
					 | 
				
			||||||
	validpgpkeys = D3A93CAD751C2AF4F8C7AD516C35B99309B5FA62
 | 
					 | 
				
			||||||
	b2sums = ac7898f5eb8a7c5f151a526d1bb38913a68b50a65e4d010ac09fa20b6c801c671c790d780f23ccb8e4ecdfc686f4aa588082ccc9eb5c80c7b0e30788f824c1eb
 | 
					 | 
				
			||||||
	b2sums = SKIP
 | 
					 | 
				
			||||||
	b2sums = 39cbfd18ad05778e3a5a44429261b45e4abc3efe7730ee890674d968890fe5e52c73bc1f8d271c7c3bc72d5754e3f7fcb209bd139e823d19cb9ea4ce1440164d
 | 
					 | 
				
			||||||
	b2sums = a76d19c7830b0a141302890522086fc1548c177611501caac7e66d576e541b64ca3f6e977de715268a9872dfdd6368a011b92e01f7944ec0088f899ac0d2a2a5
 | 
					 | 
				
			||||||
	b2sums = 02b655b5668f7dea51c3b3e4ff46d5a4aee5a04ed5e26b98a6470f39c2e98ddc0519bffeeedd982c31ef3c171457e4d1beaff32767d1aedd9346837aac4ec3ee
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = gcc10
 | 
					 | 
				
			||||||
	pkgdesc = The GNU Compiler Collection - C and C++ frontends (10.x.x)
 | 
					 | 
				
			||||||
	depends = gcc10-libs=10.3.0-2
 | 
					 | 
				
			||||||
	depends = binutils>=2.28
 | 
					 | 
				
			||||||
	depends = libmpc
 | 
					 | 
				
			||||||
	depends = zstd
 | 
					 | 
				
			||||||
	options = !emptydirs
 | 
					 | 
				
			||||||
	options = staticlibs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = gcc10-libs
 | 
					 | 
				
			||||||
	pkgdesc = Runtime libraries shipped by GCC (10.x.x)
 | 
					 | 
				
			||||||
	depends = glibc>=2.27
 | 
					 | 
				
			||||||
	provides = libgfortran.so
 | 
					 | 
				
			||||||
	provides = libubsan.so
 | 
					 | 
				
			||||||
	provides = libasan.so
 | 
					 | 
				
			||||||
	provides = libtsan.so
 | 
					 | 
				
			||||||
	provides = liblsan.so
 | 
					 | 
				
			||||||
	options = !emptydirs
 | 
					 | 
				
			||||||
	options = !strip
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = gcc10-fortran
 | 
					 | 
				
			||||||
	pkgdesc = Fortran front-end for GCC (10.x.x)
 | 
					 | 
				
			||||||
	depends = gcc10=10.3.0-2
 | 
					 | 
				
			||||||
@ -1,28 +0,0 @@
 | 
				
			|||||||
pkgbase = jellyfin-ffmpeg5-bin
 | 
					 | 
				
			||||||
	pkgdesc = FFmpeg5 binary version for Jellyfin
 | 
					 | 
				
			||||||
	pkgver = 5.1.2
 | 
					 | 
				
			||||||
	pkgrel = 7
 | 
					 | 
				
			||||||
	url = https://github.com/jellyfin/jellyfin-ffmpeg
 | 
					 | 
				
			||||||
	arch = x86_64
 | 
					 | 
				
			||||||
	arch = aarch64
 | 
					 | 
				
			||||||
	license = GPL3
 | 
					 | 
				
			||||||
	optdepends = intel-media-driver: for Intel VAAPI support (Broadwell and newer)
 | 
					 | 
				
			||||||
	optdepends = intel-media-sdk: for Intel Quick Sync Video
 | 
					 | 
				
			||||||
	optdepends = onevpl-intel-gpu: for Intel Quick Sync Video (12th Gen and newer)
 | 
					 | 
				
			||||||
	optdepends = intel-compute-runtime: for Intel OpenCL runtime based Tonemapping
 | 
					 | 
				
			||||||
	optdepends = libva-intel-driver: for Intel legacy VAAPI support (10th Gen and older)
 | 
					 | 
				
			||||||
	optdepends = libva-mesa-driver: for AMD VAAPI support
 | 
					 | 
				
			||||||
	optdepends = nvidia-utils: for Nvidia NVDEC/NVENC support
 | 
					 | 
				
			||||||
	optdepends = opencl-amd: for AMD OpenCL runtime based Tonemapping
 | 
					 | 
				
			||||||
	optdepends = vulkan-radeon: for AMD RADV Vulkan support
 | 
					 | 
				
			||||||
	optdepends = vulkan-intel: for Intel ANV Vulkan support
 | 
					 | 
				
			||||||
	conflicts = jellyfin-ffmpeg
 | 
					 | 
				
			||||||
	conflicts = jellyfin-ffmpeg5
 | 
					 | 
				
			||||||
	source_x86_64 = https://repo.jellyfin.org/releases/ffmpeg/5.1.2-7/jellyfin-ffmpeg_5.1.2-7_portable_linux64-gpl.tar.xz
 | 
					 | 
				
			||||||
	depends_x86_64 = glibc>=2.23
 | 
					 | 
				
			||||||
	sha256sums_x86_64 = 78420fd1edbaf24a07e92938878d8582d895e009cae02c8e9d5be3f26de905e3
 | 
					 | 
				
			||||||
	source_aarch64 = https://repo.jellyfin.org/releases/ffmpeg/5.1.2-7/jellyfin-ffmpeg_5.1.2-7_portable_linuxarm64-gpl.tar.xz
 | 
					 | 
				
			||||||
	depends_aarch64 = glibc>=2.27
 | 
					 | 
				
			||||||
	sha256sums_aarch64 = 8ac4066981f203c2b442754eaf7286b4e481df9692d0ff8910a824d89c831df0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = jellyfin-ffmpeg5-bin
 | 
					 | 
				
			||||||
@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					# Maintainer : nyanmisaka <nst799610810@gmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pkgname=jellyfin-ffmpeg6-bin
 | 
				
			||||||
 | 
					pkgver=6.0
 | 
				
			||||||
 | 
					pkgrel=6
 | 
				
			||||||
 | 
					pkgdesc='FFmpeg6 binary version for Jellyfin'
 | 
				
			||||||
 | 
					arch=('x86_64' 'aarch64')
 | 
				
			||||||
 | 
					url='https://github.com/jellyfin/jellyfin-ffmpeg'
 | 
				
			||||||
 | 
					license=('GPL3')
 | 
				
			||||||
 | 
					depends_x86_64=('glibc>=2.23')
 | 
				
			||||||
 | 
					depends_aarch64=('glibc>=2.27')
 | 
				
			||||||
 | 
					optdepends=('intel-media-driver: for Intel VAAPI support (Broadwell and newer)'
 | 
				
			||||||
 | 
					            'intel-media-sdk: for Intel Quick Sync Video'
 | 
				
			||||||
 | 
					            'onevpl-intel-gpu: for Intel Quick Sync Video (12th Gen and newer)'
 | 
				
			||||||
 | 
					            'intel-compute-runtime: for Intel OpenCL runtime based Tonemapping'
 | 
				
			||||||
 | 
					            'libva-intel-driver: for Intel legacy VAAPI support (10th Gen and older)'
 | 
				
			||||||
 | 
					            'libva-mesa-driver: for AMD VAAPI support'
 | 
				
			||||||
 | 
					            'nvidia-utils: for Nvidia NVDEC/NVENC support'
 | 
				
			||||||
 | 
					            'opencl-amd: for AMD OpenCL runtime based Tonemapping'
 | 
				
			||||||
 | 
					            'vulkan-radeon: for AMD RADV Vulkan support'
 | 
				
			||||||
 | 
					            'vulkan-intel: for Intel ANV Vulkan support')
 | 
				
			||||||
 | 
					conflicts=('jellyfin-ffmpeg' 'jellyfin-ffmpeg5' 'jellyfin-ffmpeg5-bin' 'jellyfin-ffmpeg6')
 | 
				
			||||||
 | 
					source_x86_64=("https://repo.jellyfin.org/releases/ffmpeg/${pkgver}-${pkgrel}/jellyfin-ffmpeg_${pkgver}-${pkgrel}_portable_linux64-gpl.tar.xz")
 | 
				
			||||||
 | 
					source_aarch64=("https://repo.jellyfin.org/releases/ffmpeg/${pkgver}-${pkgrel}/jellyfin-ffmpeg_${pkgver}-${pkgrel}_portable_linuxarm64-gpl.tar.xz")
 | 
				
			||||||
 | 
					sha256sums_x86_64=('32cbe40942d26072faa1182835ccc89029883766de11778c731b529aa632ff37')
 | 
				
			||||||
 | 
					sha256sums_aarch64=('22b8f2a3c92c6b1c9e6830a6631f08f3f0a7ae80739ace71ad30704a28045184')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package() {
 | 
				
			||||||
 | 
					    install -Dm 755 ffmpeg ${pkgdir}/usr/lib/jellyfin-ffmpeg/ffmpeg
 | 
				
			||||||
 | 
					    install -Dm 755 ffprobe ${pkgdir}/usr/lib/jellyfin-ffmpeg/ffprobe
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								tests/testresources/models/package_tpacpi-bat-git_pkgbuild
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/testresources/models/package_tpacpi-bat-git_pkgbuild
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					# Maintainer: Frederik Schwan <freswa at archlinux dot org>
 | 
				
			||||||
 | 
					# Contributor: Lucky <archlinux@builds.lucky.li>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pkgname=tpacpi-bat-git
 | 
				
			||||||
 | 
					pkgver=3.1.r13.g4959b52
 | 
				
			||||||
 | 
					pkgrel=1
 | 
				
			||||||
 | 
					pkgdesc='A Perl script with ACPI calls for recent ThinkPads which are not supported by tp_smapi'
 | 
				
			||||||
 | 
					arch=('any')
 | 
				
			||||||
 | 
					url='https://github.com/teleshoes/tpacpi-bat'
 | 
				
			||||||
 | 
					license=('GPL3')
 | 
				
			||||||
 | 
					depends=('perl' 'acpi_call')
 | 
				
			||||||
 | 
					makedepends=('git')
 | 
				
			||||||
 | 
					provides=('tpacpi-bat')
 | 
				
			||||||
 | 
					conflicts=('tpacpi-bat')
 | 
				
			||||||
 | 
					backup=('etc/conf.d/tpacpi')
 | 
				
			||||||
 | 
					source=('git+https://github.com/teleshoes/tpacpi-bat.git')
 | 
				
			||||||
 | 
					b2sums=('SKIP')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pkgver() {
 | 
				
			||||||
 | 
					  cd ${pkgname/-git/}
 | 
				
			||||||
 | 
					  echo $(git describe --tags | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package() {
 | 
				
			||||||
 | 
					  cd ${pkgname/-git/}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  install -Dm755 tpacpi-bat "${pkgdir}"/usr/bin/tpacpi-bat
 | 
				
			||||||
 | 
					  install -Dm644 examples/systemd_dynamic_threshold/tpacpi.service "${pkgdir}"/usr/lib/systemd/system/tpacpi-bat.service
 | 
				
			||||||
 | 
					  install -Dm644 examples/systemd_dynamic_threshold/tpacpi.conf.d "${pkgdir}"/etc/conf.d/tpacpi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,17 +0,0 @@
 | 
				
			|||||||
pkgbase = tpacpi-bat-git
 | 
					 | 
				
			||||||
        pkgdesc = A Perl script with ACPI calls for recent ThinkPads which are not supported by tp_smapi
 | 
					 | 
				
			||||||
        pkgver = 3.1.r13.g4959b52
 | 
					 | 
				
			||||||
        pkgrel = 1
 | 
					 | 
				
			||||||
        url = https://github.com/teleshoes/tpacpi-bat
 | 
					 | 
				
			||||||
        arch = any
 | 
					 | 
				
			||||||
        license = GPL3
 | 
					 | 
				
			||||||
        makedepends = git
 | 
					 | 
				
			||||||
        depends = perl
 | 
					 | 
				
			||||||
        depends = acpi_call
 | 
					 | 
				
			||||||
        provides = tpacpi-bat
 | 
					 | 
				
			||||||
        conflicts = tpacpi-bat
 | 
					 | 
				
			||||||
        backup = etc/conf.d/tpacpi
 | 
					 | 
				
			||||||
        source = git+https://github.com/teleshoes/tpacpi-bat.git
 | 
					 | 
				
			||||||
        b2sums = SKIP
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = tpacpi-bat-git
 | 
					 | 
				
			||||||
							
								
								
									
										37
									
								
								tests/testresources/models/package_yay_pkgbuild
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/testresources/models/package_yay_pkgbuild
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					# Maintainer: Jguer <pkgbuilds at jguer.space>
 | 
				
			||||||
 | 
					pkgname=yay
 | 
				
			||||||
 | 
					pkgver=12.3.5
 | 
				
			||||||
 | 
					pkgrel=1
 | 
				
			||||||
 | 
					pkgdesc="Yet another yogurt. Pacman wrapper and AUR helper written in go."
 | 
				
			||||||
 | 
					arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv7h' 'armv6h' 'aarch64' 'riscv64')
 | 
				
			||||||
 | 
					url="https://github.com/Jguer/yay"
 | 
				
			||||||
 | 
					options=(!lto)
 | 
				
			||||||
 | 
					license=('GPL-3.0-or-later')
 | 
				
			||||||
 | 
					depends=(
 | 
				
			||||||
 | 
					  'pacman>6.1'
 | 
				
			||||||
 | 
					  'git'
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					optdepends=(
 | 
				
			||||||
 | 
					  'sudo: privilege elevation'
 | 
				
			||||||
 | 
					  'doas: privilege elevation'
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					makedepends=('go>=1.21')
 | 
				
			||||||
 | 
					source=("${pkgname}-${pkgver}.tar.gz::https://github.com/Jguer/yay/archive/v${pkgver}.tar.gz")
 | 
				
			||||||
 | 
					sha256sums=('2fb6121a6eb4c5e6afaf22212b2ed15022500a4bc34bb3dc0f9782c1d43c3962')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build() {
 | 
				
			||||||
 | 
					  export GOPATH="$srcdir"/gopath
 | 
				
			||||||
 | 
					  export CGO_CPPFLAGS="${CPPFLAGS}"
 | 
				
			||||||
 | 
					  export CGO_CFLAGS="${CFLAGS}"
 | 
				
			||||||
 | 
					  export CGO_CXXFLAGS="${CXXFLAGS}"
 | 
				
			||||||
 | 
					  export CGO_LDFLAGS="${LDFLAGS}"
 | 
				
			||||||
 | 
					  export CGO_ENABLED=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cd "$srcdir/$pkgname-$pkgver"
 | 
				
			||||||
 | 
					  make VERSION=$pkgver DESTDIR="$pkgdir" PREFIX="/usr" build
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package() {
 | 
				
			||||||
 | 
					  cd "$srcdir/$pkgname-$pkgver"
 | 
				
			||||||
 | 
					  make VERSION=$pkgver DESTDIR="$pkgdir" PREFIX="/usr" install
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,21 +0,0 @@
 | 
				
			|||||||
pkgbase = yay
 | 
					 | 
				
			||||||
        pkgdesc = Yet another yogurt. Pacman wrapper and AUR helper written in go.
 | 
					 | 
				
			||||||
        pkgver = 10.2.0
 | 
					 | 
				
			||||||
        pkgrel = 1
 | 
					 | 
				
			||||||
        url = https://github.com/Jguer/yay
 | 
					 | 
				
			||||||
        arch = i686
 | 
					 | 
				
			||||||
        arch = pentium4
 | 
					 | 
				
			||||||
        arch = x86_64
 | 
					 | 
				
			||||||
        arch = arm
 | 
					 | 
				
			||||||
        arch = armv7h
 | 
					 | 
				
			||||||
        arch = armv6h
 | 
					 | 
				
			||||||
        arch = aarch64
 | 
					 | 
				
			||||||
        license = GPL3
 | 
					 | 
				
			||||||
        makedepends = go
 | 
					 | 
				
			||||||
        depends = pacman>5
 | 
					 | 
				
			||||||
        depends = git
 | 
					 | 
				
			||||||
        optdepends = sudo
 | 
					 | 
				
			||||||
        source = yay-10.2.0.tar.gz::https://github.com/Jguer/yay/archive/v10.2.0.tar.gz
 | 
					 | 
				
			||||||
        sha256sums = 755d049ec09cc20bdcbb004b12ab4e35ba3bb94a7dce9dfa544d24f87deda8aa
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pkgname = yay
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user