-
Notifications
You must be signed in to change notification settings - Fork 5
/
main.go
134 lines (114 loc) · 3.22 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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
const (
ApplicationName = "git-cgi-server"
defaultAddr = ":8080"
shutdownTimeout = time.Second * 5
)
var (
// injected by build process
version = "unknown"
)
type Args struct {
ProjectRoot string
ExportAll bool
BackendCGI string
BasicAuthFile string
DigestAuthFile string
AuthRealm string
URIPrefix string
Addr string
CertFile string
KeyFile string
PID string
}
func parseArgs() (*Args, error) {
var args Args
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(),
"%s version %s\n\nUsage: %s [REPOS_DIR]\n", ApplicationName, version, os.Args[0])
flag.PrintDefaults()
}
flag.BoolVar(&args.ExportAll, "export-all", false, "export all repositories")
flag.StringVar(&args.BackendCGI, "backend-cgi", "", "path to the CGI (git-http-backend)")
flag.StringVar(&args.BasicAuthFile, "basic-auth-file", "", "path to the basic auth file (htpasswd)")
flag.StringVar(&args.DigestAuthFile, "digest-auth-file", "", "path to the digest auth file (htdigest)")
flag.StringVar(&args.AuthRealm, "auth-realm", "Git", "realm name for the auth")
flag.StringVar(&args.URIPrefix, "uri-prefix", "/", "URI prefix")
flag.StringVar(&args.Addr, "addr", defaultAddr, "server address")
flag.StringVar(&args.CertFile, "cert-file", "", "TLS Certificate")
flag.StringVar(&args.KeyFile, "key-file", "", "TLS Certificate Key")
flag.StringVar(&args.PID, "pid", "", "PID file")
flag.Parse()
if args.CertFile != "" && args.KeyFile == "" {
fmt.Println("-key-file is required when -cert-file specified")
os.Exit(1)
}
projectRoot, err := getProjectRoot(flag.Args())
if err != nil {
return nil, err
}
args.ProjectRoot = projectRoot
return &args, nil
}
func main() {
args, err := parseArgs()
if err != nil {
log.Fatalln(err)
}
server := &GitCGIServer{
ProjectRoot: args.ProjectRoot,
ExportAll: args.ExportAll,
BackendCGI: args.BackendCGI,
BasicAuthFile: args.BasicAuthFile,
DigestAuthFile: args.DigestAuthFile,
AuthRealm: args.AuthRealm,
URIPrefix: args.URIPrefix,
Addr: args.Addr,
CertFile: args.CertFile,
KeyFile: args.KeyFile,
ShutdownTimeout: shutdownTimeout,
}
idleConnsClosed := make(chan struct{})
go func() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
log.Printf("Shutting down HTTP server by signal '%s' received\n", <-sigCh)
if err := server.Shutdown(context.Background()); err != nil {
log.Printf("HTTP server shutdown error: %v", err)
}
close(idleConnsClosed)
}()
if args.PID != "" {
if err := writePIDFile(args.PID); err != nil {
log.Fatalln(err)
}
defer removePIDFile(args.PID)
}
log.Printf("Starting HTTP server on %s (PID=%d)\n", args.Addr, os.Getpid())
if err := server.Serve(); err != nil && err != http.ErrServerClosed {
log.Println("HTTP server error:", err)
}
<-idleConnsClosed
log.Println("HTTP server stopped")
}
func getProjectRoot(args []string) (string, error) {
if len(args) > 0 && args[0] != "" {
return args[0], nil
}
cwd, err := os.Getwd()
if err != nil {
return "", nil
}
return cwd, nil
}