Skip to content

Git auto-init: use regular (non-bare) repo so pushed files are served as static resources #468

Description

@melvincarvalho

Context

#466 shipped auto-init on first push, choosing git init --bare. That's correct for the "pod is a git remote" use case (clone / fetch / push all work), but breaks the symmetrical "install an app via git push" use case that motivated the feature in the first place (jspod#25, #464).

Repro

git clone https://github.com/solid-apps/hub.git
cd hub
git remote add pod http://localhost:5444/public/apps/hub
git push pod HEAD:main
# Push succeeds: * [new branch] HEAD -> main

curl http://localhost:5444/public/apps/hub/index.html
# 404 — there is no index.html file. The contents live inside the
# bare repo's pack objects, not as files in the directory.

ls pod-data/public/apps/hub/
# HEAD  branches  config  description  hooks  info  objects  refs
# (bare-repo internals, no working tree)

Root cause

tryAutoInitBareRepo runs spawnSync('git', ['init', '--bare', repoAbs]). Bare repos by definition have no working tree.

Proposed fix

Auto-init regular (non-bare) repos. The existing handler in handleGit already does the right thing for non-bare repos on every push:

// For non-bare repos, auto-update working directory after push
if (gitInfo.isRegular) {
  execSync('git config receive.denyCurrentBranch updateInstead', {
    cwd: repoAbs,
    env: { ...process.env, GIT_DIR: gitInfo.gitDir }
  });
}

So switching auto-init to non-bare automatically composes with the existing receive-pack flow. Files land in the working tree on each push, JSS's static-file serving picks them up at the corresponding URL, the data browser renders them — apps "install" by git push.

Diff size

  • src/handlers/git.js: drop --bare from one spawnSync arg list. ~1 LoC.
  • test/git-auto-init.test.js: update assertions to look for .git/HEAD (regular) instead of root-level HEAD (bare). ~5 LoC.

Trade-offs

  • Storage: a regular repo has both .git/ history AND the checked-out working tree. Roughly 2× the disk footprint of a bare repo for the same content. Acceptable: most Solid pods are content-light and this matches what users expect from "files served by my pod."
  • Semantics: cloning / fetching / pushing still works identically. The only observable difference is that the directory contents are now visible to HTTP GET (which is the whole point).
  • Existing behaviour preserved: this only changes the auto-init path. Operators who manually pre-create a bare repo at a pod path (the workflow that existed before feat(git): auto-init a bare repo on first push to an empty path #466) still get bare semantics — findGitDir already handles both shapes.

Recommendation

Switch auto-init to regular repos. The bare-repo flavor of "pod as git remote" remains available for anyone who explicitly creates bare repos manually; the auto-init path now serves the "install" use case it was originally motivated by.

Cross-references

  • #466 — the PR that introduced auto-init (this is a follow-up)
  • #465 — the original init-primitive issue
  • #464 — apps-in-pods at the protocol level
  • jspod#25 — wrapper-side jspod install (the consumer)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions