- {{ range .Tags }}
-
-
{{ .Ref.Name }}
-
browse
-
log
-
tar.gz
- {{ if .Message }}
-
{{ .Message }}
+
+
+ {{ range .Tags }}
+
+
+
+
+
+
+
+ {{ if .Tag }}
+ {{ $messageParts := splitN .Tag.Message "\n\n" 2 }}
+
{{ index $messageParts 0 }}
+ {{ if gt (len $messageParts) 1 }}
+
{{ nl2br (index $messageParts 1) }}
{{ end }}
-
- {{ end }}
+ {{ else }}
+
no message
+ {{ end }}
+
+
+
+ {{ end }}
+
{{ end }}
diff --git a/appview/state/repo.go b/appview/state/repo.go
index 47658385..1bf88c6e 100644
--- a/appview/state/repo.go
+++ b/appview/state/repo.go
@@ -82,23 +82,44 @@ func (s *State) RepoIndex(w http.ResponseWriter, r *http.Request) {
tagMap[hash] = append(tagMap[hash], branch.Name)
}
- c, t := balanceTagsAndCommits(len(result.Commits), len(result.Tags), 10)
- commits := result.Commits[:c]
- tags := result.Tags[:t]
- emails := uniqueEmails(commits)
+ slices.SortFunc(result.Branches, func(a, b types.Branch) int {
+ if a.Name == result.Ref {
+ return -1
+ }
+ if a.IsDefault {
+ return -1
+ }
+ if a.Commit != nil {
+ if a.Commit.Author.When.Before(b.Commit.Author.When) {
+ return 1
+ } else {
+ return -1
+ }
+ }
+ return strings.Compare(a.Name, b.Name) * -1
+ })
- for _, tag := range tags {
- fmt.Printf("%#v\n\n", tag)
- }
+ commitCount := len(result.Commits)
+ branchCount := len(result.Branches)
+ tagCount := len(result.Tags)
+ fileCount := len(result.Files)
+
+ commitCount, branchCount, tagCount = balanceIndexItems(commitCount, branchCount, tagCount, fileCount)
+ commitsTrunc := result.Commits[:min(commitCount, len(result.Commits))]
+ tagsTrunc := result.Tags[:min(tagCount, len(result.Tags))]
+ branchesTrunc := result.Branches[:min(branchCount, len(result.Branches))]
+
+ emails := uniqueEmails(commitsTrunc)
user := s.auth.GetUser(r)
s.pages.RepoIndexPage(w, pages.RepoIndexParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(s, user),
TagMap: tagMap,
- Tags: tags,
RepoIndexResponse: result,
- CommitsTrunc: commits,
+ CommitsTrunc: commitsTrunc,
+ TagsTrunc: tagsTrunc,
+ BranchesTrunc: branchesTrunc,
EmailToDidOrHandle: EmailToDidOrHandle(s, emails),
})
return
@@ -121,12 +142,13 @@ func (s *State) RepoLog(w http.ResponseWriter, r *http.Request) {
ref := chi.URLParam(r, "ref")
- protocol := "http"
- if !s.config.Dev {
- protocol = "https"
+ us, err := NewUnsignedClient(f.Knot, s.config.Dev)
+ if err != nil {
+ log.Println("failed to create unsigned client", err)
+ return
}
- resp, err := http.Get(fmt.Sprintf("%s://%s/%s/%s/log/%s?page=%d&per_page=60", protocol, f.Knot, f.OwnerDid(), f.RepoName, ref, page))
+ resp, err := us.Log(f.OwnerDid(), f.RepoName, ref, page)
if err != nil {
log.Println("failed to reach knotserver", err)
return
@@ -358,12 +380,13 @@ func (s *State) RepoTags(w http.ResponseWriter, r *http.Request) {
return
}
- protocol := "http"
- if !s.config.Dev {
- protocol = "https"
+ us, err := NewUnsignedClient(f.Knot, s.config.Dev)
+ if err != nil {
+ log.Println("failed to create unsigned client", err)
+ return
}
- resp, err := http.Get(fmt.Sprintf("%s://%s/%s/%s/tags", protocol, f.Knot, f.OwnerDid(), f.RepoName))
+ resp, err := us.Tags(f.OwnerDid(), f.RepoName)
if err != nil {
log.Println("failed to reach knotserver", err)
return
@@ -423,6 +446,20 @@ func (s *State) RepoBranches(w http.ResponseWriter, r *http.Request) {
return
}
+ slices.SortFunc(result.Branches, func(a, b types.Branch) int {
+ if a.IsDefault {
+ return -1
+ }
+ if a.Commit != nil {
+ if a.Commit.Author.When.Before(b.Commit.Author.When) {
+ return 1
+ } else {
+ return -1
+ }
+ }
+ return strings.Compare(a.Name, b.Name) * -1
+ })
+
user := s.auth.GetUser(r)
s.pages.RepoBranches(w, pages.RepoBranchesParams{
LoggedInUser: user,
diff --git a/appview/state/repo_util.go b/appview/state/repo_util.go
index 1d78e32a..3ba3403c 100644
--- a/appview/state/repo_util.go
+++ b/appview/state/repo_util.go
@@ -82,32 +82,32 @@ func uniqueEmails(commits []*object.Commit) []string {
return uniqueEmails
}
-func balanceTagsAndCommits(commits, tags, totalDesired int) (int, int) {
- if commits == 0 && tags == 0 {
- return 0, 0
+func balanceIndexItems(commitCount, branchCount, tagCount, fileCount int) (commitsTrunc int, branchesTrunc int, tagsTrunc int) {
+ if commitCount == 0 && tagCount == 0 && branchCount == 0 {
+ return
}
- half := totalDesired / 2
+ // typically 1 item on right side = 2 files in height
+ availableSpace := fileCount / 2
- if commits+tags <= totalDesired {
- return commits, tags
+ // clamp tagcount
+ if tagCount > 0 {
+ tagsTrunc = 1
+ availableSpace -= 1 // an extra subtracted for headers etc.
}
- if commits >= half && tags >= half {
- return half, half
+ // clamp branchcount
+ if branchCount > 0 {
+ branchesTrunc = min(max(branchCount, 1), 2)
+ availableSpace -= branchesTrunc // an extra subtracted for headers etc.
}
- if commits < half {
- return commits, min(tags, totalDesired-commits)
+ // show
+ if commitCount > 0 {
+ commitsTrunc = max(availableSpace, 3)
}
- if tags < half {
- return min(commits, totalDesired-tags), tags
- }
-
- c := min(commits, half)
- t := min(tags, totalDesired-c)
- return c, t
+ return
}
func EmailToDidOrHandle(s *State, emails []string) map[string]string {
diff --git a/appview/state/signer.go b/appview/state/signer.go
index 687b6ab9..53469b3a 100644
--- a/appview/state/signer.go
+++ b/appview/state/signer.go
@@ -11,6 +11,7 @@ import (
"log"
"net/http"
"net/url"
+ "strconv"
"time"
"tangled.sh/tangled.sh/core/types"
@@ -286,8 +287,15 @@ func NewUnsignedClient(domain string, dev bool) (*UnsignedClient, error) {
return unsignedClient, nil
}
-func (us *UnsignedClient) newRequest(method, endpoint string, body []byte) (*http.Request, error) {
- return http.NewRequest(method, us.Url.JoinPath(endpoint).String(), bytes.NewReader(body))
+func (us *UnsignedClient) newRequest(method, endpoint string, query url.Values, body []byte) (*http.Request, error) {
+ reqUrl := us.Url.JoinPath(endpoint)
+
+ // add query parameters
+ if query != nil {
+ reqUrl.RawQuery = query.Encode()
+ }
+
+ return http.NewRequest(method, reqUrl.String(), bytes.NewReader(body))
}
func (us *UnsignedClient) Index(ownerDid, repoName, ref string) (*http.Response, error) {
@@ -300,7 +308,26 @@ func (us *UnsignedClient) Index(ownerDid, repoName, ref string) (*http.Response,
endpoint = fmt.Sprintf("/%s/%s", ownerDid, repoName)
}
- req, err := us.newRequest(Method, endpoint, nil)
+ req, err := us.newRequest(Method, endpoint, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return us.client.Do(req)
+}
+
+func (us *UnsignedClient) Log(ownerDid, repoName, ref string, page int) (*http.Response, error) {
+ const (
+ Method = "GET"
+ )
+
+ endpoint := fmt.Sprintf("/%s/%s/log/%s", ownerDid, repoName, url.PathEscape(ref))
+
+ query := url.Values{}
+ query.Add("page", strconv.Itoa(page))
+ query.Add("per_page", strconv.Itoa(60))
+
+ req, err := us.newRequest(Method, endpoint, query, nil)
if err != nil {
return nil, err
}
@@ -315,7 +342,22 @@ func (us *UnsignedClient) Branches(ownerDid, repoName string) (*http.Response, e
endpoint := fmt.Sprintf("/%s/%s/branches", ownerDid, repoName)
- req, err := us.newRequest(Method, endpoint, nil)
+ req, err := us.newRequest(Method, endpoint, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return us.client.Do(req)
+}
+
+func (us *UnsignedClient) Tags(ownerDid, repoName string) (*http.Response, error) {
+ const (
+ Method = "GET"
+ )
+
+ endpoint := fmt.Sprintf("/%s/%s/tags", ownerDid, repoName)
+
+ req, err := us.newRequest(Method, endpoint, nil, nil)
if err != nil {
return nil, err
}
@@ -330,7 +372,7 @@ func (us *UnsignedClient) Branch(ownerDid, repoName, branch string) (*http.Respo
endpoint := fmt.Sprintf("/%s/%s/branches/%s", ownerDid, repoName, url.PathEscape(branch))
- req, err := us.newRequest(Method, endpoint, nil)
+ req, err := us.newRequest(Method, endpoint, nil, nil)
if err != nil {
return nil, err
}
@@ -345,7 +387,7 @@ func (us *UnsignedClient) DefaultBranch(ownerDid, repoName string) (*http.Respon
endpoint := fmt.Sprintf("/%s/%s/branches/default", ownerDid, repoName)
- req, err := us.newRequest(Method, endpoint, nil)
+ req, err := us.newRequest(Method, endpoint, nil, nil)
if err != nil {
return nil, err
}
@@ -359,7 +401,7 @@ func (us *UnsignedClient) Capabilities() (*types.Capabilities, error) {
Endpoint = "/capabilities"
)
- req, err := us.newRequest(Method, Endpoint, nil)
+ req, err := us.newRequest(Method, Endpoint, nil, nil)
if err != nil {
return nil, err
}
@@ -385,7 +427,7 @@ func (us *UnsignedClient) Compare(ownerDid, repoName, rev1, rev2 string) (*types
endpoint := fmt.Sprintf("/%s/%s/compare/%s/%s", ownerDid, repoName, url.PathEscape(rev1), url.PathEscape(rev2))
- req, err := us.newRequest(Method, endpoint, nil)
+ req, err := us.newRequest(Method, endpoint, nil, nil)
if err != nil {
return nil, fmt.Errorf("Failed to create request.")
}
diff --git a/knotserver/git/git.go b/knotserver/git/git.go
index 8bc3e47f..959f3d46 100644
--- a/knotserver/git/git.go
+++ b/knotserver/git/git.go
@@ -156,6 +156,10 @@ func (g *GitRepo) Commits() ([]*object.Commit, error) {
return commits, nil
}
+func (g *GitRepo) Commit(h plumbing.Hash) (*object.Commit, error) {
+ return g.r.CommitObject(h)
+}
+
func (g *GitRepo) LastCommit() (*object.Commit, error) {
c, err := g.r.CommitObject(g.h)
if err != nil {
@@ -222,16 +226,36 @@ func (g *GitRepo) Tags() ([]*TagReference, error) {
return tags, nil
}
-func (g *GitRepo) Branches() ([]*plumbing.Reference, error) {
+func (g *GitRepo) Branches() ([]types.Branch, error) {
bi, err := g.r.Branches()
if err != nil {
return nil, fmt.Errorf("branchs: %w", err)
}
- branches := []*plumbing.Reference{}
+ branches := []types.Branch{}
+
+ defaultBranch, err := g.FindMainBranch()
+ if err != nil {
+ return nil, fmt.Errorf("getting default branch", "error", err.Error())
+ }
_ = bi.ForEach(func(ref *plumbing.Reference) error {
- branches = append(branches, ref)
+ b := types.Branch{}
+ b.Hash = ref.Hash().String()
+ b.Name = ref.Name().Short()
+
+ // resolve commit that this branch points to
+ commit, _ := g.Commit(ref.Hash())
+ if commit != nil {
+ b.Commit = commit
+ }
+
+ if defaultBranch != "" && defaultBranch == b.Name {
+ b.IsDefault = true
+ }
+
+ branches = append(branches, b)
+
return nil
})
diff --git a/knotserver/routes.go b/knotserver/routes.go
index 4ab94618..10c05355 100644
--- a/knotserver/routes.go
+++ b/knotserver/routes.go
@@ -93,14 +93,6 @@ func (h *Handle) RepoIndex(w http.ResponseWriter, r *http.Request) {
return
}
- bs := []types.Branch{}
- for _, branch := range branches {
- b := types.Branch{}
- b.Hash = branch.Hash().String()
- b.Name = branch.Name().Short()
- bs = append(bs, b)
- }
-
tags, err := gr.Tags()
if err != nil {
// Non-fatal, we *should* have at least one branch to show.
@@ -160,7 +152,7 @@ func (h *Handle) RepoIndex(w http.ResponseWriter, r *http.Request) {
Readme: readmeContent,
ReadmeFileName: readmeFile,
Files: files,
- Branches: bs,
+ Branches: branches,
Tags: rtags,
TotalCommits: total,
}
@@ -293,6 +285,8 @@ func (h *Handle) Archive(w http.ResponseWriter, r *http.Request) {
func (h *Handle) Log(w http.ResponseWriter, r *http.Request) {
ref := chi.URLParam(r, "ref")
+ ref, _ = url.PathUnescape(ref)
+
path, _ := securejoin.SecureJoin(h.c.Repo.ScanPath, didPath(r))
l := h.l.With("handler", "Log", "ref", ref, "path", path)
@@ -442,16 +436,8 @@ func (h *Handle) Branches(w http.ResponseWriter, r *http.Request) {
return
}
- bs := []types.Branch{}
- for _, branch := range branches {
- b := types.Branch{}
- b.Hash = branch.Hash().String()
- b.Name = branch.Name().Short()
- bs = append(bs, b)
- }
-
resp := types.RepoBranchesResponse{
- Branches: bs,
+ Branches: branches,
}
writeJSON(w, resp)
@@ -473,17 +459,35 @@ func (h *Handle) Branch(w http.ResponseWriter, r *http.Request) {
ref, err := gr.Branch(branchName)
if err != nil {
- l.Error("getting branches", "error", err.Error())
+ l.Error("getting branch", "error", err.Error())
+ writeError(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ commit, err := gr.Commit(ref.Hash())
+ if err != nil {
+ l.Error("getting commit object", "error", err.Error())
writeError(w, err.Error(), http.StatusInternalServerError)
return
}
+ defaultBranch, err := gr.FindMainBranch()
+ isDefault := false
+ if err != nil {
+ l.Error("getting default branch", "error", err.Error())
+ // do not quit though
+ } else if defaultBranch == branchName {
+ isDefault = true
+ }
+
resp := types.RepoBranchResponse{
Branch: types.Branch{
Reference: types.Reference{
Name: ref.Name().Short(),
Hash: ref.Hash().String(),
},
+ Commit: commit,
+ IsDefault: isDefault,
},
}
diff --git a/types/repo.go b/types/repo.go
index 29cec5c0..3d5dbd26 100644
--- a/types/repo.go
+++ b/types/repo.go
@@ -61,6 +61,8 @@ type Reference struct {
type Branch struct {
Reference `json:"reference"`
+ Commit *object.Commit `json:"commit,omitempty"`
+ IsDefault bool `json:"is_deafult,omitempty"`
}
type RepoTagsResponse struct {