如何在 Go 中进行适当的 Git 兼容的 hex sha 打包/压缩

我已经到了需要将文件内容的压缩哈希值存储到树中以写入磁盘的部分,但是我在执行 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 的格式字符串决定。

的编码,MODEFILE_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 位数字中的四位。我们可以将其分成二十个八位块,而不是将这些位分成四十块,每块四位&mdash;&mdash;八位是一个字节。所以这里发生的一切就是 160 位对象 ID 以二进制形式存储为 20 个字节,而不是代表十六进制数字的 40 个字符。


MM们
浏览 130回答 1
1回答

一只名叫tom的猫

hex在包中可以找到二进制和十六进制字符串之间转换的函数。例如:将输入的十六进制字符串转换为字节数组(其中每个字节包含两个初始十六进制字符串数字)的函数是 --hex.DecodeString或者hex.Decode如果您的输入是 a[]byte而不是string.如果你想重新实现这个功能:输入字符串的每个字符都应转换为其数值,每对值都应被视为 base 16 中的数字:var newByte byte = 16*one + two
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go