all repos

mugit @ f399e2a

馃惍 git server that your cow will love
4 files changed, 54 insertions(+), 12 deletions(-)
feat: pagination for log page
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-02-24 23:27:33 +0200
Authored at: 2026-02-24 22:56:50 +0200
Change ID: squqrynrrltxkpllnkmyksqmrlplnwpw
Parent: b883855
M internal/git/repo.go
路路路
        11
        11
         	"github.com/go-git/go-git/v5"

      
        12
        12
         	"github.com/go-git/go-git/v5/plumbing"

      
        13
        13
         	"github.com/go-git/go-git/v5/plumbing/object"

      
        
        14
        +	"github.com/go-git/go-git/v5/plumbing/storer"

      
        14
        15
         	"github.com/go-git/go-git/v5/plumbing/transport"

      
        15
        16
         	"github.com/go-git/go-git/v5/plumbing/transport/http"

      
        16
        17
         )

      路路路
        129
        130
         	}

      
        130
        131
         }

      
        131
        132
         

      
        132
        
        -func (g *Repo) Commits() ([]*Commit, error) {

      
        
        133
        +const CommitsPage = 150

      
        
        134
        +

      
        
        135
        +// Commits returns [CommitsPage] commits after the given commit hash cursor.

      
        
        136
        +// If after is empty, starts from HEAD.

      
        
        137
        +func (g *Repo) Commits(after string) ([]*Commit, error) {

      
        133
        138
         	if g.IsEmpty() {

      
        134
        139
         		return []*Commit{}, nil

      
        135
        140
         	}

      
        136
        141
         

      
        
        142
        +	from := g.h

      
        
        143
        +	if after != "" {

      
        
        144
        +		hash, err := g.r.ResolveRevision(plumbing.Revision(after))

      
        
        145
        +		if err != nil {

      
        
        146
        +			return nil, fmt.Errorf("invalid cursor: %w", err)

      
        
        147
        +		}

      
        
        148
        +		from = *hash

      
        
        149
        +	}

      
        
        150
        +

      
        137
        151
         	ci, err := g.r.Log(&git.LogOptions{

      
        138
        
        -		From:  g.h,

      
        
        152
        +		From:  from,

      
        139
        153
         		Order: git.LogOrderCommitterTime,

      
        140
        154
         	})

      
        141
        155
         	if err != nil {

      
        142
        156
         		return nil, fmt.Errorf("commits from ref: %w", err)

      
        143
        157
         	}

      
        144
        158
         

      
        145
        
        -	var commits []*Commit

      
        
        159
        +	// since after commit was shown on prev page, skip it

      
        
        160
        +	if after != "" {

      
        
        161
        +		ci.Next()

      
        
        162
        +	}

      
        
        163
        +

      
        
        164
        +	commits := make([]*Commit, 0, CommitsPage)

      
        146
        165
         	ci.ForEach(func(c *object.Commit) error {

      
        
        166
        +		if len(commits) == CommitsPage {

      
        
        167
        +			return storer.ErrStop

      
        
        168
        +		}

      
        147
        169
         		commits = append(commits, newCommit(c))

      
        148
        170
         		return nil

      
        149
        171
         	})

      
M internal/handlers/repo.go
路路路
        94
        94
         		return

      
        95
        95
         	}

      
        96
        96
         

      
        97
        
        -	p.Commits, err = repo.Commits()

      
        
        97
        +	p.Commits, err = repo.Commits("")

      
        98
        98
         	if err != nil {

      
        99
        99
         		h.write500(w, err)

      
        100
        100
         		return

      路路路
        239
        239
         }

      
        240
        240
         

      
        241
        241
         type RepoLog struct {

      
        242
        
        -	Desc    string

      
        243
        
        -	Commits []*git.Commit

      
        244
        
        -	Ref     string

      
        
        242
        +	Desc      string

      
        
        243
        +	Commits   []*git.Commit

      
        
        244
        +	Ref       string

      
        
        245
        +	NextAfter string

      
        245
        246
         }

      
        246
        247
         

      
        247
        248
         func (h *handlers) logHandler(w http.ResponseWriter, r *http.Request) {

      
        248
        249
         	name := r.PathValue("name")

      
        249
        250
         	ref := h.parseRef(r.PathValue("ref"))

      
        
        251
        +	after := r.URL.Query().Get("after")

      
        250
        252
         

      
        251
        253
         	repo, err := h.openPublicRepo(name, ref)

      
        252
        254
         	if err != nil {

      路路路
        254
        256
         		return

      
        255
        257
         	}

      
        256
        258
         

      
        257
        
        -	commits, err := repo.Commits()

      
        
        259
        +	desc, err := repo.Description()

      
        258
        260
         	if err != nil {

      
        259
        261
         		h.write500(w, err)

      
        260
        262
         		return

      
        261
        263
         	}

      
        262
        264
         

      
        263
        
        -	desc, err := repo.Description()

      
        
        265
        +	commits, err := repo.Commits(after)

      
        264
        266
         	if err != nil {

      
        265
        267
         		h.write500(w, err)

      
        266
        268
         		return

      
        267
        269
         	}

      
        268
        270
         

      
        
        271
        +	// if we got full page of commits, we probably have more.

      
        
        272
        +	// NOTE: this has edge case, when last page has git.CommitsPage, "load more would be shown"

      
        
        273
        +	nextAfter := ""

      
        
        274
        +	if len(commits) == git.CommitsPage && len(commits) > 0 {

      
        
        275
        +		nextAfter = commits[len(commits)-1].HashShort

      
        
        276
        +	}

      
        
        277
        +

      
        269
        278
         	h.templ(w, "repo_log", h.pageData(repo, RepoLog{

      
        270
        
        -		Desc:    desc,

      
        271
        
        -		Commits: commits,

      
        272
        
        -		Ref:     ref,

      
        
        279
        +		Desc:      desc,

      
        
        280
        +		Ref:       ref,

      
        
        281
        +		Commits:   commits,

      
        
        282
        +		NextAfter: nextAfter,

      
        273
        283
         	}))

      
        274
        284
         }

      
        275
        285
         

      
M web/static/style.css
路路路
        100
        100
         .fill { width: 100%; }

      
        101
        101
         .muted { color: var(--gray); }

      
        102
        102
         

      
        
        103
        +.center {

      
        
        104
        +  display: flex;

      
        
        105
        +  justify-content: center;

      
        
        106
        +}

      
        
        107
        +

      
        103
        108
         .size { text-align: right; }

      
        104
        109
         

      
        105
        110
         .mode, .size,

      
M web/templates/repo_log.html
路路路
        46
        46
                   {{ end }}

      
        47
        47
                 </tbody>

      
        48
        48
               </table>

      
        
        49
        +      <div class="center">

      
        
        50
        +        {{- if .P.NextAfter }}

      
        
        51
        +        <a href="?after={{ urlencode .P.NextAfter }}">[load more]</a>

      
        
        52
        +        {{- end }}

      
        
        53
        +      </div>

      
        49
        54
             </main>

      
        50
        55
           </body>

      
        51
        56
         </html>