aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/main.rs
blob: 49ee61f36e11eb90d202fa1639adc7a148545b8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! ref: composer/bin/composer

use shirabe_php_shim::{PHP_ENV, PHP_SERVER};
use std::io::IsTerminal as _;

/// Initialize a tracing subscriber from the environment variable `$SHIRABE_TRACING`.
fn init_tracing() {
    let Ok(directives) = std::env::var("SHIRABE_TRACING") else {
        return;
    };
    if directives.is_empty() {
        return;
    }

    let env_filter = match tracing_subscriber::EnvFilter::builder().parse(&directives) {
        Ok(env_filter) => env_filter,
        Err(e) => {
            eprintln!("SHIRABE_TRACING: invalid filter directives {directives:?}: {e}");
            return;
        }
    };

    tracing_subscriber::fmt()
        .with_env_filter(env_filter)
        .with_writer(std::io::stderr)
        .with_ansi(std::io::stderr().is_terminal())
        .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE)
        .init();
}

fn main() {
    // TODO(phase-c): PHP: `$xdebug = new XdebugHandler('Composer'); $xdebug->check(); unset($xdebug);`
    // (restart the process without Xdebug loaded, for performance) is not ported. Since no
    // XdebugHandler is ever constructed, `self::$name` never gets set, so the
    // COMPOSER_ORIGINAL_INIS-env-var branch of XdebugHandler::getAllIniFiles() (see
    // shirabe-external-packages' xdebug_handler.rs and shirabe/src/util/ini_helper.rs) is
    // unreachable in this port, not merely unexercised by current tests.

    // Take the $_ENV / $_SERVER snapshots before any putenv() mutates the real environment.
    // See `docs/dev/env-vars-porting.md` for details.
    std::sync::LazyLock::force(&PHP_ENV);
    std::sync::LazyLock::force(&PHP_SERVER);

    // The single process-wide tokio Runtime. `shirabe::run` and everything under it
    // (Command::execute and friends) is still synchronous top to bottom; entering the runtime
    // here (rather than driving `run` via `.block_on`) just makes it ambiently available via
    // `Handle::try_current()` for `util::sync_executor::block_on`'s many scattered call sites,
    // which ride it through `tokio::task::block_in_place` instead of each spinning up (or
    // busy-spin-polling without) their own. See sync_executor.rs for the TODO(phase-e) tracking
    // the eventual goal of propagating `async fn` all the way up to here instead.
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .expect("failed to build the top-level tokio runtime");
    let _runtime_guard = runtime.enter();

    init_tracing();

    let result = shirabe::run(std::env::args().collect());
    let exit_code = match result {
        Ok(exit_code) => exit_code,
        Err(e) => {
            eprintln!("{}", e);
            1
        }
    };
    std::process::exit(exit_code.min(255));
}