Hi… I am well aware that this diff view is very suboptimal. It will be fixed when the refactored server comes along!
http upload pack: Decode compressed bodies
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> package unsorted import ( "bytes"
"compress/gzip" "compress/zlib" "fmt" "io"
"log" "net/http" "os" "os/exec"
"strings"
"github.com/jackc/pgx/v5/pgtype"
)
// httpHandleUploadPack handles incoming Git fetch/pull/clone's over the Smart
// HTTP protocol.
func (s *Server) httpHandleUploadPack(writer http.ResponseWriter, request *http.Request, params map[string]any) (err error) {
if ct := request.Header.Get("Content-Type"); !strings.HasPrefix(ct, "application/x-git-upload-pack-request") {
http.Error(writer, "bad content-type", http.StatusUnsupportedMediaType)
return nil
}
decoded, err := decodeBody(request)
if err != nil {
http.Error(writer, "cannot decode request body", http.StatusBadRequest)
return err
}
defer decoded.Close()
var groupPath []string
var repoName string
var repoPath string
var cmd *exec.Cmd
groupPath, repoName = params["group_path"].([]string), params["repo_name"].(string)
if err := s.database.QueryRow(request.Context(), `
WITH RECURSIVE group_path_cte AS (
-- Start: match the first name in the path where parent_group IS NULL
SELECT
id,
parent_group,
name,
1 AS depth
FROM groups
WHERE name = ($1::text[])[1]
AND parent_group IS NULL
UNION ALL
-- Recurse: jion next segment of the path
SELECT
g.id,
g.parent_group,
g.name,
group_path_cte.depth + 1
FROM groups g
JOIN group_path_cte ON g.parent_group = group_path_cte.id
WHERE g.name = ($1::text[])[group_path_cte.depth + 1]
AND group_path_cte.depth + 1 <= cardinality($1::text[])
)
SELECT r.filesystem_path
FROM group_path_cte c
JOIN repos r ON r.group_id = c.id
WHERE c.depth = cardinality($1::text[])
AND r.name = $2
`,
pgtype.FlatArray[string](groupPath),
repoName,
).Scan(&repoPath); err != nil {
return err
}
writer.Header().Set("Content-Type", "application/x-git-upload-pack-result")
writer.Header().Set("Connection", "Keep-Alive")
writer.Header().Set("Transfer-Encoding", "chunked")
writer.WriteHeader(http.StatusOK)
// writer.Header().Set("Connection", "Keep-Alive")
// writer.Header().Set("Transfer-Encoding", "chunked")
cmd = exec.Command("git", "upload-pack", "--stateless-rpc", repoPath)
cmd = exec.CommandContext(request.Context(), "git", "upload-pack", "--stateless-rpc", repoPath)
cmd.Env = append(os.Environ(), "LINDENII_FORGE_HOOKS_SOCKET_PATH="+s.config.Hooks.Socket) var stderrBuf bytes.Buffer cmd.Stderr = &stderrBuf cmd.Stdout = writer
cmd.Stdin = request.Body
cmd.Stdin = decoded
if gp := request.Header.Get("Git-Protocol"); gp != "" {
cmd.Env = append(cmd.Env, "GIT_PROTOCOL="+gp)
}
if err = cmd.Run(); err != nil {
log.Println(stderrBuf.String())
return err
}
return nil
}
func decodeBody(r *http.Request) (io.ReadCloser, error) {
switch ce := strings.ToLower(strings.TrimSpace(r.Header.Get("Content-Encoding"))); ce {
case "", "identity":
return r.Body, nil
case "gzip":
zr, err := gzip.NewReader(r.Body)
if err != nil { return nil, err }
return zr, nil
case "deflate":
zr, err := zlib.NewReader(r.Body)
if err != nil { return nil, err }
return zr, nil
default:
return nil, fmt.Errorf("unsupported Content-Encoding: %q", ce)
}
}