golang使用占位符创建文本模板并集成Git仓库元数据的插件库tbd

Golang 使用占位符创建文本模板并集成 Git 仓库元数据的插件库 tbd

简介

tbd (to be defined) 是一个简单易用的文本模板工具,支持通过占位符创建动态文本模板,并自动集成 Git 仓库元数据。

内置变量

当在 Git 仓库中执行时,tbd 会自动导出一些与 Git 仓库相关的变量:

  • ARCH - 系统架构
  • OS - 操作系统
  • REPO_COMMIT - 仓库提交哈希
  • REPO_HOST - 仓库主机
  • REPO_NAME - 仓库名称
  • REPO_ROOT - 仓库根目录
  • REPO_TAG - 仓库标签
  • REPO_TAG_CLEAN - 清理后的仓库标签
  • REPO_URL - 仓库 URL
  • TIMESTAMP - 时间戳

查看当前变量:

$ tbd vars
+----------------+------------------------------------------+
| ARCH           | amd64                                    |
| OS             | linux                                    |
| REPO_COMMIT    | a3193274112d3a6f5c2a0277e2ca07ec238d622f |
| REPO_HOST      | github.com                               |
| REPO_NAME      | tbd                                      |
| REPO_ROOT      | lucasepe                                 |
| REPO_TAG       | v0.1.1                                   |
| REPO_TAG_CLEAN | 0.1.1                                    |
| REPO_URL       | https://github.com/lucasepe/tbd          |
| TIMESTAMP      | 2021-07-26T14:22:36Z                     |
+----------------+------------------------------------------+

模板示例

模板是包含占位符的文本文档,占位符由 {{}} 包围。

YAML 模板示例

apiVersion: v1
kind: Pod
metadata:
  name: {{ metadata.name }}
  labels:
    app: {{ metadata.labels.app }}
 spec:
  containers:
    - name: {{ container.1.name }}
      image: {{ container.1.image }}
      ports:
        - containerPort: {{ container.1.port }}
    - name: {{ container.2.name }}
      image: {{ container.2.image }}
      ports:
        - containerPort: {{ container.2.port }}

文本模板示例

{{ greeting }}

I will be out of the office from {{ start.date }} until {{ return.date }}. 
If you need immediate assistance while I'm away, please email {{ contact.email }}.

Best,
{{ name }}

定义占位符值

创建变量文件定义占位符值:

# metadata values
metadata.name = rss-site
metadata.labels.app = web

# containers values
container.1.name = front-end
container.1.image = nginx
container.1.port = 80

container.2.name = rss-reader
container.2.image: nickchase/rss-php-nginx:v1
container.2.port: 88

或:

greeting: Greetings
start.date: August, 9 
return.date: August 23
contact.email: pinco.pallo@gmail.com
name: Pinco Pallo

填充模板

使用 merge 命令填充模板:

$ tbd merge /path/to/your/template /path/to/your/envfile

示例:

$ tbd merge testdata/sample.tbd testdata/sample.vars

输出:

Greetings

I will be out of the office from August, 9 until August 23. 
If you need immediate assistance while I'm away, please email pinco.pallo@gmail.com.

Best,
Pinco Pallo

列出模板占位符

使用 marks 命令:

$ tbd marks /path/to/your/template

示例:

$ tbd marks testdata/sample.tbd
greeting
start.date
return.date
contact.email
name

列出所有变量

使用 vars 命令:

$ tbd vars /path/to/your/envfile

示例:

$ tbd vars testdata/sample.vars
+----------------+------------------------------------------+
| Label          | Value                                    |
+----------------+------------------------------------------+
| ARCH           | amd64                                    |
| OS             | linux                                    |
| REPO_COMMIT    | a3193274112d3a6f5c2a0277e2ca07ec238d622f |
| REPO_HOST      | github.com                               |
| REPO_NAME      | tbd                                      |
| REPO_ROOT      | lucasepe                                 |
| REPO_TAG       | v0.1.1                                   |
| REPO_TAG_CLEAN | 0.1.1                                    |
| REPO_URL       | https://github.com/lucasepe/tbd          |
| TIMESTAMP      | 2021-07-26T14:17:49Z                     |
| contact.email  | pinco.pallo@gmail.com                    |
| greeting       | Greetings                                |
| name           | Pinco Pallo                              |
| return.date    | August 23                                |
| start.date     | August, 9                                |
+----------------+------------------------------------------+

