Skip to content

Commit 9afdfcb

Browse files
committed
fix(persistence): Migrate settings to persistent user data directory
Addresses a critical bug where `settings.json` was being deleted during auto-updates, leading to loss of user data. This change: - Ensures `settings.json` is always stored in the OS-standard, persistent user data directory. - Implements a one-time migration process for existing users to move their `settings.json` from the application executable's directory to the new, safe location. - Updates documentation to reflect the new data storage strategy and migration.
1 parent 6b68662 commit 9afdfcb

File tree

6 files changed

+57
-12
lines changed

6 files changed

+57
-12
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [0.2.2]
6+
7+
### Fixed
8+
- **CRITICAL:** Fixed a major bug where `settings.json` was deleted during an auto-update, causing all user settings and repositories to be lost. The application now correctly stores all user data in the standard persistent user data directory. A one-time migration process has been added to automatically move existing settings for users updating from older versions.
9+
510
## [0.2.1]
611

712
### Added

FUNCTIONAL_MANUAL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ Click the **cog icon** in the header to access global settings.
119119
- **Check for Pre-Releases:** If enabled, the auto-updater will include beta and other pre-release versions when checking for updates.
120120
- **Enable Debug Logging:** Controls the verbose internal logging used by the Debug Panel. Disabling this may improve performance.
121121

122+
**Note on Data Safety:** All settings and repository configurations are stored in a safe location on your computer. This means your data will be automatically preserved when the application updates to a new version.
123+
122124
## 6. The Debug Panel
123125

124126
For advanced troubleshooting, a debug panel is available. You can open it by clicking the **"Debug"** button in the status bar at the very bottom of the window, or by pressing `Ctrl+D` (or `Cmd+D` on macOS).

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This application provides a simple, powerful dashboard to manage and automate th
1717
- **Advanced Debugging:** A powerful debug console with log filtering and a save-to-file feature for in-depth troubleshooting.
1818
- **Reliable Auto-Updates:** Get notified with a clear banner when a new version is ready and install it with a single click.
1919
- **Easy Configuration:** Add new repositories and configure them through a simple, unified form.
20+
- **Persistent & Safe Configuration:** All your settings and repository configurations are stored safely in a persistent location, ensuring they are never lost during application updates.
2021
- **Global Settings:** Customize the application theme, icon set, notifications, and behavior like enabling pre-release updates or choosing your preferred web browser.
2122
- **Cross-Platform:** Works on Windows, macOS, and Linux.
2223

TECHNICAL_MANUAL.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,17 @@ The application is split into three main processes, which is standard for Electr
4545
## 3. State Management and Data Flow
4646

4747
- **Primary State:** The root `App.tsx` component manages the entire application state, including the list of repositories, global settings, the active view, and the state of modals and panels. UI-specific state, such as the position and visibility of the right-click `ContextMenu`, is also managed here to ensure a single source of truth.
48-
- **Persistence:** All application data, including repositories and global settings, is persisted to a single `settings.json` file in the application's user data directory. A `SettingsProvider` context handles loading this data on startup and saving it whenever it changes.
4948
- **VCS State:** `App.tsx` also holds state for `detailedStatuses` and `branchLists` which are fetched periodically and after tasks complete to keep the UI in sync with the file system.
5049
- **Parallel Task Execution:** To support running multiple tasks concurrently, a unique `executionId` is generated for each task run. This ID is passed between the renderer and main processes, allowing log output (`task-log`) and completion events (`task-step-end`) to be correctly routed to the appropriate repository and UI components without conflict.
5150

51+
### Data Persistence
52+
53+
All application data, including repositories and global settings, is persisted to a single `settings.json` file.
54+
55+
- **Location:** The file is stored in the standard application user data directory for your operating system (e.g., `%APPDATA%` on Windows, `~/Library/Application Support` on macOS). This ensures that user settings are preserved across application updates.
56+
- **Management:** A `SettingsProvider` context handles loading this data on startup and saving it whenever it changes.
57+
- **Migration:** A one-time migration process runs on startup to move `settings.json` for users updating from versions prior to `0.2.2`, where the file was incorrectly stored next to the application executable.
58+
5259
## 4. Development Workflow
5360

5461
1. **Installation:** Run `npm install` to install all dependencies.

