Skip to content

Commit

Permalink
feat: add support for including specific files in git diff
Browse files Browse the repository at this point in the history
This commit adds support for including specific files in the `git diff` command. It introduces a new `include` option in the `Cmd` struct, which allows users to specify a list of files to include in the diff. The `include` option is then passed to the `git::diff` function, which appends the included files to the `git diff` command.

The motivation behind this change is to provide more flexibility in generating the diff. Users can now choose to include only specific files in the diff, rather than seeing the changes for all files in the repository. This can be useful in scenarios where users are only interested in reviewing changes in a subset of files.

The `include` option accepts a list of `PathBuf` objects, representing the paths of the files to include in the diff. These paths are then converted to strings and passed as arguments to the `git diff` command.

This commit also includes a new `pre_commit` module in the `external` module, which contains a `run` function. This function executes the `pre-commit` command with the `run` argument. If the command succeeds, the function returns `Ok(())`. Otherwise, an error is returned.

The `pre-commit` command is a popular tool for managing and enforcing pre-commit hooks in Git repositories. By running the `pre-commit` command before committing changes, users can ensure that their code adheres to certain standards and guidelines.

This change is part of an ongoing effort to improve the commit workflow and provide a more streamlined experience for users.
  • Loading branch information
liblaf committed Nov 18, 2023
1 parent 9db60f3 commit 259eb3b
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 4 deletions.
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ clap = { features = ["cargo", "derive", "env"], version = "4.4.8" }
clap_complete = "4.4.4"
colored = "2.0.4"
inquire = "0.6.2"
regex = "1.10.2"
tokio = { features = ["full"], version = "1.34.0" }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
Expand Down
40 changes: 38 additions & 2 deletions src/cmd/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use async_openai::Client;
use clap::Args;
use colored::Colorize;
use inquire::Select;
use regex::Regex;

use crate::cmd::Run;
use crate::common::log::LogResult;
Expand All @@ -22,6 +23,9 @@ pub struct Cmd {
#[arg(short, long)]
exclude: Vec<PathBuf>,

#[arg(short, long)]
include: Vec<PathBuf>,

#[arg(long, default_value = "gpt-3.5-turbo-16k")]
model: String,

Expand Down Expand Up @@ -55,12 +59,13 @@ impl Cmd {
#[async_trait::async_trait]
impl Run for Cmd {
async fn run(&self) -> anyhow::Result<()> {
crate::external::pre_commit::run()?;
let mut exclude: Vec<_> = EXCLUDE.iter().map(PathBuf::from).collect();
self.exclude
.iter()
.for_each(|f| exclude.push(f.to_path_buf()));
crate::external::git::status(&exclude)?;
let diff = crate::external::git::diff(exclude)?;
crate::external::git::status(&exclude, &self.include)?;
let diff = crate::external::git::diff(exclude, &self.include)?;
crate::ensure!(!diff.trim().is_empty());
let client = Client::with_config(OpenAIConfig::new().with_api_key(self.api_key()?));
let request = CreateChatCompletionRequestArgs::default()
Expand Down Expand Up @@ -104,10 +109,41 @@ impl Run for Cmd {
.choices
.iter()
.filter_map(|c| c.message.content.as_deref())
.filter_map(sanitize)
.collect(),
)
.prompt()
.log()?;
crate::external::git::commit(select)
}
}

fn sanitize<S>(message: S) -> Option<String>
where
S: AsRef<str>,
{
let message = message.as_ref();
let mut lines: Vec<_> = message.trim().split('\n').collect();
let subject = lines[0].trim();
let pattern: Regex =
Regex::new(r"(?P<type>\w+)(?:\((?P<scope>\w+)\))?(?P<breaking>!)?: (?P<description>.+)")
.log()
.unwrap();
let matches = pattern.captures(subject)?;
let type_ = matches.name("type")?.as_str();
let scope = matches.name("scope").map(|s| s.as_str().to_lowercase());
let breaking = matches.name("breaking").is_some();
let description = matches.name("description")?.as_str();
let description = description.chars().next()?.to_lowercase().to_string() + &description[1..];
let mut subject = type_.to_string();
if let Some(scope) = scope {
subject += &format!("({})", scope);
}
if breaking {
subject += "!";
}
subject += ": ";
subject += &description;
lines[0] = &subject;
Some(lines.join("\n"))
}
14 changes: 12 additions & 2 deletions src/external/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ where
Ok(())
}

pub fn diff<I, S>(exclude: I) -> Result<String>
pub fn diff<I, J, S, T>(exclude: I, include: J) -> Result<String>
where
I: IntoIterator<Item = S>,
J: IntoIterator<Item = T>,
S: AsRef<Path>,
T: AsRef<Path>,
{
let mut cmd = Command::new("git");
cmd.args(["diff", "--cached"]);
exclude.into_iter().for_each(|p| {
cmd.arg(format!(":(exclude){}", p.as_ref().to_str().unwrap()));
});
include.into_iter().for_each(|p| {
cmd.arg(p.as_ref().to_str().unwrap());
});
cmd.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::inherit());
Expand All @@ -45,10 +50,12 @@ where
String::from_utf8(output.stdout).log()
}

pub fn status<I, S>(exclude: I) -> Result<()>
pub fn status<I, J, S, T>(exclude: I, include: J) -> Result<()>
where
I: IntoIterator<Item = S>,
J: IntoIterator<Item = T>,
S: AsRef<Path>,
T: AsRef<Path>,
{
let mut cmd = Command::new("git");
if std::io::stdout().is_terminal() {
Expand All @@ -58,6 +65,9 @@ where
exclude.into_iter().for_each(|p| {
cmd.arg(format!(":(exclude){}", p.as_ref().to_str().unwrap()));
});
include.into_iter().for_each(|p| {
cmd.arg(p.as_ref().to_str().unwrap());
});
cmd.stdin(Stdio::null())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());
Expand Down
1 change: 1 addition & 0 deletions src/external/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod bitwarden;
pub mod git;
pub mod pre_commit;
16 changes: 16 additions & 0 deletions src/external/pre_commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use std::io::IsTerminal;
use std::process::Command;

use crate::common::log::LogResult;
use anyhow::Result;

pub fn run() -> Result<()> {
let mut cmd = Command::new("pre-commit");
cmd.arg("run");
if std::io::stdout().is_terminal() {
cmd.arg("--color=always");
}
let status = cmd.status()?;
crate::ensure!(status.success());
Ok(())
}

0 comments on commit 259eb3b

Please sign in to comment.