Skip to content

Commit 94bf511

Browse files
committed
fix: hash-based cache naming + project root annotation (#40)
- Flat cache: .imports/<hash>-<filename> - Annotation: '(project root)' to avoid ambiguity REFERENCE: #40
1 parent 3baf93a commit 94bf511

File tree

5 files changed

+27
-39
lines changed

5 files changed

+27
-39
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!-- CHANGELOG.md -->
12
# CHANGELOG
23

34

src/workflow_as_list/executor/loader.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ def _add_annotations_to_source(self, workflow_path: Path, content: str) -> None:
7979
hash_value = self.compute_hash(expanded)
8080
rel_cache_path = cache_path.relative_to(self.base_path)
8181

82-
# Create annotation
82+
# Create annotation with explicit "project root" note
8383
indent = len(line) - len(line.lstrip())
8484
annotation = (
85-
" " * indent + f"# you see: <{rel_cache_path}> <{hash_value}>"
85+
" " * indent
86+
+ f"# you see: <{rel_cache_path}> (project root) <{hash_value}>"
8687
)
8788
added_annotations[import_path] = annotation
8889

@@ -129,7 +130,8 @@ def _expand_imports(self, content: str, base_path: Path, cache: bool = True) ->
129130
# Add annotation BEFORE import line (with matching indent)
130131
indent = len(line) - len(line.lstrip())
131132
annotation = (
132-
" " * indent + f"# you see: <{rel_cache_path}> <{hash_value}>"
133+
" " * indent
134+
+ f"# you see: <{rel_cache_path}> (project root) <{hash_value}>"
133135
)
134136
output.append(annotation)
135137

@@ -170,25 +172,27 @@ def _fetch_remote(self, url: str) -> str:
170172
raise RuntimeError(f"Failed to fetch {url}: {e}") from e
171173

172174
def _get_import_cache_path(self, import_path: str, base_path: Path) -> Path:
173-
"""Get cache file path for a single import.
175+
"""Get cache file path using hash-based naming (flat structure).
174176
175-
Each import is cached independently with a clear name.
177+
Design:
178+
- Cache files named by content hash prefix + original filename
179+
- Flat structure (no deep directories)
180+
- Deduplication: same content = same cache file
181+
- User reads import line for source, cache is internal storage
176182
"""
183+
# Fetch content to compute hash
184+
imported_content = self._fetch_import(import_path, base_path)
185+
content_hash = hashlib.sha256(imported_content.encode("utf-8")).hexdigest()[:16]
186+
187+
# Extract original filename for readability
177188
if import_path.startswith(("http://", "https://")):
178-
# URL: create path from URL structure
179-
# https://raw.githubusercontent.com/user/repo/main/file.workflow.list
180-
# → .imports/raw.githubusercontent.com/user/repo/main/file.workflow.list
181-
url_parts = (
182-
import_path.replace("https://", "").replace("http://", "").split("/")
183-
)
184-
cache_path = self.imports_dir / "/".join(url_parts)
189+
original_name = import_path.split("/")[-1]
185190
else:
186-
# Local path: preserve relative structure
187-
if Path(import_path).is_absolute():
188-
rel_path = Path(import_path).relative_to(base_path)
189-
else:
190-
rel_path = Path(import_path)
191-
cache_path = self.imports_dir / rel_path
191+
original_name = Path(import_path).name
192+
193+
# Format: <hash-prefix>-<original-name>
194+
cache_filename = f"{content_hash}-{original_name}"
195+
cache_path = self.imports_dir / cache_filename
192196

193197
cache_path.parent.mkdir(parents=True, exist_ok=True)
194198
return cache_path
@@ -199,8 +203,8 @@ def compute_hash(self, content: str) -> str:
199203
return f"sha256:{hash_value}"
200204

201205
def validate_cache_annotation(self, annotation: str) -> tuple[str, str] | None:
202-
"""Validate cache annotation format: # you see: <path> <algo:hash>."""
203-
pattern = r"# you see: <([\w./-]+)> <(sha256|md5):([a-f0-9]+)>"
206+
"""Validate cache annotation format: # you see: <path> (project root) <algo:hash>."""
207+
pattern = r"# you see: <([\w./-]+)> \(project root\) <(sha256|md5):([a-f0-9]+)>"
204208
match = re.match(pattern, annotation.strip())
205209
if not match:
206210
return None

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

workflow/test-import.workflow.list

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
# test-import.workflow.list
22
# Purpose: Test import caching mechanism
3-
#
4-
# This workflow tests the import expansion feature.
53

64
- (start) Test Import Workflow
7-
# Import base workflow for common steps
8-
# you see: <.imports/main.workflow.list> <sha256:6b30743e0e2cbec36c0c98c0fd27814a8ba6fd4a73aed0e40d020111cc199994>
5+
# you see: <.imports/6b30743e0e2cbec3-main.workflow.list> (project root) <sha256:6b30743e0e2cbec36c0c98c0fd27814a8ba6fd4a73aed0e40d020111cc199994>
96
import: ./main.workflow.list
107

11-
- (test) Local test step
12-
- Ask: Import caching works? (yes/no)
13-
- If yes: Print "SUCCESS"
14-
- If no: Print "FAILED"
15-
168
- End
Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
# test-remote-import.workflow.list
22
# Purpose: Test remote URL import caching
3-
#
4-
# This workflow tests remote import expansion.
53

64
- (start) Test Remote Import
7-
# Import from remote URL
8-
# you see: <.imports/raw.githubusercontent.com/tracer-mohist/workflow-as-list/refs/heads/main/examples/git/commit.workflow.list> <sha256:61726152b038af779e07b68db164187111b6d02a6427db25c03fd987f4ac0c30>
95
import: https://raw.githubusercontent.com/tracer-mohist/workflow-as-list/refs/heads/main/examples/git/commit.workflow.list
106

11-
- (test) Verify import
12-
- Ask: Remote import cached? (yes/no)
13-
- If yes: Print "SUCCESS"
14-
- If no: Print "FAILED"
15-
167
- End

0 commit comments

Comments
 (0)