Last active
October 19, 2024 04:13
-
-
Save lostfictions/2341c97428055bad271db22b02fde71a to your computer and use it in GitHub Desktop.
show current and new version for flatpak apps with updates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import asyncio | |
# boilerplate for asyncio | |
async def run(cmd: str) -> str: | |
proc = await asyncio.create_subprocess_shell( | |
cmd, | |
stdout=asyncio.subprocess.PIPE, | |
stderr=asyncio.subprocess.PIPE, | |
) | |
stdout, stderr = await proc.communicate() | |
if proc.returncode != 0: | |
raise RuntimeError(f"Command failed: {cmd}\n{stderr.decode()}") | |
return stdout.decode() | |
async def get_updates() -> list[tuple[str, str, str]]: | |
# `flatpak remote-ls --updates` can include a `version` column, but the | |
# version it shows is actually the installed version instead of the new one! | |
# what's more, requesting the version column is far slower than fetching only | |
# the updated app ids and using `flatpak list` later to get the local versions. | |
masked_apps, updatable_apps = await asyncio.gather( | |
run("flatpak mask"), | |
run("flatpak remote-ls --updates --app --columns=application"), | |
) | |
masked = {line.strip() for line in masked_apps.splitlines()} | |
updates = {row for row in updatable_apps.splitlines() if not row in masked} | |
if not updates: | |
return [] | |
# if there are unmasked updates, check the actual remote versions via another | |
# invocation of `flatpak remote-ls` (without `--update`) | |
*remote_apps, local_apps = await asyncio.gather( | |
# HACK: the wrong versions are reported as of flatpak 1.14.10. see | |
# https://github.com/flatpak/flatpak/issues/5974 for details. we can | |
# request version details one-by-one directly from flathub api instead. | |
*[ | |
run( | |
f"curl -s https://flathub.org/api/v2/appstream/{u} | jq -r '.releases[0].version' | sed 's/^/{u}\t/'" | |
) | |
for u in updates | |
], | |
# run("flatpak remote-ls --app --columns=application,version"), | |
run("flatpak list --app --columns=application,version"), | |
) | |
current_versions = dict(row.split("\t") for row in local_apps.splitlines()) | |
# not all remote apps include a version column, so we can't unpack immediately | |
return [ | |
(id_and_ver[0], current_versions[id_and_ver[0]], id_and_ver[1]) | |
for row in remote_apps | |
if (id_and_ver := row.split("\t"))[0] in updates | |
] | |
async def main() -> None: | |
print("Looking up Flatpak app version update info...\n") | |
updates = await get_updates() | |
if updates: | |
id_pad = 12 | |
version_pad = 12 | |
for id, old, new in updates: | |
id_pad = max(id_pad, len(id)) | |
version_pad = max(version_pad, len(old), len(new)) | |
print( | |
f"{'Application ID':<{id_pad}} {'Old Version':<{version_pad}} {'New Version':<{version_pad}}" | |
) | |
for id, old, new in updates: | |
print(f"{id:<{id_pad}} {old:<{version_pad}} {new:<{version_pad}}") | |
if __name__ == "__main__": | |
asyncio.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment