Fix uninstalling on latest steam deck with offload (#502)

This commit is contained in:
Ana Hobden 2023-06-02 07:34:31 -07:00 committed by GitHub
parent 1d51b25bf7
commit 99941446df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 21 deletions

View file

@ -54,9 +54,7 @@ impl Action for SetupDefaultProfile {
// Find an `nix` package
let nix_pkg_glob = format!("{}/nix-*/store/*-nix-*.*.*", self.unpacked_path.display());
let mut found_nix_pkg = None;
for entry in glob(&nix_pkg_glob)
.map_err(|e| Self::error(SetupDefaultProfileError::GlobPatternError(e)))?
{
for entry in glob(&nix_pkg_glob).map_err(|e| Self::error(e))? {
match entry {
Ok(path) => {
// If we are curing, the user may have multiple of these installed
@ -85,9 +83,7 @@ impl Action for SetupDefaultProfile {
self.unpacked_path.display()
);
let mut found_nss_ca_cert_pkg = None;
for entry in glob(&nss_ca_cert_pkg_glob)
.map_err(|e| Self::error(SetupDefaultProfileError::GlobPatternError(e)))?
{
for entry in glob(&nss_ca_cert_pkg_glob).map_err(|e| Self::error(e))? {
match entry {
Ok(path) => {
// If we are curing, the user may have multiple of these installed
@ -113,9 +109,9 @@ impl Action for SetupDefaultProfile {
};
let found_nix_paths = glob::glob(&format!("{}/nix-*", self.unpacked_path.display()))
.map_err(|e| Self::error(SetupDefaultProfileError::from(e)))?
.map_err(|e| Self::error(e))?
.collect::<Result<Vec<_>, _>>()
.map_err(|e| Self::error(SetupDefaultProfileError::from(e)))?;
.map_err(|e| Self::error(e))?;
if found_nix_paths.len() != 1 {
return Err(Self::error(ActionErrorKind::MalformedBinaryTarball));
}
@ -240,18 +236,6 @@ impl Action for SetupDefaultProfile {
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum SetupDefaultProfileError {
#[error("Glob pattern error")]
GlobPatternError(
#[from]
#[source]
glob::PatternError,
),
#[error("Glob globbing error")]
GlobGlobError(
#[from]
#[source]
glob::GlobError,
),
#[error("Unarchived Nix store did not appear to include a `nss-cacert` location")]
NoNssCacert,
#[error("Unarchived Nix store did not appear to include a `nix` location")]

View file

@ -1,9 +1,11 @@
pub(crate) mod ensure_steamos_nix_directory;
pub(crate) mod provision_selinux;
pub(crate) mod revert_clean_steamos_nix_offload;
pub(crate) mod start_systemd_unit;
pub(crate) mod systemctl_daemon_reload;
pub use ensure_steamos_nix_directory::EnsureSteamosNixDirectory;
pub use provision_selinux::ProvisionSelinux;
pub use revert_clean_steamos_nix_offload::RevertCleanSteamosNixOffload;
pub use start_systemd_unit::{StartSystemdUnit, StartSystemdUnitError};
pub use systemctl_daemon_reload::SystemctlDaemonReload;

View file

@ -0,0 +1,79 @@
use std::path::Path;
use tracing::{span, Span};
use crate::action::{ActionError, ActionErrorKind, ActionTag};
use crate::action::{Action, ActionDescription, StatefulAction};
const OFFLOAD_PATH: &'static str = "/home/.steamos/offload/nix";
/**
Clean out the `/home/.steamos/offload/nix`
In SteamOS build ID 20230522.1000 (and, presumably, later) a `/home/.steamos/offload/nix` directory
exists by default and needs to be cleaned out on uninstall, otherwise uninstall won't work.
*/
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct RevertCleanSteamosNixOffload;
impl RevertCleanSteamosNixOffload {
#[tracing::instrument(level = "debug", skip_all)]
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
if Path::new(OFFLOAD_PATH).exists() {
Ok(StatefulAction::uncompleted(RevertCleanSteamosNixOffload))
} else {
Ok(StatefulAction::completed(RevertCleanSteamosNixOffload))
}
}
}
#[async_trait::async_trait]
#[typetag::serde(name = "revert_clean_steamos_nix_offload")]
impl Action for RevertCleanSteamosNixOffload {
fn action_tag() -> ActionTag {
ActionTag("revert_clean_steamos_nix_offload")
}
fn tracing_synopsis(&self) -> String {
format!("Clean the `{OFFLOAD_PATH}` directory")
}
fn tracing_span(&self) -> Span {
span!(tracing::Level::DEBUG, "revert_clean_steamos_nix_offload",)
}
fn execute_description(&self) -> Vec<ActionDescription> {
vec![]
}
#[tracing::instrument(level = "debug", skip_all)]
async fn execute(&mut self) -> Result<(), ActionError> {
// noop
Ok(())
}
fn revert_description(&self) -> Vec<ActionDescription> {
vec![ActionDescription::new(
self.tracing_synopsis(),
vec![
format!("On more recent versions of SteamOS, the `{OFFLOAD_PATH}` folder contains the Nix store, and needs to be cleaned on uninstall."),
],
)]
}
#[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> {
let paths = glob::glob(OFFLOAD_PATH).map_err(Self::error)?;
for path in paths {
let path = path.map_err(Self::error)?;
tracing::trace!(path = %path.display(), "Removing");
tokio::fs::remove_dir_all(&path)
.await
.map_err(|e| Self::error(ActionErrorKind::Remove(path.into(), e)))?;
}
Ok(())
}
}

View file

@ -473,6 +473,18 @@ pub enum ActionErrorKind {
NoGroup(String),
#[error("Chowning path `{0}`")]
Chown(std::path::PathBuf, #[source] nix::errno::Errno),
#[error("Glob globbing error")]
GlobGlobError(
#[from]
#[source]
glob::GlobError,
),
#[error("Glob pattern error")]
GlobPatternError(
#[from]
#[source]
glob::PatternError,
),
/// Failed to execute command
#[error("Failed to execute command `{command}`",
command = .command,

View file

@ -104,7 +104,10 @@ use crate::{
action::{
base::{CreateDirectory, CreateFile, RemoveDirectory},
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
linux::{EnsureSteamosNixDirectory, StartSystemdUnit, SystemctlDaemonReload},
linux::{
EnsureSteamosNixDirectory, RevertCleanSteamosNixOffload, StartSystemdUnit,
SystemctlDaemonReload,
},
Action, StatefulAction,
},
planner::{Planner, PlannerError},
@ -248,10 +251,16 @@ impl Planner for SteamDeck {
.map_err(PlannerError::Action)?;
actions.push(create_bind_mount_unit.boxed());
} else {
let revert_clean_streamos_nix_offload = RevertCleanSteamosNixOffload::plan()
.await
.map_err(PlannerError::Action)?;
actions.push(revert_clean_streamos_nix_offload.boxed());
let ensure_steamos_nix_directory = EnsureSteamosNixDirectory::plan()
.await
.map_err(PlannerError::Action)?;
actions.push(ensure_steamos_nix_directory.boxed());
let start_nix_mount = StartSystemdUnit::plan("nix.mount".to_string(), true)
.await
.map_err(PlannerError::Action)?;