Goit

Simple and lightweight Git web server
Mirror of https://github.com/Jamozed/Goit
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2023-08-07 07:22:06
Commit0dadb00e59a08480835e2e6b9de8510d42857b64
Parentb4ad3bf77335e5b65d31eac65fe46a3b6c80eeaf

Update the repository refs page

Diffstat

M main.go | 2 +-
M res/index.html | 2 +-
M res/repo/refs.html | 30 +++++++++++++++++++-----------
M src/repo.go | 66 ------------------------------------------------------------------
A src/repo/refs.go | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

5 files changed, 131 insertions, 79 deletions

diff --git a/main.go b/main.go
index 6767f94..90df6ef 100644
--- a/main.go
+++ b/main.go
@@ -44,7 +44,7 @@ func main() {
 	h.Path("/{repo}/tree").Methods("GET").HandlerFunc(repo.HandleTree)
 	h.Path("/{repo}/tree/{path:.*}").Methods("GET").HandlerFunc(repo.HandleTree)
 	h.Path("/{repo}/file/{path:.*}").Methods("GET").HandlerFunc(repo.HandleFile)
-	h.Path("/{repo}/refs").Methods("GET").HandlerFunc(goit.HandleRepoRefs)
+	h.Path("/{repo}/refs").Methods("GET").HandlerFunc(repo.HandleRefs)
 	h.Path("/{repo}/info/refs").Methods("GET").HandlerFunc(goit.HandleInfoRefs)
 	h.Path("/{repo}/git-upload-pack").Methods("POST").HandlerFunc(goit.HandleUploadPack)
 	h.Path("/{repo}/git-receive-pack").Methods("POST").HandlerFunc(goit.HandleReceivePack)
diff --git a/res/index.html b/res/index.html
index b8ea778..df35113 100644
--- a/res/index.html
+++ b/res/index.html
@@ -29,7 +29,7 @@
 		</table>
 	</header><hr>
 	<main>
-		<table>
+		<table class="highlight-row">
 			<thead>
 				<tr>
 					<td><b>Name</b></td>
diff --git a/res/repo/refs.html b/res/repo/refs.html
index 9869b06..ac0d253 100644
--- a/res/repo/refs.html
+++ b/res/repo/refs.html
@@ -3,43 +3,51 @@
 <body>
 	<header>{{template "repo/header" .}}</header><hr>
 	<main>
-	{{if .Branches}}
 		<h2>Branches</h2>
 		<table class="highlight-row">
 			<thead>
 				<tr>
 					<td><b>Name</b></td>
-					<td><b>Hash</b></td>
+					<td><b>Message</b></td>
+					<td><b>Author</b></td>
+					<td><b>Last Commit</b></td>
 				</tr>
 			</thead>
 			<tbody>
 			{{range .Branches}}
 				<tr>
-					<td>{{.Name}}</a></td>
-					<td>{{.Hash}}</td>
+					<td>{{.Name}}</td>
+					<td><a href="/{{$.Name}}/commit/{{.Hash}}">{{.Message}}</a></td>
+					<td>{{.Author}}</td>
+					<td>{{.LastCommit}}</td>
 				</tr>
+			{{else}}
+				<tr><td colspan="4">No branches</td></tr>
 			{{end}}
 			</tbody>
 		</table>
-	{{end}}
-	{{if .Tags}}
-		<h2>Tags</h2>
+		<br><h2>Tags</h2>
 		<table class="highlight-row">
 			<thead>
 				<tr>
 					<td><b>Name</b></td>
-					<td><b>Hash</b></td>
+					<td><b>Message</b></td>
+					<td><b>Author</b></td>
+					<td><b>Last Commit</b></td>
 				</tr>
 			</thead>
 			<tbody>
 			{{range .Tags}}
 				<tr>
-					<td>{{.Name}}</a></td>
-					<td>{{.Hash}}</td>
+					<td>{{.Name}}</td>
+					<td><a href="/{{$.Name}}/commit/{{.Hash}}">{{.Message}}</a></td>
+					<td>{{.Author}}</td>
+					<td>{{.LastCommit}}</td>
 				</tr>
+			{{else}}
+				<tr><td colspan="4">No tags</td></tr>
 			{{end}}
 			</tbody>
 		</table>
-	{{end}}
 	</main>
 </body>
diff --git a/src/repo.go b/src/repo.go
index 0200eb1..afe986a 100644
--- a/src/repo.go
+++ b/src/repo.go
@@ -7,15 +7,10 @@ package goit
 import (
 	"database/sql"
 	"errors"
-	"log"
-	"net/http"
 	"os"
 	"strings"
 
-	"github.com/Jamozed/Goit/src/util"
 	"github.com/go-git/go-git/v5"
-	"github.com/go-git/go-git/v5/plumbing"
-	"github.com/gorilla/mux"
 )
 
 type Repo struct {
@@ -27,64 +22,6 @@ type Repo struct {
 	IsPrivate     bool
 }
 
-func HandleRepoRefs(w http.ResponseWriter, r *http.Request) {
-	reponame := mux.Vars(r)["repo"]
-
-	repo, err := GetRepoByName(reponame)
-	if err != nil {
-		HttpError(w, http.StatusInternalServerError)
-		return
-	} else if repo == nil {
-		HttpError(w, http.StatusNotFound)
-		return
-	}
-
-	type bra struct{ Name, Hash string }
-	type tag struct{ Name, Hash string }
-	bras := []bra{}
-	tags := []tag{}
-
-	if gr, err := git.PlainOpen(RepoPath(reponame)); err != nil {
-		log.Println("[Repo:Refs]", err.Error())
-		HttpError(w, http.StatusInternalServerError)
-		return
-	} else if iter, err := gr.Branches(); err != nil {
-		log.Println("[Repo:Refs]", err.Error())
-		HttpError(w, http.StatusInternalServerError)
-		return
-	} else if err := iter.ForEach(func(b *plumbing.Reference) error {
-		bras = append(bras, bra{b.Name().Short(), b.Hash().String()})
-		return nil
-	}); err != nil {
-		log.Println("[Repo:Refs]", err.Error())
-		HttpError(w, http.StatusInternalServerError)
-		return
-	} else if iter, err := gr.Tags(); err != nil {
-		log.Println("[Repo:Refs]", err.Error())
-		HttpError(w, http.StatusInternalServerError)
-		return
-	} else if err := iter.ForEach(func(b *plumbing.Reference) error {
-		tags = append(tags, tag{b.Name().Short(), b.Hash().String()})
-		return nil
-	}); err != nil {
-		log.Println("[Repo:Refs]", err.Error())
-		HttpError(w, http.StatusInternalServerError)
-		return
-	}
-
-	if err := Tmpl.ExecuteTemplate(w, "repo/refs", struct {
-		Title, Name, Description, Url string
-		Readme, Licence               string
-		Branches                      []bra
-		Tags                          []tag
-	}{
-		"Refs", reponame, repo.Description, util.If(Conf.UsesHttps, "https://", "http://") + r.Host + "/" + repo.Name,
-		"", "", bras, tags,
-	}); err != nil {
-		log.Println("[Repo:Refs]", err.Error())
-	}
-}
-
 func GetRepo(id int64) (*Repo, error) {
 	r := &Repo{}
 
diff --git a/src/repo/refs.go b/src/repo/refs.go
new file mode 100644
index 0000000..6bff474
--- /dev/null
+++ b/src/repo/refs.go
@@ -0,0 +1,110 @@
+package repo
+
+import (
+	"errors"
+	"log"
+	"net/http"
+	"path"
+	"strings"
+	"time"
+
+	goit "github.com/Jamozed/Goit/src"
+	"github.com/Jamozed/Goit/src/util"
+	"github.com/go-git/go-git/v5"
+	"github.com/go-git/go-git/v5/plumbing"
+	"github.com/gorilla/mux"
+)
+
+func HandleRefs(w http.ResponseWriter, r *http.Request) {
+	auth, uid := goit.AuthCookie(w, r, true)
+
+	repo, err := goit.GetRepoByName(mux.Vars(r)["repo"])
+	if err != nil {
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	} else if repo == nil || (repo.IsPrivate && (!auth || repo.OwnerId != uid)) {
+		goit.HttpError(w, http.StatusNotFound)
+		return
+	}
+
+	type row struct{ Name, Message, Author, LastCommit, Hash string }
+	data := struct {
+		Title, Name, Description, Url string
+		Readme, Licence               string
+		Branches, Tags                []row
+	}{
+		Title: repo.Name + " - References", Name: repo.Name, Description: repo.Description,
+		Url: util.If(goit.Conf.UsesHttps, "https://", "http://") + r.Host + "/" + repo.Name,
+	}
+
+	gr, err := git.PlainOpen(goit.RepoPath(repo.Name))
+	if err != nil {
+		log.Println("[/repo/refs]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	}
+
+	ref, err := gr.Head()
+	if err != nil {
+		if !errors.Is(err, plumbing.ErrReferenceNotFound) {
+			log.Println("[/repo/log]", err.Error())
+			goit.HttpError(w, http.StatusInternalServerError)
+			return
+		}
+	} else {
+		if readme, _ := findReadme(gr, ref); readme != "" {
+			data.Readme = path.Join("/", repo.Name, "file", readme)
+		}
+		if licence, _ := findLicence(gr, ref); licence != "" {
+			data.Licence = path.Join("/", repo.Name, "file", licence)
+		}
+	}
+
+	if iter, err := gr.Branches(); err != nil {
+		log.Println("[/repo/refs]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	} else if err := iter.ForEach(func(r *plumbing.Reference) error {
+		commit, err := gr.CommitObject(r.Hash())
+		if err != nil {
+			return err
+		}
+
+		data.Branches = append(data.Branches, row{
+			Name: r.Name().Short(), Message: strings.SplitN(commit.Message, "\n", 2)[0], Author: commit.Author.Name,
+			LastCommit: commit.Author.When.UTC().Format(time.DateTime), Hash: r.Hash().String(),
+		})
+
+		return nil
+	}); err != nil {
+		log.Println("[/repo/refs]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	}
+
+	if iter, err := gr.Tags(); err != nil {
+		log.Println("[Repo:Refs]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	} else if err := iter.ForEach(func(r *plumbing.Reference) error {
+		commit, err := gr.CommitObject(r.Hash())
+		if err != nil {
+			return err
+		}
+
+		data.Tags = append(data.Tags, row{
+			Name: r.Name().Short(), Message: strings.SplitN(commit.Message, "\n", 2)[0], Author: commit.Author.Name,
+			LastCommit: commit.Author.When.UTC().Format(time.DateTime), Hash: r.Hash().String(),
+		})
+
+		return nil
+	}); err != nil {
+		log.Println("[Repo:Refs]", err.Error())
+		goit.HttpError(w, http.StatusInternalServerError)
+		return
+	}
+
+	if err := goit.Tmpl.ExecuteTemplate(w, "repo/refs", data); err != nil {
+		log.Println("[/repo/refs]", err.Error())
+	}
+}