Store relative accounts path in accounts.toml

This makes it possible to move accounts dir, especially useful for bots.
This commit is contained in:
link2xt
2022-12-12 18:54:30 +00:00
parent d1e3135331
commit 5922fb38da
3 changed files with 34 additions and 20 deletions

View File

@@ -9,6 +9,7 @@
add the new recipients as group members #3781 add the new recipients as group members #3781
- Remove `pytest-async` plugin #3846 - Remove `pytest-async` plugin #3846
- Only send the message about ephemeral timer change if the chat is promoted #3847 - Only send the message about ephemeral timer change if the chat is promoted #3847
- Use relative paths in `accounts.toml` #3838
### API-Changes ### API-Changes

View File

@@ -14,9 +14,7 @@ class Rpc:
if accounts_dir: if accounts_dir:
kwargs["env"] = { kwargs["env"] = {
**kwargs.get("env", os.environ), **kwargs.get("env", os.environ),
"DC_ACCOUNTS_PATH": os.path.abspath( "DC_ACCOUNTS_PATH": str(accounts_dir),
os.path.expanduser(str(accounts_dir))
),
} }
self._kwargs = kwargs self._kwargs = kwargs

View File

@@ -64,7 +64,7 @@ impl Accounts {
let events = Events::new(); let events = Events::new();
let stockstrings = StockStrings::new(); let stockstrings = StockStrings::new();
let accounts = config let accounts = config
.load_accounts(&events, &stockstrings) .load_accounts(&events, &stockstrings, &dir)
.await .await
.context("failed to load accounts")?; .context("failed to load accounts")?;
@@ -107,10 +107,11 @@ impl Accounts {
/// ///
/// Returns account ID. /// Returns account ID.
pub async fn add_account(&mut self) -> Result<u32> { pub async fn add_account(&mut self) -> Result<u32> {
let account_config = self.config.new_account(&self.dir).await?; let account_config = self.config.new_account().await?;
let dbfile = account_config.dbfile(&self.dir);
let ctx = Context::new( let ctx = Context::new(
&account_config.dbfile(), &dbfile,
account_config.id, account_config.id,
self.events.clone(), self.events.clone(),
self.stockstrings.clone(), self.stockstrings.clone(),
@@ -123,10 +124,10 @@ impl Accounts {
/// Adds a new closed account. /// Adds a new closed account.
pub async fn add_closed_account(&mut self) -> Result<u32> { pub async fn add_closed_account(&mut self) -> Result<u32> {
let account_config = self.config.new_account(&self.dir).await?; let account_config = self.config.new_account().await?;
let ctx = Context::new_closed( let ctx = Context::new_closed(
&account_config.dbfile(), &account_config.dbfile(&self.dir),
account_config.id, account_config.id,
self.events.clone(), self.events.clone(),
self.stockstrings.clone(), self.stockstrings.clone(),
@@ -147,6 +148,8 @@ impl Accounts {
drop(ctx); drop(ctx);
if let Some(cfg) = self.config.get_account(id) { if let Some(cfg) = self.config.get_account(id) {
let account_path = self.dir.join(cfg.dir);
// Spend up to 1 minute trying to remove the files. // Spend up to 1 minute trying to remove the files.
// Files may remain locked up to 30 seconds due to r2d2 bug: // Files may remain locked up to 30 seconds due to r2d2 bug:
// https://github.com/sfackler/r2d2/issues/99 // https://github.com/sfackler/r2d2/issues/99
@@ -154,7 +157,7 @@ impl Accounts {
loop { loop {
counter += 1; counter += 1;
if let Err(err) = fs::remove_dir_all(&cfg.dir) if let Err(err) = fs::remove_dir_all(&account_path)
.await .await
.context("failed to remove account data") .context("failed to remove account data")
{ {
@@ -187,16 +190,16 @@ impl Accounts {
// create new account // create new account
let account_config = self let account_config = self
.config .config
.new_account(&self.dir) .new_account()
.await .await
.context("failed to create new account")?; .context("failed to create new account")?;
let new_dbfile = account_config.dbfile(); let new_dbfile = account_config.dbfile(&self.dir);
let new_blobdir = Context::derive_blobdir(&new_dbfile); let new_blobdir = Context::derive_blobdir(&new_dbfile);
let new_walfile = Context::derive_walfile(&new_dbfile); let new_walfile = Context::derive_walfile(&new_dbfile);
let res = { let res = {
fs::create_dir_all(&account_config.dir) fs::create_dir_all(self.dir.join(&account_config.dir))
.await .await
.context("failed to create dir")?; .context("failed to create dir")?;
fs::rename(&dbfile, &new_dbfile) fs::rename(&dbfile, &new_dbfile)
@@ -358,8 +361,17 @@ impl Config {
/// Read a configuration from the given file into memory. /// Read a configuration from the given file into memory.
pub async fn from_file(file: PathBuf) -> Result<Self> { pub async fn from_file(file: PathBuf) -> Result<Self> {
let dir = file.parent().context("can't get config file directory")?;
let bytes = fs::read(&file).await.context("failed to read file")?; let bytes = fs::read(&file).await.context("failed to read file")?;
let inner: InnerConfig = toml::from_slice(&bytes).context("failed to parse config")?; let mut inner: InnerConfig = toml::from_slice(&bytes).context("failed to parse config")?;
// Previous versions of the core stored absolute paths in account config.
// Convert them to relative paths.
for account in &mut inner.accounts {
if let Ok(new_dir) = account.dir.strip_prefix(dir) {
account.dir = new_dir.to_path_buf();
}
}
Ok(Config { file, inner }) Ok(Config { file, inner })
} }
@@ -372,12 +384,13 @@ impl Config {
&self, &self,
events: &Events, events: &Events,
stockstrings: &StockStrings, stockstrings: &StockStrings,
dir: &Path,
) -> Result<BTreeMap<u32, Context>> { ) -> Result<BTreeMap<u32, Context>> {
let mut accounts = BTreeMap::new(); let mut accounts = BTreeMap::new();
for account_config in &self.inner.accounts { for account_config in &self.inner.accounts {
let ctx = Context::new( let ctx = Context::new(
&account_config.dbfile(), &account_config.dbfile(dir),
account_config.id, account_config.id,
events.clone(), events.clone(),
stockstrings.clone(), stockstrings.clone(),
@@ -386,7 +399,7 @@ impl Config {
.with_context(|| { .with_context(|| {
format!( format!(
"failed to create context from file {:?}", "failed to create context from file {:?}",
account_config.dbfile() account_config.dbfile(dir)
) )
})?; })?;
@@ -396,12 +409,12 @@ impl Config {
Ok(accounts) Ok(accounts)
} }
/// Create a new account in the given root directory. /// Creates a new account in the account manager directory.
async fn new_account(&mut self, dir: &Path) -> Result<AccountConfig> { async fn new_account(&mut self) -> Result<AccountConfig> {
let id = { let id = {
let id = self.inner.next_id; let id = self.inner.next_id;
let uuid = Uuid::new_v4(); let uuid = Uuid::new_v4();
let target_dir = dir.join(uuid.to_string()); let target_dir = PathBuf::from(uuid.to_string());
self.inner.accounts.push(AccountConfig { self.inner.accounts.push(AccountConfig {
id, id,
@@ -473,14 +486,16 @@ struct AccountConfig {
/// Unique id. /// Unique id.
pub id: u32, pub id: u32,
/// Root directory for all data for this account. /// Root directory for all data for this account.
///
/// The path is relative to the account manager directory.
pub dir: std::path::PathBuf, pub dir: std::path::PathBuf,
pub uuid: Uuid, pub uuid: Uuid,
} }
impl AccountConfig { impl AccountConfig {
/// Get the canoncial dbfile name for this configuration. /// Get the canoncial dbfile name for this configuration.
pub fn dbfile(&self) -> std::path::PathBuf { pub fn dbfile(&self, accounts_dir: &Path) -> std::path::PathBuf {
self.dir.join(DB_NAME) accounts_dir.join(&self.dir).join(DB_NAME)
} }
} }