Skip to content

Commit 112182d

Browse files
authored
Merge pull request #61 from ZFordDev/55-migration-system-json-sqlite
migration from legacy JSON storage
2 parents c53d26e + 04bb0d8 commit 112182d

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

src/storage/migration.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""
2+
migration.py
3+
------------
4+
Handles migration from legacy JSON storage to the new SQLite database.
5+
6+
This module:
7+
- Detects old JSON file
8+
- Loads legacy tasks
9+
- Inserts them into the DB via Repository
10+
- Writes migration version into metadata
11+
- Archives the old JSON file
12+
"""
13+
14+
import json
15+
import os
16+
from typing import List
17+
18+
from storage.paths import get_json_path
19+
from storage.models import Entry
20+
from storage.repository import Repository
21+
22+
23+
MIGRATION_VERSION = "1"
24+
25+
26+
def needs_migration(repo: Repository) -> bool:
27+
"""
28+
Returns True if migration has not been performed yet.
29+
"""
30+
cursor = repo.conn.cursor()
31+
row = cursor.execute(
32+
"SELECT value FROM metadata WHERE key = 'migration_version'"
33+
).fetchone()
34+
35+
if row:
36+
return False # already migrated
37+
38+
# If JSON exists, migration is needed
39+
return os.path.exists(get_json_path())
40+
41+
42+
def run_migration(repo: Repository) -> None:
43+
"""
44+
Performs JSON → DB migration.
45+
"""
46+
json_path = get_json_path()
47+
48+
if not os.path.exists(json_path):
49+
return # nothing to migrate
50+
51+
print("[MIGRATION] Legacy JSON detected. Migrating to SQLite...")
52+
53+
# Load JSON
54+
try:
55+
with open(json_path, "r", encoding="utf-8") as f:
56+
data = json.load(f)
57+
except Exception as e:
58+
print(f"[MIGRATION ERROR] Failed to read JSON: {e}")
59+
return
60+
61+
tasks = data.get("tasks", [])
62+
63+
# Insert tasks into DB
64+
for t in tasks:
65+
title = t.get("text", "Untitled Task")
66+
date = t.get("date")
67+
time = t.get("time")
68+
69+
# Combine date + time into ISO 8601
70+
due_date = None
71+
if date and time:
72+
due_date = f"{date}T{time}"
73+
74+
entry = repo.create_entry(
75+
title=title,
76+
description=None,
77+
due_date=due_date,
78+
)
79+
80+
# Overwrite timestamps to preserve history
81+
repo.update_entry(
82+
entry.id,
83+
created_at=t.get("createdAt"),
84+
updated_at=t.get("updatedAt"),
85+
)
86+
87+
# Write migration version
88+
cursor = repo.conn.cursor()
89+
cursor.execute(
90+
"INSERT INTO metadata (key, value) VALUES ('migration_version', ?)",
91+
(MIGRATION_VERSION,),
92+
)
93+
repo.conn.commit()
94+
95+
# Archive JSON
96+
backup_path = json_path + ".bak"
97+
try:
98+
os.rename(json_path, backup_path)
99+
print(f"[MIGRATION] JSON archived to {backup_path}")
100+
except Exception as e:
101+
print(f"[MIGRATION WARNING] Could not archive JSON: {e}")
102+
103+
print("[MIGRATION] Completed successfully.")

0 commit comments

Comments
 (0)