Feature: Import collections from a Git URL #97

Open
opened 2026-06-03 16:39:44 +00:00 by thabeta · 1 comment
Owner

Problem

Currently there is no way to pull a set of slides into hero_slides from an external Git repository. Users need a way to import and sync slide collections.

Proposed solution

Add a command (or UI flow) that takes a Git URL, clones/pulls the repo into the correct local location, and registers it as a collection in hero_slides.

We already have hero_lib code for Git operations (clone, pull, resolve to the right path), so the implementation can lean on that rather than rolling our own.

Acceptance criteria

  • User can provide a Git URL (HTTPS or SSH)
  • Repo is cloned into the correct local collections directory
  • Existing collections can be updated via pull/sync
  • Auth is handled via existing hero_lib Git utilities (no new auth surface)
  • CLI command and/or UI entry point for the flow

Notes

hero_lib already provides Git helpers — look for the existing module before implementing anything custom.

## Problem Currently there is no way to pull a set of slides into hero_slides from an external Git repository. Users need a way to import and sync slide collections. ## Proposed solution Add a command (or UI flow) that takes a Git URL, clones/pulls the repo into the correct local location, and registers it as a collection in hero_slides. We already have hero_lib code for Git operations (clone, pull, resolve to the right path), so the implementation can lean on that rather than rolling our own. ## Acceptance criteria - [ ] User can provide a Git URL (HTTPS or SSH) - [ ] Repo is cloned into the correct local collections directory - [ ] Existing collections can be updated via `pull`/`sync` - [ ] Auth is handled via existing hero_lib Git utilities (no new auth surface) - [ ] CLI command and/or UI entry point for the flow ## Notes hero_lib already provides Git helpers — look for the existing module before implementing anything custom.
Member

Investigated reusing herolib_os::git here — it's a net regression for this feature, so we keep our own module

The issue says to lean on hero_lib's git helpers "rather than rolling our own" with "no new auth surface." I checked the actual herolib_os::git module (crates/os/src/git/, locked main rev) against our hero_slides_lib/src/git.rs. Two blockers make a switch worse, not better:

1. GitRepo can't authenticate a private repo. Its pull/push/fetch/commit are bare git -C <path> ... — no http.extraHeader token and no GIT_TERMINAL_PROMPT=0. A private Forgejo collection would fail auth, and on a tty-less server it would hang on the credential prompt. Token injection in herolib lives only in the Forge layer, which is hard-wired to the flat $PATH_CODE/{name} layout and can't operate on an arbitrary collection root the way our code (and GitRepo::new(path)) does.

2. herolib has zero Git-LFS support. Not a single lfs reference in the module. Our collections are image-heavy/LFS-backed, and our module's whole reason for existing is the native HTTP LFS batch-API download (no git-lfs binary required), pointer parsing + sha256 verify, GIT_LFS_SKIP_SMUDGE=1 on clone, --skip-worktree marking, and lfs_counts for the progress bar. None of that has an equivalent.

What a switch would map to: git_statusGitRepo::status() (clean); clone_collectionGitTree::clone_repo().branch().execute() (but loses token auth + skip-smudge + dest-cleanup-on-failure); pull/pushrepo.pull()/repo.commit().push() (unauthenticated → breaks private collections); LFS → no replacement, kept regardless. We'd delete working, tested code to lose auth + LFS.

Decision: keep hero_slides_lib/src/git.rs as-is. herolib is the broader library in general, but it's missing exactly the two things this feature needs most.

Filed the upstream gap so GitRepo can eventually become reusable for private repos: lhumina_code/hero_lib#150 (token-injected pull/push, optional LFS). If/when Gap 1 there lands, we can optionally lean on GitRepo for richer read-only introspection (log/diff/blame) while keeping our clone/sync/LFS path.

### Investigated reusing `herolib_os::git` here — it's a net regression for this feature, so we keep our own module The issue says to lean on hero_lib's git helpers "rather than rolling our own" with "no new auth surface." I checked the actual `herolib_os::git` module (`crates/os/src/git/`, locked `main` rev) against our `hero_slides_lib/src/git.rs`. Two blockers make a switch worse, not better: **1. `GitRepo` can't authenticate a private repo.** Its `pull`/`push`/`fetch`/`commit` are bare `git -C <path> ...` — no `http.extraHeader` token and no `GIT_TERMINAL_PROMPT=0`. A private Forgejo collection would fail auth, and on a tty-less server it would *hang* on the credential prompt. Token injection in herolib lives only in the `Forge` layer, which is hard-wired to the flat `$PATH_CODE/{name}` layout and can't operate on an arbitrary collection root the way our code (and `GitRepo::new(path)`) does. **2. herolib has zero Git-LFS support.** Not a single `lfs` reference in the module. Our collections are image-heavy/LFS-backed, and our module's whole reason for existing is the native HTTP LFS batch-API download (no `git-lfs` binary required), pointer parsing + sha256 verify, `GIT_LFS_SKIP_SMUDGE=1` on clone, `--skip-worktree` marking, and `lfs_counts` for the progress bar. None of that has an equivalent. **What a switch would map to:** `git_status` → `GitRepo::status()` (clean); `clone_collection` → `GitTree::clone_repo().branch().execute()` (but loses token auth + skip-smudge + dest-cleanup-on-failure); `pull`/`push` → `repo.pull()`/`repo.commit().push()` (**unauthenticated → breaks private collections**); LFS → **no replacement, kept regardless**. We'd delete working, tested code to lose auth + LFS. **Decision:** keep `hero_slides_lib/src/git.rs` as-is. herolib is the broader library in general, but it's missing exactly the two things this feature needs most. Filed the upstream gap so `GitRepo` can eventually become reusable for private repos: **lhumina_code/hero_lib#150** (token-injected pull/push, optional LFS). If/when Gap 1 there lands, we can optionally lean on `GitRepo` for richer read-only introspection (log/diff/blame) while keeping our clone/sync/LFS path.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_slides#97
No description provided.