Commit 3700715
Eric Bower
·
2023-08-05 23:40:43 -0400 EDT
parent e51bb05
looking good
6 files changed,
+141,
-77
M
go.mod
+1,
-0
| ... | ... | @@ -4,6 +4,7 @@ go 1.18 | |
| 4 | 4 | ||
| 5 | 5 | require ( | |
| 6 | 6 | github.com/gogs/git-module v1.6.0 | |
| 7 | + | github.com/mergestat/timediff v0.0.3 | |
| 7 | 8 | github.com/picosh/pico v1.1.6 | |
| 8 | 9 | github.com/spf13/viper v1.12.0 | |
| 9 | 10 | ) |
M
go.sum
+2,
-0
| ... | ... | @@ -213,6 +213,8 @@ github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= | |
| 213 | 213 | github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= | |
| 214 | 214 | github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk= | |
| 215 | 215 | github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo= | |
| 216 | + | github.com/mergestat/timediff v0.0.3 h1:ucCNh4/ZrTPjFZ081PccNbhx9spymCJkFxSzgVuPU+Y= | |
| 217 | + | github.com/mergestat/timediff v0.0.3/go.mod h1:yvMUaRu2oetc+9IbPLYBJviz6sA7xz8OXMDfhBl7YSI= | |
| 216 | 218 | github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg= | |
| 217 | 219 | github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= | |
| 218 | 220 | github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= |
+11,
-11
| ... | ... | @@ -5,17 +5,17 @@ | |
| 5 | 5 | {{template "header" .}} | |
| 6 | 6 | ||
| 7 | 7 | <dl> | |
| 8 | - | <dt>commit</dt> | |
| 9 | - | <dd><a href="{{.Data.CommitURL}}">{{.Data.Commit.ID}}</a></dd> | |
| 8 | + | <dt>commit</dt> | |
| 9 | + | <dd><a href="{{.Data.CommitURL}}">{{.Data.CommitID}}</a></dd> | |
| 10 | 10 | ||
| 11 | - | <dt>parent</dt> | |
| 12 | - | <dd><a href="{{.Data.ParentURL}}">{{.Data.Parent}}</a></dd> | |
| 11 | + | <dt>parent</dt> | |
| 12 | + | <dd><a href="{{.Data.ParentURL}}">{{.Data.Parent}}</a></dd> | |
| 13 | 13 | ||
| 14 | - | <dt>author</dt> | |
| 15 | - | <dd>{{.Data.Commit.Author.Name}}</dd> | |
| 14 | + | <dt>author</dt> | |
| 15 | + | <dd>{{.Data.Commit.Author.Name}}</dd> | |
| 16 | 16 | ||
| 17 | - | <dt>date</dt> | |
| 18 | - | <dd>{{.Data.Commit.Author.When}}</dd> | |
| 17 | + | <dt>date</dt> | |
| 18 | + | <dd>{{.Data.Commit.Author.When}}</dd> | |
| 19 | 19 | </dl> | |
| 20 | 20 | ||
| 21 | 21 | <pre>{{.Data.Commit.Message}}</pre> |
| ... | ... | @@ -31,15 +31,15 @@ | |
| 31 | 31 | {{range .Data.Diff.Files}} | |
| 32 | 32 | <div> | |
| 33 | 33 | <span>{{.FileType}}</span> | |
| 34 | - | <span>{{.Name}}</span> | |
| 34 | + | <a href="#diff-{{.Name}}">{{.Name}}</a> | |
| 35 | 35 | </div> | |
| 36 | 36 | {{end}} | |
| 37 | 37 | </div> | |
| 38 | 38 | </div> | |
| 39 | 39 | ||
| 40 | 40 | {{range .Data.Diff.Files}} | |
| 41 | - | <div class="flex justify-between mono"> | |
| 42 | - | <span>{{.FileType}} {{.OldName}} => {{.Name}}</span> | |
| 41 | + | <div id="diff-{{.Name}}" class="flex justify-between mono"> | |
| 42 | + | <span>{{.FileType}} {{if eq .FileType "R"}}{{.OldName}} => {{end}}{{.Name}}</span> | |
| 43 | 43 | <div> | |
| 44 | 44 | <span class="color-green">+{{.NumAdditions}}</span>, | |
| 45 | 45 | <span class="color-red">-{{.NumDeletions}}</span> |
+13,
-6
| ... | ... | @@ -3,10 +3,17 @@ | |
| 3 | 3 | {{define "title"}}index{{end}} | |
| 4 | 4 | ||
| 5 | 5 | {{define "content"}} | |
| 6 | - | <h1>repos</h1> | |
| 7 | - | {{range .RepoList}} | |
| 8 | - | <div> | |
| 9 | - | <a href="{{.URL}}">{{.Name}}</a> | |
| 10 | - | </div> | |
| 11 | - | {{end}} | |
| 6 | + | <h1 class="text-xl">repos</h1> | |
| 7 | + | <div> | |
| 8 | + | {{range .RepoList}} | |
| 9 | + | <div class="my box"> | |
| 10 | + | <div class="flex justify-between items-center"> | |
| 11 | + | <div><a class="text-lg" href="{{.URL}}">{{.Name}}</a></div> | |
| 12 | + | <div class="text-sm">{{.LastCommit.Author.When}}</div> | |
| 13 | + | </div> | |
| 14 | + | ||
| 15 | + | <div class="my">{{.Desc}}</div> | |
| 16 | + | </div> | |
| 17 | + | {{end}} | |
| 18 | + | </div> | |
| 12 | 19 | {{end}} |
+20,
-12
| ... | ... | @@ -5,16 +5,24 @@ | |
| 5 | 5 | {{define "content"}} | |
| 6 | 6 | {{template "header" .}} | |
| 7 | 7 | ||
| 8 | - | <div> | |
| 9 | - | {{range .Data.Tree}} | |
| 10 | - | <div class="flex justify-between mt"> | |
| 11 | - | <div class="text-md"> | |
| 12 | - | <a href="{{.URL}}">{{.Path}}</a> | |
| 13 | - | </div> | |
| 14 | - | <div class="mono"> | |
| 15 | - | <span>lines: {{.NumLines}}</span> | |
| 16 | - | </div> | |
| 17 | - | </div> | |
| 18 | - | {{end}} | |
| 19 | - | </div> | |
| 8 | + | <table> | |
| 9 | + | <tbody> | |
| 10 | + | {{range .Data.Tree}} | |
| 11 | + | <tr> | |
| 12 | + | <td> | |
| 13 | + | <a href="{{.URL}}">{{.Path}}</a> | |
| 14 | + | </td> | |
| 15 | + | <td> | |
| 16 | + | <a href="{{.CommitURL}}">{{.Desc}}</a> | |
| 17 | + | </td> | |
| 18 | + | <td> | |
| 19 | + | {{.When}} | |
| 20 | + | </td> | |
| 21 | + | <td class="mono font-bold"> | |
| 22 | + | L{{.NumLines}} | |
| 23 | + | </td> | |
| 24 | + | </tr> | |
| 25 | + | {{end}} | |
| 26 | + | </tbody> | |
| 27 | + | </table> | |
| 20 | 28 | {{end}} |
M
main.go
+94,
-48
| ... | ... | @@ -6,9 +6,11 @@ import ( | |
| 6 | 6 | html "html/template" | |
| 7 | 7 | "os" | |
| 8 | 8 | "path/filepath" | |
| 9 | + | "sort" | |
| 9 | 10 | "strings" | |
| 10 | 11 | ||
| 11 | 12 | git "github.com/gogs/git-module" | |
| 13 | + | "github.com/mergestat/timediff" | |
| 12 | 14 | "github.com/picosh/pico/pastes" | |
| 13 | 15 | "github.com/spf13/viper" | |
| 14 | 16 | ) |
| ... | ... | @@ -16,8 +18,10 @@ import ( | |
| 16 | 18 | var defaultBranches = []string{"main", "master"} | |
| 17 | 19 | ||
| 18 | 20 | type RepoItemData struct { | |
| 19 | - | URL string | |
| 20 | - | Name string | |
| 21 | + | URL string | |
| 22 | + | Name string | |
| 23 | + | Desc string | |
| 24 | + | LastCommit *git.Commit | |
| 21 | 25 | } | |
| 22 | 26 | ||
| 23 | 27 | type IndexPage struct { |
| ... | ... | @@ -32,6 +36,7 @@ type RepoData struct { | |
| 32 | 36 | LogURL string | |
| 33 | 37 | RefsURL string | |
| 34 | 38 | CloneURL string | |
| 39 | + | MaxCommits int | |
| 35 | 40 | } | |
| 36 | 41 | ||
| 37 | 42 | type CommitData struct { |
| ... | ... | @@ -44,6 +49,9 @@ type TreeItem struct { | |
| 44 | 49 | URL string | |
| 45 | 50 | Path string | |
| 46 | 51 | Entry *git.TreeEntry | |
| 52 | + | CommitURL string | |
| 53 | + | Desc string | |
| 54 | + | When string | |
| 47 | 55 | } | |
| 48 | 56 | ||
| 49 | 57 | type PageData struct { |
| ... | ... | @@ -59,6 +67,7 @@ type PageData struct { | |
| 59 | 67 | ||
| 60 | 68 | type CommitPageData struct { | |
| 61 | 69 | CommitMsg template.HTML | |
| 70 | + | CommitID string | |
| 62 | 71 | Commit *CommitData | |
| 63 | 72 | Diff *DiffRender | |
| 64 | 73 | Repo *RepoData |
| ... | ... | @@ -114,7 +123,7 @@ func bail(err error) { | |
| 114 | 123 | } | |
| 115 | 124 | } | |
| 116 | 125 | ||
| 117 | - | func CommitURL(repo string, commitID string) string { | |
| 126 | + | func commitURL(repo string, commitID string) string { | |
| 118 | 127 | return fmt.Sprintf("/%s/commits/%s.html", repo, commitID) | |
| 119 | 128 | } | |
| 120 | 129 |
| ... | ... | @@ -283,14 +292,15 @@ func writeHTMLTreeFiles(data *PageData) string { | |
| 283 | 292 | return readme | |
| 284 | 293 | } | |
| 285 | 294 | ||
| 286 | - | func writeLogDiffs(project string, repo *git.Repository, data *PageData, cache map[string]bool) { | |
| 287 | - | for _, commit := range data.Log { | |
| 295 | + | func (c *Config) writeLogDiffs(repo *git.Repository, pageData *PageData) { | |
| 296 | + | project := pageData.Repo.Name | |
| 297 | + | for _, commit := range pageData.Log { | |
| 288 | 298 | commitID := commit.ID.String() | |
| 289 | 299 | ||
| 290 | - | if cache[commitID] { | |
| 300 | + | if c.Cache[commitID] { | |
| 291 | 301 | continue | |
| 292 | 302 | } else { | |
| 293 | - | cache[commitID] = true | |
| 303 | + | c.Cache[commitID] = true | |
| 294 | 304 | } | |
| 295 | 305 | ||
| 296 | 306 | ancestors, err := commit.Ancestors() |
| ... | ... | @@ -302,7 +312,7 @@ func writeLogDiffs(project string, repo *git.Repository, data *PageData, cache m | |
| 302 | 312 | pt := ancestors[0] | |
| 303 | 313 | parent = &CommitData{ | |
| 304 | 314 | Commit: pt, | |
| 305 | - | URL: CommitURL(project, pt.ID.String()), | |
| 315 | + | URL: commitURL(project, pt.ID.String()), | |
| 306 | 316 | } | |
| 307 | 317 | } | |
| 308 | 318 | parentID := parent.ID.String() |
| ... | ... | @@ -347,30 +357,30 @@ func writeLogDiffs(project string, repo *git.Repository, data *PageData, cache m | |
| 347 | 357 | ||
| 348 | 358 | commitData := &CommitPageData{ | |
| 349 | 359 | Commit: commit, | |
| 360 | + | CommitID: commit.ID.String()[:7], | |
| 350 | 361 | Diff: rnd, | |
| 351 | - | Repo: data.Repo, | |
| 352 | - | Parent: parentID, | |
| 353 | - | CommitURL: CommitURL(project, commitID), | |
| 354 | - | ParentURL: CommitURL(project, parentID), | |
| 362 | + | Repo: pageData.Repo, | |
| 363 | + | Parent: parentID[:7], | |
| 364 | + | CommitURL: commitURL(project, commitID), | |
| 365 | + | ParentURL: commitURL(project, parentID), | |
| 355 | 366 | } | |
| 356 | 367 | ||
| 357 | 368 | writeHtml(&WriteData{ | |
| 358 | 369 | Name: fmt.Sprintf("%s.html", commitID), | |
| 359 | 370 | Template: "./html/commit.page.tmpl", | |
| 360 | 371 | Data: commitData, | |
| 361 | - | RepoName: data.Repo.Name, | |
| 372 | + | RepoName: pageData.Repo.Name, | |
| 362 | 373 | Subdir: "commits", | |
| 363 | - | Repo: data.Repo, | |
| 374 | + | Repo: pageData.Repo, | |
| 364 | 375 | }) | |
| 365 | 376 | } | |
| 366 | 377 | } | |
| 367 | 378 | ||
| 368 | - | func writeRepo(config *RepoConfig) { | |
| 379 | + | func (c *Config) writeRepo(config *RepoConfig) *BranchOutput { | |
| 369 | 380 | repo, err := git.Open(config.Path) | |
| 370 | 381 | bail(err) | |
| 371 | 382 | ||
| 372 | 383 | name := repoName(config.Path) | |
| 373 | - | desc := config.Desc | |
| 374 | 384 | ||
| 375 | 385 | heads, err := repo.ShowRef(git.ShowRefOptions{Heads: true, Tags: false}) | |
| 376 | 386 | bail(err) |
| ... | ... | @@ -383,19 +393,19 @@ func writeRepo(config *RepoConfig) { | |
| 383 | 393 | ||
| 384 | 394 | repoData := &RepoData{ | |
| 385 | 395 | Name: name, | |
| 386 | - | Desc: desc, | |
| 396 | + | Desc: config.Desc, | |
| 397 | + | MaxCommits: config.MaxCommits, | |
| 387 | 398 | SummaryURL: fmt.Sprintf("/%s/index.html", name), | |
| 388 | 399 | TreeURL: fmt.Sprintf("/%s/tree/%s/index.html", name, revName), | |
| 389 | 400 | LogURL: fmt.Sprintf("/%s/logs/%s/index.html", name, revName), | |
| 390 | 401 | RefsURL: fmt.Sprintf("/%s/refs.html", name), | |
| 391 | - | CloneURL: fmt.Sprintf("/%s.git", name), | |
| 402 | + | CloneURL: fmt.Sprintf("https://%s/%s.git", c.URL, name), | |
| 392 | 403 | } | |
| 393 | 404 | ||
| 394 | 405 | tags, _ := repo.ShowRef(git.ShowRefOptions{Heads: false, Tags: true}) | |
| 395 | 406 | ||
| 396 | - | cache := make(map[string]bool) | |
| 397 | - | ||
| 398 | - | readme := "" | |
| 407 | + | var mainOutput *BranchOutput | |
| 408 | + | claimed := false | |
| 399 | 409 | for _, revn := range config.Refs { | |
| 400 | 410 | for _, head := range heads { | |
| 401 | 411 | _, headName := filepath.Split(head.Refspec) |
| ... | ... | @@ -410,9 +420,10 @@ func writeRepo(config *RepoConfig) { | |
| 410 | 420 | Repo: repoData, | |
| 411 | 421 | } | |
| 412 | 422 | ||
| 413 | - | branchReadme := writeBranch(repo, data, cache) | |
| 414 | - | if readme == "" { | |
| 415 | - | readme = branchReadme | |
| 423 | + | branchOutput := c.writeBranch(repo, data) | |
| 424 | + | if !claimed { | |
| 425 | + | mainOutput = branchOutput | |
| 426 | + | claimed = true | |
| 416 | 427 | } | |
| 417 | 428 | } | |
| 418 | 429 | } |
| ... | ... | @@ -423,20 +434,36 @@ func writeRepo(config *RepoConfig) { | |
| 423 | 434 | Rev: rev, | |
| 424 | 435 | RevName: revName, | |
| 425 | 436 | Repo: repoData, | |
| 426 | - | Readme: template.HTML(readme), | |
| 437 | + | Readme: template.HTML(mainOutput.Readme), | |
| 427 | 438 | } | |
| 428 | 439 | writeRefs(data) | |
| 429 | 440 | writeRootSummary(data) | |
| 441 | + | return mainOutput | |
| 442 | + | } | |
| 443 | + | ||
| 444 | + | type BranchOutput struct { | |
| 445 | + | Readme string | |
| 446 | + | LastCommit *git.Commit | |
| 430 | 447 | } | |
| 431 | 448 | ||
| 432 | - | func writeBranch(repo *git.Repository, pageData *PageData, cache map[string]bool) string { | |
| 433 | - | commits, err := repo.CommitsByPage(pageData.Rev.ID, 0, 100) | |
| 449 | + | func (c *Config) writeBranch(repo *git.Repository, pageData *PageData) *BranchOutput { | |
| 450 | + | output := &BranchOutput{} | |
| 451 | + | pageSize := pageData.Repo.MaxCommits | |
| 452 | + | if pageSize == 0 { | |
| 453 | + | pageSize = 5000 | |
| 454 | + | } | |
| 455 | + | ||
| 456 | + | commits, err := repo.CommitsByPage(pageData.Rev.ID, 0, pageSize) | |
| 434 | 457 | bail(err) | |
| 435 | 458 | ||
| 436 | 459 | logs := []*CommitData{} | |
| 437 | - | for _, commit := range commits { | |
| 460 | + | for i, commit := range commits { | |
| 461 | + | if i == 0 { | |
| 462 | + | output.LastCommit = commit | |
| 463 | + | } | |
| 464 | + | ||
| 438 | 465 | logs = append(logs, &CommitData{ | |
| 439 | - | URL: CommitURL(pageData.Repo.Name, commit.ID.String()), | |
| 466 | + | URL: commitURL(pageData.Repo.Name, commit.ID.String()), | |
| 440 | 467 | Commit: commit, | |
| 441 | 468 | }) | |
| 442 | 469 | } |
| ... | ... | @@ -447,6 +474,19 @@ func writeBranch(repo *git.Repository, pageData *PageData, cache map[string]bool | |
| 447 | 474 | treeEntries := walkTree(tree, pageData.RevName, "", entries) | |
| 448 | 475 | for _, entry := range treeEntries { | |
| 449 | 476 | entry.Path = strings.TrimPrefix(entry.Path, "/") | |
| 477 | + | ||
| 478 | + | lastCommits, err := repo.RevList([]string{pageData.Rev.Refspec}, git.RevListOptions{ | |
| 479 | + | Path: entry.Path, | |
| 480 | + | }) | |
| 481 | + | bail(err) | |
| 482 | + | ||
| 483 | + | var lc *git.Commit | |
| 484 | + | if (len(lastCommits) > 0) { | |
| 485 | + | lc = lastCommits[0] | |
| 486 | + | } | |
| 487 | + | entry.CommitURL = commitURL(pageData.Repo.Name, lc.ID.String()) | |
| 488 | + | entry.Desc = lc.Summary() | |
| 489 | + | entry.When = timediff.TimeDiff(lc.Author.When) | |
| 450 | 490 | entry.URL = filepath.Join( | |
| 451 | 491 | "/", | |
| 452 | 492 | pageData.Repo.Name, |
| ... | ... | @@ -462,25 +502,24 @@ func writeBranch(repo *git.Repository, pageData *PageData, cache map[string]bool | |
| 462 | 502 | ||
| 463 | 503 | writeLog(pageData) | |
| 464 | 504 | readme := writeHTMLTreeFiles(pageData) | |
| 465 | - | writeLogDiffs(pageData.Repo.Name, repo, pageData, cache) | |
| 505 | + | c.writeLogDiffs(repo, pageData) | |
| 466 | 506 | ||
| 467 | - | for _, def := range defaultBranches { | |
| 468 | - | if def == pageData.RevName { | |
| 469 | - | writeTree(pageData) | |
| 470 | - | } | |
| 471 | - | } | |
| 507 | + | writeTree(pageData) | |
| 472 | 508 | ||
| 473 | - | return readme | |
| 509 | + | output.Readme = readme | |
| 510 | + | return output | |
| 474 | 511 | } | |
| 475 | 512 | ||
| 476 | 513 | type RepoConfig struct { | |
| 477 | - | Path string `mapstructure:"path"` | |
| 478 | - | Refs []string `mapstructure:"refs"` | |
| 479 | - | Desc string `mapstructure:"desc"` | |
| 514 | + | Path string `mapstructure:"path"` | |
| 515 | + | Refs []string `mapstructure:"refs"` | |
| 516 | + | Desc string `mapstructure:"desc"` | |
| 517 | + | MaxCommits int `mapstructure:"max_commits"` | |
| 480 | 518 | } | |
| 481 | 519 | type Config struct { | |
| 482 | 520 | Repos []*RepoConfig `mapstructure:"repos"` | |
| 483 | 521 | URL string `mapstructure:"url"` | |
| 522 | + | Cache map[string]bool | |
| 484 | 523 | } | |
| 485 | 524 | ||
| 486 | 525 | func main() { |
| ... | ... | @@ -492,23 +531,30 @@ func main() { | |
| 492 | 531 | bail(err) | |
| 493 | 532 | ||
| 494 | 533 | var config Config | |
| 495 | - | if err := viper.Unmarshal(&config); err != nil { | |
| 496 | - | fmt.Println(err) | |
| 497 | - | return | |
| 498 | - | } | |
| 534 | + | err = viper.Unmarshal(&config) | |
| 535 | + | bail(err) | |
| 536 | + | ||
| 537 | + | config.Cache = make(map[string]bool) | |
| 538 | + | ||
| 499 | 539 | repoList := []*RepoItemData{} | |
| 500 | 540 | for _, r := range config.Repos { | |
| 541 | + | mainOutput := config.writeRepo(r) | |
| 501 | 542 | name := repoName(r.Path) | |
| 502 | 543 | url := filepath.Join("/", name, "index.html") | |
| 503 | 544 | repoList = append(repoList, &RepoItemData{ | |
| 504 | - | URL: url, | |
| 505 | - | Name: name, | |
| 545 | + | URL: url, | |
| 546 | + | Name: name, | |
| 547 | + | Desc: r.Desc, | |
| 548 | + | LastCommit: mainOutput.LastCommit, | |
| 506 | 549 | }) | |
| 507 | 550 | } | |
| 551 | + | sort.Slice(repoList, func(i, j int) bool { | |
| 552 | + | first := repoList[i].LastCommit.Author.When | |
| 553 | + | second := repoList[j].LastCommit.Author.When | |
| 554 | + | return first.After(second) | |
| 555 | + | }) | |
| 556 | + | ||
| 508 | 557 | writeIndex(&IndexPage{ | |
| 509 | 558 | RepoList: repoList, | |
| 510 | 559 | }) | |
| 511 | - | for _, r := range config.Repos { | |
| 512 | - | writeRepo(r) | |
| 513 | - | } | |
| 514 | 560 | } |