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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
#!/usr/bin/env -S nvim -l
-- Usage:
-- ./scripts/bump_deps.lua -h
assert(vim.fn.executable('gh') == 1)
assert(vim.fn.executable('sed') == 1)
local required_branch_prefix = 'bump-'
local commit_prefix = 'build(deps): '
local repos = {
'luajit/luajit',
'libuv/libuv',
'luvit/luv',
'neovim/unibilium',
'juliastrings/utf8proc',
'tree-sitter/tree-sitter',
'tree-sitter/tree-sitter-c',
'tree-sitter-grammars/tree-sitter-lua',
'tree-sitter-grammars/tree-sitter-vim',
'neovim/tree-sitter-vimdoc',
'tree-sitter-grammars/tree-sitter-query',
'tree-sitter-grammars/tree-sitter-markdown',
'bytecodealliance/wasmtime',
'uncrustify/uncrustify',
}
local dependency_table = {} --- @type table<string, string>
for _, repo in pairs(repos) do
dependency_table[vim.fs.basename(repo)] = repo
end
local function die(msg)
print(msg)
vim.cmd('cquit 1')
end
-- Executes and returns the output of `cmd`, or nil on failure.
-- if die_on_fail is true, process dies with die_msg on failure
local function _run(cmd, die_on_fail, die_msg)
local rv = vim.system(cmd):wait()
if rv.code ~= 0 then
if die_on_fail then
die(die_msg)
end
return nil
end
return vim.trim(rv.stdout)
end
-- Run a command, return nil on failure
local function run(cmd)
return _run(cmd, false, '')
end
-- Run a command, die on failure with err_msg
local function run_die(cmd, err_msg)
return _run(cmd, true, err_msg)
end
local nvim_src_dir = run({ 'git', 'rev-parse', '--show-toplevel' })
local deps_file = nvim_src_dir .. '/' .. 'cmake.deps/deps.txt'
--- @param repo string
--- @param ref string
local function get_archive_info(repo, ref)
local temp_dir = os.getenv('TMPDIR') or os.getenv('TEMP')
local archive_name = ref .. '.tar.gz'
local archive_path = temp_dir .. '/' .. archive_name
local archive_url = 'https://github.com/' .. repo .. '/archive/' .. archive_name
run_die(
{ 'curl', '-sfL', archive_url, '-o', archive_path },
'Failed to download archive from GitHub'
)
local shacmd = (
vim.fn.executable('sha256sum') == 1 and { 'sha256sum', archive_path }
or { 'shasum', '-a', '256', archive_path }
)
local archive_sha = run(shacmd):gmatch('%w+')()
return { url = archive_url, sha = archive_sha }
end
local function get_gh_commit_sha(repo, ref)
local full_repo = string.format('https://github.com/%s.git', repo)
local tag_exists = run_die({ 'git', 'ls-remote', full_repo, 'refs/tags/' .. ref }) ~= ''
-- We'd rather use the git tag over commit sha if possible
if tag_exists then
return ref
end
local sha = assert(
run_die(
{ 'gh', 'api', 'repos/' .. repo .. '/commits/' .. ref, '--jq', '.sha' },
'Failed to get commit hash from GitHub. Not a valid ref?'
)
)
return sha
end
local function update_deps_file(symbol, kind, value)
run_die({
'sed',
'-i',
'-e',
's/' .. symbol .. '_' .. kind .. '.*$' .. '/' .. symbol .. '_' .. kind .. ' ' .. value .. '/',
deps_file,
}, 'Failed to write ' .. deps_file)
end
local function ref(name, _ref)
local repo = dependency_table[name]
local symbol = string.gsub(name, 'tree%-sitter', 'treesitter'):gsub('%-', '_'):upper()
run_die(
{ 'git', 'diff', '--quiet', 'HEAD', '--', deps_file },
deps_file .. ' has uncommitted changes'
)
_ref = get_gh_commit_sha(repo, _ref)
local archive = get_archive_info(repo, _ref)
local comment = string.sub(_ref, 1, 9)
local checked_out_branch = assert(run({ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' }))
if not checked_out_branch:match('^' .. required_branch_prefix) then
print(
"Current branch '"
.. checked_out_branch
.. "' doesn't seem to start with "
.. required_branch_prefix
)
print('Checking out to bump-' .. name)
run_die({ 'git', 'checkout', '-b', 'bump-' .. name }, 'git failed to create branch')
end
print('Updating ' .. name .. ' to ' .. archive.url .. '\n')
update_deps_file(symbol, 'URL', archive.url:gsub('/', '\\/'))
update_deps_file(symbol, 'SHA256', archive.sha)
run_die({
'git',
'commit',
deps_file,
'-m',
commit_prefix .. 'bump ' .. name .. ' to ' .. comment,
}, 'git failed to commit')
end
local function usage()
local this_script = tostring(vim.fs.basename(_G.arg[0]))
local script_exe = './' .. this_script
local help = ([=[
Bump Nvim dependencies
Usage: %s [options]
Bump to HEAD, tagged version or commit:
%s luv --head
%s luv --ref 1.43.0-0
%s luv --ref abc123
Options:
-h, --help show this message and exit.
--list list all dependencies
Dependency Options:
--ref <ref> bump to a specific commit or tag.
--head bump to a current head.
]=]):format(script_exe, script_exe, script_exe, script_exe)
print(help)
end
local function list_deps()
local l = 'Dependencies:\n'
for k in vim.spairs(dependency_table) do
l = string.format('%s\n%s%s', l, string.rep(' ', 2), k)
end
print(l)
end
do
local args = {}
local i = 1
while i <= #_G.arg do
if _G.arg[i] == '-h' or _G.arg[i] == '--help' then
args.h = true
elseif _G.arg[i] == '--list' then
args.list = true
elseif _G.arg[i] == '--ref' then
args.ref = _G.arg[i + 1]
i = i + 1
elseif _G.arg[i] == '--head' then
args.ref = 'HEAD'
elseif vim.startswith(_G.arg[i], '--') then
die(string.format('Invalid argument %s\n', _G.arg[i]))
else
args.dep = _G.arg[i]
end
i = i + 1
end
if args.h then
usage()
elseif args.list then
list_deps()
elseif args.ref then
ref(args.dep, args.ref)
else
die('missing required arg\n')
end
end
|