mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Refactor context creation to a builder pattern
This mainly refactors context creation to use a builder pattern. It also adds a logdir option to this builder patter but doesn't yet use this.
This commit is contained in:
@@ -24,7 +24,7 @@ use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use deltachat::constants::DC_MSG_ID_LAST_SPECIAL;
|
||||
use deltachat::contact::Contact;
|
||||
use deltachat::context::Context;
|
||||
use deltachat::context::{Context, ContextBuilder};
|
||||
use deltachat::dc_tools::{
|
||||
as_path, dc_strdup, to_opt_string_lossy, to_string_lossy, OsStrExt, StrExt,
|
||||
};
|
||||
@@ -248,22 +248,15 @@ pub unsafe extern "C" fn dc_open(
|
||||
}
|
||||
let ffi_context = &*context;
|
||||
let rust_cb = move |_ctx: &Context, evt: Event| ffi_context.translate_cb(evt);
|
||||
|
||||
let ctx = if blobdir.is_null() || *blobdir == 0 {
|
||||
Context::new(
|
||||
Box::new(rust_cb),
|
||||
ffi_context.os_name.clone(),
|
||||
as_path(dbfile).to_path_buf(),
|
||||
)
|
||||
} else {
|
||||
Context::with_blobdir(
|
||||
Box::new(rust_cb),
|
||||
ffi_context.os_name.clone(),
|
||||
as_path(dbfile).to_path_buf(),
|
||||
as_path(blobdir).to_path_buf(),
|
||||
)
|
||||
};
|
||||
match ctx {
|
||||
let mut builder = ContextBuilder::new(
|
||||
Box::new(rust_cb),
|
||||
ffi_context.os_name.clone(),
|
||||
as_path(dbfile).to_path_buf(),
|
||||
);
|
||||
if !blobdir.is_null() && *blobdir != 0 {
|
||||
builder = builder.blobdir(as_path(blobdir).to_path_buf());
|
||||
}
|
||||
match builder.create() {
|
||||
Ok(ctx) => {
|
||||
let mut inner_guard = ffi_context.inner.write().unwrap();
|
||||
*inner_guard = Some(ctx);
|
||||
|
||||
@@ -366,11 +366,12 @@ fn main_0(args: Vec<String>) -> Result<(), failure::Error> {
|
||||
println!("Error: Bad arguments, expected [db-name].");
|
||||
return Err(format_err!("No db-name specified"));
|
||||
}
|
||||
let context = Context::new(
|
||||
let context = ContextBuilder::new(
|
||||
Box::new(receive_event),
|
||||
"CLI".into(),
|
||||
Path::new(&args[1]).to_path_buf(),
|
||||
)?;
|
||||
)
|
||||
.create()?;
|
||||
|
||||
println!("Delta Chat Core is awaiting your commands.");
|
||||
|
||||
|
||||
@@ -39,8 +39,9 @@ fn main() {
|
||||
let dir = tempdir().unwrap();
|
||||
let dbfile = dir.path().join("db.sqlite");
|
||||
println!("creating database {:?}", dbfile);
|
||||
let ctx =
|
||||
Context::new(Box::new(cb), "FakeOs".into(), dbfile).expect("Failed to create context");
|
||||
let ctx = ContextBuilder::new(Box::new(cb), "FakeOs".into(), dbfile)
|
||||
.create()
|
||||
.expect("Failed to create context");
|
||||
let running = Arc::new(RwLock::new(true));
|
||||
let info = ctx.get_info();
|
||||
let duration = time::Duration::from_millis(4000);
|
||||
|
||||
126
src/context.rs
126
src/context.rs
@@ -94,30 +94,92 @@ pub fn get_info() -> HashMap<&'static str, String> {
|
||||
res
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Creates new context.
|
||||
pub fn new(cb: Box<ContextCallback>, os_name: String, dbfile: PathBuf) -> Result<Context> {
|
||||
let mut blob_fname = OsString::new();
|
||||
blob_fname.push(dbfile.file_name().unwrap_or_default());
|
||||
/// Builder for [Context].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use deltachat::context::ContextBuilder;
|
||||
/// let dir = tempfile::tempdir().unwrap();
|
||||
/// let dbfile = dir.path().join("my-context.db");
|
||||
/// let ctx = ContextBuilder::new(Box::new(|_, _| 0), "AppName".into(), dbfile)
|
||||
/// .blobdir(dir.path().join("my-context-blobs"))
|
||||
/// .logdir(dir.path().join("my-context-logs"))
|
||||
/// .create()
|
||||
/// .unwrap();
|
||||
/// assert_eq!(ctx.get_blobdir(), dir.path().join("my-context-blobs"));
|
||||
/// ```
|
||||
#[derive(DebugStub)]
|
||||
pub struct ContextBuilder {
|
||||
#[debug_stub = "Callback"]
|
||||
cb: Box<ContextCallback>,
|
||||
os_name: String,
|
||||
dbfile: PathBuf,
|
||||
blobdir: PathBuf,
|
||||
logdir: PathBuf,
|
||||
}
|
||||
|
||||
impl ContextBuilder {
|
||||
pub fn new(cb: Box<ContextCallback>, os_name: String, dbfile: PathBuf) -> Self {
|
||||
let db_fname = OsString::from(dbfile.file_name().unwrap_or(&OsString::from("dc-context")));
|
||||
let mut blob_fname = db_fname.clone();
|
||||
blob_fname.push("-blobs");
|
||||
let blobdir = dbfile.with_file_name(blob_fname);
|
||||
if !blobdir.exists() {
|
||||
std::fs::create_dir_all(&blobdir)?;
|
||||
let mut log_fname = db_fname.clone();
|
||||
log_fname.push("-logs");
|
||||
ContextBuilder {
|
||||
cb,
|
||||
os_name,
|
||||
blobdir: dbfile.with_file_name(blob_fname),
|
||||
logdir: dbfile.with_file_name(log_fname),
|
||||
dbfile,
|
||||
}
|
||||
Context::with_blobdir(cb, os_name, dbfile, blobdir)
|
||||
}
|
||||
|
||||
pub fn with_blobdir(
|
||||
pub fn blobdir(mut self, path: PathBuf) -> Self {
|
||||
self.blobdir = path;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn logdir(mut self, path: PathBuf) -> Self {
|
||||
self.logdir = path;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn create(self) -> Result<Context> {
|
||||
if !self.blobdir.exists() {
|
||||
std::fs::create_dir_all(&self.blobdir)?;
|
||||
}
|
||||
if !self.logdir.exists() {
|
||||
std::fs::create_dir_all(&self.logdir)?;
|
||||
}
|
||||
Context::new(
|
||||
self.cb,
|
||||
self.os_name,
|
||||
self.dbfile,
|
||||
self.blobdir,
|
||||
self.logdir,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
fn new(
|
||||
cb: Box<ContextCallback>,
|
||||
os_name: String,
|
||||
dbfile: PathBuf,
|
||||
blobdir: PathBuf,
|
||||
logdir: PathBuf,
|
||||
) -> Result<Context> {
|
||||
ensure!(
|
||||
blobdir.is_dir(),
|
||||
"Blobdir does not exist: {}",
|
||||
blobdir.display()
|
||||
);
|
||||
ensure!(
|
||||
logdir.is_dir(),
|
||||
"Logdir does not exist: {}",
|
||||
logdir.display()
|
||||
);
|
||||
let ctx = Context {
|
||||
blobdir,
|
||||
dbfile,
|
||||
@@ -526,7 +588,7 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
std::fs::write(&dbfile, b"123").unwrap();
|
||||
let res = Context::new(Box::new(|_, _| 0), "FakeOs".into(), dbfile);
|
||||
let res = ContextBuilder::new(Box::new(|_, _| 0), "FakeOs".into(), dbfile).create();
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
@@ -541,7 +603,9 @@ mod tests {
|
||||
fn test_blobdir_exists() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
Context::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile).unwrap();
|
||||
ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile)
|
||||
.create()
|
||||
.unwrap();
|
||||
let blobdir = tmp.path().join("db.sqlite-blobs");
|
||||
assert!(blobdir.is_dir());
|
||||
}
|
||||
@@ -552,7 +616,7 @@ mod tests {
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
let blobdir = tmp.path().join("db.sqlite-blobs");
|
||||
std::fs::write(&blobdir, b"123").unwrap();
|
||||
let res = Context::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile);
|
||||
let res = ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile).create();
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
@@ -562,7 +626,9 @@ mod tests {
|
||||
let subdir = tmp.path().join("subdir");
|
||||
let dbfile = subdir.join("db.sqlite");
|
||||
let dbfile2 = dbfile.clone();
|
||||
Context::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile).unwrap();
|
||||
ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile)
|
||||
.create()
|
||||
.unwrap();
|
||||
assert!(subdir.is_dir());
|
||||
assert!(dbfile2.is_file());
|
||||
}
|
||||
@@ -572,7 +638,9 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
let blobdir = PathBuf::new();
|
||||
let res = Context::with_blobdir(Box::new(|_, _| 0), "FakeOS".into(), dbfile, blobdir);
|
||||
let res = ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile)
|
||||
.blobdir(blobdir)
|
||||
.create();
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
@@ -581,10 +649,36 @@ mod tests {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
let blobdir = tmp.path().join("blobs");
|
||||
let res = Context::with_blobdir(Box::new(|_, _| 0), "FakeOS".into(), dbfile, blobdir);
|
||||
ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile)
|
||||
.blobdir(blobdir.clone())
|
||||
.create()
|
||||
.unwrap();
|
||||
assert!(blobdir.is_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_empty_logdir() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
let logdir = PathBuf::new();
|
||||
let res = ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile)
|
||||
.logdir(logdir)
|
||||
.create();
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_logdir_not_exists() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dbfile = tmp.path().join("db.sqlite");
|
||||
let logdir = tmp.path().join("logs");
|
||||
ContextBuilder::new(Box::new(|_, _| 0), "FakeOS".into(), dbfile)
|
||||
.logdir(logdir.clone())
|
||||
.create()
|
||||
.unwrap();
|
||||
assert!(logdir.is_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_crashes_on_context_deref() {
|
||||
let t = dummy_context();
|
||||
|
||||
@@ -7,7 +7,7 @@ use tempfile::{tempdir, TempDir};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::constants::KeyType;
|
||||
use crate::context::{Context, ContextCallback};
|
||||
use crate::context::{Context, ContextBuilder, ContextCallback};
|
||||
use crate::events::Event;
|
||||
use crate::key;
|
||||
|
||||
@@ -33,7 +33,9 @@ pub fn test_context(callback: Option<Box<ContextCallback>>) -> TestContext {
|
||||
Some(cb) => cb,
|
||||
None => Box::new(|_, _| 0),
|
||||
};
|
||||
let ctx = Context::new(cb, "FakeOs".into(), dbfile).unwrap();
|
||||
let ctx = ContextBuilder::new(cb, "FakeOs".into(), dbfile)
|
||||
.create()
|
||||
.unwrap();
|
||||
TestContext { ctx: ctx, dir: dir }
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,9 @@ struct TestContext {
|
||||
fn create_test_context() -> TestContext {
|
||||
let dir = tempdir().unwrap();
|
||||
let dbfile = dir.path().join("db.sqlite");
|
||||
let ctx = Context::new(Box::new(cb), "FakeOs".into(), dbfile).unwrap();
|
||||
let ctx = ContextBuilder::new(Box::new(cb), "FakeOs".into(), dbfile)
|
||||
.create()
|
||||
.unwrap();
|
||||
TestContext { ctx, dir }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user