Skip to content

--git shadows plugin-owned git paths (isGitRequest is a global substring match) #616

Description

@melvincarvalho

Summary

Core's --git intercepts every git-smart-HTTP request globally, so a plugin cannot serve git-over-HTTP under its own prefix. isGitRequest(urlPath) matches by substring regardless of path:

// src/handlers/git.js
export function isGitRequest(urlPath) {
  return urlPath.includes('/info/refs')
    || urlPath.includes('/git-upload-pack')
    || urlPath.includes('/git-receive-pack');
}

The onRequest hook and the git-handler dispatch in server.js both use it, so a request like GET /forge/<owner>/<repo>.git/info/refs?service=git-upload-pack is grabbed by core's git handler — which looks the repo up under the pod root, doesn't find it, and returns 401 — before the plugin that owns /forge ever sees it.

Consumer / proof-of-need

The out-of-tree forge plugin (JavaScriptSolidServer/plugins) hosts git repos at /forge/<owner>/<name>.git and serves smart-HTTP itself (via git-http-backend, the gitscratch/ pattern). With --git enabled on the same server, clone/push to the forge's URLs fail — core shadows them. The forge's browse / UI / anchor / nostr layers work (different paths); only its git transport is shadowed. This blocks using the forge as a real remote on any pod that also runs core --git (which serves the pod's own repos).

It's an either/or today:

  • --git on → pod-git works, forge-git shadowed
  • --git off → forge-git works, but the pod's own repos lose git-over-HTTP

You can't have both.

Proposed fix

Core's git dispatch should skip paths owned by a plugin — the loader already knows each plugin's prefix (and its api.reservePath claims). Options:

  1. Exclude registered plugin prefixes from the git guard (cleanest — a plugin mounted at /forge owns /forge/*, git or not).
  2. Exclude api.reservePath-claimed paths from the git guard.
  3. A config escape hatch, e.g. gitExclude: ['/forge'].

Any of these lets core pod-git and plugin-served git coexist.

Workaround

A one-line local patch to isGitRequest excluding the plugin prefix (if (urlPath.startsWith('/forge/')) return false;) restores forge git while keeping pod-git — demo-grade, pending the general fix above.

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