failed attempt at making a single binary for CLI and GUI on Windows
This commit is contained in:
		@@ -13,7 +13,6 @@ use tokio::{
 | 
			
		||||
    io::{AsyncReadExt, AsyncWriteExt},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
use crate::app;
 | 
			
		||||
use crate::config::AppConfig;
 | 
			
		||||
use crate::credentials::{BaseCredentials, SessionCredentials};
 | 
			
		||||
@@ -23,6 +22,16 @@ use crate::errors::*;
 | 
			
		||||
pub fn parser() -> Command<'static> {
 | 
			
		||||
    Command::new("creddy")
 | 
			
		||||
        .about("A friendly AWS credentials manager")
 | 
			
		||||
        // we don't want the default help handling because it early-exits,
 | 
			
		||||
        // and on Windows we need to setup the console before we can output
 | 
			
		||||
        .disable_help_flag(true)
 | 
			
		||||
        .arg(
 | 
			
		||||
            Arg::new("help")
 | 
			
		||||
                .short('h')
 | 
			
		||||
                .long("help")
 | 
			
		||||
                .action(ArgAction::SetTrue)
 | 
			
		||||
                .help("Print this message or the help of the given subcommand(s)")
 | 
			
		||||
        )
 | 
			
		||||
        .subcommand(
 | 
			
		||||
            Command::new("run")
 | 
			
		||||
                .about("Launch Creddy")
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ use std::net::Ipv4Addr;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
use auto_launch::AutoLaunchBuilder;
 | 
			
		||||
use is_terminal::IsTerminal;
 | 
			
		||||
use serde::{Serialize, Deserialize};
 | 
			
		||||
use sqlx::SqlitePool;
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +95,7 @@ pub fn get_or_create_db_path() -> Result<PathBuf, DataDirError> {
 | 
			
		||||
    path.push("Creddy");
 | 
			
		||||
 | 
			
		||||
    std::fs::create_dir_all(&path)?;
 | 
			
		||||
    if cfg!(debug_assertions) && std::io::stdout().is_terminal() {
 | 
			
		||||
    if cfg!(debug_assertions) {
 | 
			
		||||
        path.push("creddy.dev.db");
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,20 @@
 | 
			
		||||
    windows_subsystem = "windows"
 | 
			
		||||
)]
 | 
			
		||||
 | 
			
		||||
#[cfg(windows)]
 | 
			
		||||
use {
 | 
			
		||||
    std::fs::File,
 | 
			
		||||
    std::os::windows::io::FromRawHandle,
 | 
			
		||||
    std::os::raw::c_void,
 | 
			
		||||
    gag::Redirect,
 | 
			
		||||
    windows::Win32::System::Console::{
 | 
			
		||||
        AllocConsole,
 | 
			
		||||
        AttachConsole,
 | 
			
		||||
        GetStdHandle,
 | 
			
		||||
        STD_OUTPUT_HANDLE,
 | 
			
		||||
        STD_ERROR_HANDLE,
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
mod app;
 | 
			
		||||
mod cli;
 | 
			
		||||
@@ -15,18 +29,40 @@ mod state;
 | 
			
		||||
mod server;
 | 
			
		||||
mod tray;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
use crate::errors::ErrorPopup;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
fn main() {
 | 
			
		||||
    let res = match cli::parser().get_matches().subcommand() {
 | 
			
		||||
        None | Some(("run", _)) => {
 | 
			
		||||
    let args = cli::parser().get_matches();
 | 
			
		||||
    let help = matches!(args.get_one::<bool>("help"), Some(true));
 | 
			
		||||
 | 
			
		||||
    // This is the only case that doesn't need a console
 | 
			
		||||
    if let None | Some(("run", _)) = args.subcommand() {
 | 
			
		||||
        if !help {
 | 
			
		||||
            app::run().error_popup("Creddy failed to start");
 | 
			
		||||
            Ok(())
 | 
			
		||||
        },
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // on Windows, need to do the whole allocate-a-console thing
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    attach_console();
 | 
			
		||||
    // let (out, err) = setup_console();
 | 
			
		||||
    println!("Testing stdout");
 | 
			
		||||
    // writeln!(&mut out, "Testing allocated file");
 | 
			
		||||
 | 
			
		||||
    if help {
 | 
			
		||||
        // if we can't print help, we can't print an error, so just panic
 | 
			
		||||
        dbg!(args.get_one::<bool>("help"));
 | 
			
		||||
        cli::parser().print_help().unwrap();
 | 
			
		||||
        std::thread::sleep(std::time::Duration::from_secs(3));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let res = match args.subcommand() {
 | 
			
		||||
        Some(("show", m)) => cli::show(m),
 | 
			
		||||
        Some(("exec", m)) => cli::exec(m),
 | 
			
		||||
        // clap ensures that subcommand is either None or run/show/exec
 | 
			
		||||
        _ => unreachable!(),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -34,3 +70,43 @@ fn main() {
 | 
			
		||||
        eprintln!("Error: {e}");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn attach_console() {
 | 
			
		||||
    unsafe { AttachConsole(u32::MAX); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn setup_console() -> (Redirect<File>, Redirect<File>) {
 | 
			
		||||
    let (mut stdout, stderr) = unsafe {
 | 
			
		||||
        AllocConsole();
 | 
			
		||||
        // if we can't get handles to stdout/err, we can't display these errors,
 | 
			
		||||
        // so there's no point in doing anything other than panicking
 | 
			
		||||
        let stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE).unwrap();
 | 
			
		||||
        let stderr_handle = GetStdHandle(STD_ERROR_HANDLE).unwrap();
 | 
			
		||||
 | 
			
		||||
        let mut f = File::create("C:\\Users\\Joe\\Downloads\\debug.txt").unwrap();
 | 
			
		||||
        writeln!(&mut f, "{stdout_handle:?}\n{:?}", stdout_handle.0 as *mut c_void).unwrap();
 | 
			
		||||
 | 
			
		||||
        (
 | 
			
		||||
            File::from_raw_handle(stdout_handle.0 as *mut c_void),
 | 
			
		||||
            File::from_raw_handle(stderr_handle.0 as *mut c_void),
 | 
			
		||||
        )
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    writeln!(&mut stdout, "Testing stdout before redirect")
 | 
			
		||||
        .map_err(|e| log_err(e))
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    (
 | 
			
		||||
        Redirect::stdout(stdout).unwrap(),
 | 
			
		||||
        Redirect::stderr(stderr).unwrap()
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn log_err(e: impl std::error::Error) {
 | 
			
		||||
    let mut f = File::create("C:\\Users\\Joe\\Downloads\\log.txt").unwrap();
 | 
			
		||||
    writeln!(&mut f, "{e}").unwrap();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user