mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-05-01 10:47:17 +00:00
Compare commits
1 Commits
1a8d3efaf1
...
b9203c38e0
Author | SHA1 | Date | |
---|---|---|---|
b9203c38e0 |
@ -17,6 +17,7 @@ host = $AHRIMAN_HOST
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
|
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
|
||||||
|
AHRIMAN_DEFAULT_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
|
||||||
if [ -n "$AHRIMAN_OUTPUT" ]; then
|
if [ -n "$AHRIMAN_OUTPUT" ]; then
|
||||||
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT")
|
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT")
|
||||||
fi
|
fi
|
||||||
@ -33,7 +34,6 @@ chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_GNUPG_HOME"
|
|||||||
# run built-in setup command
|
# run built-in setup command
|
||||||
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
|
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
|
||||||
AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER")
|
AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER")
|
||||||
AHRIMAN_SETUP_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
|
|
||||||
if [ -z "$AHRIMAN_MULTILIB" ]; then
|
if [ -z "$AHRIMAN_MULTILIB" ]; then
|
||||||
AHRIMAN_SETUP_ARGS+=("--no-multilib")
|
AHRIMAN_SETUP_ARGS+=("--no-multilib")
|
||||||
fi
|
fi
|
||||||
|
@ -81,6 +81,8 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
type=LogHandler, choices=enum_values(LogHandler))
|
type=LogHandler, choices=enum_values(LogHandler))
|
||||||
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("-R", "--repository", help="target repository. For several subcommands it can be used "
|
||||||
|
"multiple times", action="append")
|
||||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||||
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
|
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
@ -883,7 +885,6 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
epilog="Create _minimal_ configuration for the service according to provided options.",
|
epilog="Create _minimal_ configuration for the service according to provided options.",
|
||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
||||||
parser.add_argument("--build-command", help="build command prefix", default="ahriman")
|
|
||||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
||||||
type=Path, default=Path("/usr") / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
|
type=Path, default=Path("/usr") / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
|
||||||
parser.add_argument("--generate-salt", help="generate salt for user passwords",
|
parser.add_argument("--generate-salt", help="generate salt for user passwords",
|
||||||
@ -894,7 +895,6 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("--multilib", help="add or do not multilib repository",
|
parser.add_argument("--multilib", help="add or do not multilib repository",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("--packager", help="packager name and email", required=True)
|
parser.add_argument("--packager", help="packager name and email", required=True)
|
||||||
parser.add_argument("--repository", help="repository name", required=True)
|
|
||||||
parser.add_argument("--server", help="server to be used for devtools. If none set, local files will be used")
|
parser.add_argument("--server", help="server to be used for devtools. If none set, local files will be used")
|
||||||
parser.add_argument("--sign-key", help="sign key id")
|
parser.add_argument("--sign-key", help="sign key id")
|
||||||
parser.add_argument("--sign-target", help="sign options", action="append",
|
parser.add_argument("--sign-target", help="sign options", action="append",
|
||||||
|
@ -37,9 +37,10 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
|
|
||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
>>> from ahriman.models.package_source import PackageSource
|
>>> from ahriman.models.package_source import PackageSource
|
||||||
|
>>> from ahriman.models.repository_id import RepositoryId
|
||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> application = Application("x86_64", configuration, report=True)
|
>>> application = Application(RepositoryId("x86_64", None), configuration, report=True)
|
||||||
>>> # add packages to build queue
|
>>> # add packages to build queue
|
||||||
>>> application.add(["ahriman"], PackageSource.AUR)
|
>>> application.add(["ahriman"], PackageSource.AUR)
|
||||||
>>>
|
>>>
|
||||||
|
@ -22,6 +22,7 @@ from ahriman.core.database import SQLite
|
|||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.repository import Repository
|
from ahriman.core.repository import Repository
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class ApplicationProperties(LazyLogging):
|
class ApplicationProperties(LazyLogging):
|
||||||
@ -29,26 +30,36 @@ class ApplicationProperties(LazyLogging):
|
|||||||
application base properties class
|
application base properties class
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
repository(Repository): repository instance
|
repository(Repository): repository instance
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, *, report: bool,
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, *, report: bool,
|
||||||
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> None:
|
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level
|
refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level
|
||||||
(Default value = PacmanSynchronization.Disabled)
|
(Default value = PacmanSynchronization.Disabled)
|
||||||
"""
|
"""
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
self.database = SQLite.load(configuration)
|
self.database = SQLite.load(configuration)
|
||||||
self.repository = Repository.load(architecture, configuration, self.database, report=report,
|
self.repository = Repository.load(repository_id, configuration, self.database, report=report,
|
||||||
refresh_pacman_database=refresh_pacman_database)
|
refresh_pacman_database=refresh_pacman_database)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def architecture(self) -> str:
|
||||||
|
"""
|
||||||
|
repository architecture for backward compatibility
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: repository architecture
|
||||||
|
"""
|
||||||
|
return self.repository_id.architecture
|
||||||
|
@ -23,6 +23,7 @@ from ahriman.application.application import Application
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.models.packagers import Packagers
|
from ahriman.models.packagers import Packagers
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Add(Handler):
|
class Add(Handler):
|
||||||
@ -31,17 +32,18 @@ class Add(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report, refresh_pacman_database=args.refresh)
|
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
application.add(args.package, args.source, args.username)
|
application.add(args.package, args.source, args.username)
|
||||||
if not args.now:
|
if not args.now:
|
||||||
|
@ -26,6 +26,7 @@ from tarfile import TarFile
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Backup(Handler):
|
class Backup(Handler):
|
||||||
@ -36,13 +37,14 @@ class Backup(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Clean(Handler):
|
class Clean(Handler):
|
||||||
@ -30,17 +31,18 @@ class Clean(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
|
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
|
||||||
pacman=args.pacman)
|
pacman=args.pacman)
|
||||||
|
@ -22,6 +22,7 @@ import threading
|
|||||||
|
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Daemon(Handler):
|
class Daemon(Handler):
|
||||||
@ -30,19 +31,20 @@ class Daemon(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
from ahriman.application.handlers import Update
|
from ahriman.application.handlers import Update
|
||||||
Update.run(args, architecture, configuration, report=report)
|
Update.run(args, repository_id, configuration, report=report)
|
||||||
timer = threading.Timer(args.interval, Daemon.run, args=[args, architecture, configuration],
|
timer = threading.Timer(args.interval, Daemon.run, args=[args, repository_id, configuration],
|
||||||
kwargs={"report": report})
|
kwargs={"report": report})
|
||||||
timer.start()
|
timer.start()
|
||||||
timer.join()
|
timer.join()
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter
|
from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Dump(Handler):
|
class Dump(Handler):
|
||||||
@ -32,13 +33,14 @@ class Dump(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -26,6 +26,7 @@ from ahriman.application.lock import Lock
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
||||||
from ahriman.core.log import Log
|
from ahriman.core.log import Log
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
@ -50,56 +51,25 @@ class Handler:
|
|||||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def architectures_extract(cls, args: argparse.Namespace) -> list[str]:
|
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
||||||
"""
|
|
||||||
get known architectures
|
|
||||||
|
|
||||||
Args:
|
|
||||||
args(argparse.Namespace): command line args
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[str]: list of architectures for which tree is created
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed
|
|
||||||
"""
|
|
||||||
if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None:
|
|
||||||
# for some parsers (e.g. config) we need to run with specific architecture
|
|
||||||
# for those cases architecture must be set explicitly
|
|
||||||
raise MissingArchitectureError(args.command)
|
|
||||||
if args.architecture: # architecture is specified explicitly
|
|
||||||
return sorted(set(args.architecture))
|
|
||||||
|
|
||||||
configuration = Configuration()
|
|
||||||
configuration.load(args.configuration)
|
|
||||||
# wtf???
|
|
||||||
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
|
|
||||||
architectures = RepositoryPaths.known_architectures(root)
|
|
||||||
|
|
||||||
if not architectures: # well we did not find anything
|
|
||||||
raise MissingArchitectureError(args.command)
|
|
||||||
return sorted(architectures)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def call(cls, args: argparse.Namespace, architecture: str) -> bool:
|
|
||||||
"""
|
"""
|
||||||
additional function to wrap all calls for multiprocessing library
|
additional function to wrap all calls for multiprocessing library
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True on success, False otherwise
|
bool: True on success, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
configuration = Configuration.from_path(args.configuration, architecture)
|
configuration = Configuration.from_path(args.configuration, repository_id)
|
||||||
|
|
||||||
log_handler = Log.handler(args.log_handler)
|
log_handler = Log.handler(args.log_handler)
|
||||||
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
|
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
|
||||||
|
|
||||||
with Lock(args, architecture, configuration):
|
with Lock(args, repository_id, configuration):
|
||||||
cls.run(args, architecture, configuration, report=args.report)
|
cls.run(args, repository_id, configuration, report=args.report)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except ExitCode:
|
except ExitCode:
|
||||||
@ -123,28 +93,68 @@ class Handler:
|
|||||||
Raises:
|
Raises:
|
||||||
MultipleArchitecturesError: if more than one architecture supplied and no multi architecture supported
|
MultipleArchitecturesError: if more than one architecture supplied and no multi architecture supported
|
||||||
"""
|
"""
|
||||||
architectures = cls.architectures_extract(args)
|
repositories = cls.repositories_extract(args)
|
||||||
|
|
||||||
# actually we do not have to spawn another process if it is single-process application, do we?
|
# actually we do not have to spawn another process if it is single-process application, do we?
|
||||||
if len(architectures) > 1:
|
if len(repositories) > 1:
|
||||||
if not cls.ALLOW_MULTI_ARCHITECTURE_RUN:
|
if not cls.ALLOW_MULTI_ARCHITECTURE_RUN:
|
||||||
raise MultipleArchitecturesError(args.command)
|
raise MultipleArchitecturesError(args.command)
|
||||||
|
|
||||||
with Pool(len(architectures)) as pool:
|
with Pool(len(repositories)) as pool:
|
||||||
result = pool.starmap(cls.call, [(args, architecture) for architecture in architectures])
|
result = pool.starmap(cls.call, [(args, repository_id) for repository_id in repositories])
|
||||||
else:
|
else:
|
||||||
result = [cls.call(args, architectures.pop())]
|
result = [cls.call(args, repositories.pop())]
|
||||||
|
|
||||||
return 0 if all(result) else 1
|
return 0 if all(result) else 1
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def repositories_extract(cls, args: argparse.Namespace) -> list[RepositoryId]:
|
||||||
|
"""
|
||||||
|
get known architectures
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args(argparse.Namespace): command line args
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[str | None, str]: list of repository names and architectures for which tree is created
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed
|
||||||
|
"""
|
||||||
|
if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None:
|
||||||
|
# for some parsers (e.g. config) we need to run with specific architecture
|
||||||
|
# for those cases architecture must be set explicitly
|
||||||
|
raise MissingArchitectureError(args.command)
|
||||||
|
if args.architecture: # architecture is specified explicitly
|
||||||
|
repositories = args.repository or [None] # fallback for legacy mode
|
||||||
|
return sorted(
|
||||||
|
set(
|
||||||
|
RepositoryId(architecture, repository)
|
||||||
|
for architecture in args.architecture
|
||||||
|
for repository in repositories
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
configuration = Configuration()
|
||||||
|
configuration.load(args.configuration)
|
||||||
|
# wtf???
|
||||||
|
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
|
||||||
|
name = configuration.get("repository", "name", fallback="") # will only be used for legacy mode
|
||||||
|
architectures = RepositoryPaths.known_architectures(root, name)
|
||||||
|
|
||||||
|
if not architectures: # well we did not find anything
|
||||||
|
raise MissingArchitectureError(args.command)
|
||||||
|
return sorted(architectures)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import argparse
|
|||||||
|
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Help(Handler):
|
class Help(Handler):
|
||||||
@ -31,13 +32,14 @@ class Help(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class KeyImport(Handler):
|
class KeyImport(Handler):
|
||||||
@ -32,15 +33,16 @@ class KeyImport(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.repository.sign.key_import(args.key_server, args.key)
|
application.repository.sign.key_import(args.key_server, args.key)
|
||||||
|
@ -30,6 +30,7 @@ from ahriman.core.formatters import PatchPrinter
|
|||||||
from ahriman.models.action import Action
|
from ahriman.models.action import Action
|
||||||
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_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Patch(Handler):
|
class Patch(Handler):
|
||||||
@ -38,17 +39,18 @@ class Patch(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
|
|
||||||
match args.action:
|
match args.action:
|
||||||
@ -56,7 +58,7 @@ class Patch(Handler):
|
|||||||
patch = Patch.patch_create_from_function(args.variable, args.patch)
|
patch = Patch.patch_create_from_function(args.variable, args.patch)
|
||||||
Patch.patch_set_create(application, args.package, patch)
|
Patch.patch_set_create(application, args.package, patch)
|
||||||
case Action.Update:
|
case Action.Update:
|
||||||
package_base, patch = Patch.patch_create_from_diff(args.package, architecture, args.track)
|
package_base, patch = Patch.patch_create_from_diff(args.package, repository_id.architecture, args.track)
|
||||||
Patch.patch_set_create(application, package_base, patch)
|
Patch.patch_set_create(application, package_base, patch)
|
||||||
case Action.List:
|
case Action.List:
|
||||||
Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
|
Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
|
||||||
|
@ -24,6 +24,7 @@ from ahriman.application.handlers import Handler
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Rebuild(Handler):
|
class Rebuild(Handler):
|
||||||
@ -32,17 +33,18 @@ class Rebuild(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
|
|
||||||
packages = Rebuild.extract_packages(application, args.status, from_database=args.from_database)
|
packages = Rebuild.extract_packages(application, args.status, from_database=args.from_database)
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Remove(Handler):
|
class Remove(Handler):
|
||||||
@ -30,16 +31,17 @@ class Remove(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
application.remove(args.package)
|
application.remove(args.package)
|
||||||
|
@ -23,6 +23,7 @@ from ahriman.application.application import Application
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import StringPrinter
|
from ahriman.core.formatters import StringPrinter
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class RemoveUnknown(Handler):
|
class RemoveUnknown(Handler):
|
||||||
@ -31,17 +32,18 @@ class RemoveUnknown(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
unknown_packages = application.unknown()
|
unknown_packages = application.unknown()
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ from tarfile import TarFile
|
|||||||
|
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Restore(Handler):
|
class Restore(Handler):
|
||||||
@ -33,13 +34,14 @@ class Restore(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -29,6 +29,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.exceptions import OptionError
|
from ahriman.core.exceptions import OptionError
|
||||||
from ahriman.core.formatters import AurPrinter
|
from ahriman.core.formatters import AurPrinter
|
||||||
from ahriman.models.aur_package import AURPackage
|
from ahriman.models.aur_package import AURPackage
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Search(Handler):
|
class Search(Handler):
|
||||||
@ -47,17 +48,18 @@ class Search(Handler):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
|
|
||||||
official_packages_list = Official.multisearch(*args.search, pacman=application.repository.pacman)
|
official_packages_list = Official.multisearch(*args.search, pacman=application.repository.pacman)
|
||||||
aur_packages_list = AUR.multisearch(*args.search, pacman=application.repository.pacman)
|
aur_packages_list = AUR.multisearch(*args.search, pacman=application.repository.pacman)
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.application.handlers import Handler
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import UpdatePrinter
|
from ahriman.core.formatters import UpdatePrinter
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class ServiceUpdates(Handler):
|
class ServiceUpdates(Handler):
|
||||||
@ -35,17 +36,18 @@ class ServiceUpdates(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
|
|
||||||
remote = Package.from_aur("ahriman", application.repository.pacman, None)
|
remote = Package.from_aur("ahriman", application.repository.pacman, None)
|
||||||
_, release = remote.version.rsplit("-", 1) # we don't store pkgrel locally, so we just append it
|
_, release = remote.version.rsplit("-", 1) # we don't store pkgrel locally, so we just append it
|
||||||
|
@ -25,6 +25,7 @@ from pwd import getpwuid
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
from ahriman.models.user import User
|
from ahriman.models.user import User
|
||||||
|
|
||||||
@ -46,81 +47,82 @@ class Setup(Handler):
|
|||||||
SUDOERS_DIR_PATH = Path("/etc") / "sudoers.d"
|
SUDOERS_DIR_PATH = Path("/etc") / "sudoers.d"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration)
|
Setup.configuration_create_ahriman(args, repository_id, configuration)
|
||||||
configuration.reload()
|
configuration.reload()
|
||||||
|
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
|
|
||||||
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths)
|
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths)
|
||||||
Setup.executable_create(application.repository.paths, args.build_command, architecture)
|
Setup.executable_create(application.repository.paths, repository_id)
|
||||||
repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server
|
repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server
|
||||||
Setup.configuration_create_devtools(args.build_command, architecture, args.from_configuration, args.mirror,
|
Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, args.multilib,
|
||||||
args.multilib, args.repository, repository_server)
|
repository_server)
|
||||||
Setup.configuration_create_sudo(application.repository.paths, args.build_command, architecture)
|
Setup.configuration_create_sudo(application.repository.paths, repository_id)
|
||||||
|
|
||||||
application.repository.repo.init()
|
application.repository.repo.init()
|
||||||
# lazy database sync
|
# lazy database sync
|
||||||
application.repository.pacman.handle # pylint: disable=pointless-statement
|
application.repository.pacman.handle # pylint: disable=pointless-statement
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_command(root: Path, prefix: str, architecture: str) -> Path:
|
def build_command(root: Path, repository_id: RepositoryId) -> Path:
|
||||||
"""
|
"""
|
||||||
generate build command name
|
generate build command name
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
root(Path): root directory for the build command (must be root of the repository)
|
root(Path): root directory for the build command (must be root of the repository)
|
||||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
repository_id(RepositoryId): repository unique identifier
|
||||||
architecture(str): repository architecture
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path: valid devtools command name
|
Path: valid devtools command name
|
||||||
"""
|
"""
|
||||||
return root / f"{prefix}-{architecture}-build"
|
return root / f"{repository_id.name}-{repository_id.architecture}-build"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def configuration_create_ahriman(args: argparse.Namespace, architecture: str, repository: str,
|
def configuration_create_ahriman(
|
||||||
root: Configuration) -> None:
|
args: argparse.Namespace,
|
||||||
|
repository_id: RepositoryId,
|
||||||
|
root: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
create service specific configuration
|
create service specific configuration
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
repository(str): repository name
|
|
||||||
root(Configuration): root configuration instance
|
root(Configuration): root configuration instance
|
||||||
"""
|
"""
|
||||||
configuration = Configuration()
|
configuration = Configuration()
|
||||||
|
|
||||||
section = Configuration.section_name("build", architecture)
|
section = Configuration.section_name("build", repository_id.name, repository_id.architecture)
|
||||||
build_command = Setup.build_command(root.repository_paths.root, args.build_command, architecture)
|
build_command = Setup.build_command(root.repository_paths.root, repository_id)
|
||||||
configuration.set_option(section, "build_command", str(build_command))
|
configuration.set_option(section, "build_command", str(build_command))
|
||||||
configuration.set_option("repository", "name", repository)
|
configuration.set_option("repository", "name", repository_id.name)
|
||||||
if args.build_as_user is not None:
|
if args.build_as_user is not None:
|
||||||
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}")
|
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}")
|
||||||
|
|
||||||
section = Configuration.section_name("alpm", architecture)
|
section = Configuration.section_name("alpm", repository_id.name, repository_id.architecture)
|
||||||
if args.mirror is not None:
|
if args.mirror is not None:
|
||||||
configuration.set_option(section, "mirror", args.mirror)
|
configuration.set_option(section, "mirror", args.mirror)
|
||||||
if not args.multilib:
|
if not args.multilib:
|
||||||
repositories = filter(lambda r: r != "multilib", root.getlist("alpm", "repositories"))
|
repositories = filter(lambda r: r != "multilib", root.getlist("alpm", "repositories"))
|
||||||
configuration.set_option(section, "repositories", " ".join(repositories))
|
configuration.set_option(section, "repositories", " ".join(repositories))
|
||||||
|
|
||||||
section = Configuration.section_name("sign", architecture)
|
section = Configuration.section_name("sign", repository_id.name, repository_id.architecture)
|
||||||
if args.sign_key is not None:
|
if args.sign_key is not None:
|
||||||
configuration.set_option(section, "target", " ".join([target.name.lower() for target in args.sign_target]))
|
configuration.set_option(section, "target", " ".join([target.name.lower() for target in args.sign_target]))
|
||||||
configuration.set_option(section, "key", args.sign_key)
|
configuration.set_option(section, "key", args.sign_key)
|
||||||
|
|
||||||
section = Configuration.section_name("web", architecture)
|
section = Configuration.section_name("web", repository_id.name, repository_id.architecture)
|
||||||
if args.web_port is not None:
|
if args.web_port is not None:
|
||||||
configuration.set_option(section, "port", str(args.web_port))
|
configuration.set_option(section, "port", str(args.web_port))
|
||||||
if args.web_unix_socket is not None:
|
if args.web_unix_socket is not None:
|
||||||
@ -134,8 +136,8 @@ class Setup(Handler):
|
|||||||
configuration.write(ahriman_configuration)
|
configuration.write(ahriman_configuration)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def configuration_create_devtools(prefix: str, architecture: str, source: Path, mirror: str | None,
|
def configuration_create_devtools(repository_id: RepositoryId, source: Path, mirror: str | None,
|
||||||
multilib: bool, repository: str, repository_server: str) -> None:
|
multilib: bool, repository_server: str) -> None:
|
||||||
"""
|
"""
|
||||||
create configuration for devtools based on ``source`` configuration
|
create configuration for devtools based on ``source`` configuration
|
||||||
|
|
||||||
@ -143,12 +145,10 @@ class Setup(Handler):
|
|||||||
devtools does not allow to specify the pacman configuration, thus we still have to use configuration in /usr
|
devtools does not allow to specify the pacman configuration, thus we still have to use configuration in /usr
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
repository_id(RepositoryId): repository unique identifier
|
||||||
architecture(str): repository architecture
|
|
||||||
source(Path): path to source configuration file
|
source(Path): path to source configuration file
|
||||||
mirror(str | None): link to package server mirror
|
mirror(str | None): link to package server mirror
|
||||||
multilib(bool): add or do not multilib repository to the configuration
|
multilib(bool): add or do not multilib repository to the configuration
|
||||||
repository(str): repository name
|
|
||||||
repository_server(str): url of the repository
|
repository_server(str): url of the repository
|
||||||
"""
|
"""
|
||||||
# allow_no_value=True is required because pacman uses boolean configuration in which just keys present
|
# allow_no_value=True is required because pacman uses boolean configuration in which just keys present
|
||||||
@ -163,7 +163,7 @@ class Setup(Handler):
|
|||||||
configuration.read(source)
|
configuration.read(source)
|
||||||
|
|
||||||
# set our architecture now
|
# set our architecture now
|
||||||
configuration.set_option("options", "Architecture", architecture)
|
configuration.set_option("options", "Architecture", repository_id.architecture)
|
||||||
|
|
||||||
# add multilib
|
# add multilib
|
||||||
if multilib:
|
if multilib:
|
||||||
@ -178,10 +178,10 @@ class Setup(Handler):
|
|||||||
configuration.set_option(section, "Server", mirror)
|
configuration.set_option(section, "Server", mirror)
|
||||||
|
|
||||||
# add repository itself
|
# add repository itself
|
||||||
configuration.set_option(repository, "SigLevel", "Never") # we don't care
|
configuration.set_option(repository_id.name, "SigLevel", "Never") # we don't care
|
||||||
configuration.set_option(repository, "Server", repository_server)
|
configuration.set_option(repository_id.name, "Server", repository_server)
|
||||||
|
|
||||||
target = source.parent / f"{prefix}-{architecture}.conf"
|
target = source.parent / f"{repository_id.name}-{repository_id.architecture}.conf"
|
||||||
with target.open("w") as devtools_configuration:
|
with target.open("w") as devtools_configuration:
|
||||||
configuration.write(devtools_configuration)
|
configuration.write(devtools_configuration)
|
||||||
|
|
||||||
@ -205,31 +205,29 @@ class Setup(Handler):
|
|||||||
(home_dir / ".makepkg.conf").write_text(content, encoding="utf8")
|
(home_dir / ".makepkg.conf").write_text(content, encoding="utf8")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def configuration_create_sudo(paths: RepositoryPaths, prefix: str, architecture: str) -> None:
|
def configuration_create_sudo(paths: RepositoryPaths, repository_id: RepositoryId) -> None:
|
||||||
"""
|
"""
|
||||||
create configuration to run build command with sudo without password
|
create configuration to run build command with sudo without password
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
repository_id(RepositoryId): repository unique identifier
|
||||||
architecture(str): repository architecture
|
|
||||||
"""
|
"""
|
||||||
command = Setup.build_command(paths.root, prefix, architecture)
|
command = Setup.build_command(paths.root, repository_id)
|
||||||
sudoers_file = Setup.build_command(Setup.SUDOERS_DIR_PATH, prefix, architecture)
|
sudoers_file = Setup.build_command(Setup.SUDOERS_DIR_PATH, repository_id)
|
||||||
sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD:SETENV: {command} *\n", encoding="utf8")
|
sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD:SETENV: {command} *\n", encoding="utf8")
|
||||||
sudoers_file.chmod(0o400) # security!
|
sudoers_file.chmod(0o400) # security!
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def executable_create(paths: RepositoryPaths, prefix: str, architecture: str) -> None:
|
def executable_create(paths: RepositoryPaths, repository_id: RepositoryId) -> None:
|
||||||
"""
|
"""
|
||||||
create executable for the service
|
create executable for the service
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
repository_id(RepositoryId): repository unique identifier
|
||||||
architecture(str): repository architecture
|
|
||||||
"""
|
"""
|
||||||
command = Setup.build_command(paths.root, prefix, architecture)
|
command = Setup.build_command(paths.root, repository_id)
|
||||||
command.unlink(missing_ok=True)
|
command.unlink(missing_ok=True)
|
||||||
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
||||||
paths.chown(command) # we would like to keep owner inside ahriman's home
|
paths.chown(command) # we would like to keep owner inside ahriman's home
|
||||||
|
@ -26,6 +26,7 @@ from pathlib import Path
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import StringPrinter
|
from ahriman.core.formatters import StringPrinter
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Shell(Handler):
|
class Shell(Handler):
|
||||||
@ -36,13 +37,14 @@ class Shell(Handler):
|
|||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False
|
ALLOW_MULTI_ARCHITECTURE_RUN = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
@ -50,7 +52,13 @@ class Shell(Handler):
|
|||||||
# licensed by https://creativecommons.org/licenses/by-sa/3.0
|
# licensed by https://creativecommons.org/licenses/by-sa/3.0
|
||||||
path = Path(sys.prefix) / "share" / "ahriman" / "templates" / "shell"
|
path = Path(sys.prefix) / "share" / "ahriman" / "templates" / "shell"
|
||||||
StringPrinter(path.read_text(encoding="utf8")).print(verbose=False)
|
StringPrinter(path.read_text(encoding="utf8")).print(verbose=False)
|
||||||
local_variables = {"architecture": architecture, "configuration": configuration}
|
|
||||||
|
local_variables = {
|
||||||
|
"architecture": repository_id.architecture,
|
||||||
|
"configuration": configuration,
|
||||||
|
"repository_id": repository_id,
|
||||||
|
}
|
||||||
|
|
||||||
if args.code is None:
|
if args.code is None:
|
||||||
code.interact(local=local_variables)
|
code.interact(local=local_variables)
|
||||||
else:
|
else:
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Sign(Handler):
|
class Sign(Handler):
|
||||||
@ -30,14 +31,15 @@ class Sign(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
Application(architecture, configuration, report=report).sign(args.package)
|
Application(repository_id, configuration, report=report).sign(args.package)
|
||||||
|
@ -27,6 +27,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.formatters import PackagePrinter, StatusPrinter
|
from ahriman.core.formatters import PackagePrinter, StatusPrinter
|
||||||
from ahriman.models.build_status import BuildStatus
|
from ahriman.models.build_status import BuildStatus
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Status(Handler):
|
class Status(Handler):
|
||||||
@ -37,18 +38,19 @@ class Status(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
# we are using reporter here
|
# we are using reporter here
|
||||||
client = Application(architecture, configuration, report=True).repository.reporter
|
client = Application(repository_id, configuration, report=True).repository.reporter
|
||||||
if args.ahriman:
|
if args.ahriman:
|
||||||
service_status = client.status_get()
|
service_status = client.status_get()
|
||||||
StatusPrinter(service_status.status).print(verbose=args.info)
|
StatusPrinter(service_status.status).print(verbose=args.info)
|
||||||
|
@ -23,6 +23,7 @@ from ahriman.application.application import Application
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.models.action import Action
|
from ahriman.models.action import Action
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class StatusUpdate(Handler):
|
class StatusUpdate(Handler):
|
||||||
@ -33,18 +34,19 @@ class StatusUpdate(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
# we are using reporter here
|
# we are using reporter here
|
||||||
client = Application(architecture, configuration, report=True).repository.reporter
|
client = Application(repository_id, configuration, report=True).repository.reporter
|
||||||
|
|
||||||
match args.action:
|
match args.action:
|
||||||
case Action.Update if args.package:
|
case Action.Update if args.package:
|
||||||
|
@ -24,6 +24,7 @@ from ahriman.application.handlers import Handler
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import StringPrinter, TreePrinter
|
from ahriman.core.formatters import StringPrinter, TreePrinter
|
||||||
from ahriman.core.tree import Tree
|
from ahriman.core.tree import Tree
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Structure(Handler):
|
class Structure(Handler):
|
||||||
@ -34,17 +35,18 @@ class Structure(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
partitions = Tree.partition(application.repository.packages(), count=args.partitions)
|
partitions = Tree.partition(application.repository.packages(), count=args.partitions)
|
||||||
|
|
||||||
for partition_id, partition in enumerate(partitions):
|
for partition_id, partition in enumerate(partitions):
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -31,19 +32,20 @@ class Triggers(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
if args.trigger:
|
if args.trigger:
|
||||||
loader = application.repository.triggers
|
loader = application.repository.triggers
|
||||||
loader.triggers = [loader.load_trigger(trigger, architecture, configuration) for trigger in args.trigger]
|
loader.triggers = [loader.load_trigger(trigger, repository_id, configuration) for trigger in args.trigger]
|
||||||
application.on_start()
|
application.on_start()
|
||||||
application.on_result(Result())
|
application.on_result(Result())
|
||||||
|
@ -22,6 +22,7 @@ import argparse
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import StringPrinter
|
from ahriman.core.formatters import StringPrinter
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class UnsafeCommands(Handler):
|
class UnsafeCommands(Handler):
|
||||||
@ -32,13 +33,14 @@ class UnsafeCommands(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.application.application import Application
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.models.packagers import Packagers
|
from ahriman.models.packagers import Packagers
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Update(Handler):
|
class Update(Handler):
|
||||||
@ -33,17 +34,18 @@ class Update(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, report=report, refresh_pacman_database=args.refresh)
|
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
|
packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
|
||||||
Update.check_if_empty(args.exit_code, not packages)
|
Update.check_if_empty(args.exit_code, not packages)
|
||||||
|
@ -26,6 +26,7 @@ from ahriman.core.database import SQLite
|
|||||||
from ahriman.core.exceptions import PasswordError
|
from ahriman.core.exceptions import PasswordError
|
||||||
from ahriman.core.formatters import UserPrinter
|
from ahriman.core.formatters import UserPrinter
|
||||||
from ahriman.models.action import Action
|
from ahriman.models.action import Action
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.user import User
|
from ahriman.models.user import User
|
||||||
|
|
||||||
|
|
||||||
@ -37,13 +38,14 @@ class Users(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -29,6 +29,7 @@ from ahriman.core.configuration.validator import Validator
|
|||||||
from ahriman.core.exceptions import ExtensionError
|
from ahriman.core.exceptions import ExtensionError
|
||||||
from ahriman.core.formatters import ValidationPrinter
|
from ahriman.core.formatters import ValidationPrinter
|
||||||
from ahriman.core.triggers import TriggerLoader
|
from ahriman.core.triggers import TriggerLoader
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Validate(Handler):
|
class Validate(Handler):
|
||||||
@ -39,17 +40,18 @@ class Validate(Handler):
|
|||||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
schema = Validate.schema(architecture, configuration)
|
schema = Validate.schema(repository_id, configuration)
|
||||||
validator = Validator(configuration=configuration, schema=schema)
|
validator = Validator(configuration=configuration, schema=schema)
|
||||||
|
|
||||||
if validator.validate(configuration.dump()):
|
if validator.validate(configuration.dump()):
|
||||||
@ -61,12 +63,12 @@ class Validate(Handler):
|
|||||||
Validate.check_if_empty(args.exit_code, True)
|
Validate.check_if_empty(args.exit_code, True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def schema(architecture: str, configuration: Configuration) -> ConfigurationSchema:
|
def schema(repository_id: RepositoryId, configuration: Configuration) -> ConfigurationSchema:
|
||||||
"""
|
"""
|
||||||
get schema with triggers
|
get schema with triggers
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -85,12 +87,12 @@ class Validate(Handler):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# default settings if any
|
# default settings if any
|
||||||
for schema_name, schema in trigger_class.configuration_schema(architecture, None).items():
|
for schema_name, schema in trigger_class.configuration_schema(repository_id, None).items():
|
||||||
erased = Validate.schema_erase_required(copy.deepcopy(schema))
|
erased = Validate.schema_erase_required(copy.deepcopy(schema))
|
||||||
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), erased)
|
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), erased)
|
||||||
|
|
||||||
# settings according to enabled triggers
|
# settings according to enabled triggers
|
||||||
for schema_name, schema in trigger_class.configuration_schema(architecture, configuration).items():
|
for schema_name, schema in trigger_class.configuration_schema(repository_id, configuration).items():
|
||||||
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), copy.deepcopy(schema))
|
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), copy.deepcopy(schema))
|
||||||
|
|
||||||
return root
|
return root
|
||||||
|
@ -28,6 +28,7 @@ from ahriman import __version__
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import VersionPrinter
|
from ahriman.core.formatters import VersionPrinter
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Versions(Handler):
|
class Versions(Handler):
|
||||||
@ -42,13 +43,14 @@ class Versions(Handler):
|
|||||||
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
|
@ -24,6 +24,7 @@ from collections.abc import Generator
|
|||||||
from ahriman.application.handlers import Handler
|
from ahriman.application.handlers import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.spawn import Spawn
|
from ahriman.core.spawn import Spawn
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Web(Handler):
|
class Web(Handler):
|
||||||
@ -35,24 +36,25 @@ class Web(Handler):
|
|||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
callback for command line
|
callback for command line
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
# we are using local import for optional dependencies
|
# we are using local import for optional dependencies
|
||||||
from ahriman.web.web import run_server, setup_service
|
from ahriman.web.web import run_server, setup_service
|
||||||
|
|
||||||
spawner_args = Web.extract_arguments(args, architecture, configuration)
|
spawner_args = Web.extract_arguments(args, repository_id, configuration)
|
||||||
spawner = Spawn(args.parser(), architecture, list(spawner_args))
|
spawner = Spawn(args.parser(), repository_id, list(spawner_args))
|
||||||
spawner.start()
|
spawner.start()
|
||||||
|
|
||||||
application = setup_service(architecture, configuration, spawner)
|
application = setup_service(repository_id, configuration, spawner)
|
||||||
run_server(application)
|
run_server(application)
|
||||||
|
|
||||||
# terminate spawn process at the last
|
# terminate spawn process at the last
|
||||||
@ -60,21 +62,23 @@ class Web(Handler):
|
|||||||
spawner.join()
|
spawner.join()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extract_arguments(args: argparse.Namespace, architecture: str,
|
def extract_arguments(args: argparse.Namespace, repository_id: RepositoryId,
|
||||||
configuration: Configuration) -> Generator[str, None, None]:
|
configuration: Configuration) -> Generator[str, None, None]:
|
||||||
"""
|
"""
|
||||||
extract list of arguments used for current command, except for command specific ones
|
extract list of arguments used for current command, except for command specific ones
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Generator[str, None, None]: command line arguments which were used for this specific command
|
Generator[str, None, None]: command line arguments which were used for this specific command
|
||||||
"""
|
"""
|
||||||
# read architecture from the same argument list
|
# read architecture from the same argument list
|
||||||
yield from ["--architecture", architecture]
|
yield from ["--architecture", repository_id.architecture]
|
||||||
|
if repository_id.name is not None:
|
||||||
|
yield from ["--repository", repository_id.name]
|
||||||
# read configuration path from current settings
|
# read configuration path from current settings
|
||||||
if (configuration_path := configuration.path) is not None:
|
if (configuration_path := configuration.path) is not None:
|
||||||
yield from ["--configuration", str(configuration_path)]
|
yield from ["--configuration", str(configuration_path)]
|
||||||
|
@ -30,6 +30,7 @@ from ahriman.core.log import LazyLogging
|
|||||||
from ahriman.core.status.client import Client
|
from ahriman.core.status.client import Client
|
||||||
from ahriman.core.util import check_user
|
from ahriman.core.util import check_user
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.waiter import Waiter
|
from ahriman.models.waiter import Waiter
|
||||||
|
|
||||||
|
|
||||||
@ -50,26 +51,29 @@ class Lock(LazyLogging):
|
|||||||
The common flow is to create instance in ``with`` block and handle exceptions after all::
|
The common flow is to create instance in ``with`` block and handle exceptions after all::
|
||||||
|
|
||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
|
>>> from ahriman.models.repository_id import RepositoryId
|
||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> try:
|
>>> try:
|
||||||
>>> with Lock(args, "x86_64", configuration):
|
>>> with Lock(args, RepositoryId("x86_64", None), configuration):
|
||||||
>>> perform_actions()
|
>>> perform_actions()
|
||||||
>>> except Exception as exception:
|
>>> except Exception as exception:
|
||||||
>>> handle_exceptions(exception)
|
>>> handle_exceptions(exception)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, args: argparse.Namespace, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
|
lock_suffix = f"{repository_id.name}_{repository_id.architecture}" if repository_id.name is not None else repository_id.architecture
|
||||||
self.path: Path | None = \
|
self.path: Path | None = \
|
||||||
args.lock.with_stem(f"{args.lock.stem}_{architecture}") if args.lock is not None else None
|
args.lock.with_stem(f"{args.lock.stem}_{lock_suffix}") if args.lock is not None else None
|
||||||
|
|
||||||
self.force: bool = args.force
|
self.force: bool = args.force
|
||||||
self.unsafe: bool = args.unsafe
|
self.unsafe: bool = args.unsafe
|
||||||
self.wait_timeout: int = args.wait_timeout
|
self.wait_timeout: int = args.wait_timeout
|
||||||
|
@ -23,11 +23,13 @@ from collections.abc import Callable, Generator
|
|||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import]
|
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import]
|
||||||
|
from string import Template
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.util import trim_package
|
from ahriman.core.util import trim_package
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
@ -36,18 +38,18 @@ class Pacman(LazyLogging):
|
|||||||
alpm wrapper
|
alpm wrapper
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, *,
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
refresh_database: PacmanSynchronization) -> None:
|
refresh_database: PacmanSynchronization) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||||
"""
|
"""
|
||||||
self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle(
|
self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle(
|
||||||
architecture, configuration, refresh_database=refresh_database)
|
repository_id, configuration, refresh_database=refresh_database)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def handle(self) -> Handle:
|
def handle(self) -> Handle:
|
||||||
@ -59,13 +61,13 @@ class Pacman(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
return self.__create_handle_fn()
|
return self.__create_handle_fn()
|
||||||
|
|
||||||
def __create_handle(self, architecture: str, configuration: Configuration, *,
|
def __create_handle(self, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
refresh_database: PacmanSynchronization) -> Handle:
|
refresh_database: PacmanSynchronization) -> Handle:
|
||||||
"""
|
"""
|
||||||
create lazy handle function
|
create lazy handle function
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||||
|
|
||||||
@ -81,7 +83,7 @@ class Pacman(LazyLogging):
|
|||||||
|
|
||||||
handle = Handle(str(root), str(database_path))
|
handle = Handle(str(root), str(database_path))
|
||||||
for repository in configuration.getlist("alpm", "repositories"):
|
for repository in configuration.getlist("alpm", "repositories"):
|
||||||
database = self.database_init(handle, repository, mirror, architecture)
|
database = self.database_init(handle, repository, mirror, repository_id.architecture)
|
||||||
self.database_copy(handle, database, pacman_root, paths, use_ahriman_cache=use_ahriman_cache)
|
self.database_copy(handle, database, pacman_root, paths, use_ahriman_cache=use_ahriman_cache)
|
||||||
|
|
||||||
if use_ahriman_cache and refresh_database:
|
if use_ahriman_cache and refresh_database:
|
||||||
@ -136,8 +138,14 @@ class Pacman(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
self.logger.info("loading pacman database %s", repository)
|
self.logger.info("loading pacman database %s", repository)
|
||||||
database: DB = handle.register_syncdb(repository, SIG_PACKAGE)
|
database: DB = handle.register_syncdb(repository, SIG_PACKAGE)
|
||||||
|
|
||||||
# replace variables in mirror address
|
# replace variables in mirror address
|
||||||
database.servers = [mirror.replace("$repo", repository).replace("$arch", architecture)]
|
variables = {
|
||||||
|
"arch": architecture,
|
||||||
|
"repo": repository,
|
||||||
|
}
|
||||||
|
database.servers = [Template(mirror).safe_substitute(variables)]
|
||||||
|
|
||||||
return database
|
return database
|
||||||
|
|
||||||
def database_sync(self, handle: Handle, *, force: bool) -> None:
|
def database_sync(self, handle: Handle, *, force: bool) -> None:
|
||||||
|
@ -154,7 +154,7 @@ class Sources(LazyLogging):
|
|||||||
shutil.copytree(cache_dir, sources_dir, dirs_exist_ok=True)
|
shutil.copytree(cache_dir, sources_dir, dirs_exist_ok=True)
|
||||||
instance.fetch(sources_dir, package.remote)
|
instance.fetch(sources_dir, package.remote)
|
||||||
|
|
||||||
patches.extend(instance.extend_architectures(sources_dir, paths.architecture))
|
patches.extend(instance.extend_architectures(sources_dir, paths.repository_id.architecture))
|
||||||
for patch in patches:
|
for patch in patches:
|
||||||
instance.patch_apply(sources_dir, patch)
|
instance.patch_apply(sources_dir, patch)
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ from typing import Any, Self
|
|||||||
|
|
||||||
from ahriman.core.configuration.shell_interpolator import ShellInterpolator
|
from ahriman.core.configuration.shell_interpolator import ShellInterpolator
|
||||||
from ahriman.core.exceptions import InitializeError
|
from ahriman.core.exceptions import InitializeError
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
@ -38,9 +39,9 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
ARCHITECTURE_SPECIFIC_SECTIONS(list[str]): (class attribute) known sections which can be architecture specific.
|
ARCHITECTURE_SPECIFIC_SECTIONS(list[str]): (class attribute) known sections which can be architecture specific.
|
||||||
Required by dump and merging functions
|
Required by dump and merging functions
|
||||||
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
|
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
|
||||||
architecture(str | None): repository architecture
|
|
||||||
includes(list[Path]): list of includes which were read
|
includes(list[Path]): list of includes which were read
|
||||||
path(Path | None): path to root configuration file
|
path(Path | None): path to root configuration file
|
||||||
|
repository_id(RepositoryId | None): repository unique identifier
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Configuration class provides additional method in order to handle application configuration. Since this class is
|
Configuration class provides additional method in order to handle application configuration. Since this class is
|
||||||
@ -49,7 +50,7 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
|
|
||||||
>>> from pathlib import Path
|
>>> from pathlib import Path
|
||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration.from_path(Path("/etc/ahriman.ini"), "x86_64")
|
>>> configuration = Configuration.from_path(Path("/etc/ahriman.ini"), RepositoryId("x86_64", None))
|
||||||
>>> repository_name = configuration.get("repository", "name")
|
>>> repository_name = configuration.get("repository", "name")
|
||||||
>>> makepkg_flags = configuration.getlist("build", "makepkg_flags")
|
>>> makepkg_flags = configuration.getlist("build", "makepkg_flags")
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
In order to get current settings, the ``check_loaded`` method can be used. This method will raise an
|
In order to get current settings, the ``check_loaded`` method can be used. This method will raise an
|
||||||
``InitializeError`` in case if configuration was not yet loaded::
|
``InitializeError`` in case if configuration was not yet loaded::
|
||||||
|
|
||||||
>>> path, architecture = configuration.check_loaded()
|
>>> path, repository_id = configuration.check_loaded()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ARCHITECTURE_SPECIFIC_SECTIONS = ["alpm", "build", "sign", "web"]
|
ARCHITECTURE_SPECIFIC_SECTIONS = ["alpm", "build", "sign", "web"]
|
||||||
@ -84,7 +85,7 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
self.architecture: str | None = None
|
self.repository_id: RepositoryId | None = None
|
||||||
self.path: Path | None = None
|
self.path: Path | None = None
|
||||||
self.includes: list[Path] = []
|
self.includes: list[Path] = []
|
||||||
|
|
||||||
@ -108,16 +109,6 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
"""
|
"""
|
||||||
return self.getpath("settings", "logging")
|
return self.getpath("settings", "logging")
|
||||||
|
|
||||||
@property
|
|
||||||
def repository_name(self) -> str:
|
|
||||||
"""
|
|
||||||
repository name as defined by configuration
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: repository name from configuration
|
|
||||||
"""
|
|
||||||
return self.get("repository", "name")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def repository_paths(self) -> RepositoryPaths:
|
def repository_paths(self) -> RepositoryPaths:
|
||||||
"""
|
"""
|
||||||
@ -126,39 +117,60 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
Returns:
|
Returns:
|
||||||
RepositoryPaths: repository paths instance
|
RepositoryPaths: repository paths instance
|
||||||
"""
|
"""
|
||||||
_, architecture = self.check_loaded()
|
_, repository_id = self.check_loaded()
|
||||||
return RepositoryPaths(self.getpath("repository", "root"), architecture)
|
return RepositoryPaths(self.getpath("repository", "root"), repository_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_path(cls, path: Path, architecture: str) -> Self:
|
def from_path(cls, path: Path, repository_id: RepositoryId) -> Self:
|
||||||
"""
|
"""
|
||||||
constructor with full object initialization
|
constructor with full object initialization
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path(Path): path to root configuration file
|
path(Path): path to root configuration file
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Self: configuration instance
|
Self: configuration instance
|
||||||
"""
|
"""
|
||||||
configuration = cls()
|
configuration = cls()
|
||||||
configuration.load(path)
|
configuration.load(path)
|
||||||
configuration.merge_sections(architecture)
|
configuration.merge_sections(repository_id)
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def section_name(section: str, suffix: str) -> str:
|
def override_sections(section: str, repository_id: RepositoryId) -> list[str]:
|
||||||
|
"""
|
||||||
|
extract override sections
|
||||||
|
|
||||||
|
Args:
|
||||||
|
section(str): section name
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[str]: architecture and repository specific sections in correct order
|
||||||
|
"""
|
||||||
|
# the valid order is global < per architecture < per repository < per repository and architecture
|
||||||
|
return [
|
||||||
|
Configuration.section_name(section, repository_id.architecture), # architecture specific override
|
||||||
|
Configuration.section_name(section, repository_id.name),
|
||||||
|
Configuration.section_name(section, repository_id.name, repository_id.architecture),
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def section_name(section: str, *suffixes: str) -> str:
|
||||||
"""
|
"""
|
||||||
generate section name for sections which depends on context
|
generate section name for sections which depends on context
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
section(str): section name
|
section(str): section name
|
||||||
suffix(str): session suffix, e.g. repository architecture
|
*suffixes(str): session suffix, e.g. repository architecture
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: correct section name for repository specific section
|
str: correct section name for repository specific section
|
||||||
"""
|
"""
|
||||||
return f"{section}:{suffix}"
|
for suffix in suffixes:
|
||||||
|
section = f"{section}:{suffix}"
|
||||||
|
return section
|
||||||
|
|
||||||
def _convert_path(self, value: str) -> Path:
|
def _convert_path(self, value: str) -> Path:
|
||||||
"""
|
"""
|
||||||
@ -175,19 +187,19 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
return path
|
return path
|
||||||
return self.path.parent / path
|
return self.path.parent / path
|
||||||
|
|
||||||
def check_loaded(self) -> tuple[Path, str]:
|
def check_loaded(self) -> tuple[Path, RepositoryId]:
|
||||||
"""
|
"""
|
||||||
check if service was actually loaded
|
check if service was actually loaded
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
tuple[Path, str]: configuration root path and architecture if loaded
|
tuple[Path, RepositoryId]: configuration root path and architecture if loaded
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
InitializeError: in case if architecture and/or path are not set
|
InitializeError: in case if architecture and/or path are not set
|
||||||
"""
|
"""
|
||||||
if self.path is None or self.architecture is None:
|
if self.path is None or self.repository_id is None:
|
||||||
raise InitializeError("Configuration path and/or architecture are not set")
|
raise InitializeError("Configuration path and/or repository id are not set")
|
||||||
return self.path, self.architecture
|
return self.path, self.repository_id
|
||||||
|
|
||||||
def dump(self) -> dict[str, dict[str, str]]:
|
def dump(self) -> dict[str, dict[str, str]]:
|
||||||
"""
|
"""
|
||||||
@ -207,14 +219,14 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
|
|
||||||
def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore[empty-body]
|
def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore[empty-body]
|
||||||
|
|
||||||
def gettype(self, section: str, architecture: str, *, fallback: str | None = None) -> tuple[str, str]:
|
def gettype(self, section: str, repository_id: RepositoryId, *, fallback: str | None = None) -> tuple[str, str]:
|
||||||
"""
|
"""
|
||||||
get type variable with fallback to old logic. Despite the fact that it has same semantics as other get* methods,
|
get type variable with fallback to old logic. Despite the fact that it has same semantics as other get* methods,
|
||||||
but it has different argument list
|
but it has different argument list
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
section(str): section name
|
section(str): section name
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
fallback(str | None, optional): optional fallback type if any. If set, second element of the tuple will
|
fallback(str | None, optional): optional fallback type if any. If set, second element of the tuple will
|
||||||
be always set to this value (Default value = None)
|
be always set to this value (Default value = None)
|
||||||
|
|
||||||
@ -227,9 +239,9 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
if (group_type := self.get(section, "type", fallback=fallback)) is not None:
|
if (group_type := self.get(section, "type", fallback=fallback)) is not None:
|
||||||
return section, group_type # new-style logic
|
return section, group_type # new-style logic
|
||||||
# okay lets check for the section with architecture name
|
# okay lets check for the section with architecture name
|
||||||
full_section = self.section_name(section, architecture)
|
for specific in self.override_sections(section, repository_id):
|
||||||
if self.has_section(full_section):
|
if self.has_section(specific):
|
||||||
return full_section, section
|
return specific, section
|
||||||
# okay lets just use section as type
|
# okay lets just use section as type
|
||||||
if self.has_section(section):
|
if self.has_section(section):
|
||||||
return section, section
|
return section, section
|
||||||
@ -262,23 +274,24 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
except (FileNotFoundError, configparser.NoOptionError, configparser.NoSectionError):
|
except (FileNotFoundError, configparser.NoOptionError, configparser.NoSectionError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def merge_sections(self, architecture: str) -> None:
|
def merge_sections(self, repository_id: RepositoryId) -> None:
|
||||||
"""
|
"""
|
||||||
merge architecture specific sections into main configuration
|
merge architecture and repository specific sections into main configuration
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
"""
|
"""
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
|
|
||||||
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS:
|
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS:
|
||||||
# get overrides
|
for specific in self.override_sections(section, repository_id):
|
||||||
specific = self.section_name(section, architecture)
|
if self.has_section(specific):
|
||||||
if self.has_section(specific):
|
# if there is no such section it means that there is no overrides for this arch,
|
||||||
# if there is no such section it means that there is no overrides for this arch,
|
# but we anyway will have to delete sections for others architectures
|
||||||
# but we anyway will have to delete sections for others architectures
|
for key, value in self[specific].items():
|
||||||
for key, value in self[specific].items():
|
self.set_option(section, key, value)
|
||||||
self.set_option(section, key, value)
|
|
||||||
# remove any arch specific section
|
# remove any arch/repo specific section
|
||||||
for foreign in self.sections():
|
for foreign in self.sections():
|
||||||
# we would like to use lambda filter here, but pylint is too dumb
|
# we would like to use lambda filter here, but pylint is too dumb
|
||||||
if not foreign.startswith(f"{section}:"):
|
if not foreign.startswith(f"{section}:"):
|
||||||
@ -289,11 +302,11 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
"""
|
"""
|
||||||
reload configuration if possible or raise exception otherwise
|
reload configuration if possible or raise exception otherwise
|
||||||
"""
|
"""
|
||||||
path, architecture = self.check_loaded()
|
path, repository_id = self.check_loaded()
|
||||||
for section in self.sections(): # clear current content
|
for section in self.sections(): # clear current content
|
||||||
self.remove_section(section)
|
self.remove_section(section)
|
||||||
self.load(path)
|
self.load(path)
|
||||||
self.merge_sections(architecture)
|
self.merge_sections(repository_id)
|
||||||
|
|
||||||
def set_option(self, section: str, option: str, value: str) -> None:
|
def set_option(self, section: str, option: str, value: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -61,8 +61,8 @@ def migrate_package_depends(connection: Connection, configuration: Configuration
|
|||||||
if not configuration.repository_paths.repository.is_dir():
|
if not configuration.repository_paths.repository.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
_, architecture = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
pacman = Pacman(architecture, configuration, refresh_database=PacmanSynchronization.Disabled)
|
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
||||||
|
|
||||||
package_list = []
|
package_list = []
|
||||||
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
||||||
|
@ -58,8 +58,8 @@ def migrate_package_check_depends(connection: Connection, configuration: Configu
|
|||||||
if not configuration.repository_paths.repository.is_dir():
|
if not configuration.repository_paths.repository.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
_, architecture = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
pacman = Pacman(architecture, configuration, refresh_database=PacmanSynchronization.Disabled)
|
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
||||||
|
|
||||||
package_list = []
|
package_list = []
|
||||||
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
||||||
|
@ -64,8 +64,8 @@ def migrate_package_base_packager(connection: Connection, configuration: Configu
|
|||||||
if not configuration.repository_paths.repository.is_dir():
|
if not configuration.repository_paths.repository.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
_, architecture = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
pacman = Pacman(architecture, configuration, refresh_database=PacmanSynchronization.Disabled)
|
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
||||||
|
|
||||||
package_list = []
|
package_list = []
|
||||||
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
||||||
|
@ -30,6 +30,7 @@ from ahriman.core.util import walk
|
|||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.package_source import PackageSource
|
from ahriman.models.package_source import PackageSource
|
||||||
from ahriman.models.remote_source import RemoteSource
|
from ahriman.models.remote_source import RemoteSource
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class RemotePull(LazyLogging):
|
class RemotePull(LazyLogging):
|
||||||
@ -42,13 +43,13 @@ class RemotePull(LazyLogging):
|
|||||||
repository_paths(RepositoryPaths): repository paths instance
|
repository_paths(RepositoryPaths): repository paths instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, configuration: Configuration, architecture: str, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
architecture(str): repository architecture
|
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
self.remote_source = RemoteSource(
|
self.remote_source = RemoteSource(
|
||||||
@ -58,7 +59,7 @@ class RemotePull(LazyLogging):
|
|||||||
branch=configuration.get(section, "pull_branch", fallback="master"),
|
branch=configuration.get(section, "pull_branch", fallback="master"),
|
||||||
source=PackageSource.Local,
|
source=PackageSource.Local,
|
||||||
)
|
)
|
||||||
self.architecture = architecture
|
self.architecture = repository_id.architecture
|
||||||
self.repository_paths = configuration.repository_paths
|
self.repository_paths = configuration.repository_paths
|
||||||
|
|
||||||
def package_copy(self, pkgbuild_path: Path) -> None:
|
def package_copy(self, pkgbuild_path: Path) -> None:
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.gitremote.remote_pull import RemotePull
|
from ahriman.core.gitremote.remote_pull import RemotePull
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class RemotePullTrigger(Trigger):
|
class RemotePullTrigger(Trigger):
|
||||||
@ -56,15 +57,15 @@ class RemotePullTrigger(Trigger):
|
|||||||
}
|
}
|
||||||
CONFIGURATION_SCHEMA_FALLBACK = "gitremote"
|
CONFIGURATION_SCHEMA_FALLBACK = "gitremote"
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
self.targets = self.configuration_sections(configuration)
|
self.targets = self.configuration_sections(configuration)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -86,6 +87,6 @@ class RemotePullTrigger(Trigger):
|
|||||||
"""
|
"""
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
section, _ = self.configuration.gettype(
|
section, _ = self.configuration.gettype(
|
||||||
target, self.architecture, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
|
target, self.repository_id, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
|
||||||
runner = RemotePull(self.configuration, self.architecture, section)
|
runner = RemotePull(self.repository_id, self.configuration, section)
|
||||||
runner.run()
|
runner.run()
|
||||||
|
@ -24,6 +24,7 @@ from ahriman.core.gitremote.remote_push import RemotePush
|
|||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.models.context_key import ContextKey
|
from ahriman.models.context_key import ContextKey
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -67,15 +68,15 @@ class RemotePushTrigger(Trigger):
|
|||||||
}
|
}
|
||||||
CONFIGURATION_SCHEMA_FALLBACK = "gitremote"
|
CONFIGURATION_SCHEMA_FALLBACK = "gitremote"
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
self.targets = self.configuration_sections(configuration)
|
self.targets = self.configuration_sections(configuration)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -107,6 +108,6 @@ class RemotePushTrigger(Trigger):
|
|||||||
|
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
section, _ = self.configuration.gettype(
|
section, _ = self.configuration.gettype(
|
||||||
target, self.architecture, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
|
target, self.repository_id, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
|
||||||
runner = RemotePush(database, self.configuration, section)
|
runner = RemotePush(database, self.configuration, section)
|
||||||
runner.run(result)
|
runner.run(result)
|
||||||
|
@ -21,6 +21,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.formatters import BuildPrinter
|
from ahriman.core.formatters import BuildPrinter
|
||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -32,16 +33,16 @@ class Console(Report):
|
|||||||
use_utf(bool): print utf8 symbols instead of ASCII
|
use_utf(bool): print utf8 symbols instead of ASCII
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Report.__init__(self, architecture, configuration)
|
Report.__init__(self, repository_id, configuration)
|
||||||
self.use_utf = configuration.getboolean(section, "use_utf", fallback=True)
|
self.use_utf = configuration.getboolean(section, "use_utf", fallback=True)
|
||||||
|
|
||||||
def generate(self, packages: list[Package], result: Result) -> None:
|
def generate(self, packages: list[Package], result: Result) -> None:
|
||||||
|
@ -27,6 +27,7 @@ from ahriman.core.report.jinja_template import JinjaTemplate
|
|||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.core.util import pretty_datetime, utcnow
|
from ahriman.core.util import pretty_datetime, utcnow
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
from ahriman.models.smtp_ssl_settings import SmtpSSLSettings
|
from ahriman.models.smtp_ssl_settings import SmtpSSLSettings
|
||||||
|
|
||||||
@ -48,17 +49,17 @@ class Email(Report, JinjaTemplate):
|
|||||||
user(str | None): username to authenticate via SMTP
|
user(str | None): username to authenticate via SMTP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Report.__init__(self, architecture, configuration)
|
Report.__init__(self, repository_id, configuration)
|
||||||
JinjaTemplate.__init__(self, section, configuration)
|
JinjaTemplate.__init__(self, repository_id, configuration, section)
|
||||||
|
|
||||||
self.full_template_path = configuration.getpath(section, "full_template_path", fallback=None)
|
self.full_template_path = configuration.getpath(section, "full_template_path", fallback=None)
|
||||||
self.template_path = configuration.getpath(section, "template_path")
|
self.template_path = configuration.getpath(section, "template_path")
|
||||||
|
@ -21,6 +21,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.report.jinja_template import JinjaTemplate
|
from ahriman.core.report.jinja_template import JinjaTemplate
|
||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -33,17 +34,17 @@ class HTML(Report, JinjaTemplate):
|
|||||||
template_path(Path): path to template for full package list
|
template_path(Path): path to template for full package list
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Report.__init__(self, architecture, configuration)
|
Report.__init__(self, repository_id, configuration)
|
||||||
JinjaTemplate.__init__(self, section, configuration)
|
JinjaTemplate.__init__(self, repository_id, configuration, section)
|
||||||
|
|
||||||
self.report_path = configuration.getpath(section, "path")
|
self.report_path = configuration.getpath(section, "path")
|
||||||
self.template_path = configuration.getpath(section, "template_path")
|
self.template_path = configuration.getpath(section, "template_path")
|
||||||
|
@ -25,6 +25,7 @@ from pathlib import Path
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
from ahriman.core.util import pretty_datetime, pretty_size
|
from ahriman.core.util import pretty_datetime, pretty_size
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
from ahriman.models.sign_settings import SignSettings
|
from ahriman.models.sign_settings import SignSettings
|
||||||
|
|
||||||
@ -63,19 +64,20 @@ class JinjaTemplate:
|
|||||||
sign_targets(set[SignSettings]): targets to sign enabled in configuration
|
sign_targets(set[SignSettings]): targets to sign enabled in configuration
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, section: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
section(str): settings section name
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
self.link_path = configuration.get(section, "link_path")
|
self.link_path = configuration.get(section, "link_path")
|
||||||
|
|
||||||
# base template vars
|
# base template vars
|
||||||
self.homepage = configuration.get(section, "homepage", fallback=None)
|
self.homepage = configuration.get(section, "homepage", fallback=None)
|
||||||
self.name = configuration.repository_name
|
self.name = repository_id.name
|
||||||
|
|
||||||
self.sign_targets, self.default_pgp_key = GPG.sign_options(configuration)
|
self.sign_targets, self.default_pgp_key = GPG.sign_options(configuration)
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.core.status.web_client import WebClient
|
from ahriman.core.status.web_client import WebClient
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
from ahriman.models.waiter import Waiter
|
from ahriman.models.waiter import Waiter
|
||||||
|
|
||||||
@ -39,16 +40,16 @@ class RemoteCall(Report):
|
|||||||
wait_timeout(int): timeout to wait external process
|
wait_timeout(int): timeout to wait external process
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Report.__init__(self, architecture, configuration)
|
Report.__init__(self, repository_id, configuration)
|
||||||
|
|
||||||
self.client = WebClient(configuration)
|
self.client = WebClient(configuration)
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ from ahriman.core.exceptions import ReportError
|
|||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.report_settings import ReportSettings
|
from ahriman.models.report_settings import ReportSettings
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -32,17 +33,15 @@ class Report(LazyLogging):
|
|||||||
base report generator
|
base report generator
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
``Report`` classes provide several method in order to operate with the report generation and additional class
|
``Report`` classes provide several method in order to operate with the report generation and additional class
|
||||||
method ``load`` which can be used in order to determine right report instance::
|
method ``load`` which can be used in order to determine right report instance::
|
||||||
|
|
||||||
>>> from ahriman.core.configuration import Configuration
|
|
||||||
>>>
|
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> report = Report.load("x86_64", configuration, "email")
|
>>> report = Report.load(RepositoryId("x86_64", None), configuration, "email")
|
||||||
|
|
||||||
The ``generate`` method can be used in order to perform the report itself, whereas ``run`` method handles
|
The ``generate`` method can be used in order to perform the report itself, whereas ``run`` method handles
|
||||||
exception and raises ``ReportFailed`` instead::
|
exception and raises ``ReportFailed`` instead::
|
||||||
@ -55,49 +54,49 @@ class Report(LazyLogging):
|
|||||||
>>> report.run(Result(), [])
|
>>> report.run(Result(), [])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(architecture: str, configuration: Configuration, target: str) -> Report:
|
def load(repository_id: RepositoryId, configuration: Configuration, target: str) -> Report:
|
||||||
"""
|
"""
|
||||||
load client from settings
|
load client from settings
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
target(str): target to generate report aka section name (e.g. html)
|
target(str): target to generate report aka section name (e.g. html)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Report: client according to current settings
|
Report: client according to current settings
|
||||||
"""
|
"""
|
||||||
section, provider_name = configuration.gettype(target, architecture)
|
section, provider_name = configuration.gettype(target, repository_id)
|
||||||
match ReportSettings.from_option(provider_name):
|
match ReportSettings.from_option(provider_name):
|
||||||
case ReportSettings.HTML:
|
case ReportSettings.HTML:
|
||||||
from ahriman.core.report.html import HTML
|
from ahriman.core.report.html import HTML
|
||||||
return HTML(architecture, configuration, section)
|
return HTML(repository_id, configuration, section)
|
||||||
case ReportSettings.Email:
|
case ReportSettings.Email:
|
||||||
from ahriman.core.report.email import Email
|
from ahriman.core.report.email import Email
|
||||||
return Email(architecture, configuration, section)
|
return Email(repository_id, configuration, section)
|
||||||
case ReportSettings.Console:
|
case ReportSettings.Console:
|
||||||
from ahriman.core.report.console import Console
|
from ahriman.core.report.console import Console
|
||||||
return Console(architecture, configuration, section)
|
return Console(repository_id, configuration, section)
|
||||||
case ReportSettings.Telegram:
|
case ReportSettings.Telegram:
|
||||||
from ahriman.core.report.telegram import Telegram
|
from ahriman.core.report.telegram import Telegram
|
||||||
return Telegram(architecture, configuration, section)
|
return Telegram(repository_id, configuration, section)
|
||||||
case ReportSettings.RemoteCall:
|
case ReportSettings.RemoteCall:
|
||||||
from ahriman.core.report.remote_call import RemoteCall
|
from ahriman.core.report.remote_call import RemoteCall
|
||||||
return RemoteCall(architecture, configuration, section)
|
return RemoteCall(repository_id, configuration, section)
|
||||||
case _:
|
case _:
|
||||||
return Report(architecture, configuration) # should never happen
|
return Report(repository_id, configuration) # should never happen
|
||||||
|
|
||||||
def generate(self, packages: list[Package], result: Result) -> None:
|
def generate(self, packages: list[Package], result: Result) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -218,15 +219,15 @@ class ReportTrigger(Trigger):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
self.targets = self.configuration_sections(configuration)
|
self.targets = self.configuration_sections(configuration)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -251,5 +252,5 @@ class ReportTrigger(Trigger):
|
|||||||
packages(list[Package]): list of all available packages
|
packages(list[Package]): list of all available packages
|
||||||
"""
|
"""
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
runner = Report.load(self.architecture, self.configuration, target)
|
runner = Report.load(self.repository_id, self.configuration, target)
|
||||||
runner.run(result, packages)
|
runner.run(result, packages)
|
||||||
|
@ -22,6 +22,7 @@ from ahriman.core.http import SyncHttpClient
|
|||||||
from ahriman.core.report.jinja_template import JinjaTemplate
|
from ahriman.core.report.jinja_template import JinjaTemplate
|
||||||
from ahriman.core.report.report import Report
|
from ahriman.core.report.report import Report
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -41,17 +42,17 @@ class Telegram(Report, JinjaTemplate, SyncHttpClient):
|
|||||||
TELEGRAM_API_URL = "https://api.telegram.org"
|
TELEGRAM_API_URL = "https://api.telegram.org"
|
||||||
TELEGRAM_MAX_CONTENT_LENGTH = 4096
|
TELEGRAM_MAX_CONTENT_LENGTH = 4096
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Report.__init__(self, architecture, configuration)
|
Report.__init__(self, repository_id, configuration)
|
||||||
JinjaTemplate.__init__(self, section, configuration)
|
JinjaTemplate.__init__(self, repository_id, configuration, section)
|
||||||
SyncHttpClient.__init__(self, section, configuration)
|
SyncHttpClient.__init__(self, section, configuration)
|
||||||
|
|
||||||
self.api_key = configuration.get(section, "api_key")
|
self.api_key = configuration.get(section, "api_key")
|
||||||
|
@ -32,6 +32,7 @@ from ahriman.core.util import package_like
|
|||||||
from ahriman.models.context_key import ContextKey
|
from ahriman.models.context_key import ContextKey
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Repository(Executor, UpdateHandler):
|
class Repository(Executor, UpdateHandler):
|
||||||
@ -47,7 +48,7 @@ class Repository(Executor, UpdateHandler):
|
|||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> database = SQLite.load(configuration)
|
>>> database = SQLite.load(configuration)
|
||||||
>>> repository = Repository.load("x86_64", configuration, database, report=True)
|
>>> repository = Repository.load(RepositoryId("x86_64", None), configuration, database, report=True)
|
||||||
>>> known_packages = repository.packages()
|
>>> known_packages = repository.packages()
|
||||||
>>>
|
>>>
|
||||||
>>> build_result = repository.process_build(known_packages)
|
>>> build_result = repository.process_build(known_packages)
|
||||||
@ -58,13 +59,13 @@ class Repository(Executor, UpdateHandler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, architecture: str, configuration: Configuration, database: SQLite, *, report: bool,
|
def load(cls, repository_id: RepositoryId, configuration: Configuration, database: SQLite, *, report: bool,
|
||||||
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> Self:
|
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> Self:
|
||||||
"""
|
"""
|
||||||
load instance from argument list
|
load instance from argument list
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
@ -74,7 +75,7 @@ class Repository(Executor, UpdateHandler):
|
|||||||
Returns:
|
Returns:
|
||||||
Self: fully loaded repository class instance
|
Self: fully loaded repository class instance
|
||||||
"""
|
"""
|
||||||
instance = cls(architecture, configuration, database,
|
instance = cls(repository_id, configuration, database,
|
||||||
report=report, refresh_pacman_database=refresh_pacman_database)
|
report=report, refresh_pacman_database=refresh_pacman_database)
|
||||||
instance._set_context()
|
instance._set_context()
|
||||||
return instance
|
return instance
|
||||||
|
@ -27,6 +27,7 @@ from ahriman.core.status.client import Client
|
|||||||
from ahriman.core.triggers import TriggerLoader
|
from ahriman.core.triggers import TriggerLoader
|
||||||
from ahriman.models.packagers import Packagers
|
from ahriman.models.packagers import Packagers
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
from ahriman.models.user import User
|
from ahriman.models.user import User
|
||||||
from ahriman.models.user_access import UserAccess
|
from ahriman.models.user_access import UserAccess
|
||||||
@ -37,47 +38,65 @@ class RepositoryProperties(LazyLogging):
|
|||||||
repository internal objects holder
|
repository internal objects holder
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
ignore_list(list[str]): package bases which will be ignored during auto updates
|
ignore_list(list[str]): package bases which will be ignored during auto updates
|
||||||
name(str): repository name
|
|
||||||
pacman(Pacman): alpm wrapper instance
|
pacman(Pacman): alpm wrapper instance
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
repo(Repo): repo commands wrapper instance
|
repo(Repo): repo commands wrapper instance
|
||||||
reporter(Client): build status reporter instance
|
reporter(Client): build status reporter instance
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
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
|
vcs_allowed_age(int): maximal age of the VCS packages before they will be checked
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, database: SQLite, *, report: bool,
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, database: SQLite, *, report: bool,
|
||||||
refresh_pacman_database: PacmanSynchronization) -> None:
|
refresh_pacman_database: PacmanSynchronization) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
refresh_pacman_database(PacmanSynchronization): pacman database synchronization level
|
refresh_pacman_database(PacmanSynchronization): pacman database synchronization level
|
||||||
"""
|
"""
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.database = database
|
self.database = database
|
||||||
|
|
||||||
self.name = configuration.repository_name
|
|
||||||
self.vcs_allowed_age = configuration.getint("build", "vcs_allowed_age", fallback=0)
|
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=[])
|
||||||
self.pacman = Pacman(architecture, configuration, refresh_database=refresh_pacman_database)
|
self.pacman = Pacman(repository_id, configuration, refresh_database=refresh_pacman_database)
|
||||||
self.sign = GPG(configuration)
|
self.sign = GPG(configuration)
|
||||||
self.repo = Repo(self.name, self.paths, self.sign.repository_sign_args)
|
self.repo = Repo(self.name, self.paths, self.sign.repository_sign_args)
|
||||||
self.reporter = Client.load(configuration, report=report)
|
self.reporter = Client.load(configuration, report=report)
|
||||||
self.triggers = TriggerLoader.load(architecture, configuration)
|
self.triggers = TriggerLoader.load(repository_id, configuration)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def architecture(self) -> str:
|
||||||
|
"""
|
||||||
|
repository architecture for backward compatibility
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: repository architecture
|
||||||
|
"""
|
||||||
|
return self.repository_id.architecture
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
"""
|
||||||
|
repository name for backward compatibility
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: repository name
|
||||||
|
"""
|
||||||
|
return self.repository_id.name
|
||||||
|
|
||||||
def packager(self, packagers: Packagers, package_base: str) -> User:
|
def packager(self, packagers: Packagers, package_base: str) -> User:
|
||||||
"""
|
"""
|
||||||
|
@ -28,6 +28,7 @@ from multiprocessing import Process, Queue
|
|||||||
from threading import Lock, Thread
|
from threading import Lock, Thread
|
||||||
|
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Spawn(Thread, LazyLogging):
|
class Spawn(Thread, LazyLogging):
|
||||||
@ -37,22 +38,23 @@ class Spawn(Thread, LazyLogging):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
active(dict[str, Process]): map of active child processes required to avoid zombies
|
active(dict[str, Process]): map of active child processes required to avoid zombies
|
||||||
architecture(str): repository architecture
|
|
||||||
command_arguments(list[str]): base command line arguments
|
command_arguments(list[str]): base command line arguments
|
||||||
queue(Queue[tuple[str, bool, int]]): multiprocessing queue to read updates from processes
|
queue(Queue[tuple[str, bool, int]]): multiprocessing queue to read updates from processes
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, args_parser: argparse.ArgumentParser, architecture: str, command_arguments: list[str]) -> None:
|
def __init__(self, args_parser: argparse.ArgumentParser, repository_id: RepositoryId,
|
||||||
|
command_arguments: list[str]) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args_parser(argparse.ArgumentParser): command line parser for the application
|
args_parser(argparse.ArgumentParser): command line parser for the application
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
command_arguments(list[str]): base command line arguments
|
command_arguments(list[str]): base command line arguments
|
||||||
"""
|
"""
|
||||||
Thread.__init__(self, name="spawn")
|
Thread.__init__(self, name="spawn")
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
|
|
||||||
self.args_parser = args_parser
|
self.args_parser = args_parser
|
||||||
self.command_arguments = command_arguments
|
self.command_arguments = command_arguments
|
||||||
@ -77,20 +79,20 @@ class Spawn(Thread, LazyLogging):
|
|||||||
return name if value else f"no-{name}"
|
return name if value else f"no-{name}"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process(callback: Callable[[argparse.Namespace, str], bool], args: argparse.Namespace, architecture: str,
|
def process(callback: Callable[[argparse.Namespace, RepositoryId], bool], args: argparse.Namespace,
|
||||||
process_id: str, queue: Queue[tuple[str, bool, int]]) -> None: # pylint: disable=unsubscriptable-object
|
repository_id: RepositoryId, process_id: str, queue: Queue[tuple[str, bool, int]]) -> None: # pylint: disable=unsubscriptable-object
|
||||||
"""
|
"""
|
||||||
helper to run external process
|
helper to run external process
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. Handler.run method)
|
callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. Handler.run method)
|
||||||
args(argparse.Namespace): command line arguments
|
args(argparse.Namespace): command line arguments
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
process_id(str): process unique identifier
|
process_id(str): process unique identifier
|
||||||
queue(Queue[tuple[str, bool, int]]): output queue
|
queue(Queue[tuple[str, bool, int]]): output queue
|
||||||
"""
|
"""
|
||||||
start_time = time.monotonic()
|
start_time = time.monotonic()
|
||||||
result = callback(args, architecture)
|
result = callback(args, repository_id)
|
||||||
stop_time = time.monotonic()
|
stop_time = time.monotonic()
|
||||||
|
|
||||||
consumed_time = int(1000 * (stop_time - start_time))
|
consumed_time = int(1000 * (stop_time - start_time))
|
||||||
@ -128,7 +130,7 @@ class Spawn(Thread, LazyLogging):
|
|||||||
|
|
||||||
callback = parsed.handler.call
|
callback = parsed.handler.call
|
||||||
process = Process(target=self.process,
|
process = Process(target=self.process,
|
||||||
args=(callback, parsed, self.architecture, process_id, self.queue),
|
args=(callback, parsed, self.repository_id, process_id, self.queue),
|
||||||
daemon=True)
|
daemon=True)
|
||||||
process.start()
|
process.start()
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.core.repository import Repository
|
|||||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||||
from ahriman.models.log_record_id import LogRecordId
|
from ahriman.models.log_record_id import LogRecordId
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Watcher(LazyLogging):
|
class Watcher(LazyLogging):
|
||||||
@ -32,26 +33,26 @@ class Watcher(LazyLogging):
|
|||||||
package status watcher
|
package status watcher
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
known(dict[str, tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
known(dict[str, tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
||||||
be used instead
|
be used instead
|
||||||
repository(Repository): repository object
|
repository(Repository): repository object
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
status(BuildStatus): daemon status
|
status(BuildStatus): daemon status
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, database: SQLite) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, database: SQLite) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
"""
|
"""
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
self.database = database
|
self.database = database
|
||||||
self.repository = Repository.load(architecture, configuration, database, report=False)
|
self.repository = Repository.load(repository_id, configuration, database, report=False)
|
||||||
|
|
||||||
self.known: dict[str, tuple[Package, BuildStatus]] = {}
|
self.known: dict[str, tuple[Package, BuildStatus]] = {}
|
||||||
self.status = BuildStatus()
|
self.status = BuildStatus()
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.core.support.package_creator import PackageCreator
|
|||||||
from ahriman.core.support.pkgbuild.keyring_generator import KeyringGenerator
|
from ahriman.core.support.pkgbuild.keyring_generator import KeyringGenerator
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.models.context_key import ContextKey
|
from ahriman.models.context_key import ContextKey
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class KeyringTrigger(Trigger):
|
class KeyringTrigger(Trigger):
|
||||||
@ -82,15 +83,15 @@ class KeyringTrigger(Trigger):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
self.targets = self.configuration_sections(configuration)
|
self.targets = self.configuration_sections(configuration)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -115,6 +116,6 @@ class KeyringTrigger(Trigger):
|
|||||||
database = ctx.get(ContextKey("database", SQLite))
|
database = ctx.get(ContextKey("database", SQLite))
|
||||||
|
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
generator = KeyringGenerator(database, sign, self.configuration, target)
|
generator = KeyringGenerator(database, sign, self.repository_id, self.configuration, target)
|
||||||
runner = PackageCreator(self.configuration, generator)
|
runner = PackageCreator(self.configuration, generator)
|
||||||
runner.run()
|
runner.run()
|
||||||
|
@ -21,6 +21,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.support.package_creator import PackageCreator
|
from ahriman.core.support.package_creator import PackageCreator
|
||||||
from ahriman.core.support.pkgbuild.mirrorlist_generator import MirrorlistGenerator
|
from ahriman.core.support.pkgbuild.mirrorlist_generator import MirrorlistGenerator
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class MirrorlistTrigger(Trigger):
|
class MirrorlistTrigger(Trigger):
|
||||||
@ -75,15 +76,15 @@ class MirrorlistTrigger(Trigger):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
self.targets = self.configuration_sections(configuration)
|
self.targets = self.configuration_sections(configuration)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -104,6 +105,6 @@ class MirrorlistTrigger(Trigger):
|
|||||||
trigger action which will be called at the start of the application
|
trigger action which will be called at the start of the application
|
||||||
"""
|
"""
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
generator = MirrorlistGenerator(self.configuration, target)
|
generator = MirrorlistGenerator(self.repository_id, self.configuration, target)
|
||||||
runner = PackageCreator(self.configuration, generator)
|
runner = PackageCreator(self.configuration, generator)
|
||||||
runner.run()
|
runner.run()
|
||||||
|
@ -66,6 +66,6 @@ class PackageCreator:
|
|||||||
# register package
|
# register package
|
||||||
ctx = context.get()
|
ctx = context.get()
|
||||||
database: SQLite = ctx.get(ContextKey("database", SQLite))
|
database: SQLite = ctx.get(ContextKey("database", SQLite))
|
||||||
_, architecture = self.configuration.check_loaded()
|
_, repository_id = self.configuration.check_loaded()
|
||||||
package = Package.from_build(local_path, architecture, None)
|
package = Package.from_build(local_path, repository_id.architecture, None)
|
||||||
database.package_update(package, BuildStatus())
|
database.package_update(package, BuildStatus())
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.core.database import SQLite
|
|||||||
from ahriman.core.exceptions import PkgbuildGeneratorError
|
from ahriman.core.exceptions import PkgbuildGeneratorError
|
||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
from ahriman.core.support.pkgbuild.pkgbuild_generator import PkgbuildGenerator
|
from ahriman.core.support.pkgbuild.pkgbuild_generator import PkgbuildGenerator
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class KeyringGenerator(PkgbuildGenerator):
|
class KeyringGenerator(PkgbuildGenerator):
|
||||||
@ -43,18 +44,20 @@ class KeyringGenerator(PkgbuildGenerator):
|
|||||||
trusted(list[str]): lif of trusted PGP keys
|
trusted(list[str]): lif of trusted PGP keys
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, database: SQLite, sign: GPG, configuration: Configuration, section: str) -> None:
|
def __init__(self, database: SQLite, sign: GPG, repository_id: RepositoryId,
|
||||||
|
configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
sign(GPG): GPG wrapper instance
|
sign(GPG): GPG wrapper instance
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
self.sign = sign
|
self.sign = sign
|
||||||
self.name = configuration.repository_name
|
self.name = repository_id.name
|
||||||
|
|
||||||
# configuration fields
|
# configuration fields
|
||||||
packager_keys = [packager.key for packager in database.user_list(None, None) if packager.key is not None]
|
packager_keys = [packager.key for packager in database.user_list(None, None) if packager.key is not None]
|
||||||
|
@ -23,6 +23,7 @@ from pathlib import Path
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.support.pkgbuild.pkgbuild_generator import PkgbuildGenerator
|
from ahriman.core.support.pkgbuild.pkgbuild_generator import PkgbuildGenerator
|
||||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class MirrorlistGenerator(PkgbuildGenerator):
|
class MirrorlistGenerator(PkgbuildGenerator):
|
||||||
@ -38,24 +39,24 @@ class MirrorlistGenerator(PkgbuildGenerator):
|
|||||||
servers(list[str]): list of mirror servers
|
servers(list[str]): list of mirror servers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
name = configuration.repository_name
|
|
||||||
|
|
||||||
# configuration fields
|
# configuration fields
|
||||||
self.servers = configuration.getlist(section, "servers")
|
self.servers = configuration.getlist(section, "servers")
|
||||||
self.path = configuration.getpath(section, "path", fallback=Path("/etc") / "pacman.d" / f"{name}-mirrorlist")
|
self.path = configuration.getpath(
|
||||||
|
section, "path", fallback=Path("/etc") / "pacman.d" / f"{repository_id.name}-mirrorlist")
|
||||||
self.path = self.path.relative_to("/") # in pkgbuild we are always operating with relative to / path
|
self.path = self.path.relative_to("/") # in pkgbuild we are always operating with relative to / path
|
||||||
# pkgbuild description fields
|
# pkgbuild description fields
|
||||||
self.pkgbuild_pkgname = configuration.get(section, "package", fallback=f"{name}-mirrorlist")
|
self.pkgbuild_pkgname = configuration.get(section, "package", fallback=f"{repository_id.name}-mirrorlist")
|
||||||
self.pkgbuild_pkgdesc = configuration.get(
|
self.pkgbuild_pkgdesc = configuration.get(
|
||||||
section, "description", fallback=f"{name} mirror list for use by pacman")
|
section, "description", fallback=f"{repository_id.name} mirror list for use by pacman")
|
||||||
self.pkgbuild_license = configuration.getlist(section, "license", fallback=["Unlicense"])
|
self.pkgbuild_license = configuration.getlist(section, "license", fallback=["Unlicense"])
|
||||||
self.pkgbuild_url = configuration.get(section, "homepage", fallback="")
|
self.pkgbuild_url = configuration.get(section, "homepage", fallback="")
|
||||||
|
|
||||||
|
@ -102,10 +102,11 @@ class Tree:
|
|||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
>>> from ahriman.core.database import SQLite
|
>>> from ahriman.core.database import SQLite
|
||||||
>>> from ahriman.core.repository import Repository
|
>>> from ahriman.core.repository import Repository
|
||||||
|
>>> from ahriman.models.repository_id import RepositoryId
|
||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> database = SQLite.load(configuration)
|
>>> database = SQLite.load(configuration)
|
||||||
>>> repository = Repository.load("x86_64", configuration, database, report=True)
|
>>> repository = Repository.load(RepositoryId("x86_64", None), configuration, database, report=True)
|
||||||
>>> packages = repository.packages()
|
>>> packages = repository.packages()
|
||||||
>>>
|
>>>
|
||||||
>>> tree = Tree.resolve(packages)
|
>>> tree = Tree.resolve(packages)
|
||||||
|
@ -23,6 +23,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.configuration.schema import ConfigurationSchema
|
from ahriman.core.configuration.schema import ConfigurationSchema
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -34,8 +35,8 @@ class Trigger(LazyLogging):
|
|||||||
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
||||||
CONFIGURATION_SCHEMA_FALLBACK(str | None): (class attribute) optional fallback option for defining
|
CONFIGURATION_SCHEMA_FALLBACK(str | None): (class attribute) optional fallback option for defining
|
||||||
configuration schema type used
|
configuration schema type used
|
||||||
architecture(str): repository architecture
|
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
This class must be used in order to create own extension. Basically idea is the following::
|
This class must be used in order to create own extension. Basically idea is the following::
|
||||||
@ -51,26 +52,27 @@ class Trigger(LazyLogging):
|
|||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> configuration.set_option("build", "triggers", "my.awesome.package.CustomTrigger")
|
>>> configuration.set_option("build", "triggers", "my.awesome.package.CustomTrigger")
|
||||||
>>>
|
>>>
|
||||||
>>> loader = TriggerLoader.load("x86_64", configuration)
|
>>> loader = TriggerLoader.load(RepositoryId("x86_64", None), configuration)
|
||||||
>>> loader.on_result(Result(), [])
|
>>> loader.on_result(Result(), [])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CONFIGURATION_SCHEMA: ConfigurationSchema = {}
|
CONFIGURATION_SCHEMA: ConfigurationSchema = {}
|
||||||
CONFIGURATION_SCHEMA_FALLBACK: str | None = None
|
CONFIGURATION_SCHEMA_FALLBACK: str | None = None
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def configuration_schema(cls, architecture: str, configuration: Configuration | None) -> ConfigurationSchema:
|
def configuration_schema(cls, repository_id: RepositoryId,
|
||||||
|
configuration: Configuration | None) -> ConfigurationSchema:
|
||||||
"""
|
"""
|
||||||
configuration schema based on supplied service configuration
|
configuration schema based on supplied service configuration
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ class Trigger(LazyLogging):
|
|||||||
Schema must be in cerberus format, for details and examples you can check built-in triggers.
|
Schema must be in cerberus format, for details and examples you can check built-in triggers.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(str): repository unique identifier
|
||||||
configuration(Configuration | None): configuration instance. If set to None, the default schema
|
configuration(Configuration | None): configuration instance. If set to None, the default schema
|
||||||
should be returned
|
should be returned
|
||||||
|
|
||||||
@ -93,7 +95,7 @@ class Trigger(LazyLogging):
|
|||||||
if not configuration.has_section(target):
|
if not configuration.has_section(target):
|
||||||
continue
|
continue
|
||||||
section, schema_name = configuration.gettype(
|
section, schema_name = configuration.gettype(
|
||||||
target, architecture, fallback=cls.CONFIGURATION_SCHEMA_FALLBACK)
|
target, repository_id, fallback=cls.CONFIGURATION_SCHEMA_FALLBACK)
|
||||||
if schema_name not in cls.CONFIGURATION_SCHEMA:
|
if schema_name not in cls.CONFIGURATION_SCHEMA:
|
||||||
continue
|
continue
|
||||||
result[section] = cls.CONFIGURATION_SCHEMA[schema_name]
|
result[section] = cls.CONFIGURATION_SCHEMA[schema_name]
|
||||||
|
@ -31,6 +31,7 @@ from ahriman.core.exceptions import ExtensionError
|
|||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ class TriggerLoader(LazyLogging):
|
|||||||
|
|
||||||
Having such configuration you can create instance of the loader::
|
Having such configuration you can create instance of the loader::
|
||||||
|
|
||||||
>>> loader = TriggerLoader.load("x86_64", configuration)
|
>>> loader = TriggerLoader.load(RepositoryId("x86_64", None), configuration)
|
||||||
>>> print(loader.triggers)
|
>>> print(loader.triggers)
|
||||||
|
|
||||||
After that you are free to run triggers::
|
After that you are free to run triggers::
|
||||||
@ -65,12 +66,12 @@ class TriggerLoader(LazyLogging):
|
|||||||
self.triggers: list[Trigger] = []
|
self.triggers: list[Trigger] = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, architecture: str, configuration: Configuration) -> Self:
|
def load(cls, repository_id: RepositoryId, configuration: Configuration) -> Self:
|
||||||
"""
|
"""
|
||||||
create instance from configuration
|
create instance from configuration
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -78,7 +79,7 @@ class TriggerLoader(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
instance = cls()
|
instance = cls()
|
||||||
instance.triggers = [
|
instance.triggers = [
|
||||||
instance.load_trigger(trigger, architecture, configuration)
|
instance.load_trigger(trigger, repository_id, configuration)
|
||||||
for trigger in instance.selected_triggers(configuration)
|
for trigger in instance.selected_triggers(configuration)
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -166,13 +167,13 @@ class TriggerLoader(LazyLogging):
|
|||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
raise ExtensionError(f"Module {package} not found") from None
|
raise ExtensionError(f"Module {package} not found") from None
|
||||||
|
|
||||||
def load_trigger(self, module_path: str, architecture: str, configuration: Configuration) -> Trigger:
|
def load_trigger(self, module_path: str, repository_id: RepositoryId, configuration: Configuration) -> Trigger:
|
||||||
"""
|
"""
|
||||||
load trigger by module path
|
load trigger by module path
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
module_path(str): module import path to load
|
module_path(str): module import path to load
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -183,7 +184,7 @@ class TriggerLoader(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
trigger_type = self.load_trigger_class(module_path)
|
trigger_type = self.load_trigger_class(module_path)
|
||||||
try:
|
try:
|
||||||
trigger = trigger_type(architecture, configuration)
|
trigger = trigger_type(repository_id, configuration)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise ExtensionError(f"Could not load instance of trigger from {trigger_type} loaded from {module_path}")
|
raise ExtensionError(f"Could not load instance of trigger from {trigger_type} loaded from {module_path}")
|
||||||
|
|
||||||
|
@ -25,32 +25,44 @@ from typing import Any
|
|||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.upload.http_upload import HttpUpload
|
from ahriman.core.upload.http_upload import HttpUpload
|
||||||
|
from ahriman.core.upload.upload import Upload
|
||||||
from ahriman.core.util import walk
|
from ahriman.core.util import walk
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Github(HttpUpload):
|
class Github(Upload, HttpUpload):
|
||||||
"""
|
"""
|
||||||
upload files to GitHub releases
|
upload files to GitHub releases
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
github_owner(str): GitHub repository owner
|
github_owner(str): GitHub repository owner
|
||||||
|
github_release_tag(str): GitHub release tag
|
||||||
|
github_release_tag_name(str): GitHub release tag name
|
||||||
github_repository(str): GitHub repository name
|
github_repository(str): GitHub repository name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
HttpUpload.__init__(self, architecture, configuration, section)
|
Upload.__init__(self, repository_id, configuration)
|
||||||
|
HttpUpload.__init__(self, section, configuration)
|
||||||
|
|
||||||
self.github_owner = configuration.get(section, "owner")
|
self.github_owner = configuration.get(section, "owner")
|
||||||
self.github_repository = configuration.get(section, "repository")
|
self.github_repository = configuration.get(section, "repository")
|
||||||
|
|
||||||
|
if repository_id.name is not None:
|
||||||
|
self.github_release_tag = f"{repository_id.name}-{repository_id.architecture}"
|
||||||
|
self.github_release_tag_name = f"{repository_id.name} {repository_id.architecture}"
|
||||||
|
else:
|
||||||
|
self.github_release_tag_name = self.github_release_tag = repository_id.architecture
|
||||||
|
|
||||||
def asset_remove(self, release: dict[str, Any], name: str) -> None:
|
def asset_remove(self, release: dict[str, Any], name: str) -> None:
|
||||||
"""
|
"""
|
||||||
remove asset from the release by name
|
remove asset from the release by name
|
||||||
@ -136,7 +148,10 @@ class Github(HttpUpload):
|
|||||||
dict[str, Any]: GitHub API release object for the new release
|
dict[str, Any]: GitHub API release object for the new release
|
||||||
"""
|
"""
|
||||||
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases"
|
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases"
|
||||||
response = self.make_request("POST", url, json={"tag_name": self.architecture, "name": self.architecture})
|
response = self.make_request("POST", url, json={
|
||||||
|
"tag_name": self.github_release_tag,
|
||||||
|
"name": self.github_release_tag_name,
|
||||||
|
})
|
||||||
release: dict[str, Any] = response.json()
|
release: dict[str, Any] = response.json()
|
||||||
return release
|
return release
|
||||||
|
|
||||||
@ -147,7 +162,7 @@ class Github(HttpUpload):
|
|||||||
Returns:
|
Returns:
|
||||||
dict[str, Any] | None: GitHub API release object if release found and None otherwise
|
dict[str, Any] | None: GitHub API release object if release found and None otherwise
|
||||||
"""
|
"""
|
||||||
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases/tags/{self.architecture}"
|
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases/tags/{self.github_release_tag}"
|
||||||
try:
|
try:
|
||||||
response = self.make_request("GET", url)
|
response = self.make_request("GET", url)
|
||||||
release: dict[str, Any] = response.json()
|
release: dict[str, Any] = response.json()
|
||||||
|
@ -21,28 +21,14 @@ import hashlib
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
|
||||||
from ahriman.core.http import SyncHttpClient
|
from ahriman.core.http import SyncHttpClient
|
||||||
from ahriman.core.upload.upload import Upload
|
|
||||||
|
|
||||||
|
|
||||||
class HttpUpload(Upload, SyncHttpClient):
|
class HttpUpload(SyncHttpClient):
|
||||||
"""
|
"""
|
||||||
helper for the http based uploads
|
helper for the http based uploads
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
|
||||||
"""
|
|
||||||
default constructor
|
|
||||||
|
|
||||||
Args:
|
|
||||||
architecture(str): repository architecture
|
|
||||||
configuration(Configuration): configuration instance
|
|
||||||
section(str): configuration section name
|
|
||||||
"""
|
|
||||||
Upload.__init__(self, architecture, configuration)
|
|
||||||
SyncHttpClient.__init__(self, section, configuration)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_hash(path: Path) -> str:
|
def calculate_hash(path: Path) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -27,10 +27,12 @@ from ahriman.core.http import MultipartType
|
|||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
from ahriman.core.status.web_client import WebClient
|
from ahriman.core.status.web_client import WebClient
|
||||||
from ahriman.core.upload.http_upload import HttpUpload
|
from ahriman.core.upload.http_upload import HttpUpload
|
||||||
|
from ahriman.core.upload.upload import Upload
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class RemoteService(HttpUpload):
|
class RemoteService(Upload, HttpUpload):
|
||||||
"""
|
"""
|
||||||
upload files to another server instance
|
upload files to another server instance
|
||||||
|
|
||||||
@ -38,16 +40,17 @@ class RemoteService(HttpUpload):
|
|||||||
client(WebClient): web client instance
|
client(WebClient): web client instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
HttpUpload.__init__(self, architecture, configuration, section)
|
Upload.__init__(self, repository_id, configuration)
|
||||||
|
HttpUpload.__init__(self, section, configuration)
|
||||||
self.client = WebClient(configuration)
|
self.client = WebClient(configuration)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -23,6 +23,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.upload.upload import Upload
|
from ahriman.core.upload.upload import Upload
|
||||||
from ahriman.core.util import check_output
|
from ahriman.core.util import check_output
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class Rsync(Upload):
|
class Rsync(Upload):
|
||||||
@ -36,16 +37,16 @@ class Rsync(Upload):
|
|||||||
|
|
||||||
_check_output = check_output
|
_check_output = check_output
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Upload.__init__(self, architecture, configuration)
|
Upload.__init__(self, repository_id, configuration)
|
||||||
self.command = configuration.getlist(section, "command")
|
self.command = configuration.getlist(section, "command")
|
||||||
self.remote = configuration.get(section, "remote")
|
self.remote = configuration.get(section, "remote")
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.upload.upload import Upload
|
from ahriman.core.upload.upload import Upload
|
||||||
from ahriman.core.util import walk
|
from ahriman.core.util import walk
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class S3(Upload):
|
class S3(Upload):
|
||||||
@ -37,21 +38,25 @@ class S3(Upload):
|
|||||||
Attributes
|
Attributes
|
||||||
bucket(Any): boto3 S3 bucket object
|
bucket(Any): boto3 S3 bucket object
|
||||||
chunk_size(int): chunk size for calculating checksums
|
chunk_size(int): chunk size for calculating checksums
|
||||||
|
remote_root(Path): relative path to which packages will be uploaded
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration, section: str) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
section(str): settings section name
|
section(str): settings section name
|
||||||
"""
|
"""
|
||||||
Upload.__init__(self, architecture, configuration)
|
Upload.__init__(self, repository_id, configuration)
|
||||||
self.bucket = self.get_bucket(configuration, section)
|
self.bucket = self.get_bucket(configuration, section)
|
||||||
self.chunk_size = configuration.getint(section, "chunk_size", fallback=8 * 1024 * 1024)
|
self.chunk_size = configuration.getint(section, "chunk_size", fallback=8 * 1024 * 1024)
|
||||||
|
|
||||||
|
paths = configuration.repository_paths
|
||||||
|
self.remote_root = paths.repository.relative_to(paths.root / "repository")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_etag(path: Path, chunk_size: int) -> str:
|
def calculate_etag(path: Path, chunk_size: int) -> str:
|
||||||
"""
|
"""
|
||||||
@ -127,7 +132,7 @@ class S3(Upload):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
local_path = path / local_file
|
local_path = path / local_file
|
||||||
remote_path = Path(self.architecture) / local_file
|
remote_path = self.remote_root / local_file
|
||||||
(mime, _) = mimetypes.guess_type(local_path)
|
(mime, _) = mimetypes.guess_type(local_path)
|
||||||
extra_args = {"ContentType": mime} if mime is not None else None
|
extra_args = {"ContentType": mime} if mime is not None else None
|
||||||
|
|
||||||
@ -155,8 +160,8 @@ class S3(Upload):
|
|||||||
Returns:
|
Returns:
|
||||||
dict[Path, Any]: map of path object to the remote s3 object
|
dict[Path, Any]: map of path object to the remote s3 object
|
||||||
"""
|
"""
|
||||||
objects = self.bucket.objects.filter(Prefix=self.architecture)
|
objects = self.bucket.objects.filter(Prefix=str(self.remote_root))
|
||||||
return {Path(item.key).relative_to(self.architecture): item for item in objects}
|
return {Path(item.key).relative_to(self.remote_root): item for item in objects}
|
||||||
|
|
||||||
def sync(self, path: Path, built_packages: list[Package]) -> None:
|
def sync(self, path: Path, built_packages: list[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.exceptions import SynchronizationError
|
from ahriman.core.exceptions import SynchronizationError
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.upload_settings import UploadSettings
|
from ahriman.models.upload_settings import UploadSettings
|
||||||
|
|
||||||
|
|
||||||
@ -33,18 +34,16 @@ class Upload(LazyLogging):
|
|||||||
base remote sync class
|
base remote sync class
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
||||||
Basic flow includes class instantiating by using the ``load`` method and then calling the ``run`` method which
|
Basic flow includes class instantiating by using the ``load`` method and then calling the ``run`` method which
|
||||||
wraps any internal exceptions into the ``SyncFailed`` exception::
|
wraps any internal exceptions into the ``SyncFailed`` exception::
|
||||||
|
|
||||||
>>> from ahriman.core.configuration import Configuration
|
|
||||||
>>>
|
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> upload = Upload.load("x86_64", configuration, "s3")
|
>>> upload = Upload.load(RepositoryId("x86_64", None), configuration, "s3")
|
||||||
>>> upload.run(configuration.repository_paths.repository, [])
|
>>> upload.run(configuration.repository_paths.repository, [])
|
||||||
|
|
||||||
Or in case if direct access to exception is required, the ``sync`` method can be used::
|
Or in case if direct access to exception is required, the ``sync`` method can be used::
|
||||||
@ -55,46 +54,46 @@ class Upload(LazyLogging):
|
|||||||
>>> handle_exceptions(ex)
|
>>> handle_exceptions(ex)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.architecture = architecture
|
self.repository_id = repository_id
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(architecture: str, configuration: Configuration, target: str) -> Upload:
|
def load(repository_id: RepositoryId, configuration: Configuration, target: str) -> Upload:
|
||||||
"""
|
"""
|
||||||
load client from settings
|
load client from settings
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
target(str): target to run sync (e.g. s3)
|
target(str): target to run sync (e.g. s3)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Upload: client according to current settings
|
Upload: client according to current settings
|
||||||
"""
|
"""
|
||||||
section, provider_name = configuration.gettype(target, architecture)
|
section, provider_name = configuration.gettype(target, repository_id)
|
||||||
match UploadSettings.from_option(provider_name):
|
match UploadSettings.from_option(provider_name):
|
||||||
case UploadSettings.Rsync:
|
case UploadSettings.Rsync:
|
||||||
from ahriman.core.upload.rsync import Rsync
|
from ahriman.core.upload.rsync import Rsync
|
||||||
return Rsync(architecture, configuration, section)
|
return Rsync(repository_id, configuration, section)
|
||||||
case UploadSettings.S3:
|
case UploadSettings.S3:
|
||||||
from ahriman.core.upload.s3 import S3
|
from ahriman.core.upload.s3 import S3
|
||||||
return S3(architecture, configuration, section)
|
return S3(repository_id, configuration, section)
|
||||||
case UploadSettings.GitHub:
|
case UploadSettings.GitHub:
|
||||||
from ahriman.core.upload.github import Github
|
from ahriman.core.upload.github import Github
|
||||||
return Github(architecture, configuration, section)
|
return Github(repository_id, configuration, section)
|
||||||
case UploadSettings.RemoteService:
|
case UploadSettings.RemoteService:
|
||||||
from ahriman.core.upload.remote_service import RemoteService
|
from ahriman.core.upload.remote_service import RemoteService
|
||||||
return RemoteService(architecture, configuration, section)
|
return RemoteService(repository_id, configuration, section)
|
||||||
case _:
|
case _:
|
||||||
return Upload(architecture, configuration) # should never happen
|
return Upload(repository_id, configuration) # should never happen
|
||||||
|
|
||||||
def run(self, path: Path, built_packages: list[Package]) -> None:
|
def run(self, path: Path, built_packages: list[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,7 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.core.upload.upload import Upload
|
from ahriman.core.upload.upload import Upload
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -138,15 +139,15 @@ class UploadTrigger(Trigger):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
default constructor
|
default constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
self.targets = self.configuration_sections(configuration)
|
self.targets = self.configuration_sections(configuration)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -171,5 +172,5 @@ class UploadTrigger(Trigger):
|
|||||||
packages(list[Package]): list of all available packages
|
packages(list[Package]): list of all available packages
|
||||||
"""
|
"""
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
runner = Upload.load(self.architecture, self.configuration, target)
|
runner = Upload.load(self.repository_id, self.configuration, target)
|
||||||
runner.run(self.configuration.repository_paths.repository, result.success)
|
runner.run(self.configuration.repository_paths.repository, result.success)
|
||||||
|
@ -68,9 +68,10 @@ class AURPackage:
|
|||||||
>>>
|
>>>
|
||||||
>>> from ahriman.core.alpm.pacman import Pacman
|
>>> from ahriman.core.alpm.pacman import Pacman
|
||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
|
>>> from ahriman.models.repository_id import RepositoryId
|
||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> pacman = Pacman("x86_64", configuration)
|
>>> pacman = Pacman(RepositoryId("x86_64", None), configuration)
|
||||||
>>> metadata = pacman.package_get("pacman")
|
>>> metadata = pacman.package_get("pacman")
|
||||||
>>> package = AURPackage.from_pacman(next(metadata)) # load package from pyalpm wrapper
|
>>> package = AURPackage.from_pacman(next(metadata)) # load package from pyalpm wrapper
|
||||||
"""
|
"""
|
||||||
|
@ -56,9 +56,10 @@ class PackageDescription:
|
|||||||
>>> from pathlib import Path
|
>>> from pathlib import Path
|
||||||
>>> from ahriman.core.alpm.pacman import Pacman
|
>>> from ahriman.core.alpm.pacman import Pacman
|
||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
|
>>> from ahriman.models.repository_id import RepositoryId
|
||||||
>>>
|
>>>
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> pacman = Pacman("x86_64", configuration)
|
>>> pacman = Pacman(RepositoryId("x86_64", None), configuration)
|
||||||
>>> pyalpm_description = next(package for package in pacman.package_get("pacman"))
|
>>> pyalpm_description = next(package for package in pacman.package_get("pacman"))
|
||||||
>>> description = PackageDescription.from_package(
|
>>> description = PackageDescription.from_package(
|
||||||
>>> pyalpm_description, Path("/var/cache/pacman/pkg/pacman-6.0.1-4-x86_64.pkg.tar.zst"))
|
>>> pyalpm_description, Path("/var/cache/pacman/pkg/pacman-6.0.1-4-x86_64.pkg.tar.zst"))
|
||||||
|
65
src/ahriman/models/repository_id.py
Normal file
65
src/ahriman/models/repository_id.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2023 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 dataclasses import dataclass
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from ahriman.core.exceptions import InitializeError
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class RepositoryId:
|
||||||
|
"""
|
||||||
|
unique identifier of the repository
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
architecture(str): repository architecture
|
||||||
|
name(str): repository name
|
||||||
|
"""
|
||||||
|
|
||||||
|
architecture: str
|
||||||
|
name: str
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
"""
|
||||||
|
check that name is set
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
InitializeError: in case if name is not set
|
||||||
|
"""
|
||||||
|
if not self.name:
|
||||||
|
raise InitializeError("Repository name is not set")
|
||||||
|
|
||||||
|
def __lt__(self, other: Any) -> bool:
|
||||||
|
"""
|
||||||
|
comparison operator for sorting
|
||||||
|
|
||||||
|
Args:
|
||||||
|
other(Any): other object to compare
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True in case if this is less than other and False otherwise
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TypeError: if other is different from RepositoryId type
|
||||||
|
"""
|
||||||
|
if not isinstance(other, RepositoryId):
|
||||||
|
raise ValueError(f"'<' not supported between instances of '{type(self)}' and '{type(other)}'")
|
||||||
|
|
||||||
|
return self.name <= other.name and self.architecture < other.architecture
|
@ -20,10 +20,12 @@
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from collections.abc import Generator
|
||||||
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ahriman.core.exceptions import PathError
|
from ahriman.core.exceptions import PathError
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@ -32,13 +34,13 @@ class RepositoryPaths:
|
|||||||
repository paths holder. For the most operations with paths you want to use this object
|
repository paths holder. For the most operations with paths you want to use this object
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
root(Path): repository root (i.e. ahriman home)
|
root(Path): repository root (i.e. ahriman home)
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
This class can be used in order to access the repository tree structure::
|
This class can be used in order to access the repository tree structure::
|
||||||
|
|
||||||
>>> paths = RepositoryPaths(Path("/var/lib/ahriman"), "x86_64")
|
>>> paths = RepositoryPaths(Path("/var/lib/ahriman"), RepositoryId("x86_64", None))
|
||||||
|
|
||||||
Additional methods can be used in order to ensure that tree is created::
|
Additional methods can be used in order to ensure that tree is created::
|
||||||
|
|
||||||
@ -51,7 +53,19 @@ class RepositoryPaths:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
root: Path
|
root: Path
|
||||||
architecture: str
|
repository_id: RepositoryId
|
||||||
|
_suffix: Path = field(init=False)
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
"""
|
||||||
|
load suffix for different modes (legacy or not
|
||||||
|
"""
|
||||||
|
if self.repository.parent.with_name(self.repository_id.architecture).exists():
|
||||||
|
# there is created legacy tree
|
||||||
|
_suffix = Path(self.repository_id.architecture)
|
||||||
|
else:
|
||||||
|
_suffix = Path(self.repository_id.name) / self.repository_id.architecture
|
||||||
|
object.__setattr__(self, "_suffix", _suffix)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cache(self) -> Path:
|
def cache(self) -> Path:
|
||||||
@ -72,7 +86,7 @@ class RepositoryPaths:
|
|||||||
Path: full patch to devtools chroot directory
|
Path: full patch to devtools chroot directory
|
||||||
"""
|
"""
|
||||||
# for the chroot directory devtools will create own tree, and we don"t have to specify architecture here
|
# for the chroot directory devtools will create own tree, and we don"t have to specify architecture here
|
||||||
return self.root / "chroot"
|
return self.root / "chroot" / self.repository_id.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def packages(self) -> Path:
|
def packages(self) -> Path:
|
||||||
@ -82,7 +96,7 @@ class RepositoryPaths:
|
|||||||
Returns:
|
Returns:
|
||||||
Path: full path to built packages directory
|
Path: full path to built packages directory
|
||||||
"""
|
"""
|
||||||
return self.root / "packages" / self.architecture
|
return self.root / "packages" / self._suffix
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pacman(self) -> Path:
|
def pacman(self) -> Path:
|
||||||
@ -92,7 +106,7 @@ class RepositoryPaths:
|
|||||||
Returns:
|
Returns:
|
||||||
Path: full path to pacman local database cache
|
Path: full path to pacman local database cache
|
||||||
"""
|
"""
|
||||||
return self.root / "pacman" / self.architecture
|
return self.root / "pacman" / self._suffix
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def repository(self) -> Path:
|
def repository(self) -> Path:
|
||||||
@ -102,7 +116,7 @@ class RepositoryPaths:
|
|||||||
Returns:
|
Returns:
|
||||||
Path: full path to the repository directory
|
Path: full path to the repository directory
|
||||||
"""
|
"""
|
||||||
return self.root / "repository" / self.architecture
|
return self.root / "repository" / self._suffix
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root_owner(self) -> tuple[int, int]:
|
def root_owner(self) -> tuple[int, int]:
|
||||||
@ -115,22 +129,28 @@ class RepositoryPaths:
|
|||||||
return self.owner(self.root)
|
return self.owner(self.root)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def known_architectures(cls, root: Path) -> set[str]:
|
def known_architectures(cls, root: Path, name: str) -> set[RepositoryId]:
|
||||||
"""
|
"""
|
||||||
get known architectures
|
get known architectures
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
root(Path): repository root
|
root(Path): repository root
|
||||||
|
name(str): repository name from configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
set[str]: list of architectures for which tree is created
|
set[RepositoryId]: list of tuple of repository name and architectures for which tree is created
|
||||||
"""
|
"""
|
||||||
paths = cls(root, "")
|
def walk(repository_path: Path, repository_name: str) -> Generator[RepositoryId, None, None]:
|
||||||
return {
|
for architecture in filter(lambda path: path.is_dir(), repository_path.iterdir()):
|
||||||
path.name
|
yield RepositoryId(architecture.name, repository_name)
|
||||||
for path in paths.repository.iterdir()
|
|
||||||
if path.is_dir()
|
def walk_with_name(paths: RepositoryPaths) -> Generator[RepositoryId, None, None]:
|
||||||
}
|
for repository in filter(lambda path: path.is_dir(), paths.repository.iterdir()):
|
||||||
|
yield from walk(repository, repository.name)
|
||||||
|
|
||||||
|
instance = cls(root, RepositoryId("", ""))
|
||||||
|
# try to get list per repository first and then fallback to old schema if nothing found
|
||||||
|
return set(walk_with_name(instance)) or set(walk(instance.repository, name))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def owner(path: Path) -> tuple[int, int]:
|
def owner(path: Path) -> tuple[int, int]:
|
||||||
|
@ -65,9 +65,9 @@ class StatusView(BaseView):
|
|||||||
counters = Counters.from_packages(self.service.packages)
|
counters = Counters.from_packages(self.service.packages)
|
||||||
status = InternalStatus(
|
status = InternalStatus(
|
||||||
status=self.service.status,
|
status=self.service.status,
|
||||||
architecture=self.service.architecture,
|
architecture=self.service.repository_id.architecture,
|
||||||
packages=counters,
|
packages=counters,
|
||||||
repository=self.service.repository.name,
|
repository=self.service.repository_id.name,
|
||||||
version=__version__,
|
version=__version__,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ from ahriman.core.exceptions import InitializeError
|
|||||||
from ahriman.core.log.filtered_access_logger import FilteredAccessLogger
|
from ahriman.core.log.filtered_access_logger import FilteredAccessLogger
|
||||||
from ahriman.core.spawn import Spawn
|
from ahriman.core.spawn import Spawn
|
||||||
from ahriman.core.status.watcher import Watcher
|
from ahriman.core.status.watcher import Watcher
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.web.apispec import setup_apispec
|
from ahriman.web.apispec import setup_apispec
|
||||||
from ahriman.web.cors import setup_cors
|
from ahriman.web.cors import setup_cors
|
||||||
from ahriman.web.middlewares.exception_handler import exception_handler
|
from ahriman.web.middlewares.exception_handler import exception_handler
|
||||||
@ -120,12 +121,12 @@ def run_server(application: Application) -> None:
|
|||||||
access_log=logging.getLogger("http"), access_log_class=FilteredAccessLogger)
|
access_log=logging.getLogger("http"), access_log_class=FilteredAccessLogger)
|
||||||
|
|
||||||
|
|
||||||
def setup_service(architecture: str, configuration: Configuration, spawner: Spawn) -> Application:
|
def setup_service(repository_id: RepositoryId, configuration: Configuration, spawner: Spawn) -> Application:
|
||||||
"""
|
"""
|
||||||
create web application
|
create web application
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
architecture(str): repository architecture
|
repository_id(RepositoryId): repository unique identifier
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
spawner(Spawn): spawner thread
|
spawner(Spawn): spawner thread
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ def setup_service(architecture: str, configuration: Configuration, spawner: Spaw
|
|||||||
database = application["database"] = SQLite.load(configuration)
|
database = application["database"] = SQLite.load(configuration)
|
||||||
|
|
||||||
application.logger.info("setup watcher")
|
application.logger.info("setup watcher")
|
||||||
application["watcher"] = Watcher(architecture, configuration, database)
|
application["watcher"] = Watcher(repository_id, configuration, database)
|
||||||
|
|
||||||
application.logger.info("setup process spawner")
|
application.logger.info("setup process spawner")
|
||||||
application["spawn"] = spawner
|
application["spawn"] = spawner
|
||||||
|
Loading…
Reference in New Issue
Block a user