fn main()

in ingester/src/main.rs [128:186]


fn main() -> anyhow::Result<()> {
    env_logger::builder()
        .filter_level(log::LevelFilter::Warn)
        .parse_default_env()
        .init();

    let mut args = Args::parse();

    if args.config_file.is_none() && std::fs::exists(DEFAULT_CONFIG_FILE).unwrap_or_log(false) {
        args.config_file = Some(DEFAULT_CONFIG_FILE.into());
    }

    let toml_config: toml::Table = if let Some(file) = args.config_file {
        std::fs::read_to_string(&file)
            .map_err(|e| anyhow::Error::from(e))
            .and_then(|s| Ok(toml::from_str(&s)?))
            .with_context(|| format!("while reading {}", file.display()))?
    } else {
        Default::default()
    };
    let mut toml_config: toml::Value = toml_config.into();

    let cli_config: toml::Table =
        toml::from_str(&args.config.join("\n")).context("while parsing CLI TOML arguments")?;

    // Merge configs
    toml_merge(&mut toml_config, cli_config.into());

    let config: Config = toml_config.try_into()?;

    let input = args
        .input_file
        .map(|path| {
            std::fs::File::open(path).map(|f| Box::new(BufReader::new(f)) as Box<dyn BufRead>)
        })
        .unwrap_or_else(|| Ok(Box::new(std::io::stdin().lock())))?;

    let mut output = args
        .output_file
        .map(|path| std::fs::File::create(path).map(|f| Box::new(f) as Box<dyn Write>))
        .unwrap_or_else(|| Ok(Box::new(std::io::stdout())))?;

    let ingest = CrashPingIngest::new(config, JsonlReader::new(input), move |ping_info| {
        serde_json::to_writer(&mut output, &ping_info)?;
        writeln!(&mut output)?;
        Ok(())
    });

    let cancellation_status = ingest.status.clone();
    ctrlc::set_handler(move || cancellation_status.cancel())
        .expect("failed to set interrupt handler");
    let _progress = if args.no_progress {
        None
    } else {
        Progress::new(ingest.status.clone())
    };

    ingest.run()
}