From 91a1cda76646f3ece09627155d9b0821750b3d41 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Thu, 29 Oct 2026 16:29:12 -1000 Subject: Rename CHANGELOG.txt to CHANGE.txt --- CHANGE.txt | 798 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 798 insertions(+) create mode 100644 CHANGE.txt (limited to 'CHANGE.txt') diff --git a/CHANGE.txt b/CHANGE.txt new file mode 100644 index 0000000..c14bf3d --- /dev/null +++ b/CHANGE.txt @@ -0,0 +1,798 @@ +cgit - Changelog +================ + +Notable changes to this fork, newest release first. History before v2.0.0 +belongs to upstream cgit and is not covered here. + + +v2.9.2 (2026-10-25) +------------------- + +A polish release for narrow screens and for the finer details of the pages, +with the summary's columns lined up, a login that says when it failed and a +signed tag's signature folded away. + +Added +..... + +* A wrong username or password brings the login form back with a message + saying so, where it used to come back empty. Both auth filters carry it, an + unknown user is told the same as a wrong password, and the button now sits + under the fields. The README names the hooks, form.login and p.login-error. +* A signed tag's signature, PGP, SSH or X.509, is folded away under the tag's + message in details.signature, rather than printed as part of the message. +* The syntax highlighter colours CSS properties and pseudo-classes, which + Scintillua's css lexer tags with names it had no colour for. +* Links, rows and buttons fade between colours, and the line highlight fades + in, unless the reader asks for reduced motion. + +Changed +....... + +* On a narrow window the tabs stay on one row and scroll sideways with the + active tab in view, rather than wrapping a tab or two onto a second row. +* On a narrow screen each commit detail sits under its label, and a phone + leaves out the diffstat's file modes. The summary keeps its log counts on a + phone, so its rows still line up. +* List rows highlight under a mouse only, so on a touch screen the last row + tapped no longer stays highlighted. +* The logo is brighter in dark mode. +* The diffstat bars are drawn as SVG, so a strict Content Security Policy no + longer has to allow inline styles, and the diffstat box has room inside its + border. + +Fixed +..... + +* The summary's sections disagreed on how many columns its table had. With + the default config the log and clone rows stopped short of the table's edge, + on a phone the log rows did with any config, and the summary and refs pages + were invalid HTML. +* A commit's branch and tag labels were joined to the last word of its subject, + so a narrow cell broke the line before that word and stranded another. +* A download link and its signature could break across lines mid-name. +* The rule above the code on the blob and blame pages, and the line highlight, + ended at the longest line of a short file rather than at the page's edge. +* A commit that changes no files drew an empty diffstat frame. + + +v2.9.1 (2026-10-24) +------------------- + +A bugfix release for the tree and blame pages, whose line numbers had drifted +away from the code since v2.0.0 in Safari and in every browser on a typical +Linux desktop, until the code sat dozens of lines below its number at the end +of a long file. + +Added +..... + +* A character a browser would start a new line at, though git does not, is + shown as an escape sequence in span.escape on the tree and blame pages and + by the syntax highlighter: a carriage return with no line feed after it, a + vertical tab, a form feed, next line and the Unicode line and paragraph + separators. + +Changed +....... + +* Patches end with the cgit version again, written as git writes its own, so + this release signs them "cgit 2.9.1". The footer and the generator tag still + carry no version. + +Fixed +..... + +* The code beside the line numbers was set in the browser's own monospace + font, which made each of its lines a little taller than its number, by a + pixel in Safari and on Linux, so the two columns drifted apart down every + file. +* A lone carriage return started an extra line in every browser, and U+2028 + and U+2029 did in Safari, each pushing every later line below its number. +* The line highlight sat a pixel low, covered only the digits of each number, + and ended at the edge of the view on a file scrolled sideways. +* Code in a readme took the browser's own monospace font, Courier in Chrome + and Safari, rather than the theme's --font-mono. + + +v2.9.0 (2026-10-17) +------------------- + +A compatibility and hardening release. Lua 5.5 is supported, readmes render +closer to how GitHub shows them, the auth examples were overhauled, 32-bit +builds compile again, and two audits of the extensions and of the C code +closed what they found, from a cache lock that an exec filter let go of to +a log search that was never the literal match it claimed to be. + +Added +..... + +* Lua 5.5, detected when building and claimed by every extension, which + needs luaossl 20260910 or later there. +* Stable markup hooks for site themes: a data-page attribute, named sections + and a class per link kind. +* Readmes follow GitHub more closely: relative links lead into the tree at + the readme's own ref, lines of a paragraph run together, a table may cut a + paragraph short, a wrapped list item stays in its list, urls and addresses + in angle brackets link, backslash escapes and character references are + honoured, underscores inside words are left alone, and headings get the + anchors GitHub gives them. Images and badges are left out. +* The auth examples bind a session to the account's password hash, so a + changed password ends it, use a __Host- cookie where one can be set, turn + down passwords past 256 bytes unchecked, spend a missing account's login on + a real hash, load their libraries only when a request needs one, and say + which hash kinds each system's crypt checks. +* Avatars are looked up by SHA-256, offered at twice the size to dense + screens, marked decorative, and left out when luaossl is missing. +* The syntax highlighter finds a script's lexer from its shebang line. +* make get-git checks the Git tarball against the SHA-256 kernel.org lists. +* The dumb transport answers HEAD from the ref store and the index dates a + repository from its reftable, so reftable repositories clone and age. + +Changed +....... + +* enable-trailers is now enable-commit-trailers. +* The bundled Git is 2.56.0. +* The pages carry no version number, and the Lua-less build is checked by + the suite as well. +* Any path below the about page answers 404, the about filter is handed the + tree url its links need, and the about redirect keeps the query string. +* The dumb transport serves only what a clone asks for, a loose object, a + pack with its index and info/http-alternates, sends each file with its + size and keeps none of them in the cache. +* A page behind an auth filter is marked private, and every page that + follows a branch takes cache-dynamic-ttl. +* summary-branches, summary-tags and max-ref-count read a negative value as + no limit, and the feed refuses pathspec magic as the log does. +* patch, rawdiff and signature downloads hold to max-blob-size, and a + readme past it says so on the about page. +* Diffs no longer ask xdiff for a minimal result, which cost quadratic time + on a reordered file, and tar.xz snapshots are compressed on one thread. +* The cache slot lock is an flock, which outlasts an exec filter's swap of + stdout where the record lock did not. +* Git is built without translations or Tcl, the release script builds with + the compiler it probed, the two builds no longer share vendor/git at once, + sparse checks the sources as gnu17, and a musl build is documented. +* The example tracker links in link-commits.lua and link-trailers.lua ship + commented out, so an unedited copy links object names alone. +* The manual, README and sample cgitrc say what the code does: every page + and query parameter, every file make install puts in place, the defaults + and value syntax, and which filters get the repository variables. + +Fixed +..... + +* 32-bit builds, where Git 2.55's size_t object sizes no longer compiled. +* The log search matched as a regular expression after all, so a term with + a bracket in it answered a 500 and a crafted one took the memory of the + box. +* A pushed date or zone outside what git's date code accepts, and a notes + ref pointing at anything but a tree, ended the summary, refs, log, commit + and feed pages of the repository. +* A snapshot name led to a branch spelled like the tag's stem, members + of a snapshot named by its suffix alone started at a slash, and a missing + PATH refused every compressed snapshot. +* The plain view answered twice for duplicate tree entries and read a freed + mimetype on the way, a control byte in a file name made the web server + refuse the download, a scanned defbranch could name a path outside the + repository, and the error page resolved the very id it had refused. +* A fill whose last flush failed to write, on a full disk for one, left the + visitor a blank response, a cache ttl in the tens of millions of minutes + overflowed, and an empty list reached qsort as a null, which glibc's + sanitizer build aborted on. +* Links built from the repository url and the feed link's branch were not + encoded, a readme vanished behind an annotated tag, a followed log lost + its root commit and paged by the wrong name, a Lua build crashed when git + wrote before cgit's own setup, text was cut inside a multibyte character, + and the tag page offered snapshots of trees and blobs. +* An absolute symlink target was linked as a path inside the tree, a chain + of single directories ended in a dangling separator, a repository without + a path was dated from a file named "(null)", a NUL ended a config comment + early, and a tree row was left open when a link target could not be read. +* An empty repo.url is ignored, a readme ending in a colon is gated like a + path on disk, an error mid capture keeps its message, date-format= + local-local renders, an indented comment in the mimetype file is skipped, + types that only spell xml get no charset, the sendfile loop stops at a + short slot, slot keys and pages are read and written in full, and the + stats page stops after its error page. +* auth-file.lua refuses every repository when it cannot read its repos file, + cookie, readme and avatar parsing run in linear time, the cache hook keeps + its rm errors from pushers, the age hook leaves its directory writable to + the group, a Lua script may write while it loads, and every Lua filter + failure is named in the log. +* Git read the global config for its trace settings before cgit isolated + the environment, so every request probed $HOME/.gitconfig, which the + home-access test caught only once it ran on a real x86_64 kernel. +* make DEVELOPER=1 passes: string literals sit behind const pointers and + callbacks are passed by address. + + +v2.8.0 (2026-09-16) +------------------- + +A feature and hardening release. Commit trailers get a table of their own, the +mailmap is applied everywhere a person is named, the per-repository filter gate +gives way to a trust switch for scanned repositories, and an audit closed every +crash and every request that could reach git unchecked. + +Added +..... + +* Commit trailers shown as a table under the message, behind enable-trailers. +* trailer-filter, with link-trailers.lua linking Fixes, Reverts, Closes, Bug and + bare URLs. +* The .mailmap at HEAD applied to every ident and search, behind enable-mailmap. + +Changed +....... + +* enable-filter-overrides became trust-scan-config, gating only the risky keys a + scanned repository's own cgitrc or git config can set. +* A request may name a revision only by hex id or ref name, and the log search + matches literally. +* A die inside git answers a 500 page and logs the reason. +* The static ttl covers only the pages whose content the id fixes. +* One phrase and status for a bad object id or a revision that is not a commit. +* A scan path that is itself a repository is named after its directory. +* The tag page shows the tagged object's full id. + +Fixed +..... + +* Crashes on a repository without a path, an unknown page name, an empty url, a + repo.* key after scan-path, a broken git config in a scanned repository, an + unparsable commit and a history with a missing parent object. +* A full cache disk no longer fails every cacheable request, and an error mid + page finishes the page instead of starting a second response. +* Revisions, paths and snapshot names can no longer reach git as options, + pathspec magic or archive members outside the extraction directory. +* Filters answer one error page when they cannot run, start with SIGPIPE at its + default and no longer leave a page half written when they exit early. +* Limits hold for a diff limited to a directory, a large symlink target and a + deep chain of single directories. +* The about page no longer serves the repository's own files beside a readme on + disk. +* Snapshots of dash-named tags, a missing compressor, nested tags, dumb clones + of an empty repository, a symlink cycle under the scan path, the fallback + default branch, a blank line in mimetype-file and a POST body arriving in + pieces all answer correctly. +* Commit encoding, trailer splitting, notes lookup, subject truncation, ref + decorations and statistics buckets render correctly in their edge cases. +* Two builds of the same sources are byte for byte identical. + + +v2.7.1 (2026-09-08) +------------------- + +A bugfix release. A tag's snapshot names no longer depend on how git happens to +store its ref. + +Fixed +..... + +* Snapshot names shed a tag's leading v reliably again. On a case-insensitive + filesystem a freshly created tag kept the v until git packed the refs, so the + same tag could change its snapshot names over time. + + +v2.7.0 (2026-09-08) +------------------- + +A configuration release. The badly named keys are renamed, the statistics switch +folds back into max-stats, the parser now reports what it ignores, and the theme +toggle is gone. + +Added +..... + +* Unknown or misplaced configuration keys are reported to stderr instead of + being dropped silently. + +Changed +....... + +* noheader became enable-header, with its polarity flipped. +* noplainemail became enable-plain-email, with its polarity flipped. +* cache-root-ttl became cache-index-ttl. +* cache-repo-ttl became cache-summary-ttl. +* cache-scanrc-ttl became cache-scan-ttl. +* agefile became age-file. +* renamelimit became rename-limit. +* repo.extra-head-content became repo.head-content. +* Old key spellings are not read and draw the unknown-key warning. +* max-stats enables the statistics page and bounds its coarsest period again, as + it did before v2.2.0. +* enable-stats and repo.enable-stats are gone. +* repo.max-stats=0 turns the statistics page off for one repository. + +Removed +....... + +* The header theme toggle. The light and dark theme follows the system + preference alone, and a saved choice in localStorage is no longer read. +* Selects no longer submit their form the moment they change. The diff and stats + panels always show their reload button instead of keeping it for readers + without scripting. + +Fixed +..... + +* A lua filter that fails now answers with an error page naming the script and + the error, where before the page was fed back into the broken filter and the + visitor got an empty response. + + +v2.6.1 (2026-09-01) +------------------- + +A small release. Every clone row is now a link a browser can follow, and the +diffstat graph drops the output's last inline style, so a strict +Content-Security-Policy needs no exceptions. + +Changed +....... + +* Clone rows are links. The ssh, scp and git forms cannot be followed by a + browser, so those rows point at the first http url in the clone list, or at + the repository page when there is none, and the scp form stays out of the + document head since it is not a URI. +* The diffstat bars take their width from colspan on a fixed-layout table rather + than from inline styles. A site pointing css= at a stylesheet of its own needs + the new inner graph table rule from cgit.css, or the bars render as equal + width segments spaced apart. + + +v2.6.0 (2026-08-28) +------------------- + +A cleanup release. Output is ASCII only and deterministic, the statistics page +drops its language breakdown, and two bugs a cross-compiler review found are +fixed. + +Added +..... + +* README.txt documents how cgit urls are built, both url forms, every query + parameter, the endpoints that are not pages, and worked examples. +* tests/README.txt describes the suite layout, numbering and traps. +* Pages carry a meta description, from the repository or root description. +* Submodule links resolve through .gitmodules, and submodule rows are set apart + in the tree listing. + +Changed +....... + +* Output is ASCII only. The truncation marker is an ellipsis, the title path + separator is plain, and unrepresentable bytes print as a question mark. +* Non-breaking space padding is done with CSS. +* Pages are byte for byte deterministic. The footer drops its clock and an empty + atom feed is dated at the epoch. +* The charset is spelled UTF-8 everywhere. +* Snapshots use registered media types, so application/gzip, application/zip and + application/zstd replace their x- forms. +* Status lines use the standard HTTP reason phrases. +* Table header and image attributes follow the usual order. +* Test scripts are renumbered into themed ranges and prefer POSIX forms. + +Removed +....... + +* The statistics page no longer breaks the tree down by language. The built-in + extension table was a standing maintenance cost, classifying by extension + misleads, and the tree walk it needed was the only part of the page reading + object sizes. The commits-per-author table is unchanged. + +Fixed +..... + +* The statistics page no longer reads past its argument list when given a path. + The array handed to git's revision setup lacked a trailing null, so a url such + as /repo/stats/dir read whatever followed it on the stack. +* A detached head stays selected in the branch switcher. Browsing at a raw + commit or tag left it resting on the first branch, so switch moved away. + + +v2.5.0 (2026-08-23) +------------------- + +A correctness and conformance release. The generated markup moves fully to +HTML5, cgit stops emitting HTTP headers a front-end server should own, the page +cache and repository scan get real locking, and pages pinned to a commit now say +so. + +Added +..... + +* Pages pinned to a commit via the id parameter show it. The branch switcher + gains a "(detached)" entry, the page title carries the short hash, and the + path strip gains a rev crumb linking back to the branch tip. +* The shipped server configs gain Permissions-Policy, cross-origin isolation + headers and form-action in the CSP, and enable HSTS. The nginx config adds + catch-all blocks that drop requests for hostnames the site does not serve, + since cgit keys its cache on Host. +* Operators get log lines for two previously silent failures, a cache too small + for its keys and a repository scan lock that fails for reasons other than + contention. +* The documentation now spells out that the cache directory must be pre-created, + owned by the web server account and mode 0700. +* Login forms carry autocomplete hints for password managers, and avatar images + load lazily. + +Changed +....... + +* Atom feeds conform to the RFC. They are served as application/atom+xml with an + XML declaration, invalid bytes are replaced instead of emitted, and every + entry carries an author name. +* Dates render as HTML time elements with strict ISO 8601 values. +* Markup is fully HTML5. Complete documents everywhere, real table header cells, + no XHTML self-closing slashes and no HTML comments in the output. The plain + directory listing gets a doctype so browsers leave quirks mode. +* cgit no longer sends Last-Modified, Expires or ETag. Front-end caching policy + lives in the server configs, which now append headers rather than replace + cgit's own. +* Only a full object id qualifies for cache-static-ttl, since the id parameter + accepts any rev git can resolve. +* Percentages in the diffstat bars and language table print from integers, so a + filter that switches the numeric locale cannot corrupt the output. +* URL encoding is tightened. Ampersands and plus signs are percent-encoded in + paths, and query strings are escaped at each sink instead of being + pre-escaped. +* The responsive breakpoints only hide or restack chrome and never change font + sizes or gutters. Narrow screens drop the search box, branch switcher and + author columns, and diff tables scroll inside their own box. +* The client-side age refresher uses the same bucket arithmetic as the server, + so refreshed ages no longer drift from rendered ones. +* The example agefile hook was renamed to post-receive.cgit-age. + +Removed +....... + +* The repository homepage feature, including repo.homepage, the gitweb.homepage + mapping and the homepage tab. +* The post-update.update-server-info example hook. + +Fixed +..... + +* Error pages are no longer cached, so requesting a commit before it is pushed + can no longer pin a 404 into the cache forever. +* An abandoned cache fill no longer appends a second page to the response, + publishes its lock file or leaves a stale copy to be served. +* A crashed repository scan no longer freezes the index forever. Scan and cache + locks are fcntl locks released by the kernel with the process, and lock + holders re-verify their lock file after acquiring it, closing a race that + could truncate a live file. +* Blobs containing a NUL byte anywhere are treated as binary in tree and blame + views, and the raw path substitutes replacement characters instead of + truncating at the NUL. +* An annotated tag whose tagger has no email no longer passes NULL to the email + filter, repositories without an owner no longer render an empty link, + single-page logs drop the pager, and filler rows use correct colspan values. +* The dev preview server splits CGI headers at the earliest blank line, so DOS + line endings in page output no longer swallow the document head. + + +v2.4.0 (2026-08-08) +------------------- + +A performance and robustness release. Output is buffered instead of written +fragment by fragment, the hot paths shed repeated work, and a cluster of fixes +closes crashes reachable from repository-controlled content. + +Changed +....... + +* The bundled Git is updated from 2.54.0 to 2.55.0, with NO_RUST set so Cargo + does not become a silent build requirement. +* Page output is collected in a 64 KB buffer and written in whole blocks instead + of one write per HTML fragment. +* Blame and tree line numbers, hex dump rows and intra-line diff highlights are + emitted in batches rather than per line or character. +* The diff view renders each file while it is already open and replays it after + the diffstat, replacing a second full tree walk. +* Blame reuses a commit's rendered detail across its entries, the index resolves + repository ages once before sorting, and the stats page computes its period + labels once. +* Side-by-side tab expansion is a single pass, where it was previously quadratic + on tab-heavy lines. +* Search queries are clamped to 512 characters, bounding the matching work one + request can demand and the size of cache keys. +* The sources compile as gnu17 so their meaning does not drift with compiler + defaults, and the release script probes each hardening flag, preferring + FORTIFY_SOURCE level 3. + +Fixed +..... + +* A repository under scan-path could supply its own module-link template, which + was handed straight to printf. Surplus conversions could crash cgit or read + stack memory into the page. Templates are now expanded manually. +* Sorting branches by age crashed when a branch ref pointed at a tag or tree + object. +* Hunks whose header omits a length, as git writes for single-line hunks, were + numbered from zero in side-by-side diffs and lost their links. +* A request whose cache key was too long to read back could never hit, + regenerating the page every time while still writing an unusable slot. Such + requests now skip the cache and log it. +* Git config isolation ran from a constructor attribute that some compilers + silently discard. It now runs from main. +* A memory leak of deferred side-by-side lines and an integer-truncation bug in + the stats author ordering. + + +v2.3.0 (2026-08-05) +------------------- + +A consolidation release focused on how the project is laid out, deployed and +operated. Everything an operator ships or edits now lives under custom/, the +server configs became complete standalone files, and the hooks and auth filters +were hardened. + +Added +..... + +* New enable-relative-dates option, default 1. Set to 0 to always show calendar + dates in the age columns instead of elapsed times. +* New date-format option controlling those calendar dates, accepting git's date + format names plus strftime formats. +* New example hook post-receive.cgit-cache that clears cgit's output cache after + a push, so new commits appear immediately instead of after the cache TTL. +* New CGIT_EXTRA_CFLAGS make variable applying extra compiler flags to cgit's + own objects only, not the bundled git. + +Changed +....... + +* The tree was reorganized. The git submodule moved to vendor/git, and the + example cgitrc, Lua filters, hooks and server configs moved into custom/. + Operators following old paths must update them. +* Repositories with no commits get a dedicated page with working clone URLs + instead of a bare notice with dead tabs. +* A description file still holding git's "Unnamed repository" boilerplate is + treated as no description. +* The theme is applied before first paint, so pages no longer flash the wrong + theme, and the header no longer shifts as the page loads. +* The nginx, Apache and lighttpd configs are complete, runnable files carrying + their own top-level directives, rather than snippets assuming a distro base. +* The agefile hook uses committer dates from branches only, writes atomically + and keeps its output readable by the web server. The update-server-info hook + likewise forces a safe umask. +* The auth filters' secret moved from /var/cache/cgit to /var/lib/cgit, so + pruning the cache no longer invalidates every live session. +* The dev preview server forwards cookies, referers and request bodies, so the + auth filters can be exercised locally, and decodes escaped repository names. + +Removed +....... + +* The built-in help page and its enable-help option. +* GitHub Actions CI, the release workflow and the make dist target. + +Fixed +..... + +* Ordinary working trees found by scan-path are listed as repo instead of + repo/.git. +* The auth filters match cookie names containing pattern magic characters, and + auth-file tolerates a users file saved with CRLF line endings. + + +v2.2.0 (2026-07-25) +------------------- + +A hardening release that puts explicit ceilings on the work a single request can +provoke, reworks the statistics page, and overhauls the bundled Lua filters. + +Added +..... + +* The stats page gains a language breakdown, sizing the tree at HEAD by file + extension without ever loading blob contents. +* New enable-stats option, default 0, as the dedicated switch for the statistics + page. +* New max-patch-count option, default 50, bounding how many commits the patch + view emits as a series. +* New about-filter script about-render.lua, a server-side renderer for markdown, + man pages and plain text, falling back to escaped text when its dependencies + are missing. +* New make dist target staging the release tarball, so local and released + tarballs are identical. + +Changed +....... + +* max-stats no longer enables the stats page, it only bounds the coarsest + period. Instances relying on it must now also set enable-stats=1. +* The auth filters are hardened. Cookies are Secure by default, redirect targets + are validated so a login cannot bounce to another origin, password checks are + constant time even for unknown users, and a protected repository with no + resolvable users denies everyone. +* The avatar filters skip missing addresses instead of hashing garbage, + normalise the rest, and expose size, style and URL settings. +* link-commits.lua takes a user-editable list of pattern and URL rules instead + of a hardcoded issue reference, resolving all matches in one pass. +* The syntax highlighter falls back through an extension map when lexer + detection fails and emits its plain-text fallback in slices instead of one + full-size copy. +* The masthead reserves the logo column so the header no longer shifts while the + logo loads, and the logo and favicon were redrawn at higher resolution. + +Removed +....... + +* The client-side markdown renderer and the enable-markdown option. Rendered + readmes now require about-filter pointed at about-render.lua. +* The PDF documentation targets. + +Fixed +..... + +* A file name containing a quote could break out of the link attributes in + side-by-side diffs. Paths are now percent-encoded. +* A commit with no message no longer crashes the history views. +* max-blob-size also bounds the diff path, so a huge blob is reported as binary + instead of inflated into memory, and dangling refs are skipped instead of + dereferenced. +* The diff size caps are no longer silently disabled when follow is active. +* The header branch switcher respects max-ref-count instead of emitting an + option per branch on every page. +* zstd snapshots run single-threaded, so one request cannot fan out across every + core. +* The stats walk is pruned by date instead of visiting all history, and a commit + whose date cannot be represented is dropped rather than indexing a month table + out of bounds. +* The cache listing bounds its key output, and a malformed cgitrc line no longer + discards the rest of the file. +* The build no longer triggers a section-alignment warning on every macOS link. + + +v2.1.0 (2026-07-19) +------------------- + +A release about behaving well on large repositories and under a strict +Content-Security-Policy. Syntax highlighting moves out of the browser and into +an optional server-side filter. + +Added +..... + +* New max-ref-count option, default 200, capping how many branches and tags each + refs section lists, with independent pagination on the dedicated branch and + tag pages. +* New max-diff-files option, default 200. A commit touching more files renders + only its diffstat, with a notice pointing at the per-file diffs and the patch + view. +* New max-diff-lines option, default 1000. A single file exceeding it within a + whole-commit view links to its own diff page instead of rendering inline. + Single-file diffs, rawdiff and patch are never capped. +* An optional server-side syntax highlighter, syntax-highlight.lua, built on the + Scintillua lexers with around 120 languages, degrading to plain escaped text + when its dependencies are absent. +* A built-in help page documenting the site's URL patterns, behind the new + enable-help option. Removed again in v2.3.0. +* URL fragments highlight the targeted source line in blob and blame views, + support ranges like #n5-n12, and land the target mid-viewport. + +Changed +....... + +* The auto-submitting select controls drop their inline onchange handlers and + are wired up from cgit.js, so the option forms work under a CSP without + unsafe-inline. +* A plaintext readme keeps its line structure instead of collapsing into a + run-on paragraph. +* Syntax highlighting of source views moved from the browser to the optional + filter. Without a source-filter, code is served plain, and the client-side + highlighter is deleted. +* Font sizes were evened out across the interface, and the external-link icon + follows the tab's text color in both themes. +* The mobile layout hides the author and size columns, the search form and the + branch switcher, so nothing forces sideways scrolling. + +Removed +....... + +* The owner-filter hook and its per-repository override. Owners always render as + plain linked text. + +Fixed +..... + +* Release binaries no longer ship with an empty version string when git describe + fails in a shallow clone. + + +v2.0.0 (2026-07-16) +------------------- + +First release of this fork, cut from upstream cgit v1.3.1. The page chrome is +rebuilt as semantic HTML with dark mode and a phone layout, the runtime sheds +its external interpreters and crypto libraries, and around two dozen security +and correctness fixes land. + +Added +..... + +* Built-in client-side syntax highlighting in cgit.js for roughly 33 languages, + used when no source-filter is configured. +* Built-in client-side markdown rendering for about pages behind the new + enable-markdown option, restricted to safe link and image targets. +* A light and dark theme with a toggle cycling auto, light and dark, persisted + in localStorage and invisible without JavaScript. +* A responsive layout for phones and small screens, with stacking panels and a + repository index that collapses to name and age. +* New enable-tree-group-dirs option listing directories before files in the tree + view. +* New enable-cache-list option, default 0, gating the previously unprotected + cache listing page. +* A fully commented example cgitrc listing every option at its default, and + complete nginx, Apache and lighttpd examples with security headers. +* An example post-update hook running update-server-info, needed because the + built-in clone support speaks dumb HTTP. +* tools/serve.py, a dependency-free local preview server, and + tools/release-build.sh, a hardened Linux release build. +* CI covering gcc and clang, the test suite under ASan and UBSan, sparse, and a + hardened PIE build, plus a tag-triggered release workflow shipping hardened + tarballs with checksums. +* Accessible names on the search field, branch switcher and breadcrumb + navigation, and contextual titles on the nav tabs. + +Changed +....... + +* max-blob-size defaults to 10 MB instead of unlimited, and now caps everything + cgit reads into memory to serve, including plain and blob output. Oversized + objects return a 413 page. +* section-sort defaults to 0, so the order repositories are written in cgitrc is + respected rather than alphabetized. +* Repository age on the index is derived from HEAD instead of a hardcoded + refs/heads/master, so repositories on main show an age. +* The page chrome is semantic HTML instead of nested tables, keeping the + existing class and id names so custom themes still match. +* The filter scripts moved to a Lua-only set. simple-authentication.lua became + auth-inline.lua, file-authentication.lua became auth-file.lua and + commit-links.sh became link-commits.lua. +* Lua is optional and autodetected through pkg-config, preferring LuaJIT. + NO_LUA=1 forces a self-contained binary. +* The sources were reorganized into source/, libraries/, assets/, extensions/, + examples/, tools/ and tests/, with all generated output under build/. +* The auth filters compare cookie HMACs in constant time, set SameSite=Lax, and + strip header injection from Set-Cookie and Location values. + +Removed +....... + +* OpenSSL is no longer a build dependency, and libcurl is not required. +* Every Python filter script, including the Pygments highlighter, the markdown + and rst converters and the Python gravatar filter. +* The Gentoo LDAP auth filter, owner-example.lua, about-formatting.sh and the + man and txt about converters. +* The unused name query parameter and the never-read cache-max-create-time and + max-lock-attempts settings. + +Fixed +..... + +* An unauthenticated arbitrary file write through the log id parameter, which + reached git's revision parser as an option. Revisions beginning with a dash + are rejected. +* Cache poisoning through a spoofed Host header. The scheme and host are now + part of the cache key. +* Stored XSS from about pages, which were written as raw HTML when no + about-filter was configured. They are now escaped. +* Two path traversals, one past the about-path prefix check via a sibling + directory sharing a name prefix, and one through a crafted HEAD ref. +* max-blob-size is enforced before a blob is read into memory, not after. +* A signed-comparison bypass of the authentication POST size limit, and an + unbounded history walk from a crafted ofs value, now clamped. +* Every snapshot was undecompressable whenever a global git config existed, + because git's error output was compressed into the archive. +* Numerous crashes, among them out-of-bounds accesses on short paths and empty + URLs, NULL dereferences on odd blobs and authorless commits, a division by + zero in the diffstat and undefined ctype behaviour on negative chars. +* Truncated pages after stat-only diffs and binary blames, a 200 instead of a + 404 for unknown blob paths, submodule hashes losing digits in diffs, pager + links dropping search terms containing reserved characters, a missing updated + element in empty atom feeds and negative ages from the age refresher. -- cgit