+178
README.md
···+A modern CLI tool for persisting Atom/RSS feeds in Git repositories, designed to enable distributed webblog comment structures.
+169
pyproject.toml
···
+5
src/thicket/__init__.py
+6
src/thicket/__main__.py
+5
src/thicket/cli/__init__.py
+6
src/thicket/cli/commands/__init__.py
+193
src/thicket/cli/commands/add.py
···+display_name: Optional[str] = typer.Option(None, "--display-name", "-d", help="User display name"),+homepage=HttpUrl(homepage) if homepage else (discovered_metadata.author_uri or discovered_metadata.link if discovered_metadata else None),+icon=HttpUrl(icon) if icon else (discovered_metadata.logo or discovered_metadata.icon or discovered_metadata.image_url if discovered_metadata else None),+display_name=display_name or (discovered_metadata.author_name or discovered_metadata.title if discovered_metadata else None),
+121
src/thicket/cli/commands/duplicates.py
···+def add_duplicate(git_store: GitStore, duplicate_id: Optional[str], canonical_id: Optional[str]) -> None:
+77
src/thicket/cli/commands/init.py
···
+146
src/thicket/cli/commands/list_cmd.py
···
+142
src/thicket/cli/commands/sync.py
···+for feed_url in track(user_config.feeds, description=f"Syncing {user_config.username}'s feeds"):+print_info(f"User {user_config.username}: {user_new_entries} new, {user_updated_entries} updated")+commit_message = f"Sync feeds: {total_new_entries} new entries, {total_updated_entries} updated"+print_info(f"Dry run complete: would sync {total_new_entries} new entries, {total_updated_entries} updated")+print_success(f"Sync complete: {total_new_entries} new entries, {total_updated_entries} updated")+async def sync_feed(git_store: GitStore, username: str, feed_url, dry_run: bool) -> tuple[int, int]:
+45
src/thicket/cli/main.py
···
+125
src/thicket/cli/utils.py
···
+6
src/thicket/core/__init__.py
+262
src/thicket/core/feed_parser.py
···+def parse_feed(self, content: str, source_url: Optional[HttpUrl] = None) -> tuple[FeedMetadata, list[AtomEntry]]:+def _normalize_entry(self, entry: feedparser.FeedParserDict, source_url: Optional[HttpUrl] = None) -> AtomEntry:
+321
src/thicket/core/git_store.py
···
+15
src/thicket/models/__init__.py
···
+71
src/thicket/models/config.py
···
+86
src/thicket/models/feed.py
···
+79
src/thicket/models/user.py
···
+4
src/thicket/utils/__init__.py
tests/__init__.py
This is a binary file and will not be displayed.
+84
tests/conftest.py
···
+132
tests/test_feed_parser.py
···
+277
tests/test_git_store.py
···
+353
tests/test_models.py
···