diff --git a/appview/pages/templates/repo/index.html b/appview/pages/templates/repo/index.html
index ac47a90..b6da3e5 100644
--- a/appview/pages/templates/repo/index.html
+++ b/appview/pages/templates/repo/index.html
@@ -41,18 +41,22 @@
{{ range .Files }}
{{ if not .IsFile }}
{{ end }}
{{ end }}
@@ -60,18 +64,22 @@
{{ range .Files }}
{{ if .IsFile }}
{{ end }}
{{ end }}
diff --git a/appview/pages/templates/repo/tree.html b/appview/pages/templates/repo/tree.html
index 5441ab2..1a709a7 100644
--- a/appview/pages/templates/repo/tree.html
+++ b/appview/pages/templates/repo/tree.html
@@ -13,24 +13,32 @@
{{ range .Files }}
{{ if not .IsFile }}
-
-
-
{{ .Name }}/
+
-
+
{{ timeFmt .LastCommit.Author.When }}
{{ end }}
{{ end }}
{{ range .Files }}
{{ if .IsFile }}
-
diff --git a/appview/state/state.go b/appview/state/state.go
index 89141bc..79fedf7 100644
--- a/appview/state/state.go
+++ b/appview/state/state.go
@@ -519,9 +519,15 @@ func (s *State) AddRepo(w http.ResponseWriter, r *http.Request) {
s.pages.Notice(w, "repo", "Failed to create repository on knot server.")
return
}
- if resp.StatusCode != http.StatusNoContent {
- s.pages.Notice(w, "repo", fmt.Sprintf("Server returned unexpected status: %d", resp.StatusCode))
+
+ switch resp.StatusCode {
+ case http.StatusConflict:
+ s.pages.Notice(w, "repo", "A repository with that name already exists.")
return
+ case http.StatusInternalServerError:
+ s.pages.Notice(w, "repo", "Failed to create repository on knot. Try again later.")
+ case http.StatusNoContent:
+ // continue
}
// add to local db
diff --git a/input.css b/input.css
index cf59353..12529b5 100644
--- a/input.css
+++ b/input.css
@@ -21,7 +21,7 @@
@apply bg-opacity-30;
}
a {
- @apply underline text-black hover:text-gray-800 visited:text-gray-600;
+ @apply underline text-black hover:text-gray-800;
}
@layer base {
diff --git a/knotserver/git/git.go b/knotserver/git/git.go
index 0e870b0..53fad88 100644
--- a/knotserver/git/git.go
+++ b/knotserver/git/git.go
@@ -2,11 +2,14 @@ package git
import (
"archive/tar"
+ "bytes"
"fmt"
"io"
"io/fs"
+ "os/exec"
"path"
"sort"
+ "strings"
"sync"
"time"
@@ -35,8 +38,9 @@ var (
)
type GitRepo struct {
- r *git.Repository
- h plumbing.Hash
+ path string
+ r *git.Repository
+ h plumbing.Hash
}
type TagList struct {
@@ -102,7 +106,7 @@ func (self *TagList) Less(i, j int) bool {
func Open(path string, ref string) (*GitRepo, error) {
var err error
- g := GitRepo{}
+ g := GitRepo{path: path}
g.r, err = git.PlainOpen(path)
if err != nil {
return nil, fmt.Errorf("opening %s: %w", path, err)
@@ -295,33 +299,38 @@ func (g *GitRepo) WriteTar(w io.Writer, prefix string) error {
return nil
}
-func (g *GitRepo) LastCommitTime(filePath string) (*object.Commit, error) {
+func (g *GitRepo) LastCommitForPath(path string) (*object.Commit, error) {
cacheMu.RLock()
- if commit, exists := commitCache.Get(filePath); exists {
+ if commit, found := commitCache.Get(path); found {
cacheMu.RUnlock()
return commit.(*object.Commit), nil
}
cacheMu.RUnlock()
- commitIter, err := g.r.Log(&git.LogOptions{
- From: g.h,
- PathFilter: func(s string) bool {
- return s == filePath
- },
- Order: git.LogOrderCommitterTime,
- })
+ cmd := exec.Command("git", "-C", g.path, "log", "-1", "--format=%H", "--", path)
- if err != nil {
- return nil, fmt.Errorf("failed to get commit log for %s: %w", filePath, err)
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ cmd.Stderr = &out
+
+ if err := cmd.Run(); err != nil {
+ return nil, fmt.Errorf("failed to get commit hash: %w", err)
}
- commit, err := commitIter.Next()
+ commitHash := strings.TrimSpace(out.String())
+ if commitHash == "" {
+ return nil, fmt.Errorf("no commits found for path: %s", path)
+ }
+
+ hash := plumbing.NewHash(commitHash)
+
+ commit, err := g.r.CommitObject(hash)
if err != nil {
- return nil, fmt.Errorf("no commit found for %s", filePath)
+ return nil, err
}
cacheMu.Lock()
- commitCache.Set(filePath, commit, 1)
+ commitCache.Set(path, commit, 1)
cacheMu.Unlock()
return commit, nil
diff --git a/knotserver/git/tree.go b/knotserver/git/tree.go
index f47355b..3783adf 100644
--- a/knotserver/git/tree.go
+++ b/knotserver/git/tree.go
@@ -20,7 +20,7 @@ func (g *GitRepo) FileTree(path string) ([]types.NiceTree, error) {
}
if path == "" {
- files = g.makeNiceTree(tree)
+ files = g.makeNiceTree(tree, "")
} else {
o, err := tree.FindEntry(path)
if err != nil {
@@ -33,22 +33,29 @@ func (g *GitRepo) FileTree(path string) ([]types.NiceTree, error) {
return nil, err
}
- files = g.makeNiceTree(subtree)
+ files = g.makeNiceTree(subtree, path)
}
}
return files, nil
}
-func (g *GitRepo) makeNiceTree(t *object.Tree) []types.NiceTree {
+func (g *GitRepo) makeNiceTree(t *object.Tree, parent string) []types.NiceTree {
nts := []types.NiceTree{}
for _, e := range t.Entries {
mode, _ := e.Mode.ToOSFileMode()
sz, _ := t.Size(e.Name)
- lastCommit, err := g.LastCommitTime(e.Name)
+ var fpath string
+ if parent != "" {
+ fpath = fmt.Sprintf("%s/%s", parent, e.Name)
+ } else {
+ fpath = e.Name
+ }
+ lastCommit, err := g.LastCommitForPath(fpath)
if err != nil {
+ fmt.Println("error getting last commit time:", err)
continue
}
diff --git a/knotserver/routes.go b/knotserver/routes.go
index 94f9226..73507d0 100644
--- a/knotserver/routes.go
+++ b/knotserver/routes.go
@@ -17,6 +17,7 @@ import (
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/gliderlabs/ssh"
"github.com/go-chi/chi/v5"
+ gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/russross/blackfriday/v2"
@@ -504,8 +505,13 @@ func (h *Handle) NewRepo(w http.ResponseWriter, r *http.Request) {
err := git.InitBare(repoPath)
if err != nil {
l.Error("initializing bare repo", "error", err.Error())
- writeError(w, err.Error(), http.StatusInternalServerError)
- return
+ if errors.Is(err, gogit.ErrRepositoryAlreadyExists) {
+ writeError(w, "That repo already exists!", http.StatusConflict)
+ return
+ } else {
+ writeError(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
}
// add perms for this user to access the repo