Git的发行版中带了一个叫gitweb的工具,可以以web的方式来查看git仓库。但是gitweb本身是一个CGI脚本,需要一个支持CGI的Web服务器来运行它。这篇文章介绍如何用Go语言写一个简单的服务器,用来运行gitweb。
gitweb的CGI脚本一般叫gitweb.cgi
,随git一起发布。我的macOS上安装的git版本是2.16.2,gitweb.cgi
所在的目录是
/usr/local/Cellar/git/2.16.2/share/gitweb/
在这个目录下除了gitweb.cgi
之外,还有一个static
目录,里面存放着gitweb的前端资源文件。
运行gitweb需要用到Go语言的http库以及cgi库。我们会进行一下编排:
- 在
localhost:3333
启动http服务 - 使用http.ServeFile来访问
static
目录里面的文件 - 通过cgi库在服务器根目录提供
gitweb.cgi
服务
具体的代码如下:
package main
import (
"log"
"net/http"
"net/http/cgi"
"path/filepath"
"strings"
)
var GITWEB_DIR = "/usr/local/Cellar/git/2.16.2/share/gitweb"
var GITWEB_CGI = filepath.Join(GITWEB_DIR, "gitweb.cgi")
func serveGitweb(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/static/") {
http.ServeFile(w, r, filepath.Join(GITWEB_DIR, r.URL.Path))
return
}
conf, err := filepath.Abs("./gitweb.conf")
if err != nil {
log.Fatal(err)
}
env := []string{
"GITWEB_CONFIG=" + conf,
}
gitweb := cgi.Handler{
Path: GITWEB_CGI,
Root: `/`,
Env: env,
}
gitweb.ServeHTTP(w, r)
}
func main() {
http.HandleFunc("/", serveGitweb)
addr := ":3333"
log.Print("ListenAndServe", addr)
err := http.ListenAndServe(addr, nil)
if err != nil {
log.Fatal(err)
}
}
上面的文件保存为gitweb.go
。需要注意的是,为了使gitweb能够正常工作,我们在启动cgi之前,通过环境变量GITWEB_CONFIG
为gitweb指定了一个配置文件gitweb.conf
。在当前的例子中,此配置文件和gitweb.go
在同一目录下,内容为:
our $projectroot = '/path/to/repos';
our $site_name = 'My Gitweb';
其实gitweb.conf
是一个perl脚本,里面定义了两个变量,一个是$projectroot
,告诉gitweb其服务的git仓库在什么位置;另个一是$site_name
,用于作为该gitweb服务的名字。
当gitweb.go
和gitweb.conf
都准备好之后,可以运行:
go run gitweb.go
看到这行提示2018/03/07 21:10:40 ListenAndServe:3333
的时候,说明gitweb已经运行于localhost:3333
了。
其他参考:
- gitweb.conf(5) Manual Page
- gitweb(1) Manual Page
- git-instaweb(1) Manual Page
(完)