<feed xmlns='http://www.w3.org/2005/Atom'>
<title>cgit-esi.git, branch master</title>
<subtitle>cgit with ESI diff fragments -- the code running this site</subtitle>
<id>http://kernel.varnish.org/cgit-esi.git/atom/?h=master</id>
<link rel='self' href='http://kernel.varnish.org/cgit-esi.git/atom/?h=master'/>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/'/>
<updated>2026-09-10T19:37:52Z</updated>
<entry>
<title>contrib/varnish: add a cache-warming crawler</title>
<updated>2026-09-10T19:37:52Z</updated>
<author>
<name>Per Buer</name>
<email>per.buer@gmail.com</email>
</author>
<published>2026-09-10T19:37:52Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=76b686915de4e29de1e14cc921fc2d8e3d96dc79'/>
<id>urn:sha1:76b686915de4e29de1e14cc921fc2d8e3d96dc79</id>
<content type='text'>
Preloads ESI fragments so the expensive half of every commit page is
already cached before anyone asks for it. Because fragments are shared by
every repository holding the same objects, walking one fork preloads the
diffs for all of them.

Three modes. "crawl" follows links from a starting URL the way a scraper
would, queueing commit and diff pages ahead of everything else. "commits"
walks one repository's log pages; it is denser, but cgit paginates the log
by walking the revision list from the start each time, so it slows down as
the offset grows. "oids" reads object ids from stdin and has no pagination
to walk, which makes it the one to use for a bulk preload: fed from
git rev-list it measured 249 req/s against 68 for the log walk.

The reported hit rate counts only the pages the crawler asks for. ESI
fragments are fetched by Varnish itself and a client cannot see whether
they hit, so a healthy run shows a low client-side hit rate together with
roughly half the expected backend requests.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>contrib/perf: strip ESI changes out of the buffering patch</title>
<updated>2026-09-10T19:08:49Z</updated>
<author>
<name>Per Buer</name>
<email>per.buer@gmail.com</email>
</author>
<published>2026-09-10T19:08:49Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=61a2657f3333e8f634134b51dfa41b98320a7908'/>
<id>urn:sha1:61a2657f3333e8f634134b51dfa41b98320a7908</id>
<content type='text'>
02-cgit-output-buffering.patch was cut from a working tree that already
carried the ESI work, so it also contained the enable-esi config hook,
cache_key(), the repolink and cgit_fileurl fragment hunks and the
memrchr fix. That contradicted its README and made it fail to apply on
any tree that already had ESI, which is every tree in this repository.

Regenerate it with only the output buffering change: the html.c buffer
itself and the flushes in cache.c, filter.c, cgit.c and ui-shared.c.
Verified to apply cleanly both to stock cgit and on top of the ESI
commits here.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>contrib/perf: patches for ref decoration and output buffering</title>
<updated>2026-09-10T18:40:40Z</updated>
<author>
<name>Per Buer</name>
<email>per.buer@gmail.com</email>
</author>
<published>2026-09-10T18:40:40Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=1dea2b214f46f7d747284f96cc5957057fb16bf8'/>
<id>urn:sha1:1dea2b214f46f7d747284f96cc5957057fb16bf8</id>
<content type='text'>
Two independent performance patches found while measuring the ESI split,
both of which help whether or not a cache sits in front of cgit.

01-git-peel-decoration.patch applies to the git submodule. git's
add_ref_decoration() calls parse_object() on every annotated tag to
follow it to its commit, inflating all of them, even though the ref
backend already hands the callback a peeled object id when packed-refs
has one. Using that takes commit and log pages on git.git from about
6 ms to about 2 ms. Output is byte-identical and git's own t4202-log,
t3200-branch and t6300-for-each-ref pass.

02-cgit-output-buffering.patch applies to cgit. html_raw() did one
write(2) per call: a 1.7 MB diff took 99151 writes averaging 18 bytes.
A 64 KB buffer takes that to 27. The buffer has to be flushed wherever
fd 1 is redirected or handed to another writer, which is the cache slot,
exec filters, and the end of the HTTP headers, because git's archive
code writes snapshots and clone data straight to fd 1.

Kept as patches rather than applied because the first belongs upstream
in git, and the second touches enough of cgit's output path to be worth
landing on its own terms.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>contrib/varnish: example VCL for ESI diff fragments</title>
<updated>2026-09-10T18:40:40Z</updated>
<author>
<name>Per Buer</name>
<email>per.buer@gmail.com</email>
</author>
<published>2026-09-10T18:40:40Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=87f57024729ac293fd7c93727f1acbb21e6505c0'/>
<id>urn:sha1:87f57024729ac293fd7c93727f1acbb21e6505c0</id>
<content type='text'>
Turns on ESI processing for frames carrying Surrogate-Control, hashes
esi-diff fragments on their query string so that every fork sharing a
commit shares one cached rendering, and refuses fragment requests that
do not come from the ESI processor so they do not become one more thing
for crawlers to enumerate.

Frames get a short TTL on purpose: they are cheap to render and there
are a lot of them, and they should not crowd fragments out of the cache.

