Published on

为什么cgit不实现FastCGI

Authors
  • avatar
    Name
    ttyS3
    Twitter

cgit简介

cgit - A hyperfast web frontend for git repositories written in C.

cgit没有多余的功能,它就是一个简洁的Git WEB UI.

  • basic repository browsing (logs, diffs, trees...)
  • caching of generated HTML
  • cloneable URLs (implements dumb HTTP transport)
  • commit feeds (atom format)
  • discovery of Git repositories
  • on-the-fly archives for tags and commits
  • plugin support for e.g. syntax highlighting
  • side-by-side diffs
  • simple time/author statistics
  • simple virtual hosting support (macro expansion)
  • understands GitWeb project-lists
  • understands gitweb.owner in Git config files
  • has extensive filtering framework using scripts or a built-in lua interpreter

cgit 这个 WEB UI 本身没有授权验证功能,不过可以通过插件来实现。 cgit也没有仓库授权验证功能,一般可以通过配合gitolite 一起使用来实现。

从界面来说,cgit和git自带的Gitweb非常像。

gitweb后端主要是一个perl文件 https://github.com/git/git/blob/master/gitweb/gitweb.perl , 通过阅读这个文件不难发现,gitweb本身是直接通过调用git命令来实现功能的, 而cgit还是更加高效一些,因为它直接是在c层面调用git.

cgit和gitweb的关系:

cgit 0.1 是cgit的第一个版本,发布日期为2006-12-21 ( https://git.zx2c4.com/cgit/tag/?h=v0.1 )

根据gitweb的README

From the git version 1.4.0 gitweb is bundled with git.

git 1.4.0 是集成 gitweb 的第一个版本,发布日期为Jun 11, 2006 ( https://github.com/git/git/releases/tag/v1.4.0 )

所以,根据上面的发布信息,应该是先有gitweb,再有cgit. cgit第一版的发布日期,大概是gitweb发布的半年之后。可能是cgit作者觉得gitweb不好用,或者不太高效,因此才有了自己写cgit的想法吧。

因此,cgit主要适合用于托管开源代码,供人浏览代码和clone代码。

比如TI就有用cgit https://git.ti.com/cgit

如果你需要更多的功能,可能你更适合giteagitlab社区版之类的。

gitea主要是采用Golang编写,而gitlab似乎是遵循了传统,和Github一样采用了Ruby。

cgit运行方式

cgit自身没有实现httpd server, 它只是一个遵循CGI规范的可执行文件加一些css和html.

需要配合http server(比如nginx或Caddy之类的)通过CGI调用的方式来运行。

熟悉WEB开发的应该都知道,像PHP之类的脚本语言解析器,基本上都是以FastCGI的方式 + nginx 来运行应用。而cgit为什么还在坚守古老的CGI协议呢?

对此,老灯也一直不解。直到有一天在一个mail list上看到了一个cgit项目的参与贡献者的回答。

为什么能证明是参与者?随便Google下关键字John Keeping+cgit,可以找到一些信息,比如 https://git.zx2c4.com/cgit/commit/ui-tree.c?id=985fba80d06f37fdba5e72d738ce21ab5ab5a76d , 他是代码reviewer. Reviewed-by: John Keeping <[email protected]>

https://lists.zx2c4.com/pipermail/cgit/2013-April/001297.html 内容如下:

John Keeping john at keeping.me.uk Sat Apr 13 11:34:10 CEST 2013

On Sat, Apr 13, 2013 at 01:51:03AM -0700, Peter Wu wrote:

I am investigating the options for deploying cgit+gitolite. As I am running nginx, I have to use fastcgi or something similar.

Some resources that I found during a search:

Their instructions however, do suggest the use of nginx + spawn-cgi + fcgiwrap + cgit. I have some issues with it:

  • Even if nginx and cgit run as different users, nginx can still run arbitrary commands under the rights of cgit (via SCRIPT_FILENAME).
  • If the only goal of fcgiwrap is to run cgit, why fcgiwrap at all and not integrate it into cgit?

So I was wondering if somebody has already considered integrating fastcgi into cgit or other experiences with a nginx+(fastcgi+)cgit setup? I do not expect much traffic, but still want to have a secure (isolated) setup with predictable resource use.

The problem with implementing FastCGI in CGit is that CGit currently relies on the OS cleaning up resources when the process exits. So if we use the same process for multiple requests it will just keep growing (in terms of memory use).

There has recently been some progress on improving the CGit side of this, but Git also takes this approach for repository objects.

In addition to that, Git isn't designed for a process to work on more than one repository, so it would be difficult to make CGit handle multiple repositories in a single process correctly.

Given all of that, any implementation of FastCGI in CGit is going to look more or less the same as fcgiwrap, so I don't see any reason not to just use that.

AFAICT, SCRIPT_FILENAME should be managed for you by the webserver and if you are using nginx then it can't actually be used to run arbitrary commands [1]. But I've never use it so perhaps someone with experience of using CGit with nginx would like to comment here.

[1] http://nginx.localdomain.pl/wiki/FcgiWrap

简单来说就是由于cgit是严重依赖于git代码的,因此它的工作方式其实是跟git差不多。

如是你编译过cgit代码,你会发现它在编译前要下载一份完整的git源码,它自身的源码是直接依赖git源码的。所以cgit的版本是跟git版本大致绑定的。 所以这差不多14年来(2006-2020), cgit一直跟随git更新而更新。

要是cgit是采用libgit2写的,肯定切换到FastCGI会没有什么难度, 但是由于历史原因,cgit已经是这样实现了,因此,不太可能会更换到FastCGI实现了。

最后,当然是要安利一波老灯的cgit docker镜像。

这可能是最用心的一个cgit镜像了 https://hub.docker.com/r/80x86/cgit , 老灯历时三天三夜(是真的三天三夜时间,这不是台词)才完成。