aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2020-07-26 18:17:11 +0200
committerTeddy Wing2020-07-26 18:17:11 +0200
commit1d15f9739f690f2e7afbb2bf868be74044ab3f30 (patch)
treeee40d91d56c475b84424e3f3bb9b70a0f775ee7e
parentced76c1ffce4da1dfcf286b3ef358c0662f6b5a1 (diff)
downloadgit-suggestion-1d15f9739f690f2e7afbb2bf868be74044ab3f30.tar.bz2
Suggestion: Add `diff` method
Create a patch file for the suggestion. Instead of building the patch text manually, as in my earlier attempts (`patch` and `unified_diff`), apply the patch to the file in memory, and then ask libgit2 to give us a Git patch by comparing the original blob and the patched buffer. Doing this because I was unsuccessful in manually composing a patch file that Git would accept. I could create unified diffs that the `patch` program would accept, but these wouldn't work with `git-apply`. My current guess is that these didn't work because I didn't have both before and after context in my manually-created patch files. Since this tool is intended to be used with Git, I want a patch file that will work transparently with Git utilities. The easiest alternative to manually generating the patch file seemed to be to have Git create the patch text. Add a new binary, `git-sugpatch`, that outputs the patch text to standard output. TODO: This gets the original from the current HEAD in `apply_to()`. We should instead be using the contents of `blob`, because the original is not necessarily the working copy.
-rw-r--r--src/bin/git-sugpatch.rs25
-rw-r--r--src/lib.rs40
2 files changed, 63 insertions, 2 deletions
diff --git a/src/bin/git-sugpatch.rs b/src/bin/git-sugpatch.rs
new file mode 100644
index 0000000..08d1a38
--- /dev/null
+++ b/src/bin/git-sugpatch.rs
@@ -0,0 +1,25 @@
+use std::env;
+use std::process;
+
+use git_suggested_patch::{Client, SuggestionUrl};
+
+
+fn main() {
+ let args: Vec<_> = env::args().collect();
+
+ if args.len() < 2 {
+ process::exit(111);
+ }
+
+ let url: SuggestionUrl = args[1].parse().unwrap();
+
+ let client = Client::new(
+ env!("GITHUB_TOKEN"),
+ &url.owner,
+ &url.repo,
+ );
+
+ let suggestion = client.fetch(&url.comment_id).unwrap();
+
+ print!("{}", suggestion.diff());
+}
diff --git a/src/lib.rs b/src/lib.rs
index f894413..0be907a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,10 +8,10 @@ pub use crate::url::SuggestionUrl;
use std::fs;
use std::fs::{File, OpenOptions};
-use std::io::{BufRead, BufReader, Write};
+use std::io::{BufRead, BufReader, BufWriter, Write};
use std::path::Path;
-use git2::Repository;
+use git2::{Patch, Repository};
use github_rs::client::{Executor, Github};
use regex::Regex;
use serde::Deserialize;
@@ -80,6 +80,9 @@ pub struct Suggestion {
#[serde(rename = "body")]
comment: String,
+ #[serde(rename = "original_commit_id")]
+ commit: String,
+
path: String,
original_start_line: Option<usize>,
@@ -89,6 +92,7 @@ pub struct Suggestion {
}
impl Suggestion {
+ // TODO: Rename to `diff`
pub fn patch(&self) -> String {
let mut diff: Vec<_> = self.diff.lines()
.filter(|l| !l.starts_with("-"))
@@ -110,6 +114,38 @@ impl Suggestion {
diff.join("\n")
}
+ pub fn diff(&self) -> String {
+ let repo = Repository::open(".").unwrap();
+ let commit = repo.find_commit(self.commit.parse().unwrap()).unwrap();
+
+ let path = Path::new(&self.path);
+
+ let object = commit
+ .tree().unwrap()
+ .get_path(path).unwrap()
+ .to_object(&repo).unwrap();
+
+ let blob = object.as_blob().unwrap();
+
+ let mut new = BufWriter::new(Vec::new());
+ self.apply_to(&self.path, &mut new).unwrap();
+ let new_buffer = new.into_inner().unwrap();
+
+ let mut diff = Patch::from_blob_and_buffer(
+ blob,
+ Some(&path),
+ &new_buffer,
+ Some(&path),
+ None,
+ ).unwrap();
+
+ diff.to_buf()
+ .unwrap()
+ .as_str()
+ .unwrap_or("")
+ .to_owned()
+ }
+
fn suggestion_patch(&self) -> String {
let re = Regex::new(r"(?s).*(?-s)```\s*suggestion.*\n").unwrap();
let s = re.replace(&self.comment, "+");