verify_plugins.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. local completed = 0
  2. local collection = {}
  3. local active_jobs = {}
  4. local fmt = string.format
  5. local core_plugins = require "lvim.plugins"
  6. local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json")
  7. local fd = io.open(default_snapshot_path, "rb")
  8. local content
  9. if fd then
  10. content = fd:read "*a"
  11. end
  12. local default_sha1 = vim.json.decode(content)
  13. local get_short_name = function(spec)
  14. return spec[1]:match "/(%S*)"
  15. end
  16. local get_default_sha1 = function(spec)
  17. local short_name, _ = get_short_name(spec)
  18. assert(default_sha1[short_name])
  19. return default_sha1[short_name].commit
  20. end
  21. local is_directory = require("lvim.utils").is_directory
  22. -- see packer.init()
  23. local packdir = join_paths(get_runtime_dir(), "site", "pack", "packer")
  24. local verify_packer = function()
  25. if not is_directory(packdir) then
  26. io.write "Packer not installed!"
  27. os.exit(1)
  28. end
  29. local status_ok, packer = pcall(require, "packer")
  30. if status_ok and packer then
  31. return
  32. end
  33. io.write "Packer not installed!"
  34. os.exit(1)
  35. end
  36. local packer_config = { opt_dir = join_paths(packdir, "opt"), start_dir = join_paths(packdir, "start") }
  37. local is_optional = function(spec)
  38. return spec.opt or spec.event or spec.cmd or spec.module
  39. end
  40. local get_install_path = function(spec)
  41. local prefix = is_optional(spec) and packer_config.opt_dir or packer_config.start_dir
  42. local path = join_paths(prefix, get_short_name(spec))
  43. return is_directory(path) and path
  44. end
  45. local function call_proc(process, opts, cb)
  46. local output, error_output = "", ""
  47. local handle_stdout = function(err, chunk)
  48. assert(not err, err)
  49. if chunk then
  50. output = output .. chunk
  51. end
  52. end
  53. local handle_stderr = function(err, chunk)
  54. assert(not err, err)
  55. if chunk then
  56. error_output = error_output .. chunk
  57. end
  58. end
  59. local uv = vim.loop
  60. local handle
  61. local stdout = uv.new_pipe(false)
  62. local stderr = uv.new_pipe(false)
  63. local stdio = { nil, stdout, stderr }
  64. handle = uv.spawn(
  65. process,
  66. { args = opts.args, cwd = opts.cwd or uv.cwd(), stdio = stdio },
  67. vim.schedule_wrap(function(code)
  68. if code ~= 0 then
  69. stdout:read_stop()
  70. stderr:read_stop()
  71. end
  72. local check = uv.new_check()
  73. check:start(function()
  74. for _, pipe in ipairs(stdio) do
  75. if pipe and not pipe:is_closing() then
  76. return
  77. end
  78. end
  79. check:stop()
  80. handle:close()
  81. cb(code, output, error_output)
  82. end)
  83. end)
  84. )
  85. uv.read_start(stdout, handle_stdout)
  86. uv.read_start(stderr, handle_stderr)
  87. return handle
  88. end
  89. local function verify_core_plugins(verbose)
  90. for _, spec in pairs(core_plugins) do
  91. local path = get_install_path(spec)
  92. if not spec.disable and path then
  93. table.insert(collection, {
  94. name = get_short_name(spec),
  95. commit = get_default_sha1(spec),
  96. path = path,
  97. })
  98. end
  99. end
  100. for _, entry in pairs(collection) do
  101. local on_done = function(code, result, errors)
  102. completed = completed + 1
  103. if code ~= 0 then
  104. io.write(errors .. "\n")
  105. -- os.exit(code)
  106. else
  107. if verbose then
  108. io.write(fmt("verified [%s]\n", entry.name))
  109. end
  110. end
  111. local current_commit = result:gsub("\n", ""):gsub([[']], [[]]):sub(1, 7)
  112. -- just in case there are some extra qutoes or it's a longer commit hash
  113. if current_commit ~= entry.commit then
  114. io.write(fmt("mismatch at [%s]: expected [%s], got [%s]\n", entry.name, entry.commit, current_commit))
  115. os.exit(1)
  116. end
  117. end
  118. local handle = call_proc("git", { args = { "rev-parse", "--short", "HEAD" }, cwd = entry.path }, on_done)
  119. assert(handle)
  120. table.insert(active_jobs, handle)
  121. end
  122. vim.wait(#active_jobs * 60 * 1000, function()
  123. return completed == #active_jobs
  124. end)
  125. end
  126. verify_packer()
  127. verify_core_plugins()
  128. vim.cmd "q"