cgit - CGI for Git ================== This is an attempt to create a fast web interface for the Git SCM, using a built-in cache to decrease server I/O pressure. Installation ------------ Building cgit involves building a proper version of Git. How to do this depends on how you obtained the cgit sources. In a cloned cgit repository, first initialize and update the Git submodule. $ git submodule init # register the Git submodule in .git/config $ $EDITOR .git/config # if you want to specify a different url for git $ git submodule update # clone/fetch and checkout correct git version From a cgit tarball, download a proper git version instead. $ make get-git With the Git tree in place, build and install cgit. $ make $ sudo make install This installs cgit.cgi and cgit.css into /var/www/htdocs/cgit. The location and a few other things can be changed by providing a cgit.conf file, see the Makefile for details. The only required library is zlib. cgit builds without OpenSSL or libcurl, so no development packages for those are needed. Lua is optional and only powers the lua: filter extensions, the filters in custom/extensions/. A plain build auto-detects a Lua through pkg-config, preferring LuaJIT, and falls back to a Lua-less binary when none is found. To pin an implementation, name its pkg-config module. $ make LUA_PKGCONFIG=lua5.4 Acceptable LUA_PKGCONFIG values include "luajit", "lua", "lua5.4", "lua5.3", "lua5.2" and "lua5.1". To build without Lua, so the binary needs no Lua at runtime, turn it off. $ make NO_LUA=1 A binary built this way still runs every exec: filter, but a filter named with the lua: prefix has no interpreter to run in, so it is refused with an error on every page until the setting is taken out of cgitrc. make test builds this variant as well, into build/nolua, and checks it the same way. Setup ----- cgit is a CGI program. Complete, commented configurations for nginx, Apache and lighttpd live in custom/servers/, each explaining how that server routes requests to the binary and serves the static assets off disk. At runtime cgit reads /etc/cgitrc for its options and for the list of repositories to display. A fully commented starting point with every option at its default is in custom/cgitrc, and MANUAL.txt documents each option in full. Customization ------------- Every page is one document with the same skeleton, so a site stylesheet or script added through the css and js options has stable hooks to work with. * The root is div#cgit. It carries data-page with the page name, summary, log, tree and so on, and data-repo with the repository url on repository pages, so a rule can target one page or one repository. In embedded mode it also carries the class cgit-embedded. * Inside it sit header#header, nav.tabs with the search form, nav.path for the breadcrumb, main.content and footer.footer. Each nav, listing and option form carries an aria-label, and the active tab and the current pager link carry aria-current. * Every listing is a table.list with a second class naming it, repolist, summary, refs, log or tree. Each section of a listing is a tbody named repos, branches, tags, log, clone or tree, and each row carries its kind, repo, branch, tag, commit, dir, blob, link or mod. A file row's link also carries ext- followed by the file extension. * The commit and tag pages use table.commit-info, the trailer table is table.commit-trailers, the diffstat is table.diffstat and each file of a diff is div.file, or tbody.file in the side by side view, with the path in data-path. The blob and blame pages open with div.blob-header. * Ages are time elements with an age-* class and the timestamp in data-ut. Line numbers are anchors named n followed by the line. * Colours, fonts and metrics are custom properties on div#cgit, so a theme can redefine those alone. Every rule in cgit.css starts with div#cgit, and a rule of your own needs the same prefix to win. * The script exposes window.cgit.updateAges and window.cgit.highlightLines for a page that changes the rows or the lines after load. A theme that only wants a colour change is a few lines. div#cgit { --link: light-dark(#7a1f1f, #f0a0a0); --font-sans: Georgia, serif; } div#cgit[data-page='log'] table.list tr.commit:hover { background: var(--surface); } tests/t0005-markup.sh checks that every hook named here is still emitted. Filter extensions ----------------- The optional Lua filters in custom/extensions/ mostly need extra Lua modules, and each script's header lists the exact install commands for its own. * The auth filters, auth-file.lua and auth-inline.lua, need luaossl and luaposix. * The email filters, email-gravatar.lua and email-libravatar.lua, need luaossl. * The syntax highlighter, syntax-highlight.lua, needs lpeg and a Scintillua lexer set. * The about-page renderer, about-render.lua, needs lpeg for markdown and man pages. Plain text needs only Lua. * link-commits.lua and link-trailers.lua need nothing beyond Lua itself. luaossl has no Lua 5.5 build, so build cgit against 5.1 to 5.4 if you use the auth or email filters. URLs and query parameters ------------------------- cgit serves every page from one CGI program, so a url names the repository, the page and a path inside that page. There are two forms and they carry the same information. With virtual-root set, a request is a path, written as /// with anything else as a query string. Without it, the whole request lives in the query string as ?url=//. The page name is the second element and is one of about, atom, blame, blob, commit, diff, log, patch, plain, rawdiff, refs, snapshot, stats, summary, tag or tree. Leaving it out gives the repository summary, and leaving the repository out as well gives the index of repositories. Everything after the page name is the path argument, so /demo/tree/src/main.c asks for the tree page at src/main.c. A repository whose name contains a character that is special in a url has it percent-encoded, and a plus sign has to be written %2b because a bare plus decodes to a space. Every parameter is optional. The pages column names the pages that read each one, where a value of all marks the few not tied to particular pages. +----------+----------------------+--------------------------------------------+ | param | pages | description | +----------+----------------------+--------------------------------------------+ | url | all | repository, page and path in one value | | h | all | the branch or ref to read | | id | all | pin the page to one commit or object | | id2 | diff patch rawdiff | second object of a diff, paired with id | | ofs | index log refs stats | offset into a paged listing | | path | all | restrict the page to one path | | q | log | the search term, matched literally | | qt | log | one of grep, author, committer or range | | s | index | sort key for the listing | | showmsg | log | show full commit messages | | period | stats | the statistics window, one of w, m, q or y | | dt | diff commit | diff type, unified, side by side or raw | | ss | diff commit | shorthand for the side by side diff | | all | atom | include every ref rather than one branch | | context | diff commit | lines of context around a diff hunk | | ignorews | diff commit | ignore whitespace when diffing | | follow | log | follow a single path across renames | +----------+----------------------+--------------------------------------------+ A few endpoints are not ordinary pages. The snapshot page takes a filename rather than a ref, so /demo/snapshot/demo-1.0.tar.gz names both the ref and the archive format through the suffix, and the formats on offer are set by the snapshots option. The plain page serves a blob as its own bytes under headers that stop a browser treating repository content as markup. The atom page is a feed rather than a page and accepts h, path and all. The clone endpoints under info and objects implement the dumb HTTP protocol and are only present when http clone is enabled. A url fragment can address lines inside a file. The tree and blame pages give every line an anchor named n followed by its number, so #n17 jumps to line 17 and highlights it, and a range written #n17-n24 highlights the whole run and scrolls it into view. Some worked examples, in the url= form. ?url= the repository index ?url=demo summary for the demo repository ?url=demo/log&h=next log of the next branch ?url=demo/log&qt=author&q=alice commits authored by alice ?url=demo/tree/src&h=v1.0 the src directory at tag v1.0 ?url=demo/commit&id=HEAD~3 one commit, pinned ?url=demo/diff&id=main&id2=next diff between two branches ?url=demo/plain/README.md the raw bytes of one file ?url=demo/atom&h=main the commit feed for a branch Credits ------- cgit was created by Lars Hjemli and maintained upstream for many years, most recently by Jason A. Donenfeld. This repository is an independent fork that builds on their work. They are not maintainers of this fork and are not responsible for it.