summaryrefslogtreecommitdiff
path: root/mut/neovim/pack/plugins/start/blink.cmp/lua/blink/cmp/fuzzy/download/files.lua
blob: 28bbac5902a840e966fd12e265d7d94d6168f97d (plain)
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