1#![doc(html_root_url = "https://docs.rs/cargo-sync-rdme/0.5.0")]
17#![warn(
18 elided_lifetimes_in_paths,
19 explicit_outlives_requirements,
20 keyword_idents,
21 missing_copy_implementations,
22 missing_debug_implementations,
23 missing_docs,
24 single_use_lifetimes,
25 unreachable_pub,
26 unused
27)]
28
29use std::{env, io, process};
30
31use clap::{CommandFactory as _, Parser};
32use clap_complete::{Generator, Shell};
33use tracing::Level;
34use tracing_subscriber::{EnvFilter, filter::LevelFilter};
35
36#[macro_use]
37mod macros;
38
39mod cli;
40mod config;
41mod diff;
42mod sync;
43mod traits;
44mod vcs;
45mod with_source;
46
47pub use self::cli::App;
48
49pub type Error = miette::Error;
51
52pub type Result<T> = miette::Result<T>;
54
55pub fn main(bin_name: &str) -> Result<()> {
57 let env_prefix = bin_name.to_uppercase().replace("-", "_");
58 if let Ok(shell) = env::var(format!("{env_prefix}_PRINT_COMPLETION")) {
59 print_completion(bin_name, &shell);
60 process::exit(0);
61 }
62 if let Ok(output_dir) = env::var(format!("{env_prefix}_GENERATE_MAN_TO")) {
63 generate_man(&output_dir);
64 process::exit(0);
65 }
66
67 let args = env::args().enumerate().filter_map(|(idx, arg)| {
70 if idx == 1 && arg == "sync-rdme" {
71 None
72 } else {
73 Some(arg)
74 }
75 });
76 let app = App::parse_from(args);
77 install_logger(app.verbosity.into())?;
78
79 let workspace = app.workspace.metadata()?;
80 for package in app.package.packages(&workspace)? {
81 sync::sync_all(&app, &workspace, package)?;
82 }
83
84 Ok(())
85}
86
87fn install_logger(verbosity: Option<Level>) -> Result<()> {
88 let env_filter = if env::var_os("RUST_LOG").is_some() {
89 EnvFilter::from_default_env()
90 } else {
91 let default_level = match verbosity {
92 Some(Level::ERROR) => LevelFilter::ERROR,
93 Some(Level::WARN) => LevelFilter::WARN,
94 Some(Level::INFO) => LevelFilter::INFO,
95 Some(Level::DEBUG) => LevelFilter::DEBUG,
96 Some(Level::TRACE) => LevelFilter::TRACE,
97 None => LevelFilter::OFF,
98 };
99 EnvFilter::builder()
100 .with_default_directive(default_level.into())
101 .from_env_lossy()
102 };
103
104 tracing_subscriber::fmt()
105 .with_env_filter(env_filter)
106 .with_writer(io::stderr)
107 .with_target(false)
108 .try_init()
109 .map_err(|e| miette!(e))?;
110
111 Ok(())
112}
113
114fn print_completion(bin_name: &str, shell: &str) {
115 fn print<G>(bin_name: &str, g: G)
116 where
117 G: Generator,
118 {
119 clap_complete::generate(g, &mut App::command(), bin_name, &mut io::stdout());
120 }
121 match shell {
122 "bash" => print(bin_name, Shell::Bash),
123 "elvish" => print(bin_name, Shell::Elvish),
124 "fish" => print(bin_name, Shell::Fish),
125 "powershell" => print(bin_name, Shell::PowerShell),
126 "zsh" => print(bin_name, Shell::Zsh),
127 "nushell" => print(bin_name, clap_complete_nushell::Nushell),
128 _ => panic!(
129 "error: unknown shell `{shell}`, expected one of `bash`, `elvish`, `fish`, `powershell`, `zsh`, `nushell`"
130 ),
131 }
132}
133
134fn generate_man(output_dir: &str) {
135 clap_mangen::generate_to(App::command(), output_dir).unwrap();
136}