electron/main.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
import { app, BrowserWindow, dialog, ipcMain, shell } from 'electron';
42
import { autoUpdater } from 'electron-updater';
53
import path, { dirname } from 'path';
@@ -22,24 +20,52 @@ if (require('electron-squirrel-startup')) {
2220
app.quit();
2321
}
2422

25-
// --- Portable App Data Path ---
26-
const getAppDataPath = () => {
27-
// For portable app behavior, store data next to the executable in production.
28-
// In development, continue using the default userData path to avoid cluttering the project root.
29-
return app.isPackaged ? path.dirname(app.getPath('exe')) : app.getPath('userData');
23+
// --- App Data Path Configuration ---
24+
// User data is stored in the standard OS-specific location, which is persistent across updates.
25+
const userDataPath = app.getPath('userData');
26+
27+
// --- One-time Migration for Pre-0.2.2 Settings ---
28+
const migrateSettingsIfNeeded = async () => {
29+
// This is for users updating from v0.2.1 or older, where settings.json was stored next to the executable.
30+
if (!app.isPackaged) return; // Migration only needed for packaged apps.
31+
32+
const oldSettingsPath = path.join(path.dirname(app.getPath('exe')), 'settings.json');
33+
const newSettingsPath = path.join(userDataPath, 'settings.json');
34+
35+
try {
36+
// If the new settings file already exists, migration is complete or not needed.
37+
await fs.access(newSettingsPath);
38+
return;
39+
} catch (e) {
40+
// New file doesn't exist, proceed to check for the old one.
41+
}
42+
43+
try {
44+
// Check if the old settings file exists.
45+
await fs.access(oldSettingsPath);
46+
47+
// If it exists, copy it to the new location.
48+
await fs.mkdir(userDataPath, { recursive: true });
49+
await fs.copyFile(oldSettingsPath, newSettingsPath);
50+
console.log(`[Migration] Successfully migrated settings from ${oldSettingsPath} to ${newSettingsPath}`);
51+
} catch (e) {
52+
// This is expected for new installations where the old file doesn't exist.
53+
// console.log('[Migration] No old settings file found to migrate.');
54+
}
3055
};
3156

57+
3258
let mainWindow: BrowserWindow | null = null;
3359
let logStream: fsSync.WriteStream | null = null;
3460

3561
const getLogFilePath = () => {
3662
const now = new Date();
3763
const timestamp = now.toISOString().replace(/:/g, '-').replace(/\..+/, '');
38-
const logDir = path.join(getAppDataPath(), 'logs');
64+
const logDir = path.join(userDataPath, 'logs');
3965
return path.join(logDir, `git-automation-dashboard-log-${timestamp}.log`);
4066
};
4167

42-
const settingsPath = path.join(getAppDataPath(), 'settings.json');
68+
const settingsPath = path.join(userDataPath, 'settings.json');
4369
let globalSettingsCache: GlobalSettings | null = null;
4470

4571
const DEFAULTS: GlobalSettings = {
@@ -98,8 +124,11 @@ const createWindow = () => {
98124
// This method will be called when Electron has finished
99125
// initialization and is ready to create browser windows.
100126
app.on('ready', async () => {
127+
// Run migration before anything else that might access settings.
128+
await migrateSettingsIfNeeded();
129+
101130
// Ensure logs directory exists before creating a window or log file
102-
const logDir = path.join(getAppDataPath(), 'logs');
131+
const logDir = path.join(userDataPath, 'logs');
103132
fs.mkdir(logDir, { recursive: true }).catch(err => {
104133
console.error("Could not create logs directory.", err);
105134
});
@@ -191,6 +220,7 @@ ipcMain.handle('get-all-data', async () => {
191220

192221
ipcMain.on('save-all-data', async (event, data: { globalSettings: GlobalSettings, repositories: Repository[] }) => {
193222
try {
223+
await fs.mkdir(userDataPath, { recursive: true });
194224
await fs.writeFile(settingsPath, JSON.stringify(data, null, 2));
195225
globalSettingsCache = data.globalSettings; // Invalidate cache
196226
} catch (error) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "git-automation-dashboard",
3-
"version": "0.2.1",
3+
"version": "0.2.2",
44
"description": "A dashboard to manage and automate the workflow for a set of Git repositories.",
55
"main": "dist/main.js",
66
"author": "AI Assistant",

0 commit comments

Comments
 (0)