Skip to content

Commit

Permalink
Move data and log files into subdirectory
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasPickering committed Dec 5, 2023
1 parent 60f3596 commit fb7ee8c
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 23 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

### Changed

- Hide sensitive chain values in preview
- [BREAKING] Key profiles/chains/requests by ID in collection file
- [BREAKING] Move request history from `slumber/{id}.sqlite` to `slumber/{id}/requests.sqlite`
- Request history will be lost. If you want to recover it, you can move the old file to the new location (use `slumber show` to find the directory location)
- Hide sensitive chain values in preview
- Add collection ID/path to help modal ([#59](https://github.com/LucasPickering/slumber/issues/59))
- Also add collection ID to terminal title

Expand Down
4 changes: 2 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
collection::{ProfileId, RequestCollection, RequestRecipeId},
http::{HttpEngine, Repository, RequestBuilder},
template::{Prompt, Prompter, TemplateContext},
util::{data_directory, ResultExt},
util::{Directory, ResultExt},
};
use anyhow::{anyhow, Context};
use dialoguer::{Input, Password};
Expand Down Expand Up @@ -147,7 +147,7 @@ impl Subcommand {
}

Subcommand::Show => {
println!("Directory: {}", data_directory().display());
println!("Directory: {}", Directory::root());
Ok(())
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ pub struct RequestCollection<S = PathBuf> {

/// A unique ID for a collection. This is necessary to differentiate between
/// responses from different collections in the repository.
#[derive(Clone, Debug, Default, Display, From, Serialize, Deserialize)]
#[derive(
Clone, Debug, Default, Deref, Display, From, Serialize, Deserialize,
)]
pub struct CollectionId(String);

/// Mutually exclusive hot-swappable config group
Expand Down
13 changes: 8 additions & 5 deletions src/http/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::{
collection::{CollectionId, RequestRecipeId},
http::{Request, RequestId, RequestRecord, Response},
util::{data_directory, ResultExt},
util::{Directory, ResultExt},
};
use anyhow::Context;
use rusqlite::{
Expand Down Expand Up @@ -48,7 +48,7 @@ impl Repository {
/// Load the repository database. This will perform first-time setup, so
/// this should only be called at the main session entrypoint.
pub fn load(collection_id: &CollectionId) -> anyhow::Result<Self> {
let mut connection = Connection::open(Self::path(collection_id))?;
let mut connection = Connection::open(Self::path(collection_id)?)?;
// Use WAL for concurrency
connection.pragma_update(None, "journal_mode", "WAL")?;
Self::setup(&mut connection)?;
Expand All @@ -57,9 +57,12 @@ impl Repository {
})
}

/// Path to the repository database file
fn path(collection_id: &CollectionId) -> PathBuf {
data_directory().join(format!("{collection_id}.sqlite"))
/// Path to the repository database file. This will create the directory if
/// it doesn't exist
fn path(collection_id: &CollectionId) -> anyhow::Result<PathBuf> {
Ok(Directory::data(collection_id)
.create()?
.join("requests.sqlite"))
}

/// Apply first-time setup
Expand Down
5 changes: 2 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ mod tui;
mod util;

use crate::{
cli::Subcommand, collection::RequestCollection, tui::Tui,
util::data_directory,
cli::Subcommand, collection::RequestCollection, tui::Tui, util::Directory,
};
use anyhow::Context;
use clap::Parser;
Expand Down Expand Up @@ -60,7 +59,7 @@ async fn main() -> anyhow::Result<()> {

/// Set up tracing to log to a file
fn initialize_tracing() -> anyhow::Result<()> {
let directory = data_directory();
let directory = Directory::log().create()?;

std::fs::create_dir_all(&directory)
.context(format!("Error creating log directory {directory:?}"))?;
Expand Down
54 changes: 43 additions & 11 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
use crate::http::RequestError;
use crate::{collection::CollectionId, http::RequestError};
use std::{
fs,
ops::Deref,
path::{Path, PathBuf},
};
use tracing::error;

/// Where to store data and log files. The value is contextual:
/// - In development, use a directory in the current directory
/// - In release, use a platform-specific directory in the user's home
pub fn data_directory() -> PathBuf {
if cfg!(debug_assertions) {
Path::new("./data/").into()
} else {
// According to the docs, this dir will be present on all platforms
// https://docs.rs/dirs/latest/dirs/fn.data_dir.html
dirs::data_dir().unwrap().join("slumber")
/// A wrapper around `PathBuf` that makes it impossible to access a directory
/// path without creating the dir first. The idea is to prevent all the possible
/// bugs that could occur when a directory doesn't exist.
///
/// If you just want to print the path without having to create it (e.g. for
/// debug output), use the `Debug` or `Display` impls.
#[derive(Debug, Display)]
#[display("{}", _0.display())]
pub struct Directory(PathBuf);

impl Directory {
/// Root directory for all generated files. The value is contextual:
/// - In development, use a directory in the current directory
/// - In release, use a platform-specific directory in the user's home
pub fn root() -> Self {
if cfg!(debug_assertions) {
Self(Path::new("./data/").into())
} else {
// According to the docs, this dir will be present on all platforms
// https://docs.rs/dirs/latest/dirs/fn.data_dir.html
Self(dirs::data_dir().unwrap().join("slumber"))
}
}

/// Directory to store log files
pub fn log() -> Self {
Self(Self::root().0.join("log"))
}

/// Directory to store collection-specific data files
pub fn data(collection_id: &CollectionId) -> Self {
Self(Self::root().0.join(collection_id.as_str()))
}

/// Create this directory, and return the path. This is the only way to
/// access the path value directly, enforcing that it can't be used without
/// being created.
pub fn create(self) -> anyhow::Result<PathBuf> {
fs::create_dir_all(&self.0)?;
Ok(self.0)
}
}

Expand Down Expand Up @@ -61,3 +92,4 @@ macro_rules! assert_err {

#[cfg(test)]
pub(crate) use assert_err;
use derive_more::Display;

0 comments on commit fb7ee8c

Please sign in to comment.