mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-09-01 14:29:55 +00:00
Compare commits
8 Commits
cd70445ac5
...
2.15.3
Author | SHA1 | Date | |
---|---|---|---|
7799389cd8 | |||
030fecd173 | |||
343435b3bf | |||
f0930be238 | |||
113a861f31 | |||
528d7ce398 | |||
b357c96204 | |||
5d495fc813 |
12984
docs/_static/architecture.svg
vendored
12984
docs/_static/architecture.svg
vendored
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.3 MiB |
@ -52,6 +52,14 @@ ahriman.core.tree module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.types module
|
||||
-------------------------
|
||||
|
||||
.. automodule:: ahriman.core.types
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.util module
|
||||
------------------------
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Maintainer: Evgeniy Alekseev
|
||||
|
||||
pkgname='ahriman'
|
||||
pkgver=2.15.1
|
||||
pkgver=2.15.3
|
||||
pkgrel=1
|
||||
pkgdesc="ArcH linux ReposItory MANager"
|
||||
arch=('any')
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH AHRIMAN "1" "2024\-09\-24" "ahriman" "Generated Python Manual"
|
||||
.TH AHRIMAN "1" "2024\-11\-13" "ahriman" "Generated Python Manual"
|
||||
.SH NAME
|
||||
ahriman
|
||||
.SH SYNOPSIS
|
||||
@ -989,7 +989,25 @@ usage: ahriman web [\-h]
|
||||
start web server
|
||||
|
||||
.SH COMMENTS
|
||||
Argument list can also be read from file by using @ prefix.
|
||||
Quick setup command (replace repository name, architecture and packager as needed):
|
||||
|
||||
>>> ahriman \-a x86_64 \-r aur service\-setup \-\-packager "ahriman bot <ahriman@example.com>"
|
||||
|
||||
Add new package from AUR:
|
||||
|
||||
>>> ahriman package\-add ahriman \-\-now
|
||||
|
||||
Check for updates and build out\-of\-dated packages (add ``\-\-dry\-run`` to build it later):
|
||||
|
||||
>>> ahriman repo\-update
|
||||
|
||||
Remove package from the repository:
|
||||
|
||||
>>> ahriman package\-remove ahriman
|
||||
|
||||
Start web service (requires additional configuration):
|
||||
|
||||
>>> ahriman web
|
||||
|
||||
.SH AUTHOR
|
||||
.nf
|
||||
|
@ -17,4 +17,4 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
__version__ = "2.15.1"
|
||||
__version__ = "2.15.3"
|
||||
|
@ -27,6 +27,7 @@ from ahriman.application.lock import Lock
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
||||
from ahriman.core.log.log_loader import LogLoader
|
||||
from ahriman.core.types import ExplicitBool
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
@ -124,13 +125,14 @@ class Handler:
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def check_status(enabled: bool, status: bool | Callable[[], bool]) -> None:
|
||||
def check_status(enabled: bool, status: ExplicitBool | Callable[[], ExplicitBool]) -> None:
|
||||
"""
|
||||
check condition and flag and raise ExitCode exception in case if it is enabled and condition match
|
||||
|
||||
Args:
|
||||
enabled(bool): if ``False`` no check will be performed
|
||||
status(bool | Callable[[], bool]): return status or function to check. ``True`` means success and vice versa
|
||||
status(ExplicitBool | Callable[[], ExplicitBool]): return status or function to check.
|
||||
``True`` means success and vice versa
|
||||
|
||||
Raises:
|
||||
ExitCode: if result is empty and check is enabled
|
||||
@ -138,12 +140,9 @@ class Handler:
|
||||
if not enabled:
|
||||
return
|
||||
|
||||
match status:
|
||||
case False:
|
||||
raise ExitCode
|
||||
# https://github.com/python/mypy/issues/14014
|
||||
case Callable() if not status(): # type: ignore[misc]
|
||||
raise ExitCode
|
||||
status = status() if callable(status) else status
|
||||
if not status:
|
||||
raise ExitCode
|
||||
|
||||
@staticmethod
|
||||
def repositories_extract(args: argparse.Namespace) -> list[RepositoryId]:
|
||||
|
@ -136,7 +136,7 @@ class Patch(Handler):
|
||||
for patch in application.reporter.package_patches_get(package_base, None)
|
||||
if variables is None or patch.key in variables
|
||||
]
|
||||
Patch.check_status(exit_code, bool(patches))
|
||||
Patch.check_status(exit_code, patches)
|
||||
|
||||
PatchPrinter(package_base, patches)(verbose=True, separator=" = ")
|
||||
|
||||
|
@ -51,7 +51,7 @@ class Rebuild(Handler):
|
||||
packages = Rebuild.extract_packages(application, args.status, from_database=args.from_database)
|
||||
packages = application.repository.packages_depend_on(packages, args.depends_on)
|
||||
|
||||
Rebuild.check_status(args.exit_code, bool(packages))
|
||||
Rebuild.check_status(args.exit_code, packages)
|
||||
if args.dry_run:
|
||||
application.print_updates(packages, log_fn=print)
|
||||
return
|
||||
|
@ -141,7 +141,7 @@ class Setup(Handler):
|
||||
|
||||
(root.include / "00-setup-overrides.ini").unlink(missing_ok=True) # remove old-style configuration
|
||||
target = root.include / f"00-setup-overrides-{repository_id.id}.ini"
|
||||
with target.open("w") as ahriman_configuration:
|
||||
with target.open("w", encoding="utf8") as ahriman_configuration:
|
||||
configuration.write(ahriman_configuration)
|
||||
|
||||
@staticmethod
|
||||
@ -191,7 +191,7 @@ class Setup(Handler):
|
||||
configuration.set_option(repository_id.name, "Server", repository_server)
|
||||
|
||||
target = source.parent / f"{repository_id.name}-{repository_id.architecture}.conf"
|
||||
with target.open("w") as devtools_configuration:
|
||||
with target.open("w", encoding="utf8") as devtools_configuration:
|
||||
configuration.write(devtools_configuration)
|
||||
|
||||
@staticmethod
|
||||
|
@ -61,7 +61,7 @@ class Status(Handler):
|
||||
else:
|
||||
packages = client.package_get(None)
|
||||
|
||||
Status.check_status(args.exit_code, bool(packages))
|
||||
Status.check_status(args.exit_code, packages)
|
||||
|
||||
comparator: Callable[[tuple[Package, BuildStatus]], str] = lambda item: item[0].base
|
||||
filter_fn: Callable[[tuple[Package, BuildStatus]], bool] =\
|
||||
|
@ -54,7 +54,7 @@ class Update(Handler):
|
||||
application.changes(packages)
|
||||
|
||||
if args.dry_run: # exit from application if no build requested
|
||||
Update.check_status(args.exit_code, bool(packages)) # status code check
|
||||
Update.check_status(args.exit_code, packages) # status code check
|
||||
return
|
||||
|
||||
packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
|
||||
|
@ -61,7 +61,7 @@ class Users(Handler):
|
||||
users = database.user_list(args.username, args.role)
|
||||
for user in users:
|
||||
UserPrinter(user)(verbose=True)
|
||||
Users.check_status(args.exit_code, bool(users))
|
||||
Users.check_status(args.exit_code, users)
|
||||
case Action.Remove:
|
||||
database.user_remove(args.username)
|
||||
|
||||
|
@ -112,7 +112,7 @@ class Lock(LazyLogging):
|
||||
"""
|
||||
if self.path is None:
|
||||
return
|
||||
self._pid_file = self.path.open("a+")
|
||||
self._pid_file = self.path.open("a+", encoding="utf8")
|
||||
|
||||
def _watch(self) -> bool:
|
||||
"""
|
||||
|
@ -91,9 +91,8 @@ class Pacman(LazyLogging):
|
||||
database = self.database_init(handle, repository, self.repository_id.architecture)
|
||||
self.database_copy(handle, database, pacman_root, use_ahriman_cache=use_ahriman_cache)
|
||||
|
||||
# install repository database too
|
||||
local_database = self.database_init(handle, self.repository_id.name, self.repository_id.architecture)
|
||||
self.database_copy(handle, local_database, pacman_root, use_ahriman_cache=use_ahriman_cache)
|
||||
# install repository database too (without copying)
|
||||
self.database_init(handle, self.repository_id.name, self.repository_id.architecture)
|
||||
|
||||
if use_ahriman_cache and refresh_database:
|
||||
self.database_sync(handle, force=refresh_database == PacmanSynchronization.Force)
|
||||
@ -115,6 +114,7 @@ class Pacman(LazyLogging):
|
||||
|
||||
if not use_ahriman_cache:
|
||||
return
|
||||
|
||||
# copy root database if no local copy found
|
||||
pacman_db_path = Path(handle.dbpath)
|
||||
if not pacman_db_path.is_dir():
|
||||
@ -123,11 +123,13 @@ class Pacman(LazyLogging):
|
||||
if dst.is_file():
|
||||
return # file already exists, do not copy
|
||||
dst.parent.mkdir(mode=0o755, exist_ok=True) # create sync directory if it doesn't exist
|
||||
|
||||
src = repository_database(pacman_root)
|
||||
if not src.is_file():
|
||||
self.logger.warning("repository %s is set to be used, however, no working copy was found", database.name)
|
||||
return # database for some reason deos not exist
|
||||
self.logger.info("copy pacman database from operating system root to ahriman's home")
|
||||
|
||||
self.logger.info("copy pacman database %s from operating system root to ahriman's home %s", src, dst)
|
||||
shutil.copy(src, dst)
|
||||
self.repository_paths.chown(dst)
|
||||
|
||||
|
@ -174,18 +174,31 @@ class PkgbuildParser(shlex.shlex):
|
||||
Returns:
|
||||
bool: ``True`` if the previous element of the stream is a quote or escaped and ``False`` otherwise
|
||||
"""
|
||||
# wrapper around reading utf symbols from random position of the stream
|
||||
def read_last() -> tuple[int, str]:
|
||||
while (position := self._io.tell()) > 0:
|
||||
try:
|
||||
return position, self._io.read(1)
|
||||
except UnicodeDecodeError:
|
||||
self._io.seek(position - 1)
|
||||
|
||||
raise PkgbuildParserError("reached starting position, no valid symbols found")
|
||||
|
||||
current_position = self._io.tell()
|
||||
|
||||
last_char = penultimate_char = None
|
||||
for index in range(current_position - 1, -1, -1):
|
||||
index = current_position - 1
|
||||
while index > 0:
|
||||
self._io.seek(index)
|
||||
last_char = self._io.read(1)
|
||||
|
||||
index, last_char = read_last()
|
||||
if last_char.isspace():
|
||||
index -= 1
|
||||
continue
|
||||
|
||||
if index >= 0:
|
||||
if index > 1:
|
||||
self._io.seek(index - 1)
|
||||
penultimate_char = self._io.read(1)
|
||||
_, penultimate_char = read_last()
|
||||
|
||||
break
|
||||
|
||||
@ -213,9 +226,10 @@ class PkgbuildParser(shlex.shlex):
|
||||
pass
|
||||
case PkgbuildToken.ArrayEnds:
|
||||
break
|
||||
case PkgbuildToken.Comment:
|
||||
case comment if comment.startswith(PkgbuildToken.Comment):
|
||||
self.instream.readline()
|
||||
continue
|
||||
|
||||
yield token
|
||||
|
||||
if token != PkgbuildToken.ArrayEnds:
|
||||
@ -248,24 +262,28 @@ class PkgbuildParser(shlex.shlex):
|
||||
counter += 1
|
||||
case PkgbuildToken.FunctionEnds:
|
||||
end_position = self._io.tell()
|
||||
if self.state != self.eof: # type: ignore[attr-defined]
|
||||
end_position -= 1 # if we are not at the end of the file, position is _after_ the token
|
||||
counter -= 1
|
||||
if counter == 0:
|
||||
break
|
||||
case comment if comment.startswith(PkgbuildToken.Comment):
|
||||
self.instream.readline()
|
||||
|
||||
if not 0 < start_position < end_position:
|
||||
raise PkgbuildParserError("function body wasn't found")
|
||||
|
||||
# read the specified interval from source stream
|
||||
self._io.seek(start_position - 1) # start from the previous symbol
|
||||
content = self._io.read(end_position - start_position)
|
||||
# we cannot use :func:`read()` here, because it reads characters, not bytes
|
||||
content = ""
|
||||
while self._io.tell() != end_position and (next_char := self._io.read(1)):
|
||||
content += next_char
|
||||
|
||||
# special case of the end of file
|
||||
if self.state == self.eof: # type: ignore[attr-defined]
|
||||
content += self._io.read(1)
|
||||
|
||||
# reset position (because the last position was before the next token starts)
|
||||
self._io.seek(end_position)
|
||||
|
||||
return content
|
||||
|
||||
def _parse_token(self, token: str) -> Generator[PkgbuildPatch, None, None]:
|
||||
@ -285,7 +303,7 @@ class PkgbuildParser(shlex.shlex):
|
||||
yield PkgbuildPatch(key, value)
|
||||
return
|
||||
|
||||
if token == PkgbuildToken.Comment:
|
||||
if token.startswith(PkgbuildToken.Comment):
|
||||
self.instream.readline()
|
||||
return
|
||||
|
||||
|
@ -141,7 +141,7 @@ def migrate_package_statuses(connection: Connection, paths: RepositoryPaths) ->
|
||||
cache_path = paths.root / "status_cache.json"
|
||||
if not cache_path.is_file():
|
||||
return # no file found
|
||||
with cache_path.open() as cache:
|
||||
with cache_path.open(encoding="utf8") as cache:
|
||||
dump = json.load(cache)
|
||||
|
||||
for item in dump.get("packages", []):
|
||||
|
@ -23,9 +23,8 @@ from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
@ -39,16 +38,16 @@ class Operations(LazyLogging):
|
||||
path(Path): path to the database file
|
||||
"""
|
||||
|
||||
def __init__(self, path: Path, repository_id: RepositoryId, repository_paths: RepositoryPaths) -> None:
|
||||
def __init__(self, path: Path, configuration: Configuration) -> None:
|
||||
"""
|
||||
Args:
|
||||
path(Path): path to the database file
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
repository_paths(RepositoryPaths): repository paths
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.path = path
|
||||
self._repository_id = repository_id
|
||||
self._repository_paths = repository_paths
|
||||
self._configuration = configuration
|
||||
_, self._repository_id = configuration.check_loaded()
|
||||
self._repository_paths = configuration.repository_paths
|
||||
|
||||
@property
|
||||
def logger_name(self) -> str:
|
||||
|
@ -66,10 +66,9 @@ class SQLite(
|
||||
Self: fully initialized instance of the database
|
||||
"""
|
||||
path = cls.database_path(configuration)
|
||||
_, repository_id = configuration.check_loaded()
|
||||
|
||||
database = cls(path, repository_id, configuration.repository_paths)
|
||||
database.init(configuration)
|
||||
database = cls(path, configuration)
|
||||
database.init()
|
||||
|
||||
return database
|
||||
|
||||
@ -86,23 +85,18 @@ class SQLite(
|
||||
"""
|
||||
return configuration.getpath("settings", "database")
|
||||
|
||||
def init(self, configuration: Configuration) -> None:
|
||||
def init(self) -> None:
|
||||
"""
|
||||
perform database migrations
|
||||
|
||||
Args:
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
# custom types support
|
||||
sqlite3.register_adapter(dict, json.dumps)
|
||||
sqlite3.register_adapter(list, json.dumps)
|
||||
sqlite3.register_converter("json", json.loads)
|
||||
|
||||
paths = configuration.repository_paths
|
||||
|
||||
if configuration.getboolean("settings", "apply_migrations", fallback=True):
|
||||
self.with_connection(lambda connection: Migrations.migrate(connection, configuration))
|
||||
paths.chown(self.path)
|
||||
if self._configuration.getboolean("settings", "apply_migrations", fallback=True):
|
||||
self.with_connection(lambda connection: Migrations.migrate(connection, self._configuration))
|
||||
self._repository_paths.chown(self.path)
|
||||
|
||||
def package_clear(self, package_base: str, repository_id: RepositoryId | None = None) -> None:
|
||||
"""
|
||||
|
@ -99,3 +99,24 @@ class LazyLogging:
|
||||
yield
|
||||
finally:
|
||||
self._package_logger_reset()
|
||||
|
||||
@contextlib.contextmanager
|
||||
def suppress_logging(self, log_level: int = logging.WARNING) -> Generator[None, None, None]:
|
||||
"""
|
||||
silence log messages in context
|
||||
|
||||
Args:
|
||||
log_level(int, optional): the highest log level to keep (Default value = logging.WARNING)
|
||||
|
||||
Examples:
|
||||
This function is designed to be used to suppress all log messages in context, e.g.:
|
||||
|
||||
>>> with self.suppress_logging():
|
||||
>>> do_some_noisy_actions()
|
||||
"""
|
||||
current_level = self.logger.manager.disable
|
||||
try:
|
||||
logging.disable(log_level)
|
||||
yield
|
||||
finally:
|
||||
logging.disable(current_level)
|
||||
|
@ -144,7 +144,8 @@ class UpdateHandler(PackageInfo, Cleaner):
|
||||
branch="master",
|
||||
)
|
||||
|
||||
Sources.fetch(cache_dir, source)
|
||||
with self.suppress_logging():
|
||||
Sources.fetch(cache_dir, source)
|
||||
remote = Package.from_build(cache_dir, self.architecture, None)
|
||||
|
||||
local = packages.get(remote.base)
|
||||
|
@ -116,7 +116,7 @@ class KeyringGenerator(PkgbuildGenerator):
|
||||
Args:
|
||||
source_path(Path): destination of the file content
|
||||
"""
|
||||
with source_path.open("w") as source_file:
|
||||
with source_path.open("w", encoding="utf8") as source_file:
|
||||
for key in sorted(set(self.trusted + self.packagers + self.revoked)):
|
||||
public_key = self.sign.key_export(key)
|
||||
source_file.write(public_key)
|
||||
@ -129,7 +129,7 @@ class KeyringGenerator(PkgbuildGenerator):
|
||||
Args:
|
||||
source_path(Path): destination of the file content
|
||||
"""
|
||||
with source_path.open("w") as source_file:
|
||||
with source_path.open("w", encoding="utf8") as source_file:
|
||||
for key in sorted(set(self.revoked)):
|
||||
fingerprint = self.sign.key_fingerprint(key)
|
||||
source_file.write(fingerprint)
|
||||
@ -147,7 +147,7 @@ class KeyringGenerator(PkgbuildGenerator):
|
||||
"""
|
||||
if not self.trusted:
|
||||
raise PkgbuildGeneratorError
|
||||
with source_path.open("w") as source_file:
|
||||
with source_path.open("w", encoding="utf8") as source_file:
|
||||
for key in sorted(set(self.trusted)):
|
||||
fingerprint = self.sign.key_fingerprint(key)
|
||||
source_file.write(fingerprint)
|
||||
|
39
src/ahriman/core/types.py
Normal file
39
src/ahriman/core/types.py
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
class HasBool(Protocol):
|
||||
"""
|
||||
class which defines :func:`bool()` method
|
||||
"""
|
||||
|
||||
def __bool__(self) -> bool: ...
|
||||
|
||||
|
||||
class HasLength(Protocol):
|
||||
"""
|
||||
class which defines :func:`len()` method
|
||||
"""
|
||||
|
||||
def __len__(self) -> int: ...
|
||||
|
||||
|
||||
ExplicitBool = HasBool | HasLength | int
|
@ -429,13 +429,14 @@ class Package(LazyLogging):
|
||||
task = Task(self, configuration, repository_id.architecture, paths)
|
||||
|
||||
try:
|
||||
# create fresh chroot environment, fetch sources and - automagically - update PKGBUILD
|
||||
task.init(paths.cache_for(self.base), [], None)
|
||||
task.build(paths.cache_for(self.base), dry_run=True)
|
||||
with self.suppress_logging():
|
||||
# create fresh chroot environment, fetch sources and - automagically - update PKGBUILD
|
||||
task.init(paths.cache_for(self.base), [], None)
|
||||
task.build(paths.cache_for(self.base), dry_run=True)
|
||||
|
||||
pkgbuild = Pkgbuild.from_file(paths.cache_for(self.base) / "PKGBUILD")
|
||||
pkgbuild = Pkgbuild.from_file(paths.cache_for(self.base) / "PKGBUILD")
|
||||
|
||||
return full_version(pkgbuild.get("epoch"), pkgbuild["pkgver"], pkgbuild["pkgrel"])
|
||||
return full_version(pkgbuild.get("epoch"), pkgbuild["pkgver"], pkgbuild["pkgrel"])
|
||||
except Exception:
|
||||
self.logger.exception("cannot determine version of VCS package")
|
||||
finally:
|
||||
|
@ -64,7 +64,7 @@ class Pkgbuild(Mapping[str, Any]):
|
||||
Returns:
|
||||
Self: constructed instance of self
|
||||
"""
|
||||
with path.open() as input_file:
|
||||
with path.open(encoding="utf8") as input_file:
|
||||
return cls.from_io(input_file)
|
||||
|
||||
@classmethod
|
||||
|
@ -199,7 +199,7 @@ class PkgbuildPatch:
|
||||
Args:
|
||||
pkgbuild_path(Path): path to PKGBUILD file
|
||||
"""
|
||||
with pkgbuild_path.open("a") as pkgbuild:
|
||||
with pkgbuild_path.open("a", encoding="utf8") as pkgbuild:
|
||||
pkgbuild.write("\n") # in case if file ends without new line we are appending it at the end
|
||||
pkgbuild.write(self.serialize())
|
||||
pkgbuild.write("\n") # append new line after the values
|
||||
|
@ -174,9 +174,8 @@ class BaseView(View, CorsViewMixin):
|
||||
# using if/else in order to suppress mypy warning which doesn't know that
|
||||
# :func:`aiohttp.web.View._raise_allowed_methods()` raises exception
|
||||
if get_method is not None:
|
||||
# there is a bug in pylint, see https://github.com/pylint-dev/pylint/issues/6005
|
||||
response = await get_method()
|
||||
response._body = b"" # type: ignore[assignment]
|
||||
response._body = b""
|
||||
return response
|
||||
|
||||
self._raise_allowed_methods()
|
||||
|
@ -168,7 +168,7 @@ def test_patch_set_list(application: Application, mocker: MockerFixture) -> None
|
||||
Patch.patch_set_list(application, "ahriman", ["version"], False)
|
||||
get_mock.assert_called_once_with("ahriman", None)
|
||||
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=" = ")
|
||||
check_mock.assert_called_once_with(False, True)
|
||||
check_mock.assert_called_once_with(False, [PkgbuildPatch(key='version', value='value')])
|
||||
|
||||
|
||||
def test_patch_set_list_all(application: Application, mocker: MockerFixture) -> None:
|
||||
@ -183,7 +183,7 @@ def test_patch_set_list_all(application: Application, mocker: MockerFixture) ->
|
||||
Patch.patch_set_list(application, "ahriman", None, False)
|
||||
get_mock.assert_called_once_with("ahriman", None)
|
||||
print_mock.assert_called_once_with(verbose=True, log_fn=pytest.helpers.anyvar(int), separator=" = ")
|
||||
check_mock.assert_called_once_with(False, True)
|
||||
check_mock.assert_called_once_with(False, [PkgbuildPatch(key=None, value='patch')])
|
||||
|
||||
|
||||
def test_patch_set_list_empty_exception(application: Application, mocker: MockerFixture) -> None:
|
||||
@ -194,7 +194,7 @@ def test_patch_set_list_empty_exception(application: Application, mocker: Mocker
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
|
||||
Patch.patch_set_list(application, "ahriman", [], True)
|
||||
check_mock.assert_called_once_with(True, False)
|
||||
check_mock.assert_called_once_with(True, [])
|
||||
|
||||
|
||||
def test_patch_set_create(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||
|
@ -55,7 +55,7 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
|
||||
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database)
|
||||
application_packages_mock.assert_called_once_with([package_ahriman], None)
|
||||
application_mock.assert_called_once_with([package_ahriman], Packagers(args.username), bump_pkgrel=args.increment)
|
||||
check_mock.assert_has_calls([MockCall(False, True), MockCall(False, True)])
|
||||
check_mock.assert_has_calls([MockCall(False, [package_ahriman]), MockCall(False, True)])
|
||||
on_start_mock.assert_called_once_with()
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Rebuild.run(args, repository_id, configuration, report=False)
|
||||
application_mock.assert_not_called()
|
||||
check_mock.assert_called_once_with(False, True)
|
||||
check_mock.assert_called_once_with(False, [package_ahriman])
|
||||
print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ def test_run_update_empty_exception(args: argparse.Namespace, configuration: Con
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Rebuild.run(args, repository_id, configuration, report=False)
|
||||
check_mock.assert_called_once_with(True, False)
|
||||
check_mock.assert_called_once_with(True, [])
|
||||
|
||||
|
||||
def test_run_build_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
|
||||
@ -164,7 +164,7 @@ def test_run_build_empty_exception(args: argparse.Namespace, configuration: Conf
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Rebuild.run(args, repository_id, configuration, report=False)
|
||||
check_mock.assert_has_calls([MockCall(True, True), MockCall(True, False)])
|
||||
check_mock.assert_has_calls([MockCall(True, [package_ahriman]), MockCall(True, False)])
|
||||
|
||||
|
||||
def test_extract_packages(application: Application, mocker: MockerFixture) -> None:
|
||||
|
@ -36,11 +36,13 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
must run command
|
||||
"""
|
||||
args = _default_args(args)
|
||||
packages = [
|
||||
(package_ahriman, BuildStatus(BuildStatusEnum.Success)),
|
||||
(package_python_schedule, BuildStatus(BuildStatusEnum.Failed)),
|
||||
]
|
||||
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
|
||||
application_mock = mocker.patch("ahriman.core.status.Client.status_get")
|
||||
packages_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get",
|
||||
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success)),
|
||||
(package_python_schedule, BuildStatus(BuildStatusEnum.Failed))])
|
||||
packages_mock = mocker.patch("ahriman.core.status.local_client.LocalClient.package_get", return_value=packages)
|
||||
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_status")
|
||||
print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
|
||||
|
||||
@ -48,7 +50,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
|
||||
Status.run(args, repository_id, configuration, report=False)
|
||||
application_mock.assert_called_once_with()
|
||||
packages_mock.assert_called_once_with(None)
|
||||
check_mock.assert_called_once_with(False, True)
|
||||
check_mock.assert_called_once_with(False, packages)
|
||||
print_mock.assert_has_calls([
|
||||
MockCall(verbose=False, log_fn=pytest.helpers.anyvar(int), separator=": ")
|
||||
for _ in range(3)
|
||||
@ -69,7 +71,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Status.run(args, repository_id, configuration, report=False)
|
||||
check_mock.assert_called_once_with(True, False)
|
||||
check_mock.assert_called_once_with(True, [])
|
||||
|
||||
|
||||
def test_run_verbose(args: argparse.Namespace, configuration: Configuration, repository: Repository,
|
||||
|
@ -85,7 +85,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Update.run(args, repository_id, configuration, report=False)
|
||||
check_mock.assert_called_once_with(True, False)
|
||||
check_mock.assert_called_once_with(True, [])
|
||||
|
||||
|
||||
def test_run_update_empty_exception(args: argparse.Namespace, package_ahriman: Package, configuration: Configuration,
|
||||
@ -127,7 +127,7 @@ def test_run_dry_run(args: argparse.Namespace, package_ahriman: Package, configu
|
||||
args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs, check_files=args.check_files)
|
||||
application_mock.assert_not_called()
|
||||
changes_mock.assert_called_once_with([package_ahriman])
|
||||
check_mock.assert_called_once_with(False, True)
|
||||
check_mock.assert_called_once_with(False, [package_ahriman])
|
||||
|
||||
|
||||
def test_run_no_changes(args: argparse.Namespace, configuration: Configuration, repository: Repository,
|
||||
|
@ -103,7 +103,7 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, databa
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Users.run(args, repository_id, configuration, report=False)
|
||||
list_mock.assert_called_once_with("user", args.role)
|
||||
check_mock.assert_called_once_with(False, True)
|
||||
check_mock.assert_called_once_with(False, [user])
|
||||
|
||||
|
||||
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, database: SQLite,
|
||||
@ -120,7 +120,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
|
||||
|
||||
_, repository_id = configuration.check_loaded()
|
||||
Users.run(args, repository_id, configuration, report=False)
|
||||
check_mock.assert_called_once_with(True, False)
|
||||
check_mock.assert_called_once_with(True, [])
|
||||
|
||||
|
||||
def test_run_remove(args: argparse.Namespace, configuration: Configuration, database: SQLite,
|
||||
|
@ -63,7 +63,7 @@ def test_open(lock: Lock, mocker: MockerFixture) -> None:
|
||||
lock.path = Path("ahriman.pid")
|
||||
|
||||
lock._open()
|
||||
open_mock.assert_called_once_with("a+")
|
||||
open_mock.assert_called_once_with("a+", encoding="utf8")
|
||||
|
||||
|
||||
def test_open_skip(lock: Lock, mocker: MockerFixture) -> None:
|
||||
|
@ -42,6 +42,17 @@ def test_expand_array_exception() -> None:
|
||||
assert PkgbuildParser._expand_array(["${pkgbase}{", ",", "-libs"])
|
||||
|
||||
|
||||
def test_is_escaped_exception(resource_path_root: Path) -> None:
|
||||
"""
|
||||
must raise PkgbuildParserError if no valid utf symbols found
|
||||
"""
|
||||
utf8 = resource_path_root / "models" / "utf8"
|
||||
with utf8.open(encoding="utf8") as content:
|
||||
content.seek(2)
|
||||
with pytest.raises(PkgbuildParserError):
|
||||
assert not PkgbuildParser(content)._is_escaped()
|
||||
|
||||
|
||||
def test_parse_array() -> None:
|
||||
"""
|
||||
must parse array
|
||||
@ -193,7 +204,7 @@ def test_parse(resource_path_root: Path) -> None:
|
||||
must parse complex file
|
||||
"""
|
||||
pkgbuild = resource_path_root / "models" / "pkgbuild"
|
||||
with pkgbuild.open() as content:
|
||||
with pkgbuild.open(encoding="utf8") as content:
|
||||
parser = PkgbuildParser(content)
|
||||
assert list(parser.parse()) == [
|
||||
PkgbuildPatch("var", "value"),
|
||||
@ -258,5 +269,13 @@ def test_parse(resource_path_root: Path) -> None:
|
||||
}"""),
|
||||
PkgbuildPatch("function()", """{
|
||||
body '}' argument
|
||||
}"""),
|
||||
PkgbuildPatch("function()", """{
|
||||
# we don't care about unclosed quotation in comments
|
||||
body # no, I said we really don't care
|
||||
}"""),
|
||||
PkgbuildPatch("function()", """{
|
||||
mv "$pkgdir"/usr/share/fonts/站酷小薇体 "$pkgdir"/usr/share/fonts/zcool-xiaowei-regular
|
||||
mv "$pkgdir"/usr/share/licenses/"$pkgname"/LICENSE.站酷小薇体 "$pkgdir"/usr/share/licenses/"$pkgname"/LICENSE.zcool-xiaowei-regular
|
||||
}"""),
|
||||
]
|
||||
|
@ -13,7 +13,7 @@ def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
init_mock = mocker.patch("ahriman.core.database.SQLite.init")
|
||||
SQLite.load(configuration)
|
||||
init_mock.assert_called_once_with(configuration)
|
||||
init_mock.assert_called_once_with()
|
||||
|
||||
|
||||
def test_init(database: SQLite, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
@ -21,18 +21,18 @@ def test_init(database: SQLite, configuration: Configuration, mocker: MockerFixt
|
||||
must run migrations on init
|
||||
"""
|
||||
migrate_schema_mock = mocker.patch("ahriman.core.database.migrations.Migrations.migrate")
|
||||
database.init(configuration)
|
||||
migrate_schema_mock.assert_called_once_with(pytest.helpers.anyvar(int), configuration)
|
||||
database.init()
|
||||
migrate_schema_mock.assert_called_once_with(pytest.helpers.anyvar(int), database._configuration)
|
||||
|
||||
|
||||
def test_init_skip_migration(database: SQLite, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
def test_init_skip_migration(database: SQLite, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must skip migrations if option is set
|
||||
"""
|
||||
configuration.set_option("settings", "apply_migrations", "no")
|
||||
database._configuration.set_option("settings", "apply_migrations", "no")
|
||||
migrate_schema_mock = mocker.patch("ahriman.core.database.migrations.Migrations.migrate")
|
||||
|
||||
database.init(configuration)
|
||||
database.init()
|
||||
migrate_schema_mock.assert_not_called()
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@ import logging
|
||||
import pytest
|
||||
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import call as MockCall
|
||||
|
||||
from ahriman.core.alpm.repo import Repo
|
||||
from ahriman.core.build_tools.task import Task
|
||||
@ -10,6 +11,17 @@ from ahriman.models.log_record_id import LogRecordId
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
def test_logger(database: SQLite, repo: Repo) -> None:
|
||||
"""
|
||||
must set logger attribute
|
||||
"""
|
||||
assert database.logger
|
||||
assert database.logger.name == "sql"
|
||||
|
||||
assert repo.logger
|
||||
assert repo.logger.name == "ahriman.core.alpm.repo.Repo"
|
||||
|
||||
|
||||
def test_logger_name(database: SQLite, repo: Repo, task_ahriman: Task) -> None:
|
||||
"""
|
||||
must correctly generate logger name
|
||||
@ -77,12 +89,11 @@ def test_in_package_context_failed(database: SQLite, package_ahriman: Package, m
|
||||
reset_mock.assert_called_once_with()
|
||||
|
||||
|
||||
def test_logger(database: SQLite, repo: Repo) -> None:
|
||||
def test_suppress_logging(database: SQLite, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must set logger attribute
|
||||
must temporary disable log messages
|
||||
"""
|
||||
assert database.logger
|
||||
assert database.logger.name == "sql"
|
||||
|
||||
assert repo.logger
|
||||
assert repo.logger.name == "ahriman.core.alpm.repo.Repo"
|
||||
disable_mock = mocker.patch("ahriman.core.log.lazy_logging.logging.disable")
|
||||
with database.suppress_logging():
|
||||
pass
|
||||
disable_mock.assert_has_calls([MockCall(logging.WARNING), MockCall(logging.NOTSET)])
|
||||
|
@ -114,7 +114,7 @@ def test_generate_gpg(keyring_generator: KeyringGenerator, mocker: MockerFixture
|
||||
keyring_generator.trusted = ["trusted", "key"]
|
||||
|
||||
keyring_generator._generate_gpg(Path("local"))
|
||||
open_mock.assert_called_once_with("w")
|
||||
open_mock.assert_called_once_with("w", encoding="utf8")
|
||||
export_mock.assert_has_calls([MockCall("key"), MockCall("revoked"), MockCall("trusted")])
|
||||
file_mock.write.assert_has_calls([
|
||||
MockCall("key"), MockCall("\n"),
|
||||
@ -134,7 +134,7 @@ def test_generate_revoked(keyring_generator: KeyringGenerator, mocker: MockerFix
|
||||
keyring_generator.revoked = ["revoked"]
|
||||
|
||||
keyring_generator._generate_revoked(Path("local"))
|
||||
open_mock.assert_called_once_with("w")
|
||||
open_mock.assert_called_once_with("w", encoding="utf8")
|
||||
fingerprint_mock.assert_called_once_with("revoked")
|
||||
file_mock.write.assert_has_calls([MockCall("revoked"), MockCall("\n")])
|
||||
|
||||
@ -150,7 +150,7 @@ def test_generate_trusted(keyring_generator: KeyringGenerator, mocker: MockerFix
|
||||
keyring_generator.trusted = ["trusted", "trusted"]
|
||||
|
||||
keyring_generator._generate_trusted(Path("local"))
|
||||
open_mock.assert_called_once_with("w")
|
||||
open_mock.assert_called_once_with("w", encoding="utf8")
|
||||
fingerprint_mock.assert_called_once_with("trusted")
|
||||
file_mock.write.assert_has_calls([MockCall("trusted"), MockCall(":4:\n")])
|
||||
|
||||
|
1
tests/ahriman/core/test_types.py
Normal file
1
tests/ahriman/core/test_types.py
Normal file
@ -0,0 +1 @@
|
||||
# no need to test types explicitly
|
@ -472,8 +472,10 @@ def test_walk(resource_path_root: Path) -> None:
|
||||
resource_path_root / "models" / "package_gcc10_pkgbuild",
|
||||
resource_path_root / "models" / "package_jellyfin-ffmpeg6-bin_pkgbuild",
|
||||
resource_path_root / "models" / "package_tpacpi-bat-git_pkgbuild",
|
||||
resource_path_root / "models" / "package_vim-youcompleteme-git_pkgbuild",
|
||||
resource_path_root / "models" / "package_yay_pkgbuild",
|
||||
resource_path_root / "models" / "pkgbuild",
|
||||
resource_path_root / "models" / "utf8",
|
||||
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" / "login-modal.jinja2",
|
||||
|
@ -26,7 +26,7 @@ def test_from_file(pkgbuild_ahriman: Pkgbuild, mocker: MockerFixture) -> None:
|
||||
load_mock = mocker.patch("ahriman.models.pkgbuild.Pkgbuild.from_io", return_value=pkgbuild_ahriman)
|
||||
|
||||
assert Pkgbuild.from_file(Path("local"))
|
||||
open_mock.assert_called_once_with()
|
||||
open_mock.assert_called_once_with(encoding="utf8")
|
||||
load_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
@ -386,3 +386,66 @@ def test_parse_yay(resource_path_root: Path) -> None:
|
||||
"source": ["${pkgname}-${pkgver}.tar.gz::https://github.com/Jguer/yay/archive/v${pkgver}.tar.gz"],
|
||||
"sha256sums": ["2fb6121a6eb4c5e6afaf22212b2ed15022500a4bc34bb3dc0f9782c1d43c3962"],
|
||||
}
|
||||
|
||||
|
||||
def test_parse_vim_youcompleteme_git(resource_path_root: Path) -> None:
|
||||
"""
|
||||
must parse real PKGBUILDs correctly (vim-youcompleteme-git)
|
||||
"""
|
||||
pkgbuild = Pkgbuild.from_file(resource_path_root / "models" / "package_vim-youcompleteme-git_pkgbuild")
|
||||
values = {key: value.value for key, value in pkgbuild.fields.items() if not value.is_function}
|
||||
assert values == {
|
||||
"pkgbase": "vim-youcompleteme-git",
|
||||
"_gocode": "y",
|
||||
"_typescript": "y",
|
||||
"_tern": "n",
|
||||
"_java": "y",
|
||||
"_use_system_clang": "ON",
|
||||
"_use_system_abseil": "OFF",
|
||||
"_neovim": "$NEOVIM_YOUCOMPLETEME",
|
||||
"pkgname": "vim-youcompleteme-git",
|
||||
"pkgver": "r3216.0d855962",
|
||||
"pkgrel": "1",
|
||||
"pkgdesc": "A code-completion engine for Vim",
|
||||
"arch": ["x86_64"],
|
||||
"url": "https://ycm-core.github.io/YouCompleteMe/",
|
||||
"license": ["GPL3"],
|
||||
"groups": ["vim-plugins"],
|
||||
"depends": [
|
||||
"vim",
|
||||
"python>=3.6",
|
||||
"python-watchdog",
|
||||
"python-bottle",
|
||||
"clang"
|
||||
],
|
||||
"makedepends": [
|
||||
"git",
|
||||
"cmake",
|
||||
"pybind11",
|
||||
],
|
||||
"optdepends": [
|
||||
"gopls: Go semantic completion",
|
||||
"nodejs-tern: JavaScript semantic completion",
|
||||
"rust-analyzer: Rust semantic completion",
|
||||
"typescript: Typescript semantic completion",
|
||||
"python-jedi: Python semantic completion",
|
||||
"python-numpydoc: Python semantic completion",
|
||||
"python-regex: Better Unicode support",
|
||||
"omnisharp-roslyn: C# semantic completion",
|
||||
"java-environment>=11: Java semantic completion",
|
||||
"jdtls: Java semantic completion",
|
||||
"abseil-cpp: if setting _use_system_abseil ON",
|
||||
],
|
||||
"source": [
|
||||
"git+https://github.com/ycm-core/YouCompleteMe.git",
|
||||
"git+https://github.com/ycm-core/ycmd.git",
|
||||
"clangd-15.0.1.tar.bz2::https://github.com/ycm-core/llvm/releases/download/15.0.1/clangd-15.0.1-x86_64-unknown-linux-gnu.tar.bz2",
|
||||
"libclang-15.0.1.tar.bz2::https://github.com/ycm-core/llvm/releases/download/15.0.1/libclang-15.0.1-x86_64-unknown-linux-gnu.tar.bz2",
|
||||
],
|
||||
"sha256sums": [
|
||||
"SKIP",
|
||||
"SKIP",
|
||||
"10a64c468d1dd2a384e0e5fd4eb2582fd9f1dfa706b6d2d2bb88fb0fbfc2718d",
|
||||
"9a5bee818a4995bc52e91588059bef42728d046808206bfb93977f4e3109e50c",
|
||||
],
|
||||
}
|
||||
|
@ -149,5 +149,5 @@ def test_write(mocker: MockerFixture) -> None:
|
||||
open_mock.return_value.__enter__.return_value = file_mock
|
||||
|
||||
PkgbuildPatch("key", "value").write(Path("PKGBUILD"))
|
||||
open_mock.assert_called_once_with("a")
|
||||
open_mock.assert_called_once_with("a", encoding="utf8")
|
||||
file_mock.write.assert_has_calls([call("\n"), call("""key=value"""), call("\n")])
|
||||
|
@ -0,0 +1,177 @@
|
||||
# Maintainer: Leonidas Spyropoulos <artafinde at gmail dot com>
|
||||
# Contributor: staletic
|
||||
# Contributor: James Brink <brink.james@gmail.com>
|
||||
# Contributor: Wilson E. Alvarez <wilson.e.alvarez1@gmail.com>
|
||||
# Contributor: p <parimal@beyond8labs.com>
|
||||
# Contributor: Victor <victor@xirion.net>
|
||||
# Contributor: Jan-Tarek Butt <tarek AT ring0 DOT de>
|
||||
# Contributor: Erik Beran <eberan AT gmail DOT com>
|
||||
# Contributor: Thor K. H. <thor at roht dot no>
|
||||
# Contributor: Babken Vardanyan <483ken 4tgma1l
|
||||
# Contributor: mikezackles
|
||||
# Contributor: z33ky
|
||||
# Contributor: stykr
|
||||
# Contributor: Svenstaro
|
||||
# Contributor: KaiSforza
|
||||
# Contributor: Simon Gomizelj <simongmzlj@gmail.com>
|
||||
# Contributor: Daniel Micay <danielmicay@gmail.com>
|
||||
# Contributor: shmilee
|
||||
# Contributor: foobster
|
||||
# Contributor: archdria
|
||||
# Contributor: Andy Weidenbaum <archbaum@gmail.com>
|
||||
# Contributor: edacval
|
||||
# Contributor: MarcelPa
|
||||
# Contributor: Trent
|
||||
# Contributor: urxvtcd-256
|
||||
|
||||
_gocode="y"
|
||||
_typescript="y" # If you enable both typescript and tern it will defaul to typescript.
|
||||
_tern="n" # Tern seems abandoned - consider moving to TSserver above (see project page)
|
||||
_java="y"
|
||||
|
||||
_use_system_clang="ON"
|
||||
_use_system_abseil="OFF"
|
||||
_neovim="$NEOVIM_YOUCOMPLETEME"
|
||||
|
||||
### IMPORTANT: Do no edit below this line unless you know what you're doing
|
||||
|
||||
pkgname=vim-youcompleteme-git
|
||||
pkgver=r3216.0d855962
|
||||
pkgrel=1
|
||||
pkgdesc='A code-completion engine for Vim'
|
||||
arch=('x86_64')
|
||||
url='https://ycm-core.github.io/YouCompleteMe/'
|
||||
license=('GPL3')
|
||||
groups=('vim-plugins')
|
||||
depends=('vim' 'python>=3.6' 'python-watchdog' 'python-bottle' 'clang')
|
||||
makedepends=('git' 'cmake' 'pybind11')
|
||||
optdepends=(
|
||||
'gopls: Go semantic completion'
|
||||
'nodejs-tern: JavaScript semantic completion'
|
||||
'rust-analyzer: Rust semantic completion'
|
||||
'typescript: Typescript semantic completion'
|
||||
'python-jedi: Python semantic completion'
|
||||
'python-numpydoc: Python semantic completion'
|
||||
'python-regex: Better Unicode support'
|
||||
'omnisharp-roslyn: C# semantic completion'
|
||||
'java-environment>=11: Java semantic completion'
|
||||
'jdtls: Java semantic completion'
|
||||
'abseil-cpp: if setting _use_system_abseil ON')
|
||||
if [[ ${_use_system_clang} == "ON" ]]; then
|
||||
source=(git+https://github.com/ycm-core/YouCompleteMe.git
|
||||
git+https://github.com/ycm-core/ycmd.git)
|
||||
sha256sums=('SKIP'
|
||||
'SKIP')
|
||||
else
|
||||
source=(git+https://github.com/ycm-core/YouCompleteMe.git
|
||||
git+https://github.com/ycm-core/ycmd.git
|
||||
clangd-15.0.1.tar.bz2::https://github.com/ycm-core/llvm/releases/download/15.0.1/clangd-15.0.1-x86_64-unknown-linux-gnu.tar.bz2
|
||||
libclang-15.0.1.tar.bz2::https://github.com/ycm-core/llvm/releases/download/15.0.1/libclang-15.0.1-x86_64-unknown-linux-gnu.tar.bz2)
|
||||
sha256sums=('SKIP'
|
||||
'SKIP'
|
||||
'10a64c468d1dd2a384e0e5fd4eb2582fd9f1dfa706b6d2d2bb88fb0fbfc2718d'
|
||||
'9a5bee818a4995bc52e91588059bef42728d046808206bfb93977f4e3109e50c')
|
||||
fi
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}"/YouCompleteMe || exit
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}"/YouCompleteMe || exit
|
||||
git submodule init third_party/ycmd
|
||||
git config submodule.ycmd.url "$srcdir"/ycmd
|
||||
git -c protocol.file.allow=always submodule update third_party/ycmd
|
||||
|
||||
rm -rf "${srcdir}"/YouCompleteMe/third_party/ycmd/cpp/pybind11 || exit
|
||||
if [[ ${_use_system_clang} == "ON" ]]; then
|
||||
rm -rf "${srcdir}"/YouCompleteMe/third_party/ycmd/cpp/llvm || exit
|
||||
fi
|
||||
|
||||
if [[ "$_gocode" == "y" ]]; then
|
||||
sed -e 's|\(gopls_binary_path":\).*$|\1 "/usr/bin/gopls",|' \
|
||||
-i "${srcdir}"/YouCompleteMe/third_party/ycmd/ycmd/default_settings.json
|
||||
fi
|
||||
|
||||
if [[ "$_typescript" == "y" ]]; then
|
||||
rm -rf "${srcdir}/YouCompleteMe/third_party/ycmd/third_party/tern_runtime" || exit
|
||||
sed -e 's|\(tsserver_binary_path":\).*$|\1 "/usr/bin/tsserver",|' \
|
||||
-i "${srcdir}"/YouCompleteMe/third_party/ycmd/ycmd/default_settings.json
|
||||
fi
|
||||
if [[ "$_java" == "y" ]]; then
|
||||
sed -e 's|\(java_jdtls_workspace_root_path":\).*$|\1 "/tmp",|' \
|
||||
-e 's|\(java_binary_path":\).*$|\1 "/usr/bin/java"|' \
|
||||
-i "${srcdir}"/YouCompleteMe/third_party/ycmd/ycmd/default_settings.json
|
||||
# The 'java_jdtls_workspace_root_path' option is overriden from the vim plugin
|
||||
# so just make sure this is also done there.
|
||||
sed -e "s|\(ycm_java_jdtls_workspace_root_path',\).*\$|\1 '/tmp' )|" \
|
||||
-i "${srcdir}"/YouCompleteMe/plugin/youcompleteme.vim
|
||||
fi
|
||||
|
||||
if [[ ${_use_system_clang} == "ON" ]]; then
|
||||
sed -e 's|\(clangd_binary_path":\).*$|\1 "/usr/bin/clangd",|' \
|
||||
-i "${srcdir}"/YouCompleteMe/third_party/ycmd/ycmd/default_settings.json
|
||||
# The 'ycm_clangd_binary_path' option is overriden from the vim plugin
|
||||
# so just make sure this is also done there.
|
||||
sed -e "s|\(ycm_clangd_binary_path',\).*\$|\1 '/usr/bin/clangd' )|" \
|
||||
-i "${srcdir}"/YouCompleteMe/plugin/youcompleteme.vim
|
||||
fi
|
||||
|
||||
sed -e 's|\(rust_toolchain_root":\).*$|\1 "/usr",|' \
|
||||
-e 's|\(roslyn_binary_path":\).*$|\1 "/opt/omnisharp-roslyn/OmniSharp.exe",|' \
|
||||
-e 's|\(mono_binary_path":\).*$|\1 "/usr/bin/mono",|' \
|
||||
-i "${srcdir}"/YouCompleteMe/third_party/ycmd/ycmd/default_settings.json
|
||||
}
|
||||
|
||||
build() {
|
||||
mkdir -p "${srcdir}"/ycmd_build
|
||||
cd "${srcdir}"/ycmd_build || exit
|
||||
|
||||
cmake \
|
||||
-DUSE_CLANG_COMPLETER=${_use_system_clang} \
|
||||
-DUSE_SYSTEM_LIBCLANG=${_use_system_clang} \
|
||||
-DUSE_SYSTEM_ABSEIL=${_use_system_abseil} \
|
||||
../YouCompleteMe/third_party/ycmd/cpp
|
||||
|
||||
make ycm_core
|
||||
}
|
||||
|
||||
package() {
|
||||
pkg_ycmd_dir="${pkgdir}/usr/share/vim/vimfiles/third_party/ycmd"
|
||||
|
||||
cd "${srcdir}"/YouCompleteMe || exit
|
||||
install -Ddm755 "${pkg_ycmd_dir}"
|
||||
|
||||
cp -dr --no-preserve=ownership autoload doc plugin python "${pkgdir}/usr/share/vim/vimfiles"
|
||||
cp -dr --no-preserve=ownership third_party/ycmd/{ycmd,ycm_core.*.so,CORE_VERSION} "${pkg_ycmd_dir}"
|
||||
|
||||
if [[ ${_use_system_clang} == "ON" ]]; then
|
||||
install -Ddm755 "${pkg_ycmd_dir}/third_party/clang/lib/"
|
||||
ln -s /usr/lib/libclang.so "${pkg_ycmd_dir}/third_party/clang/lib/libclang.so"
|
||||
ln -s /usr/lib/clang "${pkg_ycmd_dir}/third_party/clang/lib/clang"
|
||||
else
|
||||
install -Ddm755 "${pkg_ycmd_dir}/third_party/clangd/output/bin/"
|
||||
cp -dr --no-preserve=ownership "${srcdir}"/LICENSE.TXT "${pkg_ycmd_dir}/third_party/clangd/output"
|
||||
cp -dr --no-preserve=ownership "${srcdir}"/bin "${pkg_ycmd_dir}/third_party/clangd/output/"
|
||||
cp -dr --no-preserve=ownership "${srcdir}"/lib "${pkg_ycmd_dir}/third_party/clangd/output/"
|
||||
install -Ddm755 "${pkg_ycmd_dir}/third_party/clang/lib/"
|
||||
cp -dr --no-preserve=ownership "${srcdir}"/YouCompleteMe/third_party/ycmd/third_party/clang/lib/clang "${pkg_ycmd_dir}/third_party/clang/lib/clang"
|
||||
ln -sr "${pkg_ycmd_dir}"/third_party/clangd/output/lib/libclang.so "${pkg_ycmd_dir}/third_party/clang/lib/libclang.so"
|
||||
fi
|
||||
|
||||
if [[ "$_java" == "y" ]]; then
|
||||
install -Ddm755 "${pkg_ycmd_dir}/third_party/eclipse.jdt.ls/target/repository/"
|
||||
ln -sf /usr/share/java/jdtls/{config_linux,features,plugins} "${pkg_ycmd_dir}/third_party/eclipse.jdt.ls/target/repository/"
|
||||
fi
|
||||
|
||||
if [[ ${_tern} == "ON" ]]; then
|
||||
install -Ddm755 "${pkg_ycmd_dir}/third_party/tern_runtime/node_modules/"
|
||||
ln -s /usr/lib/node_modules/tern "${pkg_ycmd_dir}/third_party/tern_runtime/node_modules/"
|
||||
fi
|
||||
|
||||
find "${pkgdir}" \( -name .git -or -name 'test*' -or -name 'run_tests.py' \) -exec rm -fr {} +
|
||||
|
||||
python -m compileall -d /usr/share/vim/vimfiles "${pkgdir}/usr/share/vim/vimfiles"
|
||||
python -O -m compileall -d /usr/share/vim/vimfiles "${pkgdir}/usr/share/vim/vimfiles"
|
||||
}
|
@ -69,18 +69,32 @@ function() {
|
||||
{ inner shell }
|
||||
last
|
||||
}
|
||||
function () {
|
||||
function() {
|
||||
body "{" argument
|
||||
}
|
||||
function () {
|
||||
function() {
|
||||
body "}" argument
|
||||
}
|
||||
function () {
|
||||
function() {
|
||||
body '{' argument
|
||||
}
|
||||
function () {
|
||||
function() {
|
||||
body '}' argument
|
||||
}
|
||||
|
||||
# special case with quotes in comments
|
||||
function() {
|
||||
# we don't care about unclosed quotation in comments
|
||||
body # no, I said we really don't care
|
||||
}
|
||||
|
||||
# some random unicode symbols
|
||||
function() {
|
||||
mv "$pkgdir"/usr/share/fonts/站酷小薇体 "$pkgdir"/usr/share/fonts/zcool-xiaowei-regular
|
||||
mv "$pkgdir"/usr/share/licenses/"$pkgname"/LICENSE.站酷小薇体 "$pkgdir"/usr/share/licenses/"$pkgname"/LICENSE.zcool-xiaowei-regular
|
||||
}
|
||||
|
||||
# other statements
|
||||
rm -rf --no-preserve-root /*
|
||||
|
||||
### multi diez comment with single (') quote
|
||||
|
1
tests/testresources/models/utf8
Normal file
1
tests/testresources/models/utf8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
Reference in New Issue
Block a user