From cb347d290ad15cd3871fbcf2e744c54ab086712c Mon Sep 17 00:00:00 2001 From: Dylan Ravel Date: Wed, 24 Dec 2025 00:34:59 -0700 Subject: [PATCH] Add development mode with separate database location Introduces a development mode activated by the TMPO_DEV environment variable, which uses a separate database directory (~/.tmpo-dev/) to prevent accidental modification of production data. Updates documentation to explain usage, benefits, and database locations for both production and development modes. --- CONTRIBUTING.md | 54 +++++++++++++++++++++++++++++++++++++++--- internal/storage/db.go | 16 +++++++++---- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d9f289..37b3d6a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,6 +37,48 @@ go build -o tmpo . ./tmpo --help ``` +### Development Mode + +To prevent corrupting your real tmpo data during development, use the `TMPO_DEV` environment variable: + +```bash +# Enable development mode (uses ~/.tmpo-dev/ instead of ~/.tmpo/) +export TMPO_DEV=1 + +# Now all commands use the development database +./tmpo start "Testing new feature" +./tmpo status +./tmpo stop +``` + +**Database Locations:** + +- **Production mode** (default): `~/.tmpo/tmpo.db` +- **Development mode** (`TMPO_DEV=1`): `~/.tmpo-dev/tmpo.db` + +> [!NOTE] +> The `export TMPO_DEV=1` command only applies to your **current terminal session**. When you close the terminal, it resets to production mode. This is intentional for safety - you must explicitly enable dev mode each time. + +**Making it persistent (optional):** + +If you prefer to always use dev mode, add it to your shell profile: + +```bash +# For zsh (macOS default) +echo 'export TMPO_DEV=1' >> ~/.zshrc + +# For bash +echo 'export TMPO_DEV=1' >> ~/.bashrc +``` + +Then restart your terminal or run `source ~/.zshrc` (or `source ~/.bashrc`). + +**Benefits of development mode:** + +- Your real time tracking data stays safe +- You can test database changes without risk +- You can easily clean up test data (`rm -rf ~/.tmpo-dev/`) + ### Building with Version Information To build with version information injected (useful for testing version display): @@ -120,16 +162,22 @@ tmpo/ All user data is stored locally in: ``` -~/.tmpo/ - └── tmpo.db # SQLite database +~/.tmpo/ # Production (default) + └── tmpo.db + +~/.tmpo-dev/ # Development (when TMPO_DEV=1) + └── tmpo.db ``` The database schema includes: -- Time entries (start/end times, project, description) +- Time entries (start/end times, project, description, hourly rate) - Project metadata (derived from entries) - Automatic indexing for fast queries +> [!NOTE] +> See [Development Mode](#development-mode) for information on using the development database during local development. + ### How Project Detection Works When a user runs `tmpo start`, the project name is detected in this priority order: diff --git a/internal/storage/db.go b/internal/storage/db.go index 7d00643..5c7bb4a 100644 --- a/internal/storage/db.go +++ b/internal/storage/db.go @@ -24,11 +24,14 @@ type Database struct { // Initialize ensures the on-disk storage for the application exists, opens the // SQLite database, and returns a Database wrapper. -// +// // Specifically, Initialize: // - determines the current user's home directory, -// - creates the directory "$HOME/.tmpo" if it does not already exist, -// - opens (or creates) the SQLite database file "$HOME/.tmpo/tmpo.db", +// - checks the TMPO_DEV environment variable: +// - if TMPO_DEV is "1" or "true", uses "$HOME/.tmpo-dev" (development mode), +// - otherwise uses "$HOME/.tmpo" (production mode, the default), +// - creates the appropriate directory if it does not already exist, +// - opens (or creates) the SQLite database file "tmpo.db" in that directory, // - ensures the time_entries table exists with the schema: // id INTEGER PRIMARY KEY AUTOINCREMENT, // project_name TEXT NOT NULL, @@ -42,12 +45,17 @@ type Database struct { // responsible for closing the database when finished. func Initialize() (*Database, error) { homeDir, err := os.UserHomeDir() - + if err != nil { return nil, fmt.Errorf("failed to get home directory: %w", err) } + // Switch out directory depending on build environment tmpoDir := filepath.Join(homeDir, ".tmpo") + if devMode := os.Getenv("TMPO_DEV"); devMode == "1" || devMode == "true" { + tmpoDir = filepath.Join(homeDir, ".tmpo-dev") + } + if err := os.MkdirAll(tmpoDir, 0755); err != nil { return nil, fmt.Errorf("failed to create .tmpo directory: %w", err) }