安装

使用 Go 安装:

$ go install github.com/lucasepe/tbd@latest

或下载预编译版本:

  • MacOS
  • Linux
  • Windows

完整示例

  1. 创建模板文件 template.txt:
Hello {{ user.name }},

Welcome to {{ project.name }} (version: {{ project.version }}).
This project was last updated on {{ timestamp }}.

Repository: {{ repo.url }}
Commit: {{ repo.commit }}
  1. 创建变量文件 vars.env:
user.name = John Doe
project.name = Awesome Project
project.version = 1.0.0

# Git repo info will be auto-populated
  1. 填充模板:
$ tbd merge template.txt vars.env

输出:

Hello John Doe,

Welcome to Awesome Project (version: 1.0.0).
This project was last updated on 2023-05-15T10:30:00Z.

Repository: https://github.com/yourusername/yourrepo
Commit: a1b2c3d4e5f6g7h8i9j0

注意事项

  • 这是一个简单工具,不支持复杂语法
  • 对于高级模板需求,推荐使用 gotemplate、pongo2 或 quicktemplate

更多关于golang使用占位符创建文本模板并集成Git仓库元数据的插件库tbd的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang使用占位符创建文本模板并集成Git仓库元数据的插件库tbd的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用Golang创建文本模板并集成Git元数据的方案

在Golang中,我们可以使用标准库的text/template包创建带有占位符的文本模板,并结合Git仓库元数据来填充这些模板。下面我将介绍一个完整的解决方案。

核心实现方案

1. 基本文本模板功能

首先,我们使用text/template包创建模板:

package main

import (
	"os"
	"text/template"
)

func main() {
	// 定义模板
	const tmpl = `项目信息:
项目名称: {{.ProjectName}}
版本: {{.Version}}
描述: {{.Description}}
Git提交: {{.GitCommit}}
分支: {{.GitBranch}}
`

	// 准备数据
	data := struct {
		ProjectName string
		Version     string
		Description string
		GitCommit   string
		GitBranch   string
	}{
		ProjectName: "MyProject",
		Version:     "1.0.0",
		Description: "这是一个示例项目",
		GitCommit:   "a1b2c3d",
		GitBranch:   "main",
	}

	// 解析并执行模板
	t := template.Must(template.New("project").Parse(tmpl))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		panic(err)
	}
}

2. 集成Git元数据

我们可以使用go-git库来获取Git仓库信息:

package gitmeta

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/go-git/go-git/v5"
)

type GitMetadata struct {
	CommitHash string
	Branch     string
	Tag        string
	RemoteURL  string
}

func GetGitMetadata(repoPath string) (*GitMetadata, error) {
	// 自动发现.git目录
	if repoPath == "" {
		var err error
		repoPath, err = findGitDir(".")
		if err != nil {
			return nil, fmt.Errorf("无法找到.git目录: %v", err)
		}
	}

	repo, err := git.PlainOpen(repoPath)
	if err != nil {
		return nil, fmt.Errorf("无法打开Git仓库: %v", err)
	}

	ref, err := repo.Head()
	if err != nil {
		return nil, fmt.Errorf("无法获取HEAD引用: %v", err)
	}

	// 获取提交哈希
	commitHash := ref.Hash().String()

	// 获取分支名称
	branch := ref.Name().Short()

	// 获取标签
	tags, err := repo.Tags()
	if err != nil {
		return nil, fmt.Errorf("无法获取标签: %v", err)
	}

	var tag string
	err = tags.ForEach(func(t *plumbing.Reference) error {
		if t.Hash() == ref.Hash() {
			tag = t.Name().Short()
		}
		return nil
	})

	// 获取远程URL
	remotes, err := repo.Remotes()
	var remoteURL string
	if err == nil && len(remotes) > 0 {
		remoteURL = remotes[0].Config().URLs[0]
	}

	return &GitMetadata{
		CommitHash: commitHash,
		Branch:     branch,
		Tag:        tag,
		RemoteURL:  remoteURL,
	}, nil
}

