Goit

Simple and lightweight Git web server
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2023-12-18 10:58:22
Commitf9225e63fa53bce959354967a75f043941f54395
Parentb43fa87f6b1f433cc0a2f518ef478cde2c7f8520

Allow admin edit upstream and mirror repo settings

Also allow case change of repository name.

Diffstat

M res/admin/repo_edit.html | 11 +++++++++++
M src/admin/repos.go | 45 ++++++++++++++++++++++++++++++++++++++-------
M src/repo/edit.go | 7 ++++---

3 files changed, 53 insertions, 10 deletions

diff --git a/res/admin/repo_edit.html b/res/admin/repo_edit.html
index 14243d0..dcad042 100644
--- a/res/admin/repo_edit.html
+++ b/res/admin/repo_edit.html
@@ -33,6 +33,17 @@
 						</select>
 					</td>
 				</tr>
+				<tr>
+					<td style="text-align: right;"><label for="upstream">Upstream</label></td>
+					<td><input type="text" name="upstream" value="{{.Edit.Upstream}}" spellcheck="false"></td>
+				</tr>
+				<tr>
+					<td style="text-align: right;"><label for="mirror">Mirror</label></td>
+					<td>
+						<input type="checkbox" name="mirror" value="mirror" {{if .Edit.IsMirror}}checked{{end}}>
+						<span id="mirror-warn">Enabling mirror will replace any existing repository data</span>
+					</td>
+				</tr>
 				<tr>
 					<td></td>
 					<td>
