From: Nikita Shubin Date: Fri, 29 Mar 2024 10:02:04 +0000 (+0300) Subject: hugolib: Add gitpurism module X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=8bbf187b6967bdbf66dc297968a1f4fc71d596fa;p=brevno-suite%2Fhugo hugolib: Add gitpurism module Add gitpurism module to extract tags and categories directly from git notes. Curently it scans notes/categories and notes/tags branches. Example: Notes (categories): categories: [git] Notes (tags): tags: [git,git-notes] Data is expected in YAML format. TODO: specify note branches to scan Signed-off-by: Nikita Shubin --- diff --git a/hugolib/gitpurism.go b/hugolib/gitpurism.go new file mode 100644 index 00000000..1ef06842 --- /dev/null +++ b/hugolib/gitpurism.go @@ -0,0 +1,122 @@ +// Copyright 2024 Nikita Shubin . All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package hugolib + +import ( + "path/filepath" + "os/exec" + "strings" + "errors" + "bytes" + "fmt" + + "github.com/gohugoio/hugo/config" + "github.com/gohugoio/hugo/resources/page" + + "gopkg.in/yaml.v2" +) + +func git(args ...string) ([]byte, error) { + out, err := exec.Command(gitExec, args...).CombinedOutput() + + if err != nil { + if ee, ok := err.(*exec.Error); ok { + if ee.Err == exec.ErrNotFound { + return nil, GitNotFound + } + } + + return nil, errors.New(string(bytes.TrimSpace(out))) + } + + return out, nil +} + +var ( + // will be modified during tests + gitExec string = "git" + GitNotFound = errors.New("Git executable not found in $PATH") +) + +type gitPurismInfo struct { + contentDir string +} + +type GitPurismInfo struct { + Tags []string + Categories []string +} + +type Tags struct { + Tags []string `yaml:"tags"` +} + +type Cats struct { + Categories []string `yaml:"categories"` +} + +func (g *gitPurismInfo) forPage(p page.Page) *GitPurismInfo { + var t_res []string + var c_res []string + + name := strings.TrimPrefix(filepath.ToSlash(p.File().Filename()), g.contentDir) + name = strings.TrimPrefix(name, "/") + + gitLogArgs := strings.Fields(fmt.Sprintf( + `--no-pager -C %s log --notes=%s --notes=%s --format=%%N -- %s`, + g.contentDir, + "tags", + "categories", + name, + )) + + out, err := git(gitLogArgs...) + entriesStr := string(out) + entriesStr = strings.Trim(entriesStr, "\n\x1e'") + entries := strings.Split(string(entriesStr), "\n") + + for _, e := range entries { + var t Tags + var c Cats + err = yaml.Unmarshal([]byte(e), &t) + if err != nil { + continue + } + + err = yaml.Unmarshal([]byte(e), &c) + if err != nil { + continue + } + + t_res = append(t_res, t.Tags...) + c_res = append(c_res, c.Categories...) + } + + return &GitPurismInfo{Tags: t_res, Categories: c_res} +} + +func newGitPurismInfo(cfg config.Provider) (*gitPurismInfo, error) { + contentDir := cfg.GetString("contentDir") + absRepoPath, err := filepath.Abs(contentDir) + + if err != nil { + return nil, err + } + + _, err = git("-C", absRepoPath, "rev-parse", "--show-cdup") + if err != nil { + return nil, err + } + + return &gitPurismInfo{contentDir: absRepoPath}, nil +}