-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
installer: minimize side effects on activation (#132)
Refactor activation logic to evaluate the system's flatpak configuration and determine whether `flatpak install` commands are required. Avoids unnecessary reinstallation and network calls during activation, improving support for "offline" environments. Introduces a new state module to manage activation-related state. Adds helpers to process `flatpak-state.json` with Nix expressions. Note: For packages pinned to a specific `commit` hash, a remote query is still required to verify the reference, resulting in a network call.
- Loading branch information
Showing
5 changed files
with
207 additions
and
8 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# Helper functions for managing nix-flatpak state. | ||
# Historically, nix-flatpak relied on `jq` to read, parse, and process | ||
# state files. Over time, the codebase is being refactored to | ||
# favor using Nix expressions instead. | ||
{ pkgs, ... }: | ||
let | ||
|
||
# Reads and parses a JSON state file. | ||
# Takes a file path, and converts it from JSON format | ||
# to a Nix-compatible data structure using built-in functions. | ||
# | ||
# Parameters: | ||
# stateFile: file path | ||
# | ||
# Returns | ||
# attrset: nix representation of the nix-flatpak state | ||
# | ||
readState = stateFile: | ||
builtins.fromJSON (builtins.readFile (builtins.toString stateFile)); | ||
|
||
|
||
# TODO: Checks if a Flatpak app's current commit matches an expected commit hash | ||
# | ||
# Parameters: | ||
# installation: type of Flatpak installation (user, system) | ||
# appId: flatpak application id (e.g., org.mozilla.firefox) | ||
# commit: expected commit hash to check against, or null to skip check | ||
# | ||
# Returns: | ||
# boolean: True if either: | ||
# - commit parameter is null (skip check) | ||
# - current installed commit matches expected commit | ||
# False otherwise | ||
# | ||
checkCommitMatch = installation: appId: commit: | ||
# we don't store commit into in flatpak-state.json, | ||
# and checks during Nix evaluation is tricky. | ||
# If a `commit` is provided, assume it does not match | ||
# the currently installed one, and force an update. In practice, | ||
# the application won't be re-donwloaded, but its ref will be looked up | ||
# in the remote. | ||
# FIXME: https://github.com/gmodena/nix-flatpak/issues/85 | ||
commit == null || false; | ||
|
||
# Determines if flatpak install command should be executed based on system state | ||
# | ||
# Parameters: | ||
# installation: Path to Flatpak installation | ||
# update: Boolean flag to force update | ||
# appId: Flatpak application ID | ||
# commit: Expected commit hash or null | ||
# | ||
# Returns: | ||
# boolean: True if any of: | ||
# - update flag is true | ||
# - app is not installed | ||
# - commit is specified and doesn't match current | ||
# | ||
shouldExecFlatpakInstall = stateData: installation: update: appId: commit: | ||
let | ||
# Currently (2024-12) we don't store the commit hash pin in nix-flatpak state. | ||
isInstalled = builtins.elem appId stateData."packages"; | ||
|
||
# Verify commit hash matches if app is installed and a commit is pinned. | ||
commitMatches = | ||
if isInstalled | ||
then checkCommitMatch installation appId commit | ||
else false; | ||
|
||
# Run `flatpak install` if: | ||
# - update flag is true OR | ||
# - app is not installed OR | ||
# - commit is specified and doesn't match current | ||
shouldInstall = update || !isInstalled || (commit != null && !commitMatches); | ||
in | ||
shouldInstall; | ||
|
||
in | ||
{ | ||
inherit readState shouldExecFlatpakInstall; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"overrides": {}, | ||
"packages": [ | ||
"im.riot.Riot" | ||
], | ||
"remotes": [ | ||
"flathub" | ||
] | ||
} | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{ pkgs ? import <nixpkgs> { } }: | ||
|
||
let | ||
inherit (pkgs) lib; | ||
inherit (lib) runTests; | ||
state = import ../modules/state.nix { inherit pkgs; }; | ||
|
||
appId = "im.riot.Riot"; | ||
|
||
pwd = builtins.getEnv "PWD"; | ||
stateData = state.readState ("${pwd}/fixtures/flatpak-state.json"); | ||
|
||
in | ||
runTests { | ||
testShoulNotExectFlatpakInstall = { | ||
# Base case: state matches runtime. We don't need to `flatpak install` apps. | ||
# installation = "user"; | ||
# update = false; | ||
# commit = null; | ||
|
||
expr = state.shouldExecFlatpakInstall stateData "user" false appId null; | ||
expected = false; | ||
}; | ||
|
||
testShoulExectFlatpakInstallWhenUpdate = { | ||
# Apps need to be updated on activation. | ||
# installation = "user"; | ||
# update = true; | ||
# commit = null; | ||
|
||
expr = state.shouldExecFlatpakInstall stateData "user" true appId null; | ||
expected = true; | ||
}; | ||
|
||
testShoulExectFlatpakInstallWhenCommit = { | ||
# Apps need to be pinned at `commit`. Currently, this requires an | ||
# update on activation. | ||
# installation = "user"; | ||
# update = false; | ||
# commit = "1234"; | ||
|
||
expr = state.shouldExecFlatpakInstall stateData "user" false appId "1234"; | ||
expected = true; | ||
}; | ||
|
||
testShoulExectFlatpakInstallOnNewApp = { | ||
# state has mutate: a new app as been added, and must be installed on activation. | ||
# update on activation. | ||
# appId = "io.github.gmodena.NewApp" | ||
# installation = "user"; | ||
# update = false; | ||
# commit = null; | ||
|
||
expr = state.shouldExecFlatpakInstall stateData "user" false "io.github.gmodena.NewApp" null; | ||
expected = true; | ||
}; | ||
} |