Skip to content

Commit b926fc7

Browse files
committed
add support for an http git server !
1 parent 205b9d2 commit b926fc7

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

example/git/main.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const { SMALLWEB_SOCKET_PATH } = Deno.env.toObject();
2+
3+
const client = Deno.createHttpClient({
4+
proxy: {
5+
transport: "unix",
6+
path: SMALLWEB_SOCKET_PATH,
7+
},
8+
});
9+
10+
export default {
11+
fetch: (req: Request) => {
12+
const url = new URL(req.url);
13+
url.host = "git.localhost";
14+
15+
return fetch(
16+
new Request(url, req),
17+
{ client },
18+
);
19+
},
20+
};

internal/api/api.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ package api
33
import (
44
"context"
55
"net/http"
6+
"net/http/cgi"
7+
"os"
8+
"os/exec"
69
"path/filepath"
10+
"strings"
711

812
"github.com/danielgtaylor/huma/v2"
913
"github.com/danielgtaylor/huma/v2/adapters/humachi"
@@ -42,6 +46,7 @@ func NewHandler(conf *utils.Config) http.Handler {
4246

4347
hr.Map("webdav.localhost", webdavRouter(conf))
4448
hr.Map("api.localhost", apiRouter(conf))
49+
hr.Map("git.localhost", gitRouter(conf))
4550
hr.Map("*", catchAllRouter())
4651

4752
r.Mount("/", hr)
@@ -121,6 +126,46 @@ func apiRouter(conf *utils.Config) chi.Router {
121126
return r
122127
}
123128

129+
func gitRouter(conf *utils.Config) chi.Router {
130+
r := chi.NewRouter()
131+
132+
repoRoot := filepath.Join(conf.String("dir"))
133+
134+
gitPath, err := exec.LookPath("git")
135+
if err != nil {
136+
r.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
137+
http.Error(w, "git binary not found on server", http.StatusInternalServerError)
138+
})
139+
return r
140+
}
141+
142+
gitHandler := &cgi.Handler{
143+
Path: gitPath,
144+
Args: []string{"http-backend"},
145+
Env: []string{
146+
"GIT_PROJECT_ROOT=" + repoRoot,
147+
"GIT_HTTP_EXPORT_ALL=", // allow read-only access
148+
},
149+
Stderr: os.Stderr,
150+
InheritEnv: []string{
151+
"PATH", "HOME", // inherit some safe env vars
152+
},
153+
}
154+
155+
r.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
156+
if strings.HasSuffix(r.URL.Path, "/git-receive-pack") {
157+
http.Error(w, "pushes are disabled", http.StatusForbidden)
158+
return
159+
}
160+
161+
fixChunked(r)
162+
163+
gitHandler.ServeHTTP(w, r)
164+
})
165+
166+
return r
167+
}
168+
124169
func catchAllRouter() chi.Router {
125170
r := chi.NewRouter()
126171

@@ -131,3 +176,14 @@ func catchAllRouter() chi.Router {
131176

132177
return r
133178
}
179+
180+
func fixChunked(req *http.Request) {
181+
if len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == `chunked` {
182+
// hacking!
183+
req.TransferEncoding = nil
184+
req.Header.Set(`Transfer-Encoding`, `chunked`)
185+
186+
// let cgi use Body.
187+
req.ContentLength = -1
188+
}
189+
}

internal/cmd/git.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func NewCmdGitReceivePack() *cobra.Command {
2626
return ExitError{1}
2727
}
2828

29-
gitCmd := exec.Command("git-receive-pack", a.Dir)
29+
gitCmd := exec.Command("git", "receive-pack", a.Dir)
3030

3131
gitCmd.Stdin = cmd.InOrStdin()
3232
gitCmd.Stdout = cmd.OutOrStdout()
@@ -65,7 +65,7 @@ func NewCmdGitUploadPack() *cobra.Command {
6565
return ExitError{1}
6666
}
6767

68-
gitCmd := exec.Command("git-upload-pack", a.Dir)
68+
gitCmd := exec.Command("git", "upload-pack", a.Dir)
6969

7070
gitCmd.Stdin = cmd.InOrStdin()
7171
gitCmd.Stdout = cmd.OutOrStdout()

0 commit comments

Comments
 (0)