Skip to main content

frm/commands/
cp_etc_file.rs

1// Copyright (c) 2025-2026 Michael S. Klishin and Contributors
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::fmt;
10use std::fs;
11use std::path::Path;
12use std::str::FromStr;
13
14use bel7_cli::print_info;
15
16use crate::Result;
17use crate::errors::Error;
18use crate::paths::Paths;
19use crate::version::Version;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum EtcFile {
23    RabbitmqConf,
24    AdvancedConfig,
25    RabbitmqConfig,
26    EnabledPlugins,
27}
28
29impl EtcFile {
30    pub const ALL: &[EtcFile] = &[
31        EtcFile::RabbitmqConf,
32        EtcFile::AdvancedConfig,
33        EtcFile::RabbitmqConfig,
34        EtcFile::EnabledPlugins,
35    ];
36
37    pub fn as_str(&self) -> &'static str {
38        match self {
39            EtcFile::RabbitmqConf => "rabbitmq.conf",
40            EtcFile::AdvancedConfig => "advanced.config",
41            EtcFile::RabbitmqConfig => "rabbitmq.config",
42            EtcFile::EnabledPlugins => "enabled_plugins",
43        }
44    }
45
46    pub fn all_names() -> Vec<&'static str> {
47        Self::ALL.iter().map(|f| f.as_str()).collect()
48    }
49}
50
51impl fmt::Display for EtcFile {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{}", self.as_str())
54    }
55}
56
57impl FromStr for EtcFile {
58    type Err = Error;
59
60    fn from_str(s: &str) -> Result<Self> {
61        match s {
62            "rabbitmq.conf" => Ok(EtcFile::RabbitmqConf),
63            "advanced.config" => Ok(EtcFile::AdvancedConfig),
64            "rabbitmq.config" => Ok(EtcFile::RabbitmqConfig),
65            "enabled_plugins" => Ok(EtcFile::EnabledPlugins),
66            _ => Err(Error::UnknownConfigFile(format!(
67                "'{}'. Valid files: {}",
68                s,
69                EtcFile::all_names().join(", ")
70            ))),
71        }
72    }
73}
74
75pub fn run_release(
76    paths: &Paths,
77    version: &Version,
78    local_path: &Path,
79    etc_file: EtcFile,
80) -> Result<()> {
81    if version.is_distributed_via_server_packages_repository() {
82        return Err(Error::ExpectedNonAlphaVersion(version.clone()));
83    }
84    run(paths, version, local_path, etc_file)
85}
86
87pub fn run_alpha(
88    paths: &Paths,
89    version: &Version,
90    local_path: &Path,
91    etc_file: EtcFile,
92) -> Result<()> {
93    if !version.is_distributed_via_server_packages_repository() {
94        return Err(Error::ExpectedAlphaVersion(version.clone()));
95    }
96    run(paths, version, local_path, etc_file)
97}
98
99fn run(paths: &Paths, version: &Version, local_path: &Path, etc_file: EtcFile) -> Result<()> {
100    if !paths.version_installed(version) {
101        return Err(Error::VersionNotInstalled(version.clone()));
102    }
103
104    if !local_path.exists() {
105        return Err(Error::FileNotFound(local_path.display().to_string()));
106    }
107
108    let etc_dir = paths.version_etc_dir(version);
109    if !etc_dir.exists() {
110        fs::create_dir_all(&etc_dir)?;
111    }
112
113    let dest_path = etc_dir.join(etc_file.as_str());
114    fs::copy(local_path, &dest_path)?;
115
116    print_info(format!(
117        "Copied {} to {}",
118        local_path.display(),
119        dest_path.display()
120    ));
121
122    Ok(())
123}