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