MCPcopy Create free account
hub / github.com/chatmail/core / export_database

Function export_database

src/imex.rs:741–790  ·  view source on GitHub ↗

Exports the database to *dest*, encrypted using *passphrase*. The directory of *dest* must already exist, if *dest* itself exists it will be overwritten. This also verifies that IO is not running during the export.

(
    context: &Context,
    dest: &Path,
    passphrase: String,
    timestamp: i64,
)

Source from the content-addressed store, hash-verified

739///
740/// This also verifies that IO is not running during the export.
741async fn export_database(
742 context: &Context,
743 dest: &Path,
744 passphrase: String,
745 timestamp: i64,
746) -> Result<()> {
747 ensure!(
748 !context.scheduler.is_running().await,
749 "cannot export backup, IO is running"
750 );
751 let timestamp = timestamp.try_into().context("32-bit UNIX time overflow")?;
752
753 // TODO: Maybe introduce camino crate for UTF-8 paths where we need them.
754 let dest = dest
755 .to_str()
756 .with_context(|| format!("path {} is not valid unicode", dest.display()))?;
757
758 context.set_config(Config::BccSelf, Some("1")).await?;
759 context
760 .sql
761 .set_raw_config_int("backup_time", timestamp)
762 .await?;
763 context
764 .sql
765 .set_raw_config_int("backup_version", DCBACKUP_VERSION)
766 .await?;
767 sql::housekeeping(context).await.log_err(context).ok();
768 context
769 .sql
770 .call_write(|conn| {
771 conn.execute("VACUUM;", ())
772 .map_err(|err| warn!(context, "Vacuum failed, exporting anyway {err}"))
773 .ok();
774 conn.execute("ATTACH DATABASE ? AS backup KEY ?", (dest, passphrase))
775 .context("failed to attach backup database")?;
776 let res = conn
777 .query_row("SELECT sqlcipher_export('backup')", [], |_row| Ok(()))
778 .context("failed to export to attached backup database");
779 conn.execute(
780 "UPDATE backup.config SET value='0' WHERE keyname='verified_one_on_one_chats';",
781 [],
782 )
783 .ok(); // Deprecated 2025-07. If verified_one_on_one_chats was not set, this errors, which we ignore
784 conn.execute("DETACH DATABASE backup", [])
785 .context("failed to detach backup database")?;
786 res?;
787 Ok(())
788 })
789 .await
790}
791
792async fn check_backup_version(context: &Context) -> Result<()> {
793 let version = (context.sql.get_raw_config_int("backup_version").await?).unwrap_or(2);

Callers 2

export_backupFunction · 0.85
prepareMethod · 0.85

Calls 7

housekeepingFunction · 0.85
set_raw_config_intMethod · 0.80
log_errMethod · 0.80
call_writeMethod · 0.80
executeMethod · 0.80
query_rowMethod · 0.80
set_configMethod · 0.45

Tested by

no test coverage detected