-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
96 lines (88 loc) · 2.31 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package main
import (
"flag"
"fmt"
"log"
"net/http"
"net/http/cgi"
"os"
"os/exec"
"path/filepath"
"strings"
)
var gitRootPath string
var prefix string
func HandleGit(w http.ResponseWriter, r *http.Request) {
pathInfo := strings.TrimPrefix(r.URL.Path, strings.TrimSuffix(prefix, "/"))
handler := cgi.Handler{
Path: "/usr/bin/git",
Root: gitRootPath,
Env: []string{
"GIT_PROJECT_ROOT=" + gitRootPath,
"GIT_HTTP_EXPORT_ALL=",
"PATH_INFO=" + pathInfo,
"QUERY_STRING=" + r.URL.RawQuery,
"REQUEST_METHOD=" + r.Method,
"CONTENT_TYPE=" + r.Header.Get("Content-Type"),
},
Args: []string{"http-backend"},
InheritEnv: []string{"PATH"},
Stderr: os.Stderr,
}
defer log.Println(r.RemoteAddr, r.Method, r.URL.Path)
handler.ServeHTTP(w, r)
}
func CreateRepository(root, name string) error {
reposDir := filepath.Join(root, name)
err := os.MkdirAll(reposDir, 0755)
if err != nil {
return err
}
cmds := [][]string{
{"git", "init", reposDir, "--bare", "--shared"},
{"git", "--git-dir", reposDir, "update-server-info"},
{"git", "--git-dir", reposDir, "config", "http.receivepack", "true"},
{"git", "--git-dir", reposDir, "config", "init.defaultBranch", "master"},
}
for _, cmd := range cmds {
c := exec.Command(cmd[0], cmd[1:]...)
c.Stdout = os.Stdout
c.Stderr = os.Stderr
if err = c.Run(); err != nil {
log.Println("Fail:", strings.Join(cmd, " "), err)
return err
}
}
return nil
}
func main() {
var addr string
var create bool = false
flag.StringVar(&addr, "addr", "127.0.0.1:8080", "address to listen on")
flag.StringVar(&gitRootPath, "root", "/tmp/git", "root repository path")
flag.StringVar(&prefix, "prefix", "/", "prefix path for git server")
flag.BoolVar(&create, "create", false, "create repository only without serving")
flag.Parse()
if create {
if flag.NArg() == 0 {
panic("missing repository name")
}
reposName := flag.Arg(0)
err := CreateRepository(gitRootPath, reposName)
if err != nil {
panic(err)
}
return
}
fullAddr := filepath.Join(addr, prefix)
welcome := `🎉Simple Git Server started on %s 🚀
Quit the server with CONTROL-C. 👻
Clone repository with:
git clone http://%s/<repository>.git
`
fmt.Printf(welcome, fullAddr, fullAddr)
err := http.ListenAndServe(addr, http.HandlerFunc(HandleGit))
if err != nil {
panic(err)
}
}