Skip to content
Merged
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
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
android-gradle-plugin = "9.3.1"
androidx-activity = "1.13.0"
androidx-camera = "1.6.1"
androidx-compose-bom = "2026.06.01"
androidx-compose-material3 = "1.5.0-alpha25"
androidx-compose-bom = "2026.08.00"
androidx-compose-material3 = "1.5.0-alpha26"
androidx-core = "1.19.0"
androidx-lifecycle-viewmodel-compose = "2.11.0"
androidx-preference = "1.2.1"
Expand Down
91 changes: 67 additions & 24 deletions gradle/update_verification.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env python3

# SPDX-FileCopyrightText: 2023-2024 Andrew Gunnerson
# SPDX-FileCopyrightText: 2023-2026 Andrew Gunnerson
# SPDX-License-Identifier: GPL-3.0-only

from collections.abc import Callable, Iterable
import dataclasses
import hashlib
import io
import os
Expand All @@ -12,12 +14,14 @@
import urllib.request
import xml.etree.ElementTree as ET


GOOGLE_MAVEN_REPO = 'https://dl.google.com/android/maven2'


def add_source_exclusions(ns, root):
def add_source_exclusions(ns: str, root: ET.Element):
configuration = root.find(f'{{{ns}}}configuration')
if configuration is None:
raise ValueError('<configuration> tag not found')

trusted_artifacts = ET.SubElement(
configuration, f'{{{ns}}}trusted-artifacts')

Expand All @@ -32,40 +36,79 @@ def add_source_exclusions(ns, root):
})


def add_missing_aapt2_platforms(ns, root):
components = root.find(f'{{{ns}}}components')
aapt2 = components.find(f'{{{ns}}}component[@name="aapt2"]')
@dataclasses.dataclass
class ArtifactInfo:
group: str
name: str
version: str

for platform in ['linux', 'osx', 'windows']:
group = aapt2.attrib['group']
name = aapt2.attrib['name']
version = aapt2.attrib['version']
filename = f'{name}-{version}-{platform}.jar'

if aapt2.find(f'{{{ns}}}artifact[@name="{filename}"]') is not None:
continue
@dataclasses.dataclass
class ArtifactAssets:
repo: str
files: list[str]


path = f'{group.replace(".", "/")}/{name}/{version}/{filename}'
url = f'{GOOGLE_MAVEN_REPO}/{path}'
def add_missing_components(
ns: str,
root: ET.Element,
name: str,
assets_for: Callable[[ArtifactInfo], ArtifactAssets],
):
components = root.find(f'{{{ns}}}components')
if components is None:
raise ValueError('<components> tag not found')

component = components.find(f'{{{ns}}}component[@name="{name}"]')
if component is None:
raise ValueError(f'<component name="{name}"> tag not found')

info = ArtifactInfo(
group=component.attrib['group'],
name=component.attrib['name'],
version=component.attrib['version'],
)
assets = assets_for(info)

for filename in assets.files:
if component.find(f'{{{ns}}}artifact[@name="{filename}"]') is not None:
continue

with urllib.request.urlopen(url) as r:
if r.status != 200:
raise Exception(f'{url} returned HTTP {r.status}')
path = f'{info.group.replace(".", "/")}/{name}/{info.version}/{filename}'
url = f'{assets.repo}/{path}'

digest = hashlib.file_digest(r, 'sha512')
try:
with urllib.request.urlopen(url) as r:
digest = hashlib.file_digest(r, 'sha512')
except urllib.request.HTTPError as e:
raise Exception(f'Failed to download: {e.url}') from e

artifact = ET.SubElement(aapt2, f'{{{ns}}}artifact',
artifact = ET.SubElement(component, f'{{{ns}}}artifact',
attrib={'name': filename})

ET.SubElement(artifact, f'{{{ns}}}sha512', attrib={
'value': digest.hexdigest(),
'origin': 'Generated by Gradle',
})

aapt2[:] = sorted(aapt2, key=lambda child: child.attrib['name'])
component[:] = sorted(component, key=lambda child: child.attrib['name'])


def add_missing_aapt2_platforms(ns: str, root: ET.Element):
platforms = ['linux', 'osx', 'windows']

add_missing_components(
ns,
root,
'aapt2',
lambda info: ArtifactAssets(
repo=GOOGLE_MAVEN_REPO,
files=[f'{info.name}-{info.version}-{p}.jar' for p in platforms],
),
)


def patch_xml(path):
def patch_xml(path: str | os.PathLike[str]):
tree = ET.parse(path)
root = tree.getroot()

Expand All @@ -75,8 +118,8 @@ def patch_xml(path):
# Add exclusions to allow Android Studio to download sources.
add_source_exclusions(ns, root)

# Gradle only adds the aapt2 entry for the host OS. We have to manually add
# the checksums for the other major desktop OSs.
# Gradle only adds entries for the host OS. We have to manually add the
# checksums for the other major desktop OSs.
add_missing_aapt2_platforms(ns, root)

# Match gradle's formatting exactly.
Expand Down
Loading