1- """File-system storage backend for graver."""
2-
31import difflib
42import json
53from datetime import datetime
1311
1412
1513class Storage :
16- """Handles all file system operations for graver.
17-
18- Args:
19- base_dir: Root directory for all prompt storage.
20- """
14+ """File-system backend; stores each prompt version as a plain-text file."""
2115
2216 def __init__ (self , base_dir : str = ".graver" ) -> None :
2317 self ._base = Path (base_dir ).resolve ()
@@ -50,18 +44,6 @@ def _latest_version_num(self, prompt_dir: Path) -> int:
5044 return max (int (f .stem [1 :]) for f in files )
5145
5246 def save (self , name : str , content : str ) -> str :
53- """Save a new version of a prompt.
54-
55- Args:
56- name: Prompt identifier.
57- content: The prompt text to persist.
58-
59- Returns:
60- The version string for the saved version (e.g. "v1").
61-
62- Raises:
63- StorageError: If any file write operation fails.
64- """
6547 prompt_dir = self ._prompt_dir (name )
6648 prompt_dir .mkdir (parents = True , exist_ok = True )
6749
@@ -95,19 +77,6 @@ def save(self, name: str, content: str) -> str:
9577 return version
9678
9779 def get (self , name : str , version : str | None = None ) -> str :
98- """Retrieve the content of a prompt version.
99-
100- Args:
101- name: Prompt identifier.
102- version: Version string to retrieve. If None, returns the latest.
103-
104- Returns:
105- The prompt text for the requested version.
106-
107- Raises:
108- PromptNotFoundError: If the prompt directory does not exist.
109- VersionNotFoundError: If the requested version file does not exist.
110- """
11180 prompt_dir = self ._prompt_dir (name )
11281 if not prompt_dir .exists ():
11382 raise PromptNotFoundError (
@@ -126,17 +95,6 @@ def get(self, name: str, version: str | None = None) -> str:
12695 return target .read_text (encoding = "utf-8" )
12796
12897 def history (self , name : str ) -> list [dict ]:
129- """Return the version history for a prompt.
130-
131- Args:
132- name: Prompt identifier.
133-
134- Returns:
135- A list of dicts with keys "version" and "timestamp".
136-
137- Raises:
138- PromptNotFoundError: If the prompt directory does not exist.
139- """
14098 prompt_dir = self ._prompt_dir (name )
14199 if not prompt_dir .exists ():
142100 raise PromptNotFoundError (
@@ -150,19 +108,6 @@ def history(self, name: str) -> list[dict]:
150108 return json .loads (history_path .read_text (encoding = "utf-8" ))
151109
152110 def diff (self , name : str , v1 : str , v2 : str ) -> dict :
153- """Compute a line-by-line diff between two versions.
154-
155- Args:
156- name: Prompt identifier.
157- v1: The base version string (e.g. "v1").
158- v2: The target version string (e.g. "v2").
159-
160- Returns:
161- A dict with keys "added", "removed", and "unchanged".
162-
163- Raises:
164- VersionNotFoundError: If either version does not exist.
165- """
166111 lines1 = self .get (name , v1 ).splitlines (keepends = True )
167112 lines2 = self .get (name , v2 ).splitlines (keepends = True )
168113
@@ -179,16 +124,6 @@ def diff(self, name: str, v1: str, v2: str) -> dict:
179124 return {"added" : added , "removed" : removed , "unchanged" : unchanged }
180125
181126 def set_main (self , name : str , version : str ) -> None :
182- """Mark a specific version as the main (canonical) version.
183-
184- Args:
185- name: Prompt identifier.
186- version: Version string to mark as main (e.g. "v2").
187-
188- Raises:
189- VersionNotFoundError: If the version does not exist.
190- StorageError: If the file write fails.
191- """
192127 if not self ._version_file (name , version ).exists ():
193128 raise VersionNotFoundError (
194129 f"Version '{ version } ' not found for prompt '{ name } '."
@@ -202,19 +137,6 @@ def set_main(self, name: str, version: str) -> None:
202137 raise StorageError (f"Failed to write main for '{ name } ': { exc } " ) from exc
203138
204139 def delete_version (self , name : str , version : str ) -> None :
205- """Delete a specific version of a prompt.
206-
207- Removes the version file and its entry from history. If the deleted
208- version was marked as main, the main pointer is also cleared.
209-
210- Args:
211- name: Prompt identifier.
212- version: Version string to delete (e.g. "v2").
213-
214- Raises:
215- VersionNotFoundError: If the version does not exist.
216- StorageError: If the file delete operation fails.
217- """
218140 version_path = self ._version_file (name , version )
219141 if not version_path .exists ():
220142 raise VersionNotFoundError (
@@ -243,18 +165,6 @@ def delete_version(self, name: str, version: str) -> None:
243165 self ._main_file (name ).unlink (missing_ok = True )
244166
245167 def delete_prompt (self , name : str ) -> None :
246- """Delete a prompt and all its versions.
247-
248- Removes the entire prompt directory including all version files,
249- history, and the main pointer.
250-
251- Args:
252- name: Prompt identifier.
253-
254- Raises:
255- PromptNotFoundError: If the prompt does not exist.
256- StorageError: If the directory removal fails.
257- """
258168 prompt_dir = self ._prompt_dir (name )
259169 if not prompt_dir .exists ():
260170 raise PromptNotFoundError (f"Prompt '{ name } ' not found." )
@@ -266,22 +176,9 @@ def delete_prompt(self, name: str) -> None:
266176 raise StorageError (f"Failed to delete prompt '{ name } ': { exc } " ) from exc
267177
268178 def list_prompts (self ) -> list [str ]:
269- """Return the names of all saved prompts.
270-
271- Returns:
272- A sorted list of prompt name strings.
273- """
274179 return sorted (d .name for d in self ._base .iterdir () if d .is_dir ())
275180
276181 def get_main (self , name : str ) -> str | None :
277- """Return the version string marked as main, or None if not set.
278-
279- Args:
280- name: Prompt identifier.
281-
282- Returns:
283- The main version string (e.g. "v2"), or None if not set.
284- """
285182 main_path = self ._main_file (name )
286183 if not main_path .exists ():
287184 return None
0 commit comments