cgit-esi.vtc exercises the VCL against a fake cgit backend, asking for
the same commit through two repository names and checking that the
backend saw exactly one fragment request.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>esi: render diffs as cache-shareable ESI fragments</title>
<updated>2026-09-10T18:40:19Z</updated>
<author>
<name>Per Buer</name>
<email>per.buer@gmail.com</email>
</author>
<published>2026-09-10T18:40:19Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=bf39010df8328f89ccc53f4ea6c9b6549d71eade'/>
<id>urn:sha1:bf39010df8328f89ccc53f4ea6c9b6549d71eade</id>
<content type='text'>
The rendered diff is the expensive part of a commit page, and its output
depends only on the objects involved. Everything around it depends on the
repository and the branch the page was reached through. A commit that
lives in many forks is therefore rendered once per fork per branch, which
is what makes crawlers so expensive on a host with many forks of the same
repository.

With "enable-esi=1", the commit and diff pages become a cheap frame: the
document head, page header, tabs, commit info and diff controls are
rendered as before, but where the diff would go cgit emits

	&lt;esi:include src='/&lt;repo&gt;/esi-diff/&lt;path&gt;?id=&lt;oid&gt;&amp;id2=&lt;oid&gt;&amp;dt=&lt;n&gt;'/&gt;

and the response carries a Surrogate-Control header announcing ESI/1.0.
The new "esi-diff" page renders just the diffstat and the diff, with no
layout and with links relative to the repository root that carry no
branch; the frame emits a matching &lt;base href&gt; so the browser resolves
them into whichever fork it came through. Object ids are always resolved
to full hashes, so symbolic names do not multiply fragments.

Because the fragment's output is repository neutral, cgit's own cache
keys it on the diff parameters rather than the raw URL, and the cache in
front is expected to do the same. Rename following is a per repository
setting that changes the diff, so that case renders inline.

With enable-esi unset, output is unchanged.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>ui-shared: avoid memrchr(), a GNU extension</title>
<updated>2026-09-10T18:39:50Z</updated>
<author>
<name>Per Buer</name>
<email>per.buer@gmail.com</email>
</author>
<published>2026-09-10T18:39:50Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=209395ed9cffb42f4c479a8d426a173b9e50ab4f'/>
<id>urn:sha1:209395ed9cffb42f4c479a8d426a173b9e50ab4f</id>
<content type='text'>
memrchr() is not in POSIX and is missing on macOS, where it breaks the
build of cgit_set_title_from_path(). Scan backwards for the separator by
hand instead; the path components handed to this function are short
enough that the difference does not matter.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Bump version</title>
<updated>2026-05-04T21:03:51Z</updated>
<author>
<name>Jason A. Donenfeld</name>
<email>Jason@zx2c4.com</email>
</author>
<published>2026-05-04T16:59:41Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=044821677c774cd24f25f1818ea51d09cc64b006'/>
<id>urn:sha1:044821677c774cd24f25f1818ea51d09cc64b006</id>
<content type='text'>
Signed-off-by: Jason A. Donenfeld &lt;Jason@zx2c4.com&gt;
</content>
</entry>
<entry>
<title>global: fix libc constness warnings</title>
<updated>2026-05-04T21:03:51Z</updated>
<author>
<name>Jason A. Donenfeld</name>
<email>Jason@zx2c4.com</email>
</author>
<published>2026-05-04T21:03:22Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=5a0f900569f421422bd7511a45c7346c7668e710'/>
<id>urn:sha1:5a0f900569f421422bd7511a45c7346c7668e710</id>
<content type='text'>
Signed-off-by: Jason A. Donenfeld &lt;Jason@zx2c4.com&gt;
</content>
</entry>
<entry>
<title>git: update to v2.54.0</title>
<updated>2026-05-04T17:01:20Z</updated>
<author>
<name>Christian Hesse</name>
<email>mail@eworm.de</email>
</author>
<published>2026-04-13T06:18:52Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=44ca1d1ec8eee7f4440fbfd613fc1072a14b441c'/>
<id>urn:sha1:44ca1d1ec8eee7f4440fbfd613fc1072a14b441c</id>
<content type='text'>
Update to git version v2.54.0, this requires changes for these
upstream commits:

* d9ecf268ef3f69130fa269012318470d908978f6
  odb: embed base source in the "files" backend

* cb506a8a69c953f7b87bb3ae099e0bed8218d3ab
  odb: introduce "files" source

... and probably more related.

Signed-off-by: Christian Hesse &lt;mail@eworm.de&gt;
Signed-off-by: Jason A. Donenfeld &lt;Jason@zx2c4.com&gt;
</content>
</entry>
<entry>
<title>cgit: truncate all config values at the newline</title>
<updated>2026-05-04T16:28:27Z</updated>
<author>
<name>Jason A. Donenfeld</name>
<email>Jason@zx2c4.com</email>
</author>
<published>2026-05-04T16:13:13Z</published>
<link rel='alternate' type='text/html' href='http://kernel.varnish.org/cgit-esi.git/commit/?id=ed05b1054df10a2fbc68000cfdd429daec03a456'/>
<id>urn:sha1:ed05b1054df10a2fbc68000cfdd429daec03a456</id>
<content type='text'>
These would be largely invalid anyway (save, I suppose, for Linux file
paths that technically can contain new lines).

The actual problem is that these get printed back out into cached -- and
trusted -- cgitrc files, and if the fields have newlines, the git-config
way of less trusted users configuring repos on a shared system can be
abused to inject newlines, which then can be used to smuggle global
options (including filters, which execute code) into the cached cgitrc.

So now, only ever duplicate up to the newline, when dealing with these
inputs.

Reported-by: Adrian Denkiewicz &lt;adrian@doyensec.com&gt;
Signed-off-by: Jason A. Donenfeld &lt;Jason@zx2c4.com&gt;
</content>
</entry>
</feed>
