今天主题相对来说简单一些, 我们就纯编程, 我们用 go 实现 git 配置文件读取和写入.
git 配置文件格式如下:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[submodule]
active = .
[remote "origin"]
url = https://github.com/xxx/xxx.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[submodule "lib/xxx"]
url = https://github.com/xxx/xxx
[submodule "lib/xxx"]
url = https://github.com/xxx/xxx
可以看到子模块中主要包含五项,因此定义如下
type ConfFile struct {
core map[string]string
submodule map[string]string
remote map[string]map[string]string
branch map[string]map[string]string
submodules map[string]map[string]string
}
对数据结构操作,首先就是初始化,当我们从零开始创建一个 conf 文件时候,我们的数据结构如下:
func NewConfFle() ConfFile {
return ConfFile{
core: map[string]string{
"repositoryformatversion": "0",
"filemode": "true",
"bare": "false",
"logallrefupdates": "true",
"ignorecase": "true",
"precomposeunicode": "true",
},
}
}
初始化中只有 core 有内容.
func ReadFileToConf(path string) (*ConfFile, error) {
confFile := &ConfFile{}
var currentSection string
var currentSubSection string
file, err := os.Open(path)
if err != nil {
panic("配置文件不存在")
}
defer file.Close()
// 读取每行内容
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
//约定注释为 # 跳过注释和空行
if strings.HasPrefix(line, "#") || line == "" {
continue
}
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
sectionLine := line[1 : len(line)-1]
currentSection = ""
currentSubSection = ""
if sectionSplit := strings.SplitN(sectionLine, " ", 2); len(sectionSplit) == 2 {
currentSection = sectionSplit[0]
currentSubSection = sectionSplit[1]
} else {
currentSection = sectionLine
}
continue
}
if currentSection != "" {
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := parts[0]
value := parts[1]
switch currentSection {
case "core":
confFile.core[key] = value
case "submodule":
if currentSubSection == "" {
confFile.submodule[key] = value
} else {
confFile.submodules[currentSubSection][key] = value
}
case "remote":
if currentSubSection == "" {
panic("conf 文件格式不正确")
}
confFile.remote[currentSubSection][key] = value
case "branch":
if currentSubSection == "" {
panic("conf 文件格式不正确")
}
confFile.branch[currentSubSection][key] = value
}
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return confFile, nil
}
上述内容逻辑很简单,就是读取文件内容,然后解析每行,匹配对应字段.
由于添加内容比较困难,因此采用覆写方式,而不是在文件中 append ,这样比较简单.
func (c *ConfFile) WriteToFile(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
panic("不是一个 git目录,无法写入文件")
}
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
panic("打开文件失败")
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
}
}(file)
// 写入 core
_, err = file.WriteString("[core]\n")
if err != nil {
panic("写入失败")
}
for k, v := range c.core {
_, err := file.WriteString(" " + k + "=" + v + "\n")
if err != nil {
panic("写入失败")
}
}
// 写入 submodule
if c.submodule != nil {
_, err = file.WriteString("[submodule]\n")
if err != nil {
return err
}
for k, v := range c.submodule {
_, err := file.WriteString(" " + k + "=" + v + "\n")
if err != nil {
panic("写入失败")
}
}
}
// 写入 remote
if c.remote != nil {
for k1, v1 := range c.submodules {
_, err := file.WriteString("[remote " + k1 + "]\n")
if err != nil {
return err
}
if v1 == nil {
continue
}
for k2, v2 := range v1 {
_, err := file.WriteString(" " + k2 + "=" + v2 + "\n")
if err != nil {
panic("写入失败")
}
}
}
}
// 写入 branch
if c.branch != nil {
for k1, v1 := range c.branch {
_, err := file.WriteString("[branch " + k1 + "]\n")
if err != nil {
return err
}
if v1 == nil {
continue
}
for k2, v2 := range v1 {
_, err := file.WriteString(" " + k2 + "=" + v2 + "\n")
if err != nil {
panic("写入失败")
}
}
}
}
// 写入 submodules
if c.submodules != nil {
for k1, v1 := range c.branch {
_, err := file.WriteString("[submodules " + k1 + "]\n")
if err != nil {
return err
}
if v1 == nil {
continue
}
for k2, v2 := range v1 {
_, err := file.WriteString(" " + k2 + "=" + v2 + "\n")
if err != nil {
panic("写入失败")
}
}
}
}
return nil
}
上述内容比较简单,具体逻辑不再解释.
上述内容就是简单实现一个功能玩一下.
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。