Goit

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

AuthorJakob Wakeling <[email protected]>
Date2023-11-28 11:14:36
Commit86e8cb8468a5da794f253effe57277f54e9bd1a0
Parentc90ff29da58650f1fef34d655a67fa91355867d6

Implement linked tree and file breadcrumbs

Diffstat

M res/repo/file.html | 2 +-
M res/repo/tree.html | 5 ++++-
M src/repo/file.go | 24 +++++++++++++++++++-----
M src/repo/tree.go | 45 ++++++++++++++++++++++++++++++++++-----------

4 files changed, 58 insertions, 18 deletions

diff --git a/res/repo/file.html b/res/repo/file.html
index 14290c3..ea7a677 100644
--- a/res/repo/file.html
+++ b/res/repo/file.html
@@ -3,7 +3,7 @@
 <body>
 	<header>
 		{{template "repo/header" .}}<hr>
-		{{.File}} ({{.Size}}) {{.Mode}} <a href="/{{.Name}}/download/{{.File}}">download</a>
+		{{.HtmlPath}} ({{.Size}}) {{.Mode}} <a href="/{{.Name}}/download/{{.Path}}">download</a>
 	</header><hr>
 	<main>
 		<table>
diff --git a/res/repo/tree.html b/res/repo/tree.html
index 5880f9c..09ec06d 100644
--- a/res/repo/tree.html
+++ b/res/repo/tree.html
@@ -1,7 +1,10 @@
 <!DOCTYPE html>
 <head lang="en-GB">{{template "base/head" .}}</head>
 <body>
-	<header>{{template "repo/header" .}}</header><hr>
+	<header>
+		{{template "repo/header" .}}<hr>
+		{{.HtmlPath}} ({{.Size}}) <a href="/{{.Name}}/download/{{.Path}}">download</a>
+	</header><hr>
 	<main>
 		<table class="highlight-row">
 			<thead>
