Skip to content

Commit

Permalink
feat: add compare-command
Browse files Browse the repository at this point in the history
  • Loading branch information
mstruebing committed Nov 19, 2020
1 parent 4db20d1 commit 89075e2
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]
### 馃殌 Added
- Add `compare`-command [#282](https://github.com/dotenv-linter/dotenv-linter/pull/282) ([@mstruebing](https://github.com/mstruebing))
- Add colored output feature and `--no-color` flag to disable colors [#307](https://github.com/dotenv-linter/dotenv-linter/pull/307) ([@Nikhil0487](https://github.com/Nikhil0487))
- Display linted files when run [#311](https://github.com/dotenv-linter/dotenv-linter/pull/311) ([@Anthuang](https://github.com/anthuang))
- Add export prefix support [#340](https://github.com/dotenv-linter/dotenv-linter/pull/340)([@skonik](https://github.com/skonik))
Expand Down
71 changes: 71 additions & 0 deletions src/lib.rs
@@ -1,5 +1,6 @@
use crate::common::*;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::error::Error;
use std::path::PathBuf;

Expand Down Expand Up @@ -135,6 +136,76 @@ fn get_needed_file_paths(args: &clap::ArgMatches) -> Vec<PathBuf> {
file_paths
}

// A structure used to compare environment files
#[derive(Debug)]
struct CompareFileType {
pub path: PathBuf,
pub keys: Vec<String>,
}

// Compares if different environment files contains the same variables and
// returns warnings if not
pub fn compare(
args: &clap::ArgMatches,
current_dir: &PathBuf,
) -> Result<Vec<String>, Box<dyn Error>> {
let mut warnings: Vec<String> = Vec::new();
let mut file_paths: Vec<PathBuf> = Vec::new();
let mut files_to_compare: Vec<CompareFileType> = Vec::new();
let mut all_keys: HashSet<String> = vec![].into_iter().collect();

// determine which files to compare
if let Some(inputs) = args.values_of("files") {
file_paths = inputs
.filter_map(|f| fs_utils::canonicalize(f).ok())
.collect();
}

// create CompareFileType structures for each file
for path in file_paths {
let mut keys: Vec<String> = Vec::new();
let relative_path = match fs_utils::get_relative_path(&path, &current_dir) {
Some(p) => p,
None => continue,
};

let (fe, strs) = match FileEntry::from(relative_path.clone()) {
Some(f) => f,
None => continue,
};

for line in get_line_entries(&fe, strs) {
if let Some(key) = line.get_key() {
all_keys.insert(key.clone());
keys.push(key)
}
}

let file_to_compare: CompareFileType = CompareFileType {
path: relative_path,
keys,
};

files_to_compare.push(file_to_compare);
}

// create warnings if any file misses any key
for file in files_to_compare {
// copy all keys
let mut missing_keys = all_keys.clone();
missing_keys.retain(|key| !file.keys.contains(key));

if !missing_keys.is_empty() {
warnings.push(format!(
"file: {:?} is missing keys: {:?}",
file.path, missing_keys
))
}
}

Ok(warnings)
}

fn get_file_paths(
dir_entries: Vec<PathBuf>,
excludes: &[PathBuf],
Expand Down
21 changes: 21 additions & 0 deletions src/main.rs
Expand Up @@ -33,6 +33,14 @@ fn main() -> Result<(), Box<dyn Error>> {

process::exit(0);
}
("compare", Some(files)) => {
if let Ok(warnings) = dotenv_linter::compare(&files, &current_dir) {
for warning in warnings {
println!("{}", warning);
process::exit(1);
}
}
}
_ => {
eprintln!("unknown command");
}
Expand Down Expand Up @@ -71,6 +79,19 @@ fn get_args(current_dir: &OsStr) -> clap::ArgMatches {
.usage("dotenv-linter fix [FLAGS] [OPTIONS] <input>...")
.about("Automatically fixes warnings"),
)
.subcommand(
SubCommand::with_name("compare")
.setting(AppSettings::ColoredHelp)
.visible_alias("c")
.arg(
Arg::with_name("files")
.help("Files to compare")
.multiple(true)
.required(true),
)
.about("Compares if files have the same keys")
.usage("dotenv_linter compare <files>"),
)
.get_matches()
}

Expand Down

0 comments on commit 89075e2

Please sign in to comment.