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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
local async = require('blink.cmp.lib.async')
local utils = require('blink.cmp.lib.utils')
local system = require('blink.cmp.fuzzy.download.system')
local function get_lib_extension()
if jit.os:lower() == 'mac' or jit.os:lower() == 'osx' then return '.dylib' end
if jit.os:lower() == 'windows' then return '.dll' end
return '.so'
end
local current_file_dir = debug.getinfo(1).source:match('@?(.*/)')
local current_file_dir_parts = vim.split(current_file_dir, '/')
local root_dir = table.concat(utils.slice(current_file_dir_parts, 1, #current_file_dir_parts - 6), '/')
local lib_folder = root_dir .. '/target/release'
local lib_filename = 'libblink_cmp_fuzzy' .. get_lib_extension()
local lib_path = lib_folder .. '/' .. lib_filename
local checksum_filename = lib_filename .. '.sha256'
local checksum_path = lib_path .. '.sha256'
local version_path = lib_folder .. '/version'
local files = {
get_lib_extension = get_lib_extension,
root_dir = root_dir,
lib_folder = lib_folder,
lib_filename = lib_filename,
lib_path = lib_path,
checksum_path = checksum_path,
checksum_filename = checksum_filename,
version_path = version_path,
}
--- Checksums ---
function files.get_checksum()
return files.read_file(files.checksum_path):map(function(checksum) return vim.split(checksum, ' ')[1] end)
end
function files.get_checksum_for_file(path)
return async.task.new(function(resolve, reject)
local os = system.get_info()
local args
if os == 'linux' then
args = { 'sha256sum', path }
elseif os == 'mac' or os == 'osx' then
args = { 'shasum', '-a', '256', path }
elseif os == 'windows' then
args = { 'certutil', '-hashfile', path, 'SHA256' }
end
vim.system(args, {}, function(out)
if out.code ~= 0 then return reject('Failed to calculate checksum of pre-built binary: ' .. out.stderr) end
local stdout = out.stdout or ''
if os == 'windows' then stdout = vim.split(stdout, '\r\n')[2] end
-- We get an output like 'sha256sum filename' on most systems, so we grab just the checksum
return resolve(vim.split(stdout, ' ')[1])
end)
end)
end
function files.verify_checksum()
return async.task
.await_all({ files.get_checksum(), files.get_checksum_for_file(files.lib_path) })
:map(function(checksums)
assert(#checksums == 2, 'Expected 2 checksums, got ' .. #checksums)
assert(checksums[1] and checksums[2], 'Expected checksums to be non-nil')
assert(
checksums[1] == checksums[2],
'Checksum of pre-built binary does not match. Expected "' .. checksums[1] .. '", got "' .. checksums[2] .. '"'
)
end)
end
--- Prebuilt binary ---
function files.get_version()
return files
.read_file(files.version_path)
:map(function(version)
if #version == 40 then
return { sha = version }
else
return { tag = version }
end
end)
:catch(function() return {} end)
end
--- @param version string
--- @return blink.cmp.Task
function files.set_version(version)
return files
.create_dir(files.root_dir .. '/target')
:map(function() return files.create_dir(files.lib_folder) end)
:map(function() return files.write_file(files.version_path, version) end)
end
--- Filesystem helpers ---
--- @param path string
--- @return blink.cmp.Task
function files.read_file(path)
return async.task.new(function(resolve, reject)
vim.uv.fs_open(path, 'r', 438, function(open_err, fd)
if open_err or fd == nil then return reject(open_err or 'Unknown error') end
vim.uv.fs_read(fd, 1024, 0, function(read_err, data)
vim.uv.fs_close(fd, function() end)
if read_err or data == nil then return reject(read_err or 'Unknown error') end
return resolve(data)
end)
end)
end)
end
--- @param path string
--- @param data string
--- @return blink.cmp.Task
function files.write_file(path, data)
return async.task.new(function(resolve, reject)
vim.uv.fs_open(path, 'w', 438, function(open_err, fd)
if open_err or fd == nil then return reject(open_err or 'Unknown error') end
vim.uv.fs_write(fd, data, 0, function(write_err)
vim.uv.fs_close(fd, function() end)
if write_err then return reject(write_err) end
return resolve()
end)
end)
end)
end
--- @param path string
--- @return blink.cmp.Task
function files.exists(path)
return async.task.new(function(resolve)
vim.uv.fs_stat(path, function(err) resolve(not err) end)
end)
end
--- @param path string
--- @return blink.cmp.Task
function files.stat(path)
return async.task.new(function(resolve, reject)
vim.uv.fs_stat(path, function(err, stat)
if err then return reject(err) end
resolve(stat)
end)
end)
end
--- @param path string
--- @return blink.cmp.Task
function files.create_dir(path)
return files
.stat(path)
:map(function(stat) return stat.type == 'directory' end)
:catch(function() return false end)
:map(function(exists)
if exists then return end
return async.task.new(function(resolve, reject)
vim.uv.fs_mkdir(path, 511, function(err)
if err then return reject(err) end
resolve()
end)
end)
end)
end
--- Renames a file
--- @param old_path string
--- @param new_path string
function files.rename(old_path, new_path)
return async.task.new(function(resolve, reject)
vim.uv.fs_rename(old_path, new_path, function(err)
if err then return reject(err) end
resolve()
end)
end)
end
return files
|