我已经到了需要将文件内容的压缩哈希值存储到树中以写入磁盘的部分,但是我在执行 Git 正在寻找的这种十六进制压缩/打包时遇到了麻烦。
这是我正在使用的 Ruby 代码
ENTRY_FORMAT = "A7Z*H40"
MODE = "100644"
FILE_NAME = "tree.rb"
SHA = "baae99010b237a699ff0aba02fd5310c18903b1b"
[MODE, FILE_NAME , SHA].pack(ENTRY_FORMAT)
显然是 Ruby pack 方法:
Array#pack 方法采用各种值的数组并返回表示这些值的字符串。每个值在字符串中的确切表示方式由我们传递给 pack 的格式字符串决定。
的编码,MODE
我FILE_NAME
认为我很擅长。这是编码我正在努力处理的 sha 的最后一部分。
• H40:通过将每对数字打包成一个字节来编码一个包含四十个十六进制数字的字符串 entry.oid
这是“将每对数字打包成一个字节,我无法理解。这是我目前的尝试:
mode := 100644
fileName := "tree.go"
sha:= "baae99010b237a699ff0aba02fd5310c18903b1b"
// slice of strings for constructing the packed sha
var eid []string
// iterate through each character in id
for i := 0; i < len(sha); i += 2 {
// gathering them in pairs of two
one, two := sha[i], sha[i+1]
// compress two digits into one byte
// using bitwise or?? addition?? bit shifting?? not sure.
eid = append(eid, string(one|two))
}
// concat the new packed id with the mode and file name.
stringRep := fmt.Sprintf("%-7d", mode) + fileName + "\x00" + strings.Join(eid, "")
因此,由于某种我无法弄清楚的原因,函数生成的树条目的字符串表示与 Git 在磁盘上存储树的方式不兼容。我试过在or
读取它们之前移动这些位,我试过将字节加在一起,但似乎没有任何效果。我基本上需要Array#pack
以 Git 接受的方式复制 Ruby 方法的行为。
非常感谢任何指导或建议。如有必要,我很乐意解释更多或发布更多代码示例。非常感谢您的参与!
PS 更多关于打包 git 执行的上下文,来自 Building Git
Git 以压缩格式存储每个条目的 ID,每个条目使用 20 个字节。每个十六进制数字代表一个从零到十五的数字,其中十用 a 表示,十一用 b 等等,直到 f 表示十五。在一个四十位的对象 ID 中,每个数字代表一个 160 位数字中的四位。我们可以将其分成二十个八位块,而不是将这些位分成四十块,每块四位——八位是一个字节。所以这里发生的一切就是 160 位对象 ID 以二进制形式存储为 20 个字节,而不是代表十六进制数字的 40 个字符。
一只名叫tom的猫
相关分类