diff --git a/src/admin/repos.go b/src/admin/repos.go
index c102f0a..7833bde 100644
--- a/src/admin/repos.go
+++ b/src/admin/repos.go
@@ -10,7 +10,9 @@ import (
 	"net/http"
 	"slices"
 	"strconv"
+	"strings"
 
+	"github.com/Jamozed/Goit/src/cron"
 	"github.com/Jamozed/Goit/src/goit"
 	"github.com/Jamozed/Goit/src/util"
 	"github.com/dustin/go-humanize"
@@ -68,7 +70,7 @@ func HandleRepos(w http.ResponseWriter, r *http.Request) {
 func HandleRepoEdit(w http.ResponseWriter, r *http.Request) {
 	auth, user, err := goit.Auth(w, r, true)
 	if err != nil {
-		log.Println("[admin/users]", err.Error())
+		log.Println("[/admin/repo/edit]", err.Error())
 		goit.HttpError(w, http.StatusInternalServerError)
 		return
 	}
@@ -78,7 +80,7 @@ func HandleRepoEdit(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	id, err := strconv.ParseInt(r.URL.Query().Get("repo"), 10, 64)
+	id, err := strconv.ParseInt(r.FormValue("repo"), 10, 64)
 	if err != nil {
 		goit.HttpError(w, http.StatusNotFound)
 		return
@@ -101,7 +103,6 @@ func HandleRepoEdit(w http.ResponseWriter, r *http.Request) {
 		return
 	} else if owner == nil {
 		log.Println("[/admin/repo/edit]", repo.Id, "is owned by a nonexistent user")
-		/* TODO have admin adopt the orphaned repository */
 		owner = &goit.User{}
 	}
 
@@ -109,8 +110,9 @@ func HandleRepoEdit(w http.ResponseWriter, r *http.Request) {
 		Title, Name string
 
 		Edit struct {
-			Id, Owner, Name, Description, Message string
-			IsPrivate                             bool
+			Id, Owner, Name, Description, Upstream string
+			IsPrivate, IsMirror                    bool
+			Message                                string
 		}
 
 		Transfer struct{ Owner, Message string }
@@ -128,14 +130,18 @@ func HandleRepoEdit(w http.ResponseWriter, r *http.Request) {
 	data.Edit.Owner = owner.FullName + " (" + owner.Name + ")[" + fmt.Sprint(owner.Id) + "]"
 	data.Edit.Name = repo.Name
 	data.Edit.Description = repo.Description
+	data.Edit.Upstream = repo.Upstream
 	data.Edit.IsPrivate = repo.IsPrivate
+	data.Edit.IsMirror = repo.IsMirror
 
 	if r.Method == http.MethodPost {
 		switch r.FormValue("action") {
 		case "edit":
 			data.Edit.Name = r.FormValue("reponame")
 			data.Edit.Description = r.FormValue("description")
+			data.Edit.Upstream = r.FormValue("upstream")
 			data.Edit.IsPrivate = r.FormValue("visibility") == "private"
+			data.Edit.IsMirror = r.FormValue("mirror") == "mirror"
 
 			if data.Edit.Name == "" {
 				data.Edit.Message = "Name cannot be empty"
@@ -145,17 +151,42 @@ func HandleRepoEdit(w http.ResponseWriter, r *http.Request) {
 				log.Println("[/admin/repo/edit]", err.Error())
 				goit.HttpError(w, http.StatusInternalServerError)
 				return
-			} else if exists && data.Edit.Name != repo.Name {
+			} else if exists && !strings.EqualFold(data.Edit.Name, repo.Name) {
 				data.Edit.Message = "Name \"" + data.Edit.Name + "\" is taken"
 			} else if len(data.Edit.Description) > 256 {
 				data.Edit.Message = "Description cannot exceed 256 characters"
 			} else if err := goit.UpdateRepo(repo.Id, goit.Repo{
-				Name: data.Edit.Name, Description: data.Edit.Description, IsPrivate: data.Edit.IsPrivate,
+				Name: data.Edit.Name, Description: data.Edit.Description, Upstream: data.Edit.Upstream,
+				IsPrivate: data.Edit.IsPrivate, IsMirror: data.Edit.IsMirror,
 			}); err != nil {
 				log.Println("[/admin/repo/edit]", err.Error())
 				goit.HttpError(w, http.StatusInternalServerError)
 				return
 			} else {
+				if (data.Edit.Upstream == "" && repo.Upstream != "") || !data.Edit.IsMirror {
+					goit.Cron.RemoveFor(repo.Id)
+					goit.Cron.Update()
+				} else if data.Edit.Upstream != "" && data.Edit.IsMirror &&
+					(data.Edit.Upstream != repo.Upstream || !repo.IsMirror) {
+					goit.Cron.RemoveFor(repo.Id)
+
+					goit.Cron.Add(repo.Id, cron.Immediate, func() {
+						if err := goit.Pull(repo.Id); err != nil {
+							log.Println("[cron:import]", err.Error())
+						}
+						log.Println("[cron:import] imported", data.Name)
+					})
+
+					goit.Cron.Add(repo.Id, cron.Daily, func() {
+						if err := goit.Pull(repo.Id); err != nil {
+							log.Println("[cron:mirror]", err.Error())
+						}
+						log.Println("[cron:mirror] updated", data.Edit.Name)
+					})
+
+					goit.Cron.Update()
+				}
+
 				data.Edit.Message = "Repository \"" + repo.Name + "\" updated successfully"
 			}
 
diff --git a/src/repo/edit.go b/src/repo/edit.go
index 05598b9..f8d766c 100644
--- a/src/repo/edit.go
+++ b/src/repo/edit.go
@@ -11,6 +11,7 @@ import (
 	"net/http"
 	"path/filepath"
 	"slices"
+	"strings"
 
 	"github.com/Jamozed/Goit/src/cron"
 	"github.com/Jamozed/Goit/src/goit"
@@ -24,12 +25,12 @@ import (
 func HandleEdit(w http.ResponseWriter, r *http.Request) {
 	auth, user, err := goit.Auth(w, r, true)
 	if err != nil {
-		log.Println("[admin/users]", err.Error())
+		log.Println("[/repo/edit]", err.Error())
 		goit.HttpError(w, http.StatusInternalServerError)
 		return
 	}
 
-	if !auth || !user.IsAdmin {
+	if !auth {
 		goit.HttpError(w, http.StatusNotFound)
 		return
 	}
@@ -128,7 +129,7 @@ func HandleEdit(w http.ResponseWriter, r *http.Request) {
 				log.Println("[/repo/edit]", err.Error())
 				goit.HttpError(w, http.StatusInternalServerError)
 				return
-			} else if exists && data.Edit.Name != repo.Name {
+			} else if exists && !strings.EqualFold(data.Edit.Name, repo.Name) {
 				data.Edit.Message = "Name \"" + data.Edit.Name + "\" is taken"
 			} else if len(data.Edit.Description) > 256 {
 				data.Edit.Message = "Description cannot exceed 256 characters"