aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-02-19 01:02:33 +0800
committerRunxi Yu <me@runxiyu.org>2025-02-19 01:02:33 +0800
commit2d3e888321baeae889c7c51f2312aafba1ec70d0 (patch)
tree030c79f59ac2f62cce1567fd3fc07607b224d2fd
parenthttp: Consistently use redirect_with{out,}_slash, never r.URL.Path (diff)
downloadforge-2d3e888321baeae889c7c51f2312aafba1ec70d0.tar.gz
forge-2d3e888321baeae889c7c51f2312aafba1ec70d0.tar.zst
forge-2d3e888321baeae889c7c51f2312aafba1ec70d0.zip
contrib: Add contrib/MR index page
-rw-r--r--git_misc.go6
-rw-r--r--http_handle_repo_contrib_index.go42
-rw-r--r--http_server.go7
-rw-r--r--schema.sql8
-rw-r--r--templates/repo_contrib_index.tmpl33
5 files changed, 89 insertions, 7 deletions
diff --git a/git_misc.go b/git_misc.go
index be75e40..db5ff89 100644
--- a/git_misc.go
+++ b/git_misc.go
@@ -19,11 +19,11 @@ var (
)
// open_git_repo opens a git repository by group and repo name.
-func open_git_repo(ctx context.Context, group_name, repo_name string) (repo *git.Repository, description string, err error) {
+func open_git_repo(ctx context.Context, group_name, repo_name string) (repo *git.Repository, description string, repo_id int, err error) {
var fs_path string
- err = database.QueryRow(ctx, "SELECT r.filesystem_path, COALESCE(r.description, '') 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(&fs_path, &description)
+ err = database.QueryRow(ctx, "SELECT r.filesystem_path, COALESCE(r.description, ''), r.id 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(&fs_path, &description, &repo_id)
if err != nil {
- return nil, "", err
+ return
}
repo, err = git.PlainOpen(fs_path)
return
diff --git a/http_handle_repo_contrib_index.go b/http_handle_repo_contrib_index.go
new file mode 100644
index 0000000..632e8f2
--- /dev/null
+++ b/http_handle_repo_contrib_index.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "net/http"
+
+ "github.com/go-git/go-git/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) {
+ _ = params["repo"].(*git.Repository)
+
+ rows, err := database.Query(r.Context(), "SELECT id, title, status FROM merge_requests WHERE repo_id = $1", params["repo_id"])
+ if 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 {
+ 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 {
+ http.Error(w, "Error ranging over merge requests: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ params["merge_requests"] = result
+
+ render_template(w, "repo_contrib_index", params)
+}
diff --git a/http_server.go b/http_server.go
index e5cb6ce..c17bc6f 100644
--- a/http_server.go
+++ b/http_server.go
@@ -146,7 +146,7 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// TODO: subgroups
- params["repo"], params["repo_description"], err = open_git_repo(r.Context(), group_name, module_name)
+ params["repo"], params["repo_description"], params["repo_id"], err = open_git_repo(r.Context(), group_name, module_name)
if err != nil {
http.Error(w, "Error opening repo: "+err.Error(), http.StatusInternalServerError)
return
@@ -189,6 +189,11 @@ func (router *http_router_t) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
params["commit_id"] = segments[separator_index+4]
handle_repo_commit(w, r, params)
+ case "contrib":
+ if redirect_with_slash(w, r) {
+ return
+ }
+ handle_repo_contrib_index(w, r, params)
default:
http.Error(w, fmt.Sprintf("Unknown repo feature: %s", repo_feature), http.StatusNotFound)
}
diff --git a/schema.sql b/schema.sql
index 1797466..ee32bd6 100644
--- a/schema.sql
+++ b/schema.sql
@@ -64,15 +64,17 @@ CREATE TABLE sessions (
UNIQUE(user_id, session_id)
);
+// TODO:
CREATE TABLE merge_requests (
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ title TEXT NOT NULL,
repo_id INTEGER NOT NULL REFERENCES repos(id) ON DELETE CASCADE,
- creator INTEGER REFERENCES users(id) ON DELETE SET NULL,
+ creator INTEGER NOT NULL REFERENCES users(id) ON DELETE SET NULL,
source_ref TEXT NOT NULL,
destination_branch TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('open', 'merged', 'closed')),
- created_at TIMESTAMP NOT NULL,
- mailing_list_id INT UNIQUE REFERENCES mailing_lists(id) ON DELETE CASCADE
+ UNIQUE (repo_id, source_ref, destination_branch),
+ UNIQUE (repo_id, id)
);
CREATE TABLE user_group_roles (
diff --git a/templates/repo_contrib_index.tmpl b/templates/repo_contrib_index.tmpl
new file mode 100644
index 0000000..6da917b
--- /dev/null
+++ b/templates/repo_contrib_index.tmpl
@@ -0,0 +1,33 @@
+{{- define "repo_contrib_index" -}}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ {{ template "head_common" . }}
+ <title>Merge requests &ndash; {{ .repo_name }} &ndash; {{ .group_name }} &ndash; {{ .global.forge_title }}</title>
+ </head>
+ <body class="repo-contrib-index">
+ {{ template "header" . }}
+ <div class="padding-wrapper">
+ <table id="recent-merge_requests" class="wide">
+ <thead>
+ <tr class="title-row">
+ <th colspan="3">Merge requests</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{- range .merge_requests }}
+ <tr>
+ <td class="merge_request-id">{{ .ID }}</td>
+ <td class="merge_request-title"><a href="{{ .ID }}/">{{ .Title }}</a></td>
+ <td class="merge_request-status">{{ .Status }}</td>
+ </tr>
+ {{- end }}
+ </tbody>
+ </table>
+ </div>
+ <footer>
+ {{ template "footer" . }}
+ </footer>
+ </body>
+</html>
+{{- end -}}