]> Sergey Matveev's repositories - sgblog.git/blob - cmd/sgblog-topics/main.go
Unify copyright comment format
[sgblog.git] / cmd / sgblog-topics / main.go
1 // SGBlog -- Git-backed CGI/UCSPI blogging/phlogging/gemlogging engine
2 // Copyright (C) 2020-2024 Sergey Matveev <stargrave@stargrave.org>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, version 3 of the License.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU Affero General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 // Git-backed CGI/UCSPI blogging/phlogging/gemlogging engine
17 package main
18
19 import (
20         "flag"
21         "fmt"
22         "log"
23         "sort"
24
25         "github.com/go-git/go-git/v5"
26         "github.com/go-git/go-git/v5/plumbing"
27         "github.com/go-git/go-git/v5/plumbing/object"
28         "go.stargrave.org/sgblog"
29 )
30
31 func main() {
32         branch := flag.String("branch", "refs/heads/master", "Blog's branch reference name")
33         topicsRefName := flag.String("topics-ref", "refs/notes/topics", "Topics reference name")
34         flag.Usage = func() {
35                 fmt.Fprintln(flag.CommandLine.Output(), "Show known topics")
36                 flag.PrintDefaults()
37         }
38         flag.Parse()
39         log.SetFlags(0)
40
41         repo, err := git.PlainOpen(".")
42         if err != nil {
43                 log.Fatalln(err)
44         }
45         head, err := repo.Reference(plumbing.ReferenceName(*branch), false)
46         if err != nil {
47                 log.Fatalln(err)
48         }
49         headHash := head.Hash()
50
51         var topicsRef *plumbing.Reference
52         var topicsTree *object.Tree
53         if notes, err := repo.Notes(); err == nil {
54                 notes.ForEach(func(ref *plumbing.Reference) error {
55                         if string(ref.Name()) == *topicsRefName {
56                                 topicsRef = ref
57                         }
58                         return nil
59                 })
60                 if topicsRef != nil {
61                         if topicsCommit, err := repo.CommitObject(topicsRef.Hash()); err == nil {
62                                 topicsTree, _ = topicsCommit.Tree()
63                         }
64                 }
65         }
66
67         repoLog, err := repo.Log(&git.LogOptions{From: headHash})
68         if err != nil {
69                 log.Fatalln(err)
70         }
71         topicsCounter := map[string]int{}
72         for {
73                 commit, err := repoLog.Next()
74                 if err != nil {
75                         break
76                 }
77                 for _, topic := range sgblog.ParseTopics(sgblog.GetNote(repo, topicsTree, commit.Hash)) {
78                         topicsCounter[topic]++
79                 }
80         }
81         topics := make([]string, 0, len(topicsCounter))
82         for topic := range topicsCounter {
83                 topics = append(topics, topic)
84         }
85         sort.Strings(topics)
86         for _, topic := range topics {
87                 fmt.Printf("%s\t%d\n", topic, topicsCounter[topic])
88         }
89 }