Skip to content

Commit

Permalink
Add scan_all and add_all methods
Browse files Browse the repository at this point in the history
  • Loading branch information
blissd committed Mar 17, 2024
1 parent 48afcc7 commit f4fda74
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 23 deletions.
37 changes: 18 additions & 19 deletions src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ pub struct Controller {
}

/// Summary of a scan
#[derive(Debug)]
#[derive(Debug, Default)]
pub struct ScanSummary {
/// Count of pictures scanned.
success_count: u32,
/// Count of pictures that could not be processed.
error_count: u32,
success_count: usize,
}

impl Controller {
Expand All @@ -28,28 +26,29 @@ impl Controller {
}

/// Scans all photos and adds them to the repository.
pub fn scan(&self) -> Result<ScanSummary> {
let mut summary = ScanSummary {
success_count: 0,
error_count: 0,
};

self.scan.visit_all(|pic| {
pub fn scan(&mut self) -> Result<ScanSummary> {
fn as_repo_pic(pic: scanner::Picture) -> repo::Picture {
let exif_date_time = pic.exif.and_then(|x| x.created_at);
let fs_date_time = pic.fs.and_then(|x| x.created_at);
let order_by_ts = exif_date_time.map(|d| d.to_utc()).or(fs_date_time);

let pic = repo::Picture {
repo::Picture {
relative_path: pic.relative_path,
order_by_ts,
};
match self.repo.add(&pic) {
Ok(_) => summary.success_count += 1,
Err(_) => summary.error_count += 1,
}
});

Ok(summary)
}

match self.scan.scan_all() {
Ok(pics) => {
// TODO can an interator be passes to add_all instead of a vector?
let pics = pics.into_iter().map(|p| as_repo_pic(p)).collect();
self.repo.add_all(&pics)?;
Ok(ScanSummary {
success_count: pics.len(),
})
}
Err(e) => Err(e),
}
}

/// Gets all photos.
Expand Down
26 changes: 26 additions & 0 deletions src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use crate::Error::*;
use crate::Result;
use chrono::*;
use rusqlite::params;
use rusqlite::Connection;
use rusqlite::Row;
use std::path;
Expand Down Expand Up @@ -78,6 +79,31 @@ impl Repository {
.map_err(|e| RepositoryError(e.to_string()))
}

/// Add all Pictures received from a vector.
pub fn add_all(&mut self, pics: &Vec<Picture>) -> Result<()> {
let tx = self
.con
.transaction()
.map_err(|e| RepositoryError(e.to_string()))?;

// Create a scope to make borrowing of tx not be an error.
{
let mut stmt = tx
.prepare_cached("INSERT INTO PICTURES (relative_path, order_by_ts) VALUES (?1, ?2)")
.map_err(|e| RepositoryError(e.to_string()))?;

for pic in pics {
stmt.execute(params![
pic.relative_path.as_path().to_str(),
pic.order_by_ts
])
.map_err(|e| RepositoryError(e.to_string()))?;
}
}

tx.commit().map_err(|e| RepositoryError(e.to_string()))
}

/// Gets all pictures in the repository, in ascending order of modification timestamp.
pub fn all(&self) -> Result<Vec<Picture>> {
let mut stmt = self
Expand Down
31 changes: 28 additions & 3 deletions src/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ impl Scanner {
Ok(Scanner { scan_base })
}

pub fn visit_all<F>(&self, func: F)
/// Scans all pictures in the base directory for function `func` to visit.
pub fn scan_all_visit<F>(&self, func: F)
where
F: FnMut(Picture),
{
Expand Down Expand Up @@ -119,6 +120,16 @@ impl Scanner {
.for_each(func); // visit
}

pub fn scan_all(&self) -> Result<Vec<Picture>> {
// Count of files in scan_base.
// Note: no filtering here, so count could be greater than number of pictures.
// Might want to use the same WalkDir logic in visit_all(...) to get exact count.
let file_count = WalkDir::new(&self.scan_base).into_iter().count();
let mut pics = Vec::with_capacity(file_count);
self.scan_all_visit(|pic| pics.push(pic));
Ok(pics)
}

pub fn scan_one(&self, path: &Path) -> Result<Picture> {
let file = fs::File::open(path).map_err(|e| ScannerError(e.to_string()))?;
let mut fs = FsMetadata::default();
Expand Down Expand Up @@ -223,14 +234,28 @@ mod tests {
}

#[test]
fn visit_all() {
fn scan_all_visit() {
let test_data_dir = picture_dir();
let mut count = 0;
let s = Scanner::build(&test_data_dir).unwrap();
s.visit_all(|_| count += 1);
s.scan_all_visit(|_| count += 1);
assert_eq!(5, count);
}

#[test]
fn scan_all() {
let test_data_dir = picture_dir();
let s = Scanner::build(&test_data_dir).unwrap();
let mut all = s.scan_all().unwrap();
assert_eq!(5, all.len());
all.sort_unstable_by(|a, b| a.relative_path.cmp(&b.relative_path));
assert!(all[0].relative_path.ends_with("Dog.jpg"));
assert!(all[1].relative_path.ends_with("Frog.jpg"));
assert!(all[2].relative_path.ends_with("Kingfisher.jpg"));
assert!(all[3].relative_path.ends_with("Lavender.jpg"));
assert!(all[4].relative_path.ends_with("Sandow.jpg"));
}

#[test]
fn scan_one() {
let test_data_dir = picture_dir();
Expand Down
2 changes: 1 addition & 1 deletion tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn test_scan_and_persist() {
Scanner::build(&pic_dir).unwrap()
};

let ctl = Controller::new(repo, scanner);
let mut ctl = Controller::new(repo, scanner);

ctl.scan().unwrap();

Expand Down

0 comments on commit f4fda74

Please sign in to comment.