Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 76 additions & 21 deletions rust/agama-cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,47 @@
use std::io::{self, Read};

use crate::{
error::CliError,
printers::{print, Format},
use std::{
io::{self, Read},
path::PathBuf,
process::Command,
};

use crate::show_progress;
use agama_lib::{
auth::AuthToken, connection, install_settings::InstallSettings, Store as SettingsStore,
};
use anyhow::anyhow;
use clap::Subcommand;
use std::io::Write;
use tempfile::Builder;

const DEFAULT_EDITOR: &str = "/usr/bin/vi";

#[derive(Subcommand, Debug)]
pub enum ConfigCommands {
/// Generates an installation profile with the current settings.
/// Generate an installation profile with the current settings.
///
/// It is possible that many configuration settings do not have a value. Those settings
/// are not included in the output.
///
/// The output of command can be used as input for the "agama config load".
Show,

/// Reads and loads a profile from the standard input.
/// Read and load a profile from the standard input.
Load,
}

pub enum ConfigAction {
Show,
Load,
/// Edit and update installation option using an external editor.
///
/// The changes are not applied if the editor exits with an error code.
///
/// If an editor is not specified, it honors the EDITOR environment variable. It falls back to
/// `/usr/bin/vi` as a last resort.
Edit {
/// Editor command (including additional arguments if needed)
#[arg(short, long)]
editor: Option<String>,
},
}

pub async fn run(subcommand: ConfigCommands, format: Format) -> anyhow::Result<()> {
pub async fn run(subcommand: ConfigCommands) -> anyhow::Result<()> {
let Some(token) = AuthToken::find() else {
println!("You need to login for generating a valid token");
return Ok(());
Expand All @@ -37,26 +50,68 @@ pub async fn run(subcommand: ConfigCommands, format: Format) -> anyhow::Result<(
let client = agama_lib::http_client(token.as_str())?;
let store = SettingsStore::new(connection().await?, client).await?;

let command = parse_config_command(subcommand)?;
match command {
ConfigAction::Show => {
match subcommand {
ConfigCommands::Show => {
let model = store.load().await?;
print(model, std::io::stdout(), format)?;
let json = serde_json::to_string_pretty(&model)?;
println!("{}", json);
Ok(())
}
ConfigAction::Load => {
ConfigCommands::Load => {
let mut stdin = io::stdin();
let mut contents = String::new();
stdin.read_to_string(&mut contents)?;
let result: InstallSettings = serde_json::from_str(&contents)?;
Ok(store.store(&result).await?)
}
ConfigCommands::Edit { editor } => {
let model = store.load().await?;
let editor = editor
.or_else(|| std::env::var("EDITOR").ok())
.unwrap_or(DEFAULT_EDITOR.to_string());
let result = edit(&model, &editor)?;
tokio::spawn(async move {
show_progress().await.unwrap();
});
store.store(&result).await?;
Ok(())
}
}
}

fn parse_config_command(subcommand: ConfigCommands) -> Result<ConfigAction, CliError> {
match subcommand {
ConfigCommands::Show => Ok(ConfigAction::Show),
ConfigCommands::Load => Ok(ConfigAction::Load),
/// Edit the installation settings using an external editor.
///
/// If the editor does not return a successful error code, it returns an error.
///
/// * `model`: current installation settings.
/// * `editor`: editor command.
fn edit(model: &InstallSettings, editor: &str) -> anyhow::Result<InstallSettings> {
let content = serde_json::to_string_pretty(model)?;
let mut file = Builder::new().suffix(".json").tempfile()?;
let path = PathBuf::from(file.path());
write!(file, "{}", content)?;

let mut command = editor_command(&editor);
let status = command.arg(path.as_os_str()).status()?;
if status.success() {
return Ok(InstallSettings::from_file(path)?);
}

Err(anyhow!(
"Ignoring the changes becase the editor was closed with an error code."
))
}

/// Return the Command to run the editor.
///
/// Separate the program and the arguments and build a Command struct.
///
/// * `command`: command to run as editor.
fn editor_command(command: &str) -> Command {
let mut parts = command.split_whitespace();
let program = parts.next().unwrap_or(DEFAULT_EDITOR);

let mut command = Command::new(program);
command.args(parts.collect::<Vec<&str>>());
command
}
8 changes: 1 addition & 7 deletions rust/agama-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod commands;
mod config;
mod error;
mod logs;
mod printers;
mod profile;
mod progress;
mod questions;
Expand All @@ -18,7 +17,6 @@ use auth::run as run_auth_cmd;
use commands::Commands;
use config::run as run_config_cmd;
use logs::run as run_logs_cmd;
use printers::Format;
use profile::run as run_profile_cmd;
use progress::InstallerProgress;
use questions::run as run_questions_cmd;
Expand All @@ -39,10 +37,6 @@ use std::{
struct Cli {
#[command(subcommand)]
pub command: Commands,

/// Format output
#[arg(value_enum, short, long, default_value_t = Format::Json)]
pub format: Format,
}

async fn probe() -> anyhow::Result<()> {
Expand Down Expand Up @@ -129,7 +123,7 @@ async fn run_command(cli: Cli) -> anyhow::Result<()> {
Commands::Config(subcommand) => {
let manager = build_manager().await?;
wait_for_services(&manager).await?;
run_config_cmd(subcommand, cli.format).await
run_config_cmd(subcommand).await
}
Commands::Probe => {
let manager = build_manager().await?;
Expand Down
74 changes: 0 additions & 74 deletions rust/agama-cli/src/printers.rs

This file was deleted.

7 changes: 7 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Thu Jun 20 12:58:32 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

- Add a new "config edit" command allows editing installation
settings using an external editor (gh#openSUSE/agama#1360).
- Remove the "--format" option (gh#openSUSE/agama#1360).

-------------------------------------------------------------------
Thu Jun 20 05:32:42 UTC 2024 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down