You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: hg.rs
    path of file: ./repos/fselect/src/ignore
    
    the code of the file until where you have to start completion: use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::ops::Add;
use std::ops::Index;
use std::path::Path;

use regex::Captures;
use regex::Error;
use regex::Regex;
use crate::util::error_exit;

#[derive(Clone, Debug)]
pub struct HgignoreFilter {
    pub regex: Regex,
}

impl HgignoreFilter {
    fn new(regex: Regex) -> HgignoreFilter {
        HgignoreFilter {
            regex
        }
    }
}

pub fn search_upstream_hgignore(hgignore_filters: &mut Vec<HgignoreFilter>, dir: &Path) {
    if let Ok(canonical_path) = crate::util::canonical_path(&dir.to_path_buf()) {
        let mut path = std::path::PathBuf::from(canonical_path);

        loop {
            let hgignore_file = path.join(".hgignore");
            let hg_directory = path.join(".hg");

            if hgignore_file.is_file() && hg_directory.is_dir() {
                update_hgignore_filters(hgignore_filters, &mut path);
                return;
            }

            let parent_found = path.pop();

            if !parent_found {
                return;
            }
        }
    }
}

fn update_hgignore_filters(hgignore_filters: &mut Vec<HgignoreFilter>, path: &Path) {
    let hgignore_file = path.join(".hgignore");
    if hgignore_file.is_file() 
    
fn convert_hgignore_glob(glob: &str, file_path: &Path) -> Result<Regex, Error> {
    #[cfg(not(windows))]
        {
            let mut pattern = HG_CONVERT_REPLACE_REGEX.replace_all(&glob, |c: &Captures| {
                match c.index(0) {
                    "**" => ".*",
                    "." => "\\.",
                    "*" => "[^/]*",
                    "?" => "[^/]+",
                    "[" => "\\[",
                    "]" => "\\]",
                    "(" => "\\(",
                    ")" => "\\)",
                    "^" => "\\^",
                    "$" => "\\$",
                    _ => error_exit(".hgignore", "Error parsing pattern")
                }.to_string()
            }).to_string();

            pattern = file_path.to_string_lossy().to_string()
                .replace("\\", "\\\\")
                .add("/([^/]+/)*").add(&pattern);

            Regex::new(&pattern)
        }

    #[cfg(windows)]
        {
            let mut pattern = HG_CONVERT_REPLACE_REGEX.replace_all(&glob, |c: &Captures| {
                match c.index(0) {
                    "**" => ".*",
                    "." => "\\.",
                    "*" => "[^\\\\]*",
                    "?" => "[^\\\\]+",
                    "[" => "\\[",
                    "]" => "\\]",
                    "(" => "\\(",
                    ")" => "\\)",
                    "^" => "\\^",
                    "$" => "\\$",
                    _ => error_exit(".hgignore", "Error parsing pattern")
                }.to_string()
            }).to_string();

            pattern = file_path.to_string_lossy().to_string()
                .replace("\\", "\\\\")
                .add("\\\\([^\\\\]+\\\\)*").add(&pattern);

            Regex::new(&pattern)
        }
}