在 git 仓库中经常会看到大家存放二进制文件,但这样会存在两个问题:
- 二进制文件是分平台的,不同的平台下会使用不同的二进制文件。
- 二进制文件会增加 git 仓库的体积。
看到了 facebook 的一个开源项目 datslash,用来解决 git 仓库中存放二进制文件的问题。
安装
在 mac 上执行如下操作:
1
| curl -LSfs https://github.com/facebook/dotslash/releases/latest/download/dotslash-macos.tar.gz | tar fxz - -C /usr/local/bin/dotslash
|
执行 dotslash --version 验证是否安装成功。
功能演示
cloudx 项目中存在一个二进制文件 build/rclone,在构建镜像时会将将该二进制文件 copy 到容器镜像中,以该文件来进行演示。
步骤 1:创建支持上传的 HTTP 服务器
打开一个新的终端窗口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| mkdir /tmp/dotslash-server
cd /tmp/dotslash-server
# 创建支持 PUT 上传的 HTTP 服务器脚本
cat > server.py << 'EOF'
import http.server
import os
class UploadHandler(http.server.SimpleHTTPRequestHandler):
def do_PUT(self):
path = self.translate_path(self.path)
length = int(self.headers['Content-Length'])
with open(path, 'wb') as f:
f.write(self.rfile.read(length))
self.send_response(201)
self.end_headers()
if __name__ == '__main__':
server = http.server.HTTPServer(('', 18000), UploadHandler)
print('Server running on http://localhost:18000')
print('Upload with: curl -T <file> http://localhost:18000/<filename>')
server.serve_forever()
EOF
# 启动服务器
python3 server.py
|
步骤 2:创建 artifacts 目录并打包 rclone
1
2
3
4
5
6
7
| cd ~/git/cloudx/cloudx/build
# 将 rclone 打包为 tar.gz
tar -czvf rclone-linux-amd64.tar.gz rclone
# 使用 curl 上传到文件服务器
curl -T rclone-linux-amd64.tar.gz http://localhost:18000/rclone-linux-amd64.tar.gz
|
步骤 3:计算文件大小和 hash
1
2
3
4
5
| # 获取文件大小(字节)
stat -f%z rclone-linux-amd64.tar.gz
# 计算 BLAKE3 hash
dotslash -- b3sum rclone-linux-amd64.tar.gz
|
记录输出的 size 和 digest 值。
步骤 4:备份原 rclone 并创建 DotSlash 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| cd ~/git/cloudx/cloudx/build
# 备份原二进制文件
rm rclone
# 创建 DotSlash 文件(将 <SIZE> 和 <DIGEST> 替换为步骤 3 获取的值)
cat > rclone << 'EOF'
#!/usr/bin/env dotslash
{
"name": "rclone",
"platforms": {
"macos-x86_64": {
"size": 20717235,
"hash": "blake3",
"digest": "9e97c4cfdbadb16faae7cbc09754e116e1aa247effcff03d7bb6aac327432bf6",
"format": "tar.gz",
"path": "rclone",
"providers": [
{
"url": "http://localhost:18000/rclone-linux-amd64.tar.gz"
}
]
},
"macos-aarch64": {
"size": 20717235,
"hash": "blake3",
"digest": "9e97c4cfdbadb16faae7cbc09754e116e1aa247effcff03d7bb6aac327432bf6",
"format": "tar.gz",
"path": "rclone",
"providers": [
{
"url": "http://localhost:18000/rclone-linux-amd64.tar.gz"
}
]
}
}
}
EOF
# 添加可执行权限
chmod +x rclone
|
步骤 5:验证 DotSlash 文件
1
2
3
4
5
6
7
| cd ~/git/cloudx/cloudx/build
# 运行 DotSlash 文件(首次会从 HTTP 服务器下载)
./rclone version
# 查看 DotSlash 缓存目录
dotslash -- cache-dir
# 再次运行(使用缓存)
./rclone version
|
实现分析
dotslash 会将文件缓存在 dotslash -- cache-dir 对应的路径上,目录结构如下:
1
2
3
4
5
6
7
8
9
10
11
| # tree /Users/kuring/Library/Caches/dotslash
/Users/kuring/Library/Caches/dotslash
├── 2b
│ └── a8aa2c317454319085d18e1d9831031dab48bf
│ └── rclone
└── locks
└── 2b
└── a8aa2c317454319085d18e1d9831031dab48bf
# ll /Users/kuring/Library/Caches/dotslash/2b/a8aa2c317454319085d18e1d9831031dab48bf/rclone
-r-xr-xr-x@ 1 kuring staff 58M Jan 26 12:27 /Users/kuring/Library/Caches/dotslash/2b/a8aa2c317454319085d18e1d9831031dab48bf/rclone
|
整体实现比较简单,代码行数:

dotslash 的局限性:
- dotslash 仅能针对代码仓库中的可执行文件来做替换,且必须是可执行文件执行的时候,对于代码仓库中非可执行文件无法处理。因为 dotslash 替换替换文件的时机是发生在执行可执行文件的时候。