//! bootstrap, the Rust build system
//!
//! This is the entry point for the build system used to compile the `rustc`
//! compiler. Lots of documentation can be found in the `README.md` file in the
//! parent directory, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.

use std::fs::{self, OpenOptions, TryLockError};
use std::io::{self, BufRead, BufReader, IsTerminal, Read, Write};
use std::path::Path;
use std::str::FromStr;
use std::sync::Once;
use std::time::Instant;
use std::{env, process};

use crate::core::builder::StepStack;
use crate::core::config::flags::{Flags, Subcommand};
use crate::core::config::{ChangeId, Config};
use crate::core::session::Session;
use crate::debug;
use crate::utils::change_tracker::{
    CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes,
};
use crate::utils::helpers::t;

fn is_tracing_enabled() -> bool {
    cfg!(feature = "tracing")
}

pub fn main() {
    #[cfg(feature = "tracing")]
    let guard = crate::utils::tracing::setup_tracing("BOOTSTRAP_TRACING");

    let _start_time = Instant::now();

    let default_panic_hook = std::panic::take_hook();
    std::panic::set_hook(Box::new(move |info| {
        static BACKTRACE_LOCK: Once = Once::new();

        // Always print backtraces to provide richer errors, to help debug hard-to-reproduce panics
        // when the user didn't specify RUST_BACKTRACE
        // Note that we only override this variable in the panic handler, because bootstrap might
        // manually capture backtraces when a command is executed, and in that case we do not want
        // to always force backtraces.
        BACKTRACE_LOCK.call_once(|| {
            if std::env::var("RUST_BACKTRACE").is_err() {
                unsafe {
                    std::env::set_var("RUST_BACKTRACE", "1");
                }
            }
        });

        default_panic_hook(info);
        StepStack::with_current(|stack| {
            eprintln!("\nBootstrap has panicked, currently active steps:");
            for step in stack.get_active_steps() {
                eprintln!("{} at {}", step.info, step.location);
            }
        });
    }));

    let args = env::args().skip(1).collect::<Vec<_>>();

    if Flags::try_parse_verbose_help(&args) {
        return;
    }

    debug!("parsing flags");
    let flags = Flags::parse(&args);
    debug!("parsing config based on flags");
    let config = Config::parse(flags);

    let mut build_lock;

    if !config.bypass_bootstrap_lock {
        // Display PID of process holding the lock
        // PID will be stored in a lock file
        let lock_path = config.out.join("lock");
        build_lock = t!(fs::OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .truncate(false)
            .open(&lock_path));
        t!(build_lock.try_lock().or_else(|e| {
            if let TryLockError::Error(e) = e {
                return Err(e);
            }
            let mut pid = String::new();
            t!(build_lock.read_to_string(&mut pid));
            // #135972: We can reach this point when the lock has been taken,
            // but the locker has not yet written its PID to the file
            if !pid.is_empty() {
                println!("WARNING: build directory locked by process {pid}, waiting for lock");
            } else {
                println!("WARNING: build directory locked, waiting for lock");
            }
            build_lock.lock()
        }));
        t!(build_lock.set_len(0));
        t!(build_lock.write_all(process::id().to_string().as_bytes()));
    }

    // check_version warnings are not printed during setup, or during CI
    let changelog_suggestion = if matches!(config.cmd, Subcommand::Setup { .. })
        || config.is_running_on_ci()
        || config.dry_run()
    {
        None
    } else {
        check_version(&config)
    };

    // NOTE: Since `./configure` generates a `bootstrap.toml`, distro maintainers will see the
    // changelog warning, not the `x.py setup` message.
    let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
    if suggest_setup {
        println!("WARNING: you have not made a `bootstrap.toml`");
        println!(
            "HELP: consider running `./x.py setup` or copying `bootstrap.example.toml` by running \
            `cp bootstrap.example.toml bootstrap.toml`"
        );
    } else if let Some(suggestion) = &changelog_suggestion {
        println!("{suggestion}");
    }

    let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
    let dump_bootstrap_shims = config.dump_bootstrap_shims;
    let out_dir = config.out.clone();

    let tracing_enabled = is_tracing_enabled();

    // Prepare a directory for tracing output
    // Also store a symlink named "latest" to point to the latest tracing directory.
    let tracing_dir = out_dir.join("bootstrap-trace").join(std::process::id().to_string());
    let latest_trace_dir = tracing_dir.parent().unwrap().join("latest");
    if tracing_enabled {
        let _ = std::fs::remove_dir_all(&tracing_dir);
        std::fs::create_dir_all(&tracing_dir).unwrap();

        #[cfg(windows)]
        let _ = std::fs::remove_dir(&latest_trace_dir);
        #[cfg(not(windows))]
        let _ = std::fs::remove_file(&latest_trace_dir);

        #[cfg(not(windows))]
        fn symlink_dir_inner(original: &Path, link: &Path) -> io::Result<()> {
            use std::os::unix::fs;
            fs::symlink(original, link)
        }

        #[cfg(windows)]
        fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
            junction::create(target, junction)
        }

        t!(symlink_dir_inner(&tracing_dir, &latest_trace_dir));
    }

    debug!("creating new session based on config");
    let mut sess = Session::new(config);
    sess.build();

    if suggest_setup {
        println!("WARNING: you have not made a `bootstrap.toml`");
        println!(
            "HELP: consider running `./x.py setup` or copying `bootstrap.example.toml` by running \
            `cp bootstrap.example.toml bootstrap.toml`"
        );
    } else if let Some(suggestion) = &changelog_suggestion {
        println!("{suggestion}");
    }

    // Give a warning if the pre-commit script is in pre-commit and not pre-push.
    // HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not.
    // We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime.
    // Instead, look for this comment, which is almost certainly not in any custom hook.
    if fs::read_to_string(pre_commit).is_ok_and(|contents| {
        contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
    }) {
        println!(
            "WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \
                  Consider moving it to .git/hooks/pre-push instead, which runs less often."
        );
    }

    if suggest_setup || changelog_suggestion.is_some() {
        println!("NOTE: this message was printed twice to make it more likely to be seen");
    }

    if dump_bootstrap_shims {
        let dump_dir = out_dir.join("bootstrap-shims-dump");
        assert!(dump_dir.exists());

        for entry in walkdir::WalkDir::new(&dump_dir) {
            let entry = t!(entry);

            if !entry.file_type().is_file() {
                continue;
            }

            let file = t!(fs::File::open(entry.path()));

            // To ensure deterministic results we must sort the dump lines.
            // This is necessary because the order of rustc invocations different
            // almost all the time.
            let mut lines: Vec<String> = t!(BufReader::new(&file).lines().collect());
            lines.sort_by_key(|t| t.to_lowercase());
            let mut file = t!(OpenOptions::new().write(true).truncate(true).open(entry.path()));
            t!(file.write_all(lines.join("\n").as_bytes()));
        }
    }

    #[cfg(feature = "tracing")]
    {
        sess.report_summary(&tracing_dir.join("command-stats.txt"), _start_time);
        sess.report_step_graph(&tracing_dir);
        guard.copy_to_dir(&tracing_dir);
        eprintln!("Tracing/profiling output has been written to {}", latest_trace_dir.display());
    }
}