diff --git a/src/repo/file.go b/src/repo/file.go
index edc42db..d0f451c 100644
--- a/src/repo/file.go
+++ b/src/repo/file.go
@@ -2,10 +2,11 @@ package repo
 
 import (
 	"errors"
+	"html/template"
 	"io"
 	"log"
 	"net/http"
-	"path/filepath"
+	"path"
 	"strings"
 
 	"github.com/Jamozed/Goit/src/goit"
@@ -42,10 +43,11 @@ func HandleFile(w http.ResponseWriter, r *http.Request) {
 	data := struct {
 		Title, Name, Description, Url string
 		Readme, Licence               string
-		Mode, File, Size              string
+		Path, Size, Mode              string
 		Lines                         []string
 		Body                          string
 		Editable                      bool
+		HtmlPath                      template.HTML
 	}{
 		Title: repo.Name + " - File", Name: repo.Name, Description: repo.Description,
 		Url:      util.If(goit.Conf.UsesHttps, "https://", "http://") + r.Host + "/" + repo.Name,
@@ -70,10 +72,10 @@ func HandleFile(w http.ResponseWriter, r *http.Request) {
 	}
 
 	if readme, _ := findReadme(gr, ref); readme != "" {
-		data.Readme = filepath.Join("/", repo.Name, "file", readme)
+		data.Readme = path.Join("/", repo.Name, "file", readme)
 	}
 	if licence, _ := findLicence(gr, ref); licence != "" {
-		data.Licence = filepath.Join("/", repo.Name, "file", licence)
+		data.Licence = path.Join("/", repo.Name, "file", licence)
 	}
 
 	commit, err := gr.CommitObject(ref.Hash())
@@ -94,9 +96,21 @@ func HandleFile(w http.ResponseWriter, r *http.Request) {
 	}
 
 	data.Mode = util.ModeString(uint32(file.Mode))
-	data.File = file.Name
+	data.Path = file.Name
 	data.Size = humanize.IBytes(uint64(file.Size))
 
+	parts := strings.Split(file.Name, "/")
+	htmlPath := "<b style=\"padding-left: 0.4rem;\"><a href=\"/" + repo.Name + "/tree\">" + repo.Name + "</a></b>/"
+	dirPath := ""
+
+	for i := 0; i < len(parts)-1; i += 1 {
+		dirPath = path.Join(dirPath, parts[i])
+		htmlPath += "<a href=\"/" + repo.Name + "/tree/" + dirPath + "\">" + parts[i] + "</a>/"
+	}
+	htmlPath += parts[len(parts)-1]
+
+	data.HtmlPath = template.HTML(htmlPath)
+
 	if rc, err := file.Blob.Reader(); err != nil {
 		log.Println("[/repo/file]", err.Error())
 		goit.HttpError(w, http.StatusInternalServerError)
diff --git a/src/repo/tree.go b/src/repo/tree.go
index e4f3bc6..18bcdff 100644
--- a/src/repo/tree.go
+++ b/src/repo/tree.go
@@ -2,9 +2,10 @@ package repo
 
 import (
 	"errors"
+	"html/template"
 	"log"
 	"net/http"
-	"path/filepath"
+	"path"
 	"sort"
 	"strings"
 
@@ -24,7 +25,7 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 		goit.HttpError(w, http.StatusInternalServerError)
 	}
 
-	path := mux.Vars(r)["path"]
+	treepath := mux.Vars(r)["path"]
 
 	repo, err := goit.GetRepoByName(mux.Vars(r)["repo"])
 	if err != nil {
@@ -42,14 +43,28 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 	data := struct {
 		Title, Name, Description, Url string
 		Readme, Licence               string
+		Path, Size                    string
 		Files                         []row
 		Editable                      bool
+		HtmlPath                      template.HTML
 	}{
 		Title: repo.Name + " - Tree", Name: repo.Name, Description: repo.Description,
 		Url:      util.If(goit.Conf.UsesHttps, "https://", "http://") + r.Host + "/" + repo.Name,
 		Editable: (auth && repo.OwnerId == user.Id),
 	}
 
+	parts := strings.Split(treepath, "/")
+	htmlPath := "<b style=\"padding-left: 0.4rem;\"><a href=\"/" + repo.Name + "/tree\">" + repo.Name + "</a></b>/"
+	dirPath := ""
+
+	for i := 0; i < len(parts)-1; i += 1 {
+		dirPath = path.Join(dirPath, parts[i])
+		htmlPath += "<a href=\"/" + repo.Name + "/tree/" + dirPath + "\">" + parts[i] + "</a>/"
+	}
+	htmlPath += parts[len(parts)-1]
+
+	data.HtmlPath = template.HTML(htmlPath)
+
 	gr, err := git.PlainOpen(goit.RepoPath(repo.Name, true))
 	if err != nil {
 		log.Println("[/repo/tree]", err.Error())
@@ -65,10 +80,10 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 		}
 	} else {
 		if readme, _ := findReadme(gr, ref); readme != "" {
-			data.Readme = filepath.Join("/", repo.Name, "file", readme)
+			data.Readme = path.Join("/", repo.Name, "file", readme)
 		}
 		if licence, _ := findLicence(gr, ref); licence != "" {
-			data.Licence = filepath.Join("/", repo.Name, "file", licence)
+			data.Licence = path.Join("/", repo.Name, "file", licence)
 		}
 
 		commit, err := gr.CommitObject(ref.Hash())
@@ -85,12 +100,12 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
-		if path != "" {
+		if treepath != "" {
 			data.Files = append(data.Files, row{
-				Mode: "d---------", Name: "..", Path: filepath.Join("tree", filepath.Dir(path)),
+				Mode: "d---------", Name: "..", Path: path.Join("tree", path.Dir(treepath)),
 			})
 
-			tree, err = tree.Tree(path)
+			tree, err = tree.Tree(treepath)
 			if errors.Is(err, object.ErrDirectoryNotFound) {
 				goit.HttpError(w, http.StatusNotFound)
 				return
@@ -109,6 +124,8 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 			return tree.Entries[i].Name < tree.Entries[j].Name
 		})
 
+		var totalSize uint64
+
 		for _, v := range tree.Entries {
 			var fpath, rpath, size string
 			var isFile bool
@@ -121,11 +138,13 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 					return
 				}
 
-				fpath = filepath.Join("file", path, v.Name)
-				rpath = filepath.Join(path, v.Name)
+				fpath = path.Join("file", treepath, v.Name)
+				rpath = path.Join(treepath, v.Name)
 				size = humanize.IBytes(uint64(file.Size))
 
 				isFile = true
+
+				totalSize += uint64(file.Size)
 			} else {
 				var dirSize uint64
 
@@ -145,9 +164,11 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 					return
 				}
 
-				fpath = filepath.Join("tree", path, v.Name)
-				rpath = filepath.Join(path, v.Name)
+				fpath = path.Join("tree", treepath, v.Name)
+				rpath = path.Join(treepath, v.Name)
 				size = humanize.IBytes(dirSize)
+
+				totalSize += dirSize
 			}
 
 			data.Files = append(data.Files, row{
@@ -155,6 +176,8 @@ func HandleTree(w http.ResponseWriter, r *http.Request) {
 				IsFile: isFile, B: util.If(strings.HasSuffix(size, " B"), true, false),
 			})
 		}
+
+		data.Size = humanize.IBytes(totalSize)
 	}
 
 	if err := goit.Tmpl.ExecuteTemplate(w, "repo/tree", data); err != nil {