Skip to content

Commit b406c30

Browse files
committed
Update diff example to allow basic diffing of blobs.
This could be improved by adding color support, etc.
1 parent b1ebf6a commit b406c30

File tree

1 file changed

+61
-33
lines changed

1 file changed

+61
-33
lines changed

examples/diff.rs

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
#![deny(warnings)]
1616

17-
use git2::{Diff, DiffOptions, Error, Object, ObjectType, Repository};
18-
use git2::{DiffFindOptions, DiffFormat};
17+
use git2::{Blob, Diff, DiffOptions, Error, Object, ObjectType, Oid, Repository};
18+
use git2::{DiffDelta, DiffFindOptions, DiffFormat, DiffHunk, DiffLine};
1919
use std::str;
2020
use structopt::StructOpt;
2121

@@ -26,6 +26,9 @@ struct Args {
2626
arg_from_oid: Option<String>,
2727
#[structopt(name = "to_oid")]
2828
arg_to_oid: Option<String>,
29+
#[structopt(name = "blobs", long)]
30+
/// treat from_oid and to_oid as blob ids
31+
flag_blobs: bool,
2932
#[structopt(name = "patch", short, long)]
3033
/// show output in patch format
3134
flag_patch: bool,
@@ -137,6 +140,33 @@ enum Cache {
137140
None,
138141
}
139142

143+
fn line_color(line: &DiffLine) -> Option<&'static str> {
144+
match line.origin() {
145+
'+' => Some(GREEN),
146+
'-' => Some(RED),
147+
'>' => Some(GREEN),
148+
'<' => Some(RED),
149+
'F' => Some(BOLD),
150+
'H' => Some(CYAN),
151+
_ => None,
152+
}
153+
}
154+
155+
fn print_diff_line(_delta: DiffDelta, _hunk: Option<DiffHunk>, line: DiffLine, args: &Args) -> bool {
156+
if args.color() {
157+
print!("{}", RESET);
158+
if let Some(color) = line_color(&line) {
159+
print!("{}", color);
160+
}
161+
}
162+
match line.origin() {
163+
'+' | '-' | ' ' => print!("{}", line.origin()),
164+
_ => {}
165+
}
166+
print!("{}", str::from_utf8(line.content()).unwrap());
167+
true
168+
}
169+
140170
fn run(args: &Args) -> Result<(), Error> {
141171
let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or(".");
142172
let repo = Repository::open(path)?;
@@ -171,6 +201,26 @@ fn run(args: &Args) -> Result<(), Error> {
171201
opts.id_abbrev(40);
172202
}
173203

204+
if args.flag_blobs {
205+
let b1 = resolve_blob(&repo, args.arg_from_oid.as_ref())?;
206+
let b2 = resolve_blob(&repo, args.arg_to_oid.as_ref())?;
207+
repo.diff_blobs(
208+
b1.as_ref(),
209+
None,
210+
b2.as_ref(),
211+
None,
212+
Some(&mut opts),
213+
None,
214+
None,
215+
None,
216+
Some(&mut |d, h, l| print_diff_line(d, h, l, args)),
217+
)?;
218+
if args.color() {
219+
print!("{}", RESET);
220+
}
221+
return Ok(());
222+
}
223+
174224
// Prepare the diff to inspect
175225
let t1 = tree_to_treeish(&repo, args.arg_from_oid.as_ref())?;
176226
let t2 = tree_to_treeish(&repo, args.arg_to_oid.as_ref())?;
@@ -220,37 +270,7 @@ fn run(args: &Args) -> Result<(), Error> {
220270
print_stats(&diff, args)?;
221271
}
222272
if args.flag_patch || !stats {
223-
if args.color() {
224-
print!("{}", RESET);
225-
}
226-
let mut last_color = None;
227-
diff.print(args.diff_format(), |_delta, _hunk, line| {
228-
if args.color() {
229-
let next = match line.origin() {
230-
'+' => Some(GREEN),
231-
'-' => Some(RED),
232-
'>' => Some(GREEN),
233-
'<' => Some(RED),
234-
'F' => Some(BOLD),
235-
'H' => Some(CYAN),
236-
_ => None,
237-
};
238-
if args.color() && next != last_color {
239-
if last_color == Some(BOLD) || next == Some(BOLD) {
240-
print!("{}", RESET);
241-
}
242-
print!("{}", next.unwrap_or(RESET));
243-
last_color = next;
244-
}
245-
}
246-
247-
match line.origin() {
248-
'+' | '-' | ' ' => print!("{}", line.origin()),
249-
_ => {}
250-
}
251-
print!("{}", str::from_utf8(line.content()).unwrap());
252-
true
253-
})?;
273+
diff.print(args.diff_format(), |d, h, l| print_diff_line(d, h, l, args))?;
254274
if args.color() {
255275
print!("{}", RESET);
256276
}
@@ -292,6 +312,14 @@ fn tree_to_treeish<'a>(
292312
Ok(Some(tree))
293313
}
294314

315+
fn resolve_blob<'a>(repo: &'a Repository, arg: Option<&String>) -> Result<Option<Blob<'a>>, Error> {
316+
let arg = match arg {
317+
Some(s) => Oid::from_str(s)?,
318+
None => return Ok(None),
319+
};
320+
repo.find_blob(arg).map(|b| Some(b))
321+
}
322+
295323
impl Args {
296324
fn cache(&self) -> Cache {
297325
if self.flag_cached {

0 commit comments

Comments
 (0)