fn check_version(config: &Config) -> Option<String> {
    let mut msg = String::new();

    let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
    let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id");

    let mut id = match config.change_id {
        Some(ChangeId::Id(id)) if id == latest_change_id => return None,
        Some(ChangeId::Ignore) => return None,
        Some(ChangeId::Id(id)) => id,
        None => {
            msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
            msg.push_str("NOTE: to silence this warning, ");
            msg.push_str(&format!(
                "add `change-id = {latest_change_id}` or `change-id = \"ignore\"` at the top of `bootstrap.toml`"
            ));
            return Some(msg);
        }
    };

    // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist,
    // then use the one from the bootstrap.toml. This way we never show the same warnings
    // more than once.
    if let Ok(t) = fs::read_to_string(&warned_id_path) {
        let last_warned_id = usize::from_str(&t)
            .unwrap_or_else(|_| panic!("{} is corrupted.", warned_id_path.display()));

        // We only use the last_warned_id if it exists in `CONFIG_CHANGE_HISTORY`.
        // Otherwise, we may retrieve all the changes if it's not the highest value.
        // For better understanding, refer to `change_tracker::find_recent_config_change_ids`.
        if CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == last_warned_id) {
            id = last_warned_id;
        }
    };

    let changes = find_recent_config_change_ids(id);

    if changes.is_empty() {
        return None;
    }

    msg.push_str("There have been changes to x.py since you last updated:\n");
    msg.push_str(&human_readable_changes(changes));

    msg.push_str("NOTE: to silence this warning, ");
    msg.push_str(&format!(
        "update `bootstrap.toml` to use `change-id = {latest_change_id}` or `change-id = \"ignore\"` instead"
    ));

    if io::stdout().is_terminal() {
        t!(fs::write(warned_id_path, latest_change_id.to_string()));
    }

    Some(msg)
}
