Repository: meilisearch/meilisearch
File: meilisearch-http/src/option.rs (Rust)

Code before:
    pub scheduler_options: SchedulerConfig,

    /// The path to a configuration file that should be used to setup the engine.
    /// Format must be TOML.
    #[serde(skip_serializing)]
    #[clap(long)]
    pub config_file_path: Option<PathBuf>,
}

impl Opt {
    /// Whether analytics should be enabled or not.
    #[cfg(all(not(debug_assertions), feature = "analytics"))]
    pub fn analytics(&self) -> bool {
        !self.no_analytics
    }

    /// Build a new Opt from config file, env vars and cli args.
    pub fn try_build() -> anyhow::Result<(Self, Option<PathBuf>)> {
        // Parse the args to get the config_file_path.
        let mut opts = Opt::parse();
        let mut config_read_from = None;
        if let Some(config_file_path) = opts.config_file_path.clone().or_else(|| {
            Some(PathBuf::from(
                env::var("MEILI_CONFIG_FILE_PATH").unwrap_or_else(|_| "./config.toml".to_string()),
            ))
        }) {
            match std::fs::read(&config_file_path) {
                Ok(config) => {
                    // If the file is successfully read, we deserialize it with `toml`.
                    let opt_from_config = toml::from_slice::<Opt>(&config)?;
                    // We inject the values from the toml in the corresponding env vars if needs be. Doing so, we respect the priority toml < env vars < cli args.
                    opt_from_config.export_to_env();
                    // Once injected we parse the cli args once again to take the new env vars into scope.
                    opts = Opt::parse();
                    config_read_from = Some(config_file_path);
                }
                // If we have an error while reading the file defined by the user.
                Err(_) if opts.config_file_path.is_some() => anyhow::bail!(
                    "unable to open or read the {:?} configuration file.",
                    opts.config_file_path.unwrap().display().to_string()
                ),
                _ => (),
            }
        }

        Ok((opts, config_read_from))
    }

    /// Exports the opts values to their corresponding env vars if they are not set.
    fn export_to_env(self) {
        let Opt {

Review comment (suggestion):
```suggestion
        let config_file_path = opts.config_file_path.clone()
        .or_else(|| env::var("MEILI_CONFIG_FILE_PATH").map(PathBuf::from).ok())
        .unwrap_or_else(|| PathBuf::from("./config.toml"));
        if let Some(config_file_path) = config_file_path {
```

I would prefer that you write that in multiple lines and then match on it after.

Code after:
    pub log_level: String,

    /// Enables Prometheus metrics and /metrics route.
    #[cfg(feature = "metrics")]
    #[clap(long, env = MEILI_ENABLE_METRICS_ROUTE)]
    #[serde(default)]
    pub enable_metrics_route: bool,

    #[serde(flatten)]
    #[clap(flatten)]
    pub indexer_options: IndexerOpts,

    #[serde(flatten)]
    #[clap(flatten)]
    pub scheduler_options: SchedulerConfig,

    /// Set the path to a configuration file that should be used to setup the engine.
    /// Format must be TOML.
    #[serde(skip_serializing)]
    #[clap(long)]
    pub config_file_path: Option<PathBuf>,
}

impl Opt {
    /// Whether analytics should be enabled or not.
    #[cfg(all(not(debug_assertions), feature = "analytics"))]
    pub fn analytics(&self) -> bool {
        !self.no_analytics
    }

    /// Build a new Opt from config file, env vars and cli args.
    pub fn try_build() -> anyhow::Result<(Self, Option<PathBuf>)> {
        // Parse the args to get the config_file_path.
        let mut opts = Opt::parse();
        let mut config_read_from = None;
        let user_specified_config_file_path = opts
            .config_file_path
            .clone()
            .or_else(|| env::var("MEILI_CONFIG_FILE_PATH").map(PathBuf::from).ok());
        let config_file_path = user_specified_config_file_path
            .clone()
            .unwrap_or_else(|| PathBuf::from(DEFAULT_CONFIG_FILE_PATH));

        match std::fs::read(&config_file_path) {
            Ok(config) => {
                // If the file is successfully read, we deserialize it with `toml`.
                let opt_from_config = toml::from_slice::<Opt>(&config)?;
                // Return an error if config file contains 'config_file_path'
                // Using that key in the config file doesn't make sense bc it creates a logical loop (config file referencing itself)
                if opt_from_config.config_file_path.is_some() {
                    anyhow::bail!("`config_file_path` is not supported in config file")