depl 2.4.3

Toolkit for a bunch of local and remote CI/CD actions
Documentation
//! `UseFromStorage` action module.

use serde::{Deserialize, Serialize};
use std::path::PathBuf;

use crate::entities::environment::RunEnvironment;
use crate::entities::info::{ContentInfo, info2str, str2info_wl};
use crate::storage::use_from_storage;

/// Use from storage action.
#[derive(Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct UseFromStorageAction {
  /// Content's short name and version (allowed to be `latest`).
  #[serde(serialize_with = "info2str", deserialize_with = "str2info_wl")]
  pub content_info: ContentInfo,

  /// Subfolder to sync.
  #[serde(skip_serializing_if = "Option::is_none")]
  pub subfolder: Option<PathBuf>,
}

impl UseFromStorageAction {
  /// Uses content from storage to given run environment.
  pub async fn execute(&self, env: &RunEnvironment<'_>) -> anyhow::Result<(bool, Vec<String>)> {
    Ok(if let Some(subpath) = &self.subfolder {
      match use_from_storage(env.storage_dir, &env.run_dir.join(subpath), &self.content_info) {
        Ok(_) => (true, vec![]),
        Err(e) => (false, vec![e.to_string()]),
      }
    } else {
      match use_from_storage(env.storage_dir, env.run_dir, &self.content_info) {
        Ok(_) => (true, vec![]),
        Err(e) => (false, vec![e.to_string()]),
      }
    })
  }

  /// Converts this action to shell script.
  pub async fn to_shell(&self, _: &RunEnvironment<'_>) -> anyhow::Result<Vec<String>> {
    let content_info_str = self.content_info.to_str();

    let target_dir = if let Some(subpath) = &self.subfolder {
      format!("./{}", subpath.display())
    } else {
      ".".to_string()
    };

    let mut commands = vec![];

    if content_info_str.ends_with("latest") {
      let short_name = self.content_info.short_name();
      commands.push(format!(
        r#"LATEST_VERSION=$(find ~/.local/share/deployer -maxdepth 1 -type d -name "{short_name}@*" | sed 's/.*@//' | sort -V | tail -1)"#,
      ));
      commands.push(format!(
        r#"if [ -z "$LATEST_VERSION" ]; then echo "Error: No versions found for {short_name}"; exit 1; fi"#
      ));
      commands.push(format!(
        r#"CONTENT_PATH=~/.local/share/deployer/{short_name}@"$LATEST_VERSION""#
      ));
      commands.push(format!(
        r#"echo "Decided to choose {short_name}@$LATEST_VERSION from latest""#
      ));
    } else {
      commands.push(format!(r#"CONTENT_PATH=~/.local/share/deployer/{content_info_str}""#));
    }

    commands.push(
      r#"if [ ! -d "$CONTENT_PATH" ]; then echo "Error: Content not found at $CONTENT_PATH"; exit 1; fi"#.to_string(),
    );

    if target_dir != "." {
      commands.push(format!(r#"mkdir -p "{target_dir}""#));
    }
    commands.push(format!(r#"cp -r "$CONTENT_PATH"/. "{target_dir}""#));

    Ok(commands)
  }
}