Skip to content

Commit 29a3afc

Browse files
committed
Initial commit.
0 parents  commit 29a3afc

8 files changed

Lines changed: 128 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
Cargo.lock

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
authors = ["steveklabnik <steve@steveklabnik.com>"]
3+
name = "dir-diff"
4+
version = "0.1.0"
5+
6+
[dependencies]
7+
diff = "0.1.10"
8+
walkdir = "1.0.7"

src/lib.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Determine if two directories have different contents.
2+
//!
3+
//! For now, only one function exists: are they different, or not? In the future,
4+
//! more functionality to actually determine the difference may be added.
5+
//!
6+
//! # Examples
7+
//!
8+
//! ```no_run
9+
//! extern crate dir_diff;
10+
//!
11+
//! assert!(dir_diff::is_different("dir/a", "dir/b").unwrap());
12+
//! ```
13+
14+
extern crate diff;
15+
extern crate walkdir;
16+
17+
use std::fs::File;
18+
use std::io::prelude::*;
19+
use std::path::Path;
20+
21+
use walkdir::WalkDir;
22+
23+
/// The various errors that can happen when diffing two directories
24+
#[derive(Debug)]
25+
pub enum Error {
26+
Io(std::io::Error),
27+
StripPrefix(std::path::StripPrefixError),
28+
WalkDir(walkdir::Error),
29+
}
30+
31+
/// Are two directories different?
32+
///
33+
/// # Examples
34+
///
35+
/// ```no_run
36+
/// extern crate dir_diff;
37+
///
38+
/// assert!(dir_diff::is_different("dir/a", "dir/b").unwrap());
39+
/// ```
40+
pub fn is_different<A: AsRef<Path>, B: AsRef<Path>>(a_base: A, b_base: B) -> Result<bool, Error> {
41+
let a_base = a_base.as_ref();
42+
let b_base = b_base.as_ref();
43+
44+
for entry in WalkDir::new(a_base) {
45+
let entry = entry?;
46+
let a = entry.path();
47+
48+
// calculate just the part of the path relative to a
49+
let no_prefix = a.strip_prefix(a_base)?;
50+
51+
// and then join that with b to get the path in b
52+
let b = b_base.join(no_prefix);
53+
54+
if a.is_dir() {
55+
if b.is_dir() {
56+
// can't compare the contents of directories, so just continue
57+
continue;
58+
} else {
59+
// if one is a file and one is a directory, we have a difference!
60+
return Ok(false)
61+
}
62+
}
63+
64+
let a_text = read_to_string(a)?;
65+
let b_text = read_to_string(b)?;
66+
67+
for result in diff::lines(&a_text, &b_text) {
68+
match result {
69+
diff::Result::Both(..) => (),
70+
_ => return Ok(false),
71+
}
72+
}
73+
}
74+
75+
Ok(true)
76+
}
77+
78+
fn read_to_string<P: AsRef<Path>>(file: P) -> Result<String, std::io::Error> {
79+
let mut data = String::new();
80+
let mut file = File::open(file.as_ref())?;
81+
82+
file.read_to_string(&mut data)?;
83+
84+
Ok(data)
85+
}
86+
87+
impl From<std::io::Error> for Error {
88+
fn from(e: std::io::Error) -> Error {
89+
Error::Io(e)
90+
}
91+
}
92+
93+
impl From<std::path::StripPrefixError> for Error {
94+
fn from(e: std::path::StripPrefixError) -> Error {
95+
Error::StripPrefix(e)
96+
}
97+
}
98+
99+
impl From<walkdir::Error> for Error {
100+
fn from(e: walkdir::Error) -> Error {
101+
Error::WalkDir(e)
102+
}
103+
}

tests/easy/bad/dir1/test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testing testing

tests/easy/bad/dir2/test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
oh no!

tests/easy/good/dir1/test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testing testing

tests/easy/good/dir2/test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testing testing

tests/smoke.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
extern crate dir_diff;
2+
3+
#[test]
4+
fn easy_good() {
5+
assert!(dir_diff::is_different("tests/easy/good/dir1", "tests/easy/good/dir2").unwrap());
6+
}
7+
8+
#[test]
9+
fn easy_bad() {
10+
assert!(!dir_diff::is_different("tests/easy/bad/dir1", "tests/easy/bad/dir2").unwrap());
11+
}

0 commit comments

Comments
 (0)