func findGitDir(startDir string) (string, error) {
	dir, err := filepath.Abs(startDir)
	if err != nil {
		return "", err
	}

	for {
		gitDir := filepath.Join(dir, ".git")
		if _, err := os.Stat(gitDir); err == nil {
			return dir, nil
		}

		parent := filepath.Dir(dir)
		if parent == dir {
			return "", fmt.Errorf("未找到.git目录")
		}
		dir = parent
	}
}

3. 完整插件库设计

下面是一个完整的模板处理器设计:

package tbd

import (
	"bytes"
	"text/template"
	
	"github.com/yourusername/tbd/gitmeta"
)

type TemplateData struct {
	Project   ProjectInfo
	Git       gitmeta.GitMetadata
	Custom    map[string]interface{}
}

type ProjectInfo struct {
	Name        string
	Version     string
	Description string
	Author      string
}

type TemplateProcessor struct {
	funcMap template.FuncMap
}

func NewTemplateProcessor() *TemplateProcessor {
	return &TemplateProcessor{
		funcMap: template.FuncMap{
			"upper": strings.ToUpper,
			"lower": strings.ToLower,
			// 可以添加更多自定义函数
		},
	}
}

func (tp *TemplateProcessor) Render(templateStr string, project ProjectInfo, customData map[string]interface{}, repoPath string) (string, error) {
	// 获取Git元数据
	gitMeta, err := gitmeta.GetGitMetadata(repoPath)
	if err != nil {
		return "", err
	}

	// 准备模板数据
	data := TemplateData{
		Project: project,
		Git:     *gitMeta,
		Custom:  customData,
	}

	// 创建并解析模板
	tmpl, err := template.New("tbd-template").
		Funcs(tp.funcMap).
		Parse(templateStr)
	if err != nil {
		return "", err
	}

	// 执行模板
	var buf bytes.Buffer
	err = tmpl.Execute(&buf, data)
	if err != nil {
		return "", err
	}

	return buf.String(), nil
}

使用示例

package main

import (
	"fmt"
	"log"
	
	"github.com/yourusername/tbd"
)

func main() {
	processor := tbd.NewTemplateProcessor()
	
	project := tbd.ProjectInfo{
		Name:        "Awesome Project",
		Version:     "1.2.3",
		Description: "This is an awesome project",
		Author:      "John Doe",
	}
	
	customData := map[string]interface{}{
		"Environment": "production",
		"Region":      "us-west-1",
	}
	
	templateStr := `# {{.Project.Name}} (v{{.Project.Version}})
	
## 项目信息
- 描述: {{.Project.Description}}
- 作者: {{.Project.Author}}
	
## Git信息
- 分支: {{.Git.Branch}}
- 提交: {{.Git.CommitHash}}
- 仓库: {{.Git.RemoteURL}}
	
## 环境
- 环境: {{.Custom.Environment}}
- 区域: {{.Custom.Region | upper}}
`
	
	result, err := processor.Render(templateStr, project, customData, "")
	if err != nil {
		log.Fatal(err)
	}
	
	fmt.Println(result)
}

高级功能扩展

  1. 模板文件支持:可以从文件加载模板而不仅是字符串
  2. 模板缓存:缓存已解析的模板以提高性能
  3. 更多Git元数据:添加更多Git相关信息如提交消息、作者等
  4. 模板继承:支持基础模板和子模板的继承关系
  5. 自定义函数:添加更多有用的模板函数

这个方案提供了灵活且强大的文本模板处理能力,同时集成了Git仓库元数据,可以满足大多数项目的需求。

回到顶部