Go 语言解析 git config
source link: http://www.worldhello.net/2019/03/17/goconfig.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
最近做的一个 go 语言的项目需要频繁读写 git config 文件,一些看似现成的解决方案并不能满足需要:
git config libgit2
在 github 上找到一个能够解析 git config 文件的项目 goconfig ,该项目的代码直接从 Git 项目的 git/config.c 移植过来,可以确保兼容性。但是这个项目只是一个半成品,因为:
-
不支持多值配置项。Git 的很多设置实际上是多值配置项,例如:
push.pushOption
、remote.<name>.fetch
等。 -
不支持配置文件嵌套,即不支持通过
include.path
指令包含其他配置文件,而这在我们要开发的应用中至关重要。 -
不支持配置文件继承(多级配置)。Git 在读取一个配置项时,会依次读取系统级配置(
/etc/gitconfig
)、用户全局配置($HOME/.gitconfig
)、仓库级配置文件(.git/config
)、嵌套的配置文件(include.path
指向的配置文件)。从优先级上看,仓库级配置文件高于全局配置,更高于系统级配置。 - 不支持写配置文件。
于是派生了一个项目到 jiangxin/goconfig ,实现了上述特性。
增加多值配置特性
实际上 Git 配置项,无论单值(如 user.name
),还是多值(如 remote.<name>.fetch
),都应该一视同仁当做多值来处理,这样配置文件嵌套、配置文件继承的处理就非常简单了。即:
user.name
为此将 goconfig.go
的返回值由 map[string]string
替换为支持多值配置的自定义类型
type GitConfig map[string]GitConfigKeys type GitConfigKeys map[string][]string
其中 GitConfig 的索引对应 config 配置文件的小节(section)名称,GitConfigKeys 的索引对应于配置项在小节内的 key。
GitConfig 最核心的方法是 GetAll
,其他方法 Get
, GetBool
, GetInt
等都是基于 GetAll
方法。
参见提交 9e83c31 (Add GitConfig to read boolean, int, multi-values, 2019-02-28) 。
增加配置文件嵌套特性
配置文件嵌套,涉及到迭代和配置文件的合并。核心方法是 GitConfig 的 Merge
方法。
参见提交 83a00ae (Parse include config files from include.path, 2019-03-05) 。
增加配置文件继承
配置文件继承和配置文件嵌套非常相似,都是 GitConfig 结构体的 Merge,只不过多了一些文件 IO,以及缓存机制。
参见提交 a033f72 (Add Load() function to read git config from disk, 2019-03-04)
增加配置文件写操作
实际上第一个版本的 GitConfig 结构体定义为 map[string][]string
,就可以实现多值配置。为了支持将 GitConfig 结构体回写为文件,对其做了提交修补(git commit –amend)操作。
GitConfig 的 map 索引变成了小节(section)名称。
为了支持写操作所做的第二个改变是为每一个值增加了一个范围(scope),这样在保存 GitConfig 到文件的时候,知道哪些配置来自于系统级(ScopeSystem)、全局级(ScopeGlobal)、 文件嵌套(ScopeGlobal),只将配置文件中的 ScopeSelf 记录到配置文件中。
参见提交:
- 784eaa8 (Mark values with scope, such as system, global, self, 2019-03-09)
- feb3e92 (String() of GitConfig is ready for saving file, 2019-03-11)
- b826f49 (Save GitConfig to file using Save(), 2019-03-11)
一个简单的 git-config 实现
作为一个 lib,goconfig 项目的根目录是名为 goconfig
的包,为了演示如何用 goconfig
实现一个完整的 git config
命令的功能,在 cmd/gocongig
目录下写了一个 main
包。
可以用如下命令编译安装这一 goconfig
示例:
go get github.com/jiangxin/goconfig/cmd/goconfig
示例代码参见: cmd/goconfig/main.go 。
欢迎使用 goconfig 并帮助改进
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK