You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: main.rs
    path of file: ./repos/ajour/src
    
    the code of the file until where you have to start completion: // Avoid spawning an console window for the program.
// This is ignored on other platforms.
// https://msdn.microsoft.com/en-us/library/4cc7ya5b.aspx for more information.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod cli;
mod command;
mod gui;
mod localization;
#[cfg(target_os = "windows")]
mod process;
#[cfg(target_os = "windows")]
mod tray;

use ajour_core::config::Config;
use ajour_core::fs::{PersistentData, CONFIG_DIR};
use ajour_core::utility::{remove_file, rename};

#[cfg(target_os = "linux")]
use anyhow::Context;
use std::env;
use std::path::Path;
#[cfg(target_os = "linux")]
use std::path::PathBuf;

pub const VERSION: &str = env!("CARGO_PKG_VERSION");

pub type Result<T, E = anyhow::Error> = std::result::Result<T, E>;

pub fn main() {
    let opts_result = cli::get_opts();

    #[cfg(debug_assertions)]
    let is_debug = true;
    #[cfg(not(debug_assertions))]
    let is_debug = false;

    // If this is a clap error, we map to None since we are going to exit and display
    // an error message anyway and this value won't matter. If it's not an error,
    // the underlying `command` will drive this variable. If a `command` is passed
    // on the command line, Ajour functions as a CLI instead of launching the GUI.
    let is_cli = opts_result
        .as_ref()
        .map(|o| &o.command)
        .unwrap_or(&None)
        .is_some();

    // This function validates whether or not we need to exit and print any message
    // due to arguments passed on the command line. If not, it will return a
    // parsed `Opts` struct. This also handles setting up our windows release build
    // fix that allows us to print to the console when not using the GUI.
    let opts = cli::validate_opts_or_exit(opts_result, is_cli, is_debug);

    if let Some(data_dir) = &opts.data_directory {
        let mut config_dir = CONFIG_DIR.lock().unwrap();

        *config_dir = data_dir.clone();
    }

    setup_logger(is_cli, is_debug).expect("setup logging");

    // Called when we launch from the temp (new release) binary during the self update
    // process.
    
pub fn main() {
    let opts_result = cli::get_opts();

    #[cfg(debug_assertions)]
    let is_debug = true;
    #[cfg(not(debug_assertions))]
    let is_debug = false;

    // If this is a clap error, we map to None since we are going to exit and display
    // an error message anyway and this value won't matter. If it's not an error,
    // the underlying `command` will drive this variable. If a `command` is passed
    // on the command line, Ajour functions as a CLI instead of launching the GUI.
    let is_cli = opts_result
        .as_ref()
        .map(|o| &o.command)
        .unwrap_or(&None)
        .is_some();

    // This function validates whether or not we need to exit and print any message
    // due to arguments passed on the command line. If not, it will return a
    // parsed `Opts` struct. This also handles setting up our windows release build
    // fix that allows us to print to the console when not using the GUI.
    let opts = cli::validate_opts_or_exit(opts_result, is_cli, is_debug);

    if let Some(data_dir) = &opts.data_directory {
        let mut config_dir = CONFIG_DIR.lock().unwrap();

        *config_dir = data_dir.clone();
    }

    setup_logger(is_cli, is_debug).expect("setup logging");

    // Called when we launch from the temp (new release) binary during the self update
    // process. We will rename the temp file (running process) to the original binary
    if let Some(cleanup_path) = &opts.self_update_temp {
        if let Err(e) = handle_self_update_temp(cleanup_path) {
            log_error(&e);
            std::process::exit(1);
        }
    }

    log_panics::init();

    log::info!("Ajour {} has started.", VERSION);

    // Ensures another instance of Ajour isn't already running.
    #[cfg(target_os = "windows")]
    process::avoid_multiple_instances();

    match opts.command {
        Some(command) => {
            // Process the command and exit
            if let Err(e) = match command {
                cli::Command::Backup {
                    backup_folder,
                    destination,
                    flavors,
                    compression_format,
                    level,
                } => command::backup(
                    backup_folder,
                    destination,
                    flavors,
                    compression_format,
                    level,
                ),
                cli::Command::Update => command::update_both(),
                cli::Command::UpdateAddons => command::update_all_addons(),
                cli::Command::UpdateAuras => command::update_all_auras(),
                cli::Command::Install { url, flavor } => command::install_from_source(url, flavor),
                cli::Command::PathAdd { path, flavor } => command::path_add(path, flavor),
            } {
                log_error(&e);
            }
        }
        None => {
            let config: Config =
                Config::load_or_default().expect("loading config on application startup");

            #[cfg(target_os = "windows")]
            tray::spawn_sys_tray(config.close_to_tray, config.start_closed_to_tray);

            // Start the GUI
            gui::run(opts, config);
        }
    }
}