Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 53 additions & 28 deletions flatpaker/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from __future__ import annotations
import argparse
import contextlib
import importlib
import importlib.resources
import pathlib
Expand Down Expand Up @@ -30,6 +31,8 @@ class BaseArguments(typing.Protocol):
export: bool
cleanup: bool
deltas: bool
verbose: bool
keep_going: bool

class BuildArguments(BaseArguments, typing.Protocol):
descriptions: typing.List[str]
Expand All @@ -45,6 +48,9 @@ def build(args: BaseArguments, description: Description) -> None:
# TODO: This could be common
appid = f"{description['common']['reverse_url']}.{flatpaker.util.sanitize_name(description['common']['name'])}"

if not args.verbose:
print('Building', appid, end=' ', flush=True)

write_build_rules = select_impl(description['common']['engine'])

with flatpaker.util.tmpdir(description['common']['name'], args.cleanup) as d:
Expand All @@ -55,14 +61,14 @@ def build(args: BaseArguments, description: Description) -> None:
flatpaker.util.build_flatpak(args, wd, appid)


def static_deltas(args: BaseArguments) -> None:
def static_deltas(args: BaseArguments, out: None | typing.BinaryIO, err: None | typing.BinaryIO) -> None:
if not (args.deltas or args.export):
return
command = ['flatpak', 'build-update-repo', args.repo, '--generate-static-deltas']
if args.gpg:
command.extend(['--gpg-sign', args.gpg])

subprocess.run(command, check=True)
subprocess.run(command, check=True, stdout=out, stderr=err)


def main() -> None:
Expand All @@ -82,6 +88,8 @@ def main() -> None:
parser.add_argument('--install', action='store_true', help="Install for the user (useful for testing)")
parser.add_argument('--no-cleanup', action='store_false', dest='cleanup', help="don't delete the temporary directory")
parser.add_argument('--static-deltas', action='store_true', dest='deltas', help="generate static deltas when exporting")
parser.add_argument('--verbose', action='store_true', help="Print more information to the terminal")
parser.add_argument('--keep-going', action='store_true', help="If one flatpak fails to build, continue to the next.")

subparsers = parser.add_subparsers()
build_parser = subparsers.add_parser('build', help='Build flatpaks from descriptions')
Expand All @@ -93,36 +101,53 @@ def main() -> None:

args = typing.cast('BaseArguments', parser.parse_args())

flatpaker.util.LOGDIR.mkdir(parents=True, exist_ok=True)

if args.action == 'build':
descriptions = typing.cast('BuildArguments', args).descriptions
for d in descriptions:
description = load_description(d)
build(args, description)
if args.deltas:
static_deltas(args)
if not args.verbose:
print('Generating static deltas', flush=True)
with contextlib.ExitStack() as manager:
o = None if args.verbose else manager.enter_context((flatpaker.util.LOGDIR / 'static-deltas.stdout').open('wb'))
e = None if args.verbose else manager.enter_context((flatpaker.util.LOGDIR / 'static-deltas.stderr').open('wb'))
static_deltas(args, o, e)
if args.action == 'install-deps':
command = [
'flatpak', 'install', '--no-auto-pin', '--user',
f'org.freedesktop.Platform//{flatpaker.util.RUNTIME_VERSION}',
f'org.freedesktop.Sdk//{flatpaker.util.RUNTIME_VERSION}',
]
subprocess.run(command, check=True)

sdk_file = importlib.resources.files('flatpaker') / 'data' / 'com.github.dcbaker.flatpaker.Sdk.yml'
platform_file = importlib.resources.files('flatpaker') / 'data' / 'com.github.dcbaker.flatpaker.Platform.yml'
for bfile in [sdk_file, platform_file]:
with importlib.resources.as_file(bfile) as sdk:
build_command: typing.List[str] = [
'flatpak-builder', '--force-clean', '--user', 'build', sdk.as_posix()]

if args.export:
build_command.extend(['--repo', args.repo])
if args.gpg:
build_command.extend(['--gpg-sign', args.gpg])
if args.install:
build_command.extend(['--install'])

subprocess.run(build_command, check=True)

if args.deltas:
static_deltas(args)
with contextlib.ExitStack() as manager:
o = None if args.verbose else manager.enter_context((flatpaker.util.LOGDIR / 'runtime.stdout').open('wb'))
e = None if args.verbose else manager.enter_context((flatpaker.util.LOGDIR / 'runtime.stderr').open('wb'))
command = [
'flatpak', 'install', '--no-auto-pin', '--user',
f'org.freedesktop.Platform//{flatpaker.util.RUNTIME_VERSION}',
f'org.freedesktop.Sdk//{flatpaker.util.RUNTIME_VERSION}',
]
subprocess.run(command, check=True, stdout=o, stderr=e)

sdk_file = importlib.resources.files('flatpaker') / 'data' / 'com.github.dcbaker.flatpaker.Sdk.yml'
platform_file = importlib.resources.files('flatpaker') / 'data' / 'com.github.dcbaker.flatpaker.Platform.yml'
for bfile in [sdk_file, platform_file]:
with importlib.resources.as_file(bfile) as sdk:
if not args.verbose:
print('Building:', sdk.name, end=' ', flush=True)

build_command: typing.List[str] = [
'flatpak-builder', '--force-clean', '--user', 'build', sdk.as_posix()]

if args.export:
build_command.extend(['--repo', args.repo])
if args.gpg:
build_command.extend(['--gpg-sign', args.gpg])
if args.install:
build_command.extend(['--install'])

p = subprocess.run(build_command, stdout=o, stderr=e)
if not args.verbose:
print('Success' if p.returncode == 0 else 'Fail', flush=True)
if p.returncode != 0 and not args.keep_going:
p.check_returncode()

if args.deltas:
static_deltas(args, o, e)
14 changes: 11 additions & 3 deletions flatpaker/util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: MIT
# Copyright © 2022-2024 Dylan Baker
# Copyright © 2022-2025 Dylan Baker

from __future__ import annotations
from xml.etree import ElementTree as ET
Expand All @@ -18,7 +18,7 @@
from .entry import BaseArguments

RUNTIME_VERSION = "24.08"

LOGDIR = pathlib.Path('.flatpaker') / 'logs'

def _subelem(elem: ET.Element, tag: str, text: typing.Optional[str] = None, **extra: str) -> ET.Element:
new = ET.SubElement(elem, tag, extra)
Expand Down Expand Up @@ -150,7 +150,15 @@ def build_flatpak(args: BaseArguments, workdir: pathlib.Path, appid: str) -> Non
if args.install:
build_command.extend(['--install'])

subprocess.run(build_command, check=True)
with contextlib.ExitStack() as manager:
o = None if args.verbose else manager.enter_context((LOGDIR / f'{appid}.stdout').open('wb'))
e = None if args.verbose else manager.enter_context((LOGDIR / f'{appid}.stderr').open('wb'))
p = subprocess.run(build_command, stdout=o, stderr=e)
if not args.verbose:
print('Success' if p.returncode == 0 else 'Fail', flush=True)
if p.returncode != 0 and not args.keep_going:
p.check_returncode()

if args.cleanup:
shutil.rmtree('build', ignore_errors=True)

Expand Down