mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-28 03:55:02 +03:00
use batch reader for deltas reader
This commit is contained in:
parent
6c6c86de82
commit
bcbf2f4d5e
@ -1,6 +1,6 @@
|
||||
use std::{collections::HashMap, path};
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use crate::{reader, sessions};
|
||||
|
||||
@ -16,6 +16,14 @@ impl<'reader> From<&'reader reader::Reader<'reader>> for DeltasReader<'reader> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ReadError {
|
||||
#[error("not found")]
|
||||
NotFound,
|
||||
#[error(transparent)]
|
||||
Other(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
impl<'reader> DeltasReader<'reader> {
|
||||
pub fn new(reader: &'reader sessions::Reader<'reader>) -> Self {
|
||||
DeltasReader {
|
||||
@ -24,43 +32,52 @@ impl<'reader> DeltasReader<'reader> {
|
||||
}
|
||||
|
||||
pub fn read_file<P: AsRef<std::path::Path>>(&self, path: P) -> Result<Option<Vec<Delta>>> {
|
||||
let path = path.as_ref();
|
||||
let file_deltas_path = std::path::Path::new("session/deltas").join(path);
|
||||
match self.reader.read(&file_deltas_path) {
|
||||
Ok(reader::Content::UTF8(content)) => {
|
||||
if content.is_empty() {
|
||||
// this is a leftover from some bug, shouldn't happen anymore
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(serde_json::from_str(&content)?))
|
||||
}
|
||||
}
|
||||
Ok(_) => Err(anyhow::anyhow!(
|
||||
"expected {} to be utf8 content",
|
||||
file_deltas_path.display()
|
||||
)),
|
||||
Err(reader::Error::NotFound) => Ok(None),
|
||||
match self.read(Some(&[path.as_ref()])) {
|
||||
Ok(deltas) => Ok(deltas.into_iter().next().map(|(_, deltas)| deltas)),
|
||||
Err(ReadError::NotFound) => Ok(None),
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
&self,
|
||||
paths: Option<&[&path::Path]>,
|
||||
) -> Result<HashMap<path::PathBuf, Vec<Delta>>> {
|
||||
filter: Option<&[&path::Path]>,
|
||||
) -> Result<HashMap<path::PathBuf, Vec<Delta>>, ReadError> {
|
||||
let deltas_dir = path::Path::new("session/deltas");
|
||||
let files = self.reader.list_files(deltas_dir)?;
|
||||
let mut result = HashMap::new();
|
||||
for file_path in files {
|
||||
if let Some(paths) = paths.as_ref() {
|
||||
if !paths.iter().any(|path| file_path.eq(path)) {
|
||||
continue;
|
||||
let mut paths = self.reader.list_files(deltas_dir)?;
|
||||
if let Some(filter) = filter {
|
||||
paths = paths
|
||||
.into_iter()
|
||||
.filter(|file_path| filter.iter().any(|path| file_path.eq(path)))
|
||||
.collect::<Vec<_>>();
|
||||
}
|
||||
paths = paths.iter().map(|path| deltas_dir.join(path)).collect();
|
||||
let files = match self.reader.batch(&paths) {
|
||||
Ok(files) => Ok(files),
|
||||
Err(reader::Error::NotFound) => return Err(ReadError::NotFound),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
if let Some(deltas) = self.read_file(file_path.clone())? {
|
||||
result.insert(file_path, deltas);
|
||||
.context("failed to read deltas")?;
|
||||
Ok(paths
|
||||
.into_iter()
|
||||
.zip(files)
|
||||
.filter_map(|(path, file)| {
|
||||
path.strip_prefix(deltas_dir)
|
||||
.ok()
|
||||
.map(|path| (path.to_path_buf(), file))
|
||||
})
|
||||
.filter_map(|(path, file)| {
|
||||
if let reader::Content::UTF8(content) = file {
|
||||
if content.is_empty() {
|
||||
// this is a leftover from some bug, shouldn't happen anymore
|
||||
return None;
|
||||
}
|
||||
let deltas = serde_json::from_str(&content).ok()?;
|
||||
Some(Ok((path, deltas)))
|
||||
} else {
|
||||
Some(Err(anyhow::anyhow!("unexpected content type")))
|
||||
}
|
||||
Ok(result)
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>>>()?)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user