Skip to content

Commit

Permalink
feat(besafe): added base pre-commit hook
Browse files Browse the repository at this point in the history
  • Loading branch information
pybash1 committed May 28, 2024
1 parent 5bc90ec commit 1a68345
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/besafe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::utils::{code_to_enum, Status};
use std::process::{exit, Command};

pub fn besafe() {
let mut gs = Command::new("git");
gs.arg("status").arg("-s");

let output_raw = gs.output().unwrap();
let output = String::from_utf8_lossy(&output_raw.stdout);
let files: Vec<String> = output
.split("\n")
.map(|i| i.to_owned())
.filter(|i| !i.is_empty())
.collect();

for file in files.iter() {
let mut file_split = file.split_whitespace();
let code = file_split.next().expect("Failed to get file status!");
let file_name = file_split.next().expect("Failed to get file info!");
let status = code_to_enum(code);
if file_name.starts_with(".env") && file_name != ".env.example" {
match status {
Status::Staged => {
println!("[besafe] {} file is staged! Unstage it and add it to .gitignore before committing.", file_name);
exit(1);
},
Status::Modified => {
println!("[besafe] {} file has changes and is not in .gitignore! Remove it and add it to .gitignore before committing.", file_name);
exit(1);
},
Status::StagedModified => {
println!("[besafe] {} file staged! Unstage it and add it to .gitignore before committing.", file_name);
exit(1);
},
Status::Untracked => println!("[besafe] {} file is not in .gitignore! Consider adding it.", file_name),
Status::Unknown => println!("[besafe] {} file found in git history but status cannot be determined! Make sure it doesn't contain any sensitive data before committing", file_name),
}
}
}
println!("No unsafe .env problems found!");
}
34 changes: 34 additions & 0 deletions src/install.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::{
env::current_exe,
fs::{read_to_string, write},
path::PathBuf,
};

const PRE_COMMIT_PATH: &str = ".git/hooks/pre-commit";

pub fn install_hook() {
let path = PathBuf::from(PRE_COMMIT_PATH);
let mut file = read_to_string(&path).unwrap_or(String::from(""));

let mut current_path = current_exe()
.unwrap_or(PathBuf::new())
.as_path()
.to_string_lossy()
.to_string();

if cfg!(windows) {
current_path = current_path.replace("\\", "/");
current_path = current_path.replace(":/", "/");
current_path = "/".to_string() + current_path.as_str();
}

file += format!("\n\n{}", current_path).as_str();

if !file.starts_with("#!/") {
file = String::from("#!/bin/sh\n\n") + &file;
}

write(path, file).expect("Failed to install pre-commit hook!");

println!("Successfully installed pre-commit hook!");
}
34 changes: 34 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::process::exit;

use besafe::besafe;
use clap::Command;
use install::install_hook;

mod besafe;
mod install;
mod utils;

fn main() {
let install = Command::new("install");

let cli = Command::new("besafe")
.version(clap::crate_version!())
.author(clap::crate_authors!())
.about("A simple Git pre-commit hook for preventing commiting of .env files!")
.subcommand(install);

match cli.try_get_matches() {
Ok(matches) => match matches.subcommand_name() {
Some("install") => install_hook(),
None => {
println!("[besafe] Checking...");
besafe();
}
Some(_) => {}
},
Err(_) => {
println!("[besafe] Invalid command!");
exit(1);
}
}
}
18 changes: 18 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[derive(Debug)]
pub enum Status {
Untracked, // ??
Staged, // A
Modified, // M
StagedModified, // AM
Unknown,
}

pub fn code_to_enum(code: &str) -> Status {
match code {
"??" => Status::Untracked,
"A" => Status::Staged,
"M" => Status::Modified,
"AM" => Status::StagedModified,
_ => Status::Unknown,
}
}

0 comments on commit 1a68345

Please sign in to comment.