Avoid registering changes if hashes are not needed

This commit is contained in:
RumovZ 2022-04-29 10:35:19 +02:00
parent 146fd2a6b6
commit 76f4bf26ea
3 changed files with 46 additions and 23 deletions

View file

@ -187,7 +187,7 @@ impl<'n> NoteContext<'n> {
fn import_notes(&mut self, notes: Vec<Note>, progress_fn: &mut ProgressFn) -> Result<()> { fn import_notes(&mut self, notes: Vec<Note>, progress_fn: &mut ProgressFn) -> Result<()> {
let mut progress = IncrementalProgress::new(|u| progress_fn(ImportProgress::Notes(u))); let mut progress = IncrementalProgress::new(|u| progress_fn(ImportProgress::Notes(u)));
for mut note in notes.into_iter() { for mut note in notes {
progress.increment()?; progress.increment()?;
if let Some(notetype_id) = self.remapped_notetypes.get(&note.notetype_id) { if let Some(notetype_id) = self.remapped_notetypes.get(&note.notetype_id) {
if self.target_guids.contains_key(&note.guid) { if self.target_guids.contains_key(&note.guid) {

View file

@ -48,7 +48,7 @@ pub fn import_colpkg(
restore_media( restore_media(
&meta, &meta,
progress_fn, &mut progress_fn,
&mut archive, &mut archive,
target_media_folder, target_media_folder,
media_db, media_db,
@ -88,17 +88,13 @@ fn restore_media(
} }
std::fs::create_dir_all(media_folder)?; std::fs::create_dir_all(media_folder)?;
let media_manager = MediaManager::new(media_folder, media_db)?; let media_manager = MediaManager::new(media_folder, media_db)?;
let mut db_progress_fn = |u| progress_fn(ImportProgress::MediaCheck(u)).is_ok(); let mut media_comparer = MediaComparer::new(meta, &mut progress_fn, &media_manager, log)?;
media_manager.register_changes(&mut db_progress_fn, log)?;
let mut get_checksum = media_manager.checksum_getter();
let mut progress = IncrementalProgress::new(|u| progress_fn(ImportProgress::Media(u))); let mut progress = IncrementalProgress::new(|u| progress_fn(ImportProgress::Media(u)));
for mut entry in media_entries {
for entry in &media_entries {
progress.increment()?; progress.increment()?;
maybe_restore_media_file(meta, media_folder, archive, entry, &mut get_checksum)?; maybe_restore_media_file(meta, media_folder, archive, &mut entry, &mut media_comparer)?;
} }
Ok(()) Ok(())
@ -108,12 +104,16 @@ fn maybe_restore_media_file(
meta: &Meta, meta: &Meta,
media_folder: &Path, media_folder: &Path,
archive: &mut ZipArchive<File>, archive: &mut ZipArchive<File>,
entry: &SafeMediaEntry, entry: &mut SafeMediaEntry,
get_checksum: &mut impl FnMut(&str) -> Result<Option<Sha1Hash>>, media_comparer: &mut MediaComparer,
) -> Result<()> { ) -> Result<()> {
let file_path = entry.file_path(media_folder); let file_path = entry.file_path(media_folder);
let mut zip_file = entry.fetch_file(archive)?; let mut zip_file = entry.fetch_file(archive)?;
let already_exists = entry.is_equal_to(meta, &zip_file, &file_path, get_checksum)?; if meta.media_list_is_hashmap() {
entry.size = zip_file.size() as u32;
}
let already_exists = media_comparer.entry_is_equal_to(entry, &file_path)?;
if !already_exists { if !already_exists {
restore_media_file(meta, &mut zip_file, &file_path)?; restore_media_file(meta, &mut zip_file, &file_path)?;
}; };
@ -150,3 +150,31 @@ fn copy_collection(
Ok(()) Ok(())
} }
#[allow(clippy::type_complexity)]
struct MediaComparer<'a>(Option<Box<dyn FnMut(&str) -> Result<Option<Sha1Hash>> + 'a>>);
impl<'a> MediaComparer<'a> {
fn new(
meta: &Meta,
mut progress_fn: impl FnMut(ImportProgress) -> Result<()>,
media_manager: &'a MediaManager,
log: &Logger,
) -> Result<Self> {
Ok(Self(if meta.media_list_is_hashmap() {
None
} else {
let mut db_progress_fn = |u| progress_fn(ImportProgress::MediaCheck(u)).is_ok();
media_manager.register_changes(&mut db_progress_fn, log)?;
Some(Box::new(media_manager.checksum_getter()))
}))
}
fn entry_is_equal_to(&mut self, entry: &SafeMediaEntry, other_path: &Path) -> Result<bool> {
if let Some(ref mut get_checksum) = self.0 {
Ok(entry.has_checksum_equal_to(get_checksum)?)
} else {
Ok(entry.has_size_equal_to(other_path))
}
}
}

View file

@ -25,7 +25,6 @@ use crate::{
/// Like [MediaEntry], but with a safe filename and set zip filename. /// Like [MediaEntry], but with a safe filename and set zip filename.
pub(super) struct SafeMediaEntry { pub(super) struct SafeMediaEntry {
pub(super) name: String, pub(super) name: String,
#[allow(dead_code)]
pub(super) size: u32, pub(super) size: u32,
pub(super) sha1: Sha1Hash, pub(super) sha1: Sha1Hash,
pub(super) index: usize, pub(super) index: usize,
@ -86,19 +85,15 @@ impl SafeMediaEntry {
.map_err(|_| AnkiError::invalid_input(&format!("{} missing from archive", self.index))) .map_err(|_| AnkiError::invalid_input(&format!("{} missing from archive", self.index)))
} }
pub(super) fn is_equal_to( pub(super) fn has_checksum_equal_to(
&self, &self,
meta: &Meta,
self_zipped: &ZipFile,
other_path: &Path,
get_checksum: &mut impl FnMut(&str) -> Result<Option<Sha1Hash>>, get_checksum: &mut impl FnMut(&str) -> Result<Option<Sha1Hash>>,
) -> Result<bool> { ) -> Result<bool> {
if meta.media_list_is_hashmap() {
Ok(fs::metadata(other_path)
.map_or(false, |metadata| metadata.len() == self_zipped.size()))
} else {
get_checksum(&self.name).map(|opt| opt.map_or(false, |sha1| sha1 == self.sha1)) get_checksum(&self.name).map(|opt| opt.map_or(false, |sha1| sha1 == self.sha1))
} }
pub(super) fn has_size_equal_to(&self, other_path: &Path) -> bool {
fs::metadata(other_path).map_or(false, |metadata| metadata.len() == self.size as u64)
} }
pub(super) fn copy_from_archive( pub(super) fn copy_from_archive(