+/*
+SGBlog -- Git-backed CGI/inetd blogging/phlogging engine
+Copyright (C) 2020-2021 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// Git-backed CGI/inetd blogging/phlogging engine
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "sort"
+
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/go-git/go-git/v5/plumbing/object"
+ "go.stargrave.org/sgblog"
+)
+
+func main() {
+ branch := flag.String("branch", "refs/heads/master", "Blog's branch reference name")
+ topicsRefName := flag.String("topics-ref", "refs/notes/topics", "Topics reference name")
+ flag.Usage = func() {
+ fmt.Fprintln(flag.CommandLine.Output(), "Show known topics")
+ flag.PrintDefaults()
+ }
+ flag.Parse()
+ log.SetFlags(0)
+
+ repo, err := git.PlainOpen(".")
+ if err != nil {
+ log.Fatalln(err)
+ }
+ head, err := repo.Reference(plumbing.ReferenceName(*branch), false)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ headHash := head.Hash()
+
+ var topicsRef *plumbing.Reference
+ var topicsTree *object.Tree
+ if notes, err := repo.Notes(); err == nil {
+ notes.ForEach(func(ref *plumbing.Reference) error {
+ if string(ref.Name()) == *topicsRefName {
+ topicsRef = ref
+ }
+ return nil
+ })
+ if topicsRef != nil {
+ if topicsCommit, err := repo.CommitObject(topicsRef.Hash()); err == nil {
+ topicsTree, _ = topicsCommit.Tree()
+ }
+ }
+ }
+
+ repoLog, err := repo.Log(&git.LogOptions{From: headHash})
+ if err != nil {
+ log.Fatalln(err)
+ }
+ topicsCounter := map[string]int{}
+ for {
+ commit, err := repoLog.Next()
+ if err != nil {
+ break
+ }
+ for _, topic := range sgblog.ParseTopics(sgblog.GetNote(repo, topicsTree, commit.Hash)) {
+ topicsCounter[topic]++
+ }
+ }
+ topics := make([]string, 0, len(topicsCounter))
+ for topic := range topicsCounter {
+ topics = append(topics, topic)
+ }
+ sort.Strings(topics)
+ for _, topic := range topics {
+ fmt.Printf("%s\t%d\n", topic, topicsCounter[topic])
+ }
+}