Hi… I am well aware that this diff view is very suboptimal. It will be fixed when the refactored server comes along!
repo/*: Use var instead of :=
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "fmt" "net/http" "strings" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/format/diff"
"github.com/go-git/go-git/v5/plumbing/object"
"go.lindenii.runxiyu.org/lindenii-common/misc" ) // The file patch type from go-git isn't really usable in HTML templates // either.
type usable_file_patch struct {
type usable_file_patch_t struct {
	From   diff.File
	To     diff.File
	Chunks []usable_chunk
}
type usable_chunk struct {
	Operation diff.Operation
	Content   string
}
func handle_repo_commit(w http.ResponseWriter, r *http.Request, params map[string]any) {
repo, commit_id_specified_string := params["repo"].(*git.Repository), params["commit_id"].(string)
var repo *git.Repository var commit_id_specified_string, commit_id_specified_string_without_suffix string var commit_id plumbing.Hash var parent_commit_hash plumbing.Hash var commit_object *object.Commit var commit_id_string string var err error var patch *object.Patch repo, commit_id_specified_string = params["repo"].(*git.Repository), params["commit_id"].(string)
	commit_id_specified_string_without_suffix := strings.TrimSuffix(commit_id_specified_string, ".patch")
	commit_id := plumbing.NewHash(commit_id_specified_string_without_suffix)
	commit_object, err := repo.CommitObject(commit_id)
	if err != nil {
	commit_id_specified_string_without_suffix = strings.TrimSuffix(commit_id_specified_string, ".patch")
	commit_id = plumbing.NewHash(commit_id_specified_string_without_suffix)
	if commit_object, err = repo.CommitObject(commit_id); err != nil {
		http.Error(w, "Error getting commit object: "+err.Error(), http.StatusInternalServerError)
		return
	}
	if commit_id_specified_string_without_suffix != commit_id_specified_string {
		patch, err := format_patch_from_commit(commit_object)
		if err != nil {
		var formatted_patch string
		if formatted_patch, err = format_patch_from_commit(commit_object); err != nil {
http.Error(w, "Error formatting patch: "+err.Error(), http.StatusInternalServerError) return }
fmt.Fprintln(w, patch)
fmt.Fprintln(w, formatted_patch)
return }
commit_id_string := commit_object.Hash.String()
commit_id_string = commit_object.Hash.String()
	if commit_id_string != commit_id_specified_string {
		http.Redirect(w, r, commit_id_string, http.StatusSeeOther)
		return
	}
	params["commit_object"] = commit_object
	params["commit_id"] = commit_id_string
parent_commit_hash, patch, err := get_patch_from_commit(commit_object)
parent_commit_hash, patch, err = get_patch_from_commit(commit_object)
	if err != nil {
		http.Error(w, "Error getting patch from commit: "+err.Error(), http.StatusInternalServerError)
		return
	}
	params["parent_commit_hash"] = parent_commit_hash.String()
	params["patch"] = patch
	params["file_patches"] = make_usable_file_patches(patch)
	render_template(w, "repo_commit", params)
}
type fake_diff_file struct {
	hash plumbing.Hash
	mode filemode.FileMode
	path string
}
func (f fake_diff_file) Hash() plumbing.Hash {
	return f.hash
}
func (f fake_diff_file) Mode() filemode.FileMode {
	return f.mode
}
func (f fake_diff_file) Path() string {
	return f.path
}
var fake_diff_file_null = fake_diff_file{
	hash: plumbing.NewHash("0000000000000000000000000000000000000000"),
	mode: misc.First_or_panic(filemode.New("100644")),
	path: "",
}
func make_usable_file_patches(patch diff.Patch) (usable_file_patches []usable_file_patch) {
	// TODO: Remove unnecessary context
	// TODO: Prepend "+"/"-"/" " instead of solely distinguishing based on color
usable_file_patches = make([]usable_file_patch, 0)
	for _, file_patch := range patch.FilePatches() {
from, to := file_patch.Files()
		var from, to diff.File
		var usable_file_patch usable_file_patch_t
		chunks := []usable_chunk{}
		from, to = file_patch.Files()
		if from == nil {
			from = fake_diff_file_null
		}
		if to == nil {
			to = fake_diff_file_null
		}
		chunks := []usable_chunk{}
		for _, chunk := range file_patch.Chunks() {
content := chunk.Content()
var content string content = chunk.Content()
			if len(content) > 0 && content[0] == '\n' {
				content = "\n" + content
			} // Horrible hack to fix how browsers newlines that immediately proceed <pre>
			chunks = append(chunks, usable_chunk{
				Operation: chunk.Type(),
				Content:   content,
			})
		}
		usable_file_patch := usable_file_patch{
		usable_file_patch = usable_file_patch_t{
Chunks: chunks, From: from, To: to, } usable_file_patches = append(usable_file_patches, usable_file_patch) } return }
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "net/http"
"github.com/jackc/pgx/v5"
)
type id_title_status_t struct {
	ID     int
	Title  string
	Status string
}
func handle_repo_contrib_index(w http.ResponseWriter, r *http.Request, params map[string]any) {
	rows, err := database.Query(r.Context(), "SELECT id, COALESCE(title, 'Untitled'), status FROM merge_requests WHERE repo_id = $1", params["repo_id"])
	if err != nil {
	var rows pgx.Rows
	var result []id_title_status_t
	var err error
	if rows, err = database.Query(r.Context(),
		"SELECT id, COALESCE(title, 'Untitled'), status FROM merge_requests WHERE repo_id = $1",
		params["repo_id"],
	); err != nil {
http.Error(w, "Error querying merge requests: "+err.Error(), http.StatusInternalServerError) return } defer rows.Close()
	result := []id_title_status_t{}
	for rows.Next() {
		var id int
		var title, status string
		if err := rows.Scan(&id, &title, &status); err != nil {
		if err = rows.Scan(&id, &title, &status); err != nil {
			http.Error(w, "Error scanning merge request: "+err.Error(), http.StatusInternalServerError)
			return
		}
		result = append(result, id_title_status_t{id, title, status})
	}
	if err := rows.Err(); err != nil {
	if err = rows.Err(); err != nil {
http.Error(w, "Error ranging over merge requests: "+err.Error(), http.StatusInternalServerError) return } params["merge_requests"] = result render_template(w, "repo_contrib_index", params) }
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "net/http" "strconv" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
func handle_repo_contrib_one(w http.ResponseWriter, r *http.Request, params map[string]any) {
mr_id_string := params["mr_id"].(string) mr_id, err := strconv.ParseInt(mr_id_string, 10, strconv.IntSize)
var mr_id_string string var mr_id int var err error var title, status, source_ref, destination_branch string var repo *git.Repository var source_ref_hash plumbing.Hash var source_commit *object.Commit mr_id_string = params["mr_id"].(string) mr_id_int64, err := strconv.ParseInt(mr_id_string, 10, strconv.IntSize)
	if err != nil {
		http.Error(w, "Merge request ID not an integer: "+err.Error(), http.StatusBadRequest)
		return
	}
mr_id = int(mr_id_int64)
	var title, status, source_ref, destination_branch string
	err = database.QueryRow(r.Context(), "SELECT COALESCE(title, ''), status, source_ref, COALESCE(destination_branch, '') FROM merge_requests WHERE id = $1", mr_id).Scan(&title, &status, &source_ref, &destination_branch)
	if err != nil {
	if err = database.QueryRow(r.Context(),
		"SELECT COALESCE(title, ''), status, source_ref, COALESCE(destination_branch, '') FROM merge_requests WHERE id = $1",
		mr_id,
	).Scan(&title, &status, &source_ref, &destination_branch); err != nil {
http.Error(w, "Error querying merge request: "+err.Error(), http.StatusInternalServerError) return }
repo := params["repo"].(*git.Repository)
repo = params["repo"].(*git.Repository)
	source_ref_hash, err := get_ref_hash_from_type_and_name(repo, "branch", source_ref)
	if err != nil {
	if source_ref_hash, err = get_ref_hash_from_type_and_name(repo, "branch", source_ref); err != nil {
http.Error(w, "Error getting source ref hash: "+err.Error(), http.StatusInternalServerError) return }
	source_commit, err := repo.CommitObject(source_ref_hash)
	if err != nil {
	if source_commit, err = repo.CommitObject(source_ref_hash); err != nil {
		http.Error(w, "Error getting source commit: "+err.Error(), http.StatusInternalServerError)
		return
	}
	params["source_commit"] = source_commit
	var destination_branch_hash plumbing.Hash
	if destination_branch == "" {
		destination_branch = "HEAD"
		destination_branch_hash, err = get_ref_hash_from_type_and_name(repo, "", "")
	} else {
		destination_branch_hash, err = get_ref_hash_from_type_and_name(repo, "branch", destination_branch)
		if err != nil {
			http.Error(w, "Error getting destination branch hash: "+err.Error(), http.StatusInternalServerError)
			return
		}
	}
	destination_commit, err := repo.CommitObject(destination_branch_hash)
	if err != nil {
		http.Error(w, "Error getting destination commit: "+err.Error(), http.StatusInternalServerError)
		return
	}
	params["destination_commit"] = destination_commit
	patch, err := destination_commit.Patch(source_commit)
	if err != nil {
		http.Error(w, "Error getting patch: "+err.Error(), http.StatusInternalServerError)
		return
	}
	params["file_patches"] = make_usable_file_patches(patch)
	params["mr_title"], params["mr_status"], params["mr_source_ref"], params["mr_destination_branch"] = title, status, source_ref, destination_branch
	render_template(w, "repo_contrib_one", params)
}
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "net/http" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object"
)
func handle_repo_index(w http.ResponseWriter, r *http.Request, params map[string]any) {
repo, repo_name, group_name := params["repo"].(*git.Repository), params["repo_name"].(string), params["group_name"].(string)
var repo *git.Repository var repo_name, group_name string var ref_hash plumbing.Hash var err error var recent_commits []*object.Commit var commit_object *object.Commit var tree *object.Tree
	ref_hash, err := get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string))
	if err != nil {
	repo, repo_name, group_name = params["repo"].(*git.Repository), params["repo_name"].(string), params["group_name"].(string)
	if ref_hash, err = get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string)); err != nil {
http.Error(w, "Error getting ref hash: "+err.Error(), http.StatusInternalServerError) return }
	recent_commits, err := get_recent_commits(repo, ref_hash, 3)
	if err != nil {
	if recent_commits, err = get_recent_commits(repo, ref_hash, 3); err != nil {
http.Error(w, "Error getting recent commits: "+err.Error(), http.StatusInternalServerError) return } params["commits"] = recent_commits
commit_object, err := repo.CommitObject(ref_hash)
commit_object, err = repo.CommitObject(ref_hash)
	if err != nil {
		http.Error(w, "Error getting commit object: "+err.Error(), http.StatusInternalServerError)
		return
	}
tree, err := commit_object.Tree()
tree, err = commit_object.Tree()
	if err != nil {
		http.Error(w, "Error getting file tree: "+err.Error(), http.StatusInternalServerError)
		return
	}
	params["readme_filename"], params["readme"] = render_readme_at_tree(tree)
	params["files"] = build_display_git_tree(tree)
	params["http_clone_url"] = generate_http_remote_url(group_name, repo_name)
	params["ssh_clone_url"] = generate_ssh_remote_url(group_name, repo_name)
	render_template(w, "repo_index", params)
}
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
package main
import (
	"fmt"
	"io"
	"net/http"
	"os/exec"
)
func handle_repo_info(w http.ResponseWriter, r *http.Request, params map[string]any) (err error) {
	group_name, repo_name := params["group_name"].(string), params["repo_name"].(string)
	var repo_path string
	err = database.QueryRow(r.Context(), "SELECT r.filesystem_path FROM repos r JOIN groups g ON r.group_id = g.id WHERE g.name = $1 AND r.name = $2;", group_name, repo_name).Scan(&repo_path)
	if err != nil {
	var group_name, repo_name, repo_path string
	group_name, repo_name = params["group_name"].(string), params["repo_name"].(string)
	if err = database.QueryRow(r.Context(),
		"SELECT r.filesystem_path FROM repos r JOIN groups g ON r.group_id = g.id WHERE g.name = $1 AND r.name = $2;",
		group_name, repo_name,
	).Scan(&repo_path); err != nil {
		return err
	}
	w.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
	w.WriteHeader(http.StatusOK)
	cmd := exec.Command("git", "upload-pack", "--stateless-rpc", "--advertise-refs", repo_path)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
cmd.Stderr = cmd.Stdout
	defer func() {
		_ = stdout.Close()
	}()
cmd.Stderr = cmd.Stdout
	err = cmd.Start()
	if err != nil {
	if err = cmd.Start(); err != nil {
return err }
	err = pack_line(w, "# service=git-upload-pack\n")
	if err != nil {
	if err = pack_line(w, "# service=git-upload-pack\n"); err != nil {
return err }
	err = pack_flush(w)
	if err != nil {
	if err = pack_flush(w); err != nil {
return }
	_, err = io.Copy(w, stdout)
	if err != nil {
	if _, err = io.Copy(w, stdout); err != nil {
return err }
	err = cmd.Wait()
	if err != nil {
	if err = cmd.Wait(); err != nil {
		return err
	}
	return nil
}
// Taken from https://github.com/icyphox/legit, MIT license
func pack_line(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}
// Taken from https://github.com/icyphox/legit, MIT license
func pack_flush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "net/http" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object"
)
// TODO: I probably shouldn't include *all* commits here...
func handle_repo_log(w http.ResponseWriter, r *http.Request, params map[string]any) {
repo := params["repo"].(*git.Repository)
var repo *git.Repository var ref_hash plumbing.Hash var err error var commits []*object.Commit repo = params["repo"].(*git.Repository)
	ref_hash, err := get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string))
	if err != nil {
	if ref_hash, err = get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string)); err != nil {
http.Error(w, "Error getting ref hash: "+err.Error(), http.StatusInternalServerError) return }
	commits, err := get_recent_commits(repo, ref_hash, -1)
	if err != nil {
	if commits, err = get_recent_commits(repo, ref_hash, -1); err != nil {
http.Error(w, "Error getting recent commits: "+err.Error(), http.StatusInternalServerError) return } params["commits"] = commits render_template(w, "repo_log", params) }
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "fmt" "net/http" "path" "strings" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
	"github.com/go-git/go-git/v5/plumbing/object"
)
func handle_repo_raw(w http.ResponseWriter, r *http.Request, params map[string]any) {
raw_path_spec := params["rest"].(string) repo, path_spec := params["repo"].(*git.Repository), strings.TrimSuffix(raw_path_spec, "/")
var raw_path_spec, path_spec string var repo *git.Repository var ref_hash plumbing.Hash var commit_object *object.Commit var tree *object.Tree var err error raw_path_spec = params["rest"].(string) repo, path_spec = params["repo"].(*git.Repository), strings.TrimSuffix(raw_path_spec, "/")
params["path_spec"] = path_spec
	ref_hash, err := get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string))
	if err != nil {
	if ref_hash, err = get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string)); err != nil {
http.Error(w, "Error getting ref hash: "+err.Error(), http.StatusInternalServerError) return }
	commit_object, err := repo.CommitObject(ref_hash)
	if err != nil {
	if commit_object, err = repo.CommitObject(ref_hash); err != nil {
http.Error(w, "Error getting commit object: "+err.Error(), http.StatusInternalServerError) return }
	tree, err := commit_object.Tree()
	if err != nil {
	if tree, err = commit_object.Tree(); err != nil {
		http.Error(w, "Error getting file tree: "+err.Error(), http.StatusInternalServerError)
		return
	}
	var target *object.Tree
	if path_spec == "" {
		target = tree
	} else {
		target, err = tree.Tree(path_spec)
		if err != nil {
			file, err := tree.File(path_spec)
			if err != nil {
		if target, err = tree.Tree(path_spec); err != nil {
			var file *object.File
			var file_contents string
			if file, err = tree.File(path_spec); err != nil {
				http.Error(w, "Error retrieving path: "+err.Error(), http.StatusInternalServerError)
				return
			}
			if len(raw_path_spec) != 0 && raw_path_spec[len(raw_path_spec)-1] == '/' {
				http.Redirect(w, r, "../"+path_spec, http.StatusSeeOther)
				return
			}
			file_contents, err := file.Contents()
			if err != nil {
			if file_contents, err = file.Contents(); err != nil {
http.Error(w, "Error reading file: "+err.Error(), http.StatusInternalServerError) return }
fmt.Fprintln(w, file_contents)
fmt.Fprint(w, file_contents)
			return
		}
	}
	if len(raw_path_spec) != 0 && raw_path_spec[len(raw_path_spec)-1] != '/' {
		http.Redirect(w, r, path.Base(path_spec)+"/", http.StatusSeeOther)
		return
	}
	params["files"] = build_display_git_tree(target)
	render_template(w, "repo_raw_dir", params)
}
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileContributor: Runxi Yu <https://runxiyu.org> package main import ( "bytes" "html/template" "net/http" "path" "strings"
"github.com/alecthomas/chroma/v2"
chroma_formatters_html "github.com/alecthomas/chroma/v2/formatters/html" chroma_lexers "github.com/alecthomas/chroma/v2/lexers" chroma_styles "github.com/alecthomas/chroma/v2/styles" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
	"github.com/go-git/go-git/v5/plumbing/object"
)
func handle_repo_tree(w http.ResponseWriter, r *http.Request, params map[string]any) {
raw_path_spec := params["rest"].(string) repo, path_spec := params["repo"].(*git.Repository), strings.TrimSuffix(raw_path_spec, "/")
var raw_path_spec, path_spec string var repo *git.Repository var ref_hash plumbing.Hash var commit_object *object.Commit var tree *object.Tree var err error raw_path_spec = params["rest"].(string) repo, path_spec = params["repo"].(*git.Repository), strings.TrimSuffix(raw_path_spec, "/")
params["path_spec"] = path_spec
	ref_hash, err := get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string))
	if err != nil {
	if ref_hash, err = get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string)); err != nil {
http.Error(w, "Error getting ref hash: "+err.Error(), http.StatusInternalServerError) return }
	commit_object, err := repo.CommitObject(ref_hash)
	if err != nil {
	if commit_object, err = repo.CommitObject(ref_hash); err != nil {
http.Error(w, "Error getting commit object: "+err.Error(), http.StatusInternalServerError) return }
	tree, err := commit_object.Tree()
	if err != nil {
	if tree, err = commit_object.Tree(); err != nil {
		http.Error(w, "Error getting file tree: "+err.Error(), http.StatusInternalServerError)
		return
	}
	var target *object.Tree
	if path_spec == "" {
		target = tree
	} else {
		target, err = tree.Tree(path_spec)
		if err != nil {
			file, err := tree.File(path_spec)
			if err != nil {
		if target, err = tree.Tree(path_spec); err != nil {
			var file *object.File
			var file_contents string
			var lexer chroma.Lexer
			var iterator chroma.Iterator
			var style *chroma.Style
			var formatter *chroma_formatters_html.Formatter
			var formatted_encapsulated template.HTML
			if file, err = tree.File(path_spec); err != nil {
				http.Error(w, "Error retrieving path: "+err.Error(), http.StatusInternalServerError)
				return
			}
			if len(raw_path_spec) != 0 && raw_path_spec[len(raw_path_spec)-1] == '/' {
				http.Redirect(w, r, "../"+path_spec, http.StatusSeeOther)
				return
			}
			file_contents, err := file.Contents()
			if err != nil {
			if file_contents, err = file.Contents(); err != nil {
http.Error(w, "Error reading file: "+err.Error(), http.StatusInternalServerError) return }
lexer := chroma_lexers.Match(path_spec)
lexer = chroma_lexers.Match(path_spec)
			if lexer == nil {
				lexer = chroma_lexers.Fallback
			}
			iterator, err := lexer.Tokenise(nil, file_contents)
			if err != nil {
			if iterator, err = lexer.Tokenise(nil, file_contents); err != nil {
http.Error(w, "Error tokenizing code: "+err.Error(), http.StatusInternalServerError) return } var formatted_unencapsulated bytes.Buffer
			style := chroma_styles.Get("autumn")
			formatter := chroma_formatters_html.New(chroma_formatters_html.WithClasses(true), chroma_formatters_html.TabWidth(8))
			err = formatter.Format(&formatted_unencapsulated, style, iterator)
			if err != nil {
			style = chroma_styles.Get("autumn")
			formatter = chroma_formatters_html.New(chroma_formatters_html.WithClasses(true), chroma_formatters_html.TabWidth(8))
			if err = formatter.Format(&formatted_unencapsulated, style, iterator); err != nil {
http.Error(w, "Error formatting code: "+err.Error(), http.StatusInternalServerError) return }
formatted_encapsulated := template.HTML(formatted_unencapsulated.Bytes())
formatted_encapsulated = template.HTML(formatted_unencapsulated.Bytes())
			params["file_contents"] = formatted_encapsulated
			render_template(w, "repo_tree_file", params)
			return
		}
	}
	if len(raw_path_spec) != 0 && raw_path_spec[len(raw_path_spec)-1] != '/' {
		http.Redirect(w, r, path.Base(path_spec)+"/", http.StatusSeeOther)
		return
	}
	params["readme_filename"], params["readme"] = render_readme_at_tree(target)
	params["files"] = build_display_git_tree(target)
	render_template(w, "repo_tree_dir", params)
}
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
package main
import (
	"io"
	"net/http"
	"os"
	"os/exec"
)
func handle_upload_pack(w http.ResponseWriter, r *http.Request, params map[string]any) (err error) {
group_name, repo_name := params["group_name"].(string), params["repo_name"].(string)
var group_name, repo_name string
var repo_path string
	err = database.QueryRow(r.Context(), "SELECT r.filesystem_path FROM repos r JOIN groups g ON r.group_id = g.id WHERE g.name = $1 AND r.name = $2;", group_name, repo_name).Scan(&repo_path)
	if err != nil {
	var stdout io.ReadCloser
	var stdin io.WriteCloser
	var cmd *exec.Cmd
	group_name, repo_name = params["group_name"].(string), params["repo_name"].(string)
	if err = database.QueryRow(r.Context(),
		"SELECT r.filesystem_path FROM repos r JOIN groups g ON r.group_id = g.id WHERE g.name = $1 AND r.name = $2;",
		group_name, repo_name,
	).Scan(&repo_path); err != nil {
		return err
	}
	w.Header().Set("Content-Type", "application/x-git-upload-pack-result")
	w.Header().Set("Connection", "Keep-Alive")
	w.Header().Set("Transfer-Encoding", "chunked")
	w.WriteHeader(http.StatusOK)
	cmd := exec.Command("git", "upload-pack", "--stateless-rpc", repo_path)
	cmd = exec.Command("git", "upload-pack", "--stateless-rpc", repo_path)
cmd.Env = append(os.Environ(), "LINDENII_FORGE_HOOKS_SOCKET_PATH="+config.Hooks.Socket)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
	if stdout, err = cmd.StdoutPipe(); err != nil {
		return err
	}
	cmd.Stderr = cmd.Stdout
	defer func() {
		_ = stdout.Close()
	}()
	stdin, err := cmd.StdinPipe()
	if err != nil {
	if stdin, err = cmd.StdinPipe(); err != nil {
		return err
	}
	defer func() {
		_ = stdin.Close()
	}()
	err = cmd.Start()
	if err != nil {
	if err = cmd.Start(); err != nil {
return err }
	_, err = io.Copy(stdin, r.Body)
	if err != nil {
	if _, err = io.Copy(stdin, r.Body); err != nil {
return err }
	err = stdin.Close()
	if err != nil {
	if err = stdin.Close(); err != nil {
return err }
	_, err = io.Copy(w, stdout)
	if err != nil {
	if _, err = io.Copy(w, stdout); err != nil {
return err }
	err = cmd.Wait()
	if err != nil {
	if err = cmd.Wait(); err != nil {
return err } return nil }