Skip to main content

zoi_cli/cmd/
transaction.rs

1//! Logic for the `transaction` command.
2
3use anyhow::Result;
4use colored::Colorize;
5use comfy_table::presets::UTF8_FULL;
6use comfy_table::{ContentArrangement, Table};
7
8use crate::pkg::{local, transaction, types};
9
10/// Returns the source of the installed manifest.
11fn manifest_source(manifest: &types::InstallManifest) -> String {
12    local::installed_manifest_source(manifest)
13}
14
15/// List all transaction logs.
16///
17/// # Errors
18///
19/// Returns an error if the transaction list cannot be retrieved.
20pub fn list() -> Result<()> {
21    let transactions = transaction::list_transactions()?;
22    if transactions.is_empty() {
23        println!("No transaction logs found.");
24        return Ok(());
25    }
26
27    let mut table = Table::new();
28    table
29        .load_style(UTF8_FULL)
30        .set_content_arrangement(ContentArrangement::Dynamic)
31        .set_header(vec!["ID", "Started", "Operations"]);
32
33    for entry in transactions {
34        table.add_row(vec![
35            entry.id,
36            entry.start_time,
37            entry.operation_count.to_string(),
38        ]);
39    }
40
41    println!("{table}");
42    Ok(())
43}
44
45/// List modified files for a specific transaction.
46///
47/// # Errors
48///
49/// Returns an error if the modified files for the given transaction ID cannot
50/// be retrieved.
51pub fn files(transaction_id: &str) -> Result<()> {
52    let mut modified_files = transaction::get_modified_files(transaction_id)?;
53    modified_files.sort();
54
55    if modified_files.is_empty() {
56        println!(
57            "No modified files recorded for transaction '{transaction_id}'."
58        );
59        return Ok(());
60    }
61
62    println!(
63        "{} Files modified by transaction '{}':",
64        "::".bold().blue(),
65        transaction_id.cyan()
66    );
67    for path in modified_files {
68        println!("  - {path}");
69    }
70    Ok(())
71}
72
73/// Show details for a specific transaction.
74///
75/// # Errors
76///
77/// Returns an error if the transaction with the given ID cannot be read.
78pub fn show(transaction_id: &str) -> Result<()> {
79    let transaction = transaction::read_transaction(transaction_id)?;
80
81    println!(
82        "{} Transaction {}",
83        "::".bold().blue(),
84        transaction.id.cyan()
85    );
86    println!("Started: {}", transaction.start_time);
87    println!("Operations: {}", transaction.operations.len());
88
89    for (index, operation) in transaction.operations.iter().enumerate() {
90        match operation {
91            types::TransactionOperation::Install { manifest } => {
92                println!(
93                    "{}. install {}",
94                    index + 1,
95                    manifest_source(manifest).green()
96                );
97            }
98            types::TransactionOperation::Uninstall { manifest } => {
99                println!(
100                    "{}. uninstall {}",
101                    index + 1,
102                    manifest_source(manifest).red()
103                );
104            }
105            types::TransactionOperation::Upgrade {
106                old_manifest,
107                new_manifest
108            } => {
109                println!(
110                    "{}. upgrade {} -> {}",
111                    index + 1,
112                    manifest_source(old_manifest).yellow(),
113                    manifest_source(new_manifest).green()
114                );
115            }
116        }
117    }
118
119    Ok(())
120}