duplicate_code 0.8.1

A tool for parsing directories scanning all the files within to find duplicate segments of code across files.
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use std::process::exit;

use regex::Regex;

use super::*;

pub type RawFiles = Vec<RawFile>;

pub struct RawFile {
    pub filename: Filename,
    pub lines: Lines,
}

pub fn get_raw_files(ignore_file_regexes: Vec<String>) -> RawFiles {
    let compiled_ignore_file_regexes = crate::regex_utilities::get_regexes(ignore_file_regexes);
    get_raw_files_in_directory("./", &compiled_ignore_file_regexes)
}

fn get_raw_files_in_directory(directory: &str, ignore_file_regexes: &[Regex]) -> RawFiles {
    let mut files = Vec::new();

    match std::fs::read_dir(directory) {
        Ok(entries) => {
            for entry in entries {
                match entry {
                    Ok(entry) => {
                        let path = entry.path();
                        let name = path.to_str().unwrap();

                        if path.is_file() {
                            if crate::regex_utilities::does_not_match_any(
                                &name,
                                ignore_file_regexes,
                            ) {
                                files.push(get_raw_file(&name));
                            } else {
                                trace!("Ignoring the file {:?}.", name);
                            }
                        } else {
                            files.extend(get_raw_files_in_directory(name, ignore_file_regexes));
                        }
                    }
                    Err(error) => {
                        error!("{}", error);
                        exit(1);
                    }
                }
            }
        }
        Err(error) => {
            error!("{}", error);
            exit(1);
        }
    }

    files
}

fn get_raw_file(filename: &str) -> RawFile {
    match read_lines(filename) {
        Ok(buffered_lines) => {
            let mut lines = vec![];

            for line in buffered_lines.flatten() {
                lines.push(line.to_string());
            }

            RawFile {
                filename: filename.to_string(),
                lines,
            }
        }
        Err(error) => {
            error!("{}", error);
            exit(1);
        }
    }
}

fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where
    P: AsRef<Path>,
{
    let file = File::open(filename)?;
    Ok(io::BufReader::new(file).lines())
}