Lindenii Project Forge
Login

server

Lindenii Forge’s main backend daemon
Commit info
ID
cab2f0547987fa3ecd32c37971dd0f4df9787465
Author
Runxi Yu <me@runxiyu.org>
Author date
Sun, 16 Mar 2025 01:36:02 +0800
Committer
Runxi Yu <me@runxiyu.org>
Committer date
Sun, 16 Mar 2025 01:36:02 +0800
Actions
Show branches
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileContributor: Runxi Yu <https://runxiyu.org>

package main

import (
	"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/storer"
	"github.com/go-git/go-git/v5/plumbing/object"
)

func handle_repo_index(w http.ResponseWriter, r *http.Request, params map[string]any) {
	var repo *git.Repository
	var repo_name string
	var group_path []string
	var ref_hash plumbing.Hash
	var err error
	var recent_commits []*object.Commit
	var commit_object *object.Commit
	var tree *object.Tree
	var notes []string
	var branches []string
	var branches_ storer.ReferenceIter

	repo, repo_name, group_path = params["repo"].(*git.Repository), params["repo_name"].(string), params["group_path"].([]string)

	if strings.Contains(repo_name, "\n") || slice_contains_newline(group_path) {
		notes = append(notes, "Path contains newlines; HTTP Git access impossible")
	}

	ref_hash, err = get_ref_hash_from_type_and_name(repo, params["ref_type"].(string), params["ref_name"].(string))
	if err != nil {
		goto no_ref
	}

	branches_, err = repo.Branches()
	if err != nil {}
	err = branches_.ForEach(func (branch *plumbing.Reference) error {
		branches = append(branches, branch.Name().Short())
		return nil
	})
	if err != nil {}
	params["branches"] = branches

	if recent_commits, err = get_recent_commits(repo, ref_hash, 3); err != nil {
		goto no_ref
	}
	params["commits"] = recent_commits

	if commit_object, err = repo.CommitObject(ref_hash); err != nil {
		goto no_ref
	}

	if tree, err = commit_object.Tree(); err != nil {
		goto no_ref
	}

	params["files"] = build_display_git_tree(tree)
	params["readme_filename"], params["readme"] = render_readme_at_tree(tree)

no_ref:

	params["http_clone_url"] = generate_http_remote_url(group_path, repo_name)
	params["ssh_clone_url"] = generate_ssh_remote_url(group_path, repo_name)
	params["notes"] = notes

	render_template(w, "repo_index", params)
}
{{/*
	SPDX-License-Identifier: AGPL-3.0-only
	SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
*/}}
{{- define "repo_index" -}}
<!DOCTYPE html>
<html lang="en">
	<head>
		{{- template "head_common" . -}}
		<title>{{ .repo_name }} &ndash; {{ template "group_path_plain" .group_path }} &ndash; {{ .global.forge_title -}}</title>
	</head>
	<body class="repo-index">
		{{- template "header" . -}}
		<div class="padding-wrapper">
			<table id="repo-info-table" class="rounded">
				<thead>
					<tr class="title-row">
						<th colspan="2">Repo info</th>
					</tr>
				</thead>
				<tbody>
					<tr>
						<th scope="row">Name</th>
						<td>{{- .repo_name -}}</td>
					</tr>
					{{- if .repo_description -}}
						<tr>
							<th scope="row">Description</th>
							<td>{{- .repo_description -}}</td>
						</tr>
					{{- end -}}
					<tr>
						<th scope="row">SSH remote</th>
						<td><code>{{- .ssh_clone_url -}}</code></td>
					</tr>
					{{- if .notes -}}
						<tr>
							<th scope="row">Notes</th>
							<td><ul>{{- range .notes -}}<li>{{- . -}}</li>{{- end -}}</ul></td>
						</tr>
					{{- end -}}
				</tbody>
			</table>
		</div>
		<div class="padding-wrapper">
			<table id="branches" class="rounded">
				<thead>
					<tr class="title-row">
						<th colspan="1">Branches</th>
					</tr>
				</thead>
				<tbody>
					{{ range .branches }}
					<tr>
						<td>
							<a href="./?branch={{ . }}">{{ . }}</a>
						</td>
					</tr>
					{{ end }}
				</tbody>
			</table>
		</div>
		<div class="padding-wrapper">
			<p>
				<a href="contrib/" class="btn-normal">Merge requests</a>
			</p>
		</div>
		{{- if .commits -}}
			<div class="padding-wrapper scroll">
				<table id="recent-commits" class="wide rounded">
					<thead>
						<tr class="title-row">
							<th colspan="3">Recent commits (<a href="log/{{- if .ref_type -}}?{{- .ref_type -}}={{- .ref_name -}}{{- end -}}">see all</a>)</th>
						</tr>
						<tr>
							<th scope="col">Title</th>
							<th scope="col">Author</th>
							<th scope="col">Author Date</th>
						</tr>
					</thead>
					<tbody>
						{{- range .commits -}}
							<tr>
								<td class="commit-title"><a href="commit/{{- .ID -}}">{{- .Message | first_line -}}</a></td>
								<td class="commit-author">
									<a class="email-name" href="mailto:{{- .Author.Email -}}">{{- .Author.Name -}}</a>
								</td>
								<td class="commit-time">
									{{- .Author.When.Format "2006-01-02 15:04:05 -0700" -}}
								</td>
							</tr>
						{{- end -}}
					</tbody>
				</table>
			</div>
		{{- end -}}
		{{- if .files -}}
			<div class="padding-wrapper scroll">
				<table id="file-tree" class="wide rounded">
					<thead>
						<tr class="title-row">
							<th colspan="3">/{{- if .ref_name -}} on {{- .ref_name -}}{{- end -}}</th>
						</tr>
						<tr>
							<th scope="col">Mode</th>
							<th scope="col">Filename</th>
							<th scope="col">Size</th>
						</tr>
					</thead>
					<tbody>
						{{- $ref_type := .ref_type -}}
						{{- $ref := .ref_name -}}
						{{- range .files -}}
							<tr>
								<td class="file-mode">{{- .Mode -}}</td>
								<td class="file-name"><a href="tree/{{- .Name -}}{{- if not .Is_file -}}/{{- end -}}{{- if $ref_type -}}?{{- $ref_type -}}={{- $ref -}}{{- end -}}">{{- .Name -}}</a>{{- if not .Is_file -}}/{{- end -}}</td>
								<td class="file-size">{{- .Size -}}</td>
							</tr>
						{{- end -}}
					</tbody>
				</table>
			</div>
		{{- end -}}
		{{- if .readme -}}
			<div class="padding-wrapper" id="readme">
				{{- .readme -}}
			</div>
		{{- end -}}
		<footer>
			{{- template "footer" . -}}
		</footer>
	</body>
</html>
{{- end -}}