Quarry serves repositories that came from fossil, and imported content — wiki pages, forum posts, check-in comments, embedded documents — is full of fossil's own URLs. This is the map from those URLs onto quarry routes, what is deliberately not mapped, and what it would take to map the rest.
Two seams do the work, both in internal/api/register.go:
FossilRoute(repo, path)— the verbs that need no index lookup. Used by the check-in comment renderer and delegated to by the resolver.resolver.ResolvePath(path)— the same table plus the verbs that need the index (/info/<hash>,/wiki?name=). Used by the markup pipeline.
An empty answer from either means quarry has no equivalent, and the caller unwraps the link to plain text. A reader is never handed a link that 404s. That policy is the important one: everything below is about which side of it a verb sits on.
Mapped
| fossil | quarry |
|---|---|
/doc/<version>/<path> |
/r/{repo}/doc/{version}/{path} |
/info/<hash>, /artifact/<hash>, /whatis/<hash> |
/r/{repo}/info/{prefix} |
/timeline |
/r/{repo}/timeline |
/forum, /forumpost/<h>, /forumthread/<h> |
/r/{repo}/forum |
/technote, /event |
/r/{repo}/technote |
/tktview/<id>, /tktview?name=<id> |
/r/{repo}/ticket/{id} |
/wiki?name=<page> |
/r/{repo}/wiki/{name} |
/dir?ci=<v>&name=<d> |
/r/{repo}/tree/{version}/{path} |
/brlist |
/r/{repo}/branch |
/tarball/<v>/…, /zip/<v>/… |
/r/{repo}/archive/{version} |
/uv/<name> |
/r/{repo}/uv/{name}, a redirect to the file in the repository's bucket |
/uvlist, /uvlist?byage=1 |
/r/{repo}/uv, /r/{repo}/uv?sort=age |
The forum entries land on the index, not the thread, on purpose: measured against a fossil clone, 303 of 304 cited forum hashes are not present locally, so a deep link would 404.
/tarball and /zip map only when the link names a version. Quarry's
archive route has no "whatever the tip is" spelling, and guessing trunk
would hand a reader a different tree than the link meant.
/uv/<name> keeps the name's slashes, so /uv/releases/1.0/x.tar.gz
names the same file it did on fossil. Unversioned files live in the
repository's own bucket (RFC 0020); a repository without one has none,
and the link lands on the listing's page saying so rather than on a 404
from a server that never had the file. Unlike fossil, quarry never
renders a published HTML file as a page: /uv/download.html downloads.
Relative links inside a document
Not a route question, but the same family of bug. Fossil serves a
document at /doc/<version>/<path>, so the URL's directory is the
document's directory and a relative link in it resolves for free. Quarry
renders the same file on the repository home page and under a tree
listing too, where the page's URL sits somewhere else entirely.
SQLite's README links doc/compile-for-unix.md. Rendered at /r/sqlite
a browser resolved that against /r/ and asked for
/r/doc/compile-for-unix.md — a 404, while the document itself sat at
/r/sqlite/doc/trunk/doc/compile-for-unix.md the whole time.
docResolver now carries the version and directory the document was read
at, and markup.rewriteDocRelative re-bases every relative href and
src onto the doc route. A body that sits at no path — a wiki page, a
forum post, a ticket comment — has no sibling to resolve against, is not
a DocResolver, and keeps its targets literal.
/finfo, and the index behind it
Quarry serves this as /r/{repo}/history/{version}/{path}, and it is the
commonest fossil verb in imported content — libfossil's wiki alone
carries ~500 references. It was dropped for a long time because the page
was unusable on a large repository: zit reconstructed a check-in manifest
for every check-in it walked, and log --long -n 50 README.md on the
SQLite mirror took 129 seconds.
zit#188 fixed the walk (0.3.14) and 0.3.15 made its index durable across commits — 0.3.14 recorded no coverage, so any commit invalidated the index and the next query rebuilt from the first check-in, which on a repository under development is the common case.
Measured on this fleet, against the SQLite mirror:
| before | after | |
|---|---|---|
/r/sqlite/history/trunk/README.md |
timed out past 120s | 923ms |
| first PATH query (builds the index) | — | 104s, once, 888 KB |
| any later path | — | ~0.6s |
The index is per REPOSITORY, not per path: once built, a query for a path nobody has asked about before is just as fast.
104 seconds is not a page, so quarry builds the index off the request
path — cmd/quarry/finfowarm.go, beside the listing warm and under the
same guard: one repository at a time, only when the tip has moved. The
warming query names .quarry-warm-file-index, a path that cannot exist:
a PATH query builds the whole index before discovering the path is not in
the tree, so the index is warmed without reading any real file's history
and without quarry needing to know a tracked path to name.
Future work
None of these are mapped, and none should be until quarry has the page. Recorded here so the decision is on the record rather than implied by silence.
The rest
| fossil | what quarry would need |
|---|---|
/leaves |
a leaves query on the index; the branch page is close |
/vdiff?from=&to= |
diff between two arbitrary versions; today quarry diffs a check-in against its parent |
/stat, /timewarps |
repository statistics pages |
/help, /md_rules |
forge-level reference pages, not repository ones |
Each is a page first and a route second. Add the page, then add one row
to FossilRoute, then delete its line from this section.