Skip to content

Commit

Permalink
feat(core): new updater with stable and nightly channels
Browse files Browse the repository at this point in the history
Signed-off-by: Micah Halter <micah@balena.io>
  • Loading branch information
mehalter committed Jun 6, 2022
1 parent 4bcc8bc commit 759bb6f
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 38 deletions.
4 changes: 2 additions & 2 deletions lua/core/autocmds.lua
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ if is_available "feline.nvim" then
})
end

create_command("AstroUpdate", astronvim.update, { desc = "Update AstroNvim" })
create_command("AstroVersion", astronvim.version, { desc = "Check AstroNvim Version" })
create_command("AstroUpdate", astronvim.updater.update, { desc = "Update AstroNvim" })
create_command("AstroVersion", astronvim.updater.version, { desc = "Check AstroNvim Version" })
create_command("ToggleHighlightURL", astronvim.toggle_url_match, { desc = "Toggle URL Highlights" })
7 changes: 7 additions & 0 deletions lua/core/plugins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,13 @@ local astro_plugins = {
},
}

if astronvim.updater.snapshot then
for plugin, options in pairs(astro_plugins) do
local pin = astronvim.updater.snapshot[plugin:match "/([^/]*)$"]
options.commit = pin and pin.commit or options.commit
end
end

local user_plugin_opts = astronvim.user_plugin_opts
local packer = astronvim.initialize_packer()
packer.startup {
Expand Down
86 changes: 86 additions & 0 deletions lua/core/utils/git.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
local git = { url = "https://github.com/" }

function git.cmd(args, ...)
return astronvim.cmd("git -C " .. vim.fn.stdpath "config" .. " " .. args, ...)
end

function git.fetch(remote, ...)
return git.cmd("fetch " .. remote, ...)
end

function git.pull(...)
return git.cmd("pull --rebase", ...)
end

function git.checkout(dest, ...)
return git.cmd("checkout " .. dest, ...)
end

function git.hard_reset(dest, ...)
return git.cmd("reset --hard " .. dest, ...)
end

function git.branch_contains(remote, branch, commit, ...)
return git.cmd("merge-base --is-ancestor " .. commit .. " " .. remote .. "/" .. branch, ...) ~= nil
end

function git.remote_add(remote, url, ...)
return git.cmd("remote add " .. remote .. " " .. url, ...)
end

function git.remote_update(remote, url, ...)
return git.cmd("remote set-url " .. remote .. " " .. url, ...)
end

function git.remote_url(remote, ...)
return astronvim.trim_or_nil(git.cmd("remote get-url " .. remote, ...))
end

function git.current_version(...)
return astronvim.trim_or_nil(git.cmd("describe --tags", ...))
end

function git.current_branch(...)
return astronvim.trim_or_nil(git.cmd("rev-parse --abbrev-ref HEAD", ...))
end

function git.local_head(...)
return astronvim.trim_or_nil(git.cmd("rev-parse HEAD", ...))
end

function git.remote_head(remote, branch, ...)
return astronvim.trim_or_nil(git.cmd("rev-list -n 1 " .. remote .. "/" .. branch, ...))
end

function git.tag_commit(tag, ...)
return astronvim.trim_or_nil(git.cmd("rev-list -n 1 " .. tag, ...))
end

function git.get_commit_range(start_hash, end_hash, ...)
local log = git.cmd("log --no-merges --pretty='format:[%h] %s' " .. start_hash .. ".." .. end_hash, ...)
return log and vim.fn.split(log, "\n") or {}
end

function git.get_versions(search, ...)
local tags = git.cmd("tag -l --sort=version:refname '" .. (search == "latest" and "v*" or search) .. "'", ...)
return tags and vim.fn.split(tags, "\n") or {}
end

function git.latest_version(versions, ...)
versions = versions and versions or git.get_versions(...)
return versions[#versions]
end

function git.parse_remote_url(str)
return vim.fn.match(str, astronvim.url_matcher) == -1
and git.url .. str .. (vim.fn.match(str, "/") == -1 and "/AstroNvim.git" or ".git")
or str
end

function git.breaking_changes(commits)
return vim.tbl_filter(function(v)
return vim.fn.match(v, "\\[.*\\]\\s\\+\\w\\+\\((\\w\\+)\\)\\?!:") ~= -1
end, commits)
end

return git
56 changes: 20 additions & 36 deletions lua/core/utils.lua → lua/core/utils/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ astronvim.user_settings = load_module_file "user.init"
astronvim.default_compile_path = stdpath "config" .. "/lua/packer_compiled.lua"
astronvim.base_notification = { title = "AstroNvim" }
astronvim.user_terminals = {}
astronvim.url_matcher =
"\\v\\c%(%(h?ttps?|ftp|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)%([&:#*@~%_\\-=?!+;/0-9a-z]+%(%([.;/?]|[.][.]+)[&:#*@~%_\\-=?!+/0-9a-z]+|:\\d+|,%(%(%(h?ttps?|ftp|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)@![0-9a-z]+))*|\\([&:#*@~%_\\-=?!+;/.0-9a-z]*\\)|\\[[&:#*@~%_\\-=?!+;/.0-9a-z]*\\]|\\{%([&:#*@~%_\\-=?!+;/.0-9a-z]*|\\{[&:#*@~%_\\-=?!+;/.0-9a-z]*})\\})+"

local function func_or_extend(overrides, default, extend)
if extend then
Expand All @@ -50,6 +52,15 @@ function astronvim.conditional_func(func, condition, ...)
end
end

function astronvim.trim_or_nil(str)
return type(str) == "string" and vim.trim(str) or nil
end

function astronvim.prompt(message, confirm)
print(message)
return string.lower(vim.fn.input "") == (confirm == nil and "y" or confirm)
end

local function user_setting_table(module)
local settings = astronvim.user_settings or {}
for tbl in string.gmatch(module, "([^%.]+)") do
Expand Down Expand Up @@ -231,11 +242,7 @@ end
function astronvim.set_url_match()
astronvim.delete_url_match()
if vim.g.highlighturl_enabled then
vim.fn.matchadd(
"HighlightURL",
"\\v\\c%(%(h?ttps?|ftp|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)%([&:#*@~%_\\-=?!+;/0-9a-z]+%(%([.;/?]|[.][.]+)[&:#*@~%_\\-=?!+/0-9a-z]+|:\\d+|,%(%(%(h?ttps?|ftp|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)@![0-9a-z]+))*|\\([&:#*@~%_\\-=?!+;/.0-9a-z]*\\)|\\[[&:#*@~%_\\-=?!+;/.0-9a-z]*\\]|\\{%([&:#*@~%_\\-=?!+;/.0-9a-z]*|\\{[&:#*@~%_\\-=?!+;/.0-9a-z]*})\\})+",
15
)
vim.fn.matchadd("HighlightURL", astronvim.url_matcher, 15)
end
end

Expand All @@ -244,38 +251,15 @@ function astronvim.toggle_url_match()
astronvim.set_url_match()
end

function astronvim.update()
(require "plenary.job")
:new({
command = "git",
args = { "pull", "--ff-only" },
cwd = stdpath "config",
on_exit = function(_, return_val)
if return_val == 0 then
vim.notify("Updated!", "info", astronvim.base_notification)
else
vim.notify("Update failed! Please try pulling manually.", "error", astronvim.base_notification)
end
end,
})
:sync()
function astronvim.cmd(cmd, show_error)
local result = vim.fn.system(cmd)
local success = vim.api.nvim_get_vvar "shell_error" == 0
if not success and (show_error == nil and true or show_error) then
vim.api.nvim_err_writeln("Error running command: " .. cmd .. "\nError message:\n" .. result)
end
return success and result or nil
end

function astronvim.version()
(require "plenary.job")
:new({
command = "git",
args = { "describe", "--tags" },
cwd = stdpath "config",
on_exit = function(out, return_val)
if return_val == 0 then
vim.notify("Version: " .. out:result()[1], "info", astronvim.base_notification)
else
vim.notify("Error retrieving version", "error", astronvim.base_notification)
end
end,
})
:start()
end
require "core.utils.updater"

return astronvim
127 changes: 127 additions & 0 deletions lua/core/utils/updater.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
local fn = vim.fn
local git = require "core.utils.git"
local options = astronvim.user_plugin_opts(
"updater",
{ remote = "origin", branch = "main", channel = "nightly", pin_plugins = true, show_changelog = true }
)

astronvim.updater = { options = options }
options.pin_plugins = options.pin_plugins == true and options.channel == "stable" and git.current_version() or false
if type(options.pin_plugins) == "string" then
local loaded, snapshot_file = pcall(fn.readfile, fn.stdpath "config" .. "/snapshots/" .. options.pin_plugins)
if loaded then
local _, snapshot = pcall(fn.json_decode, snapshot_file)
astronvim.updater.snapshot = type(snapshot) == "table" and snapshot or nil
end
end

function astronvim.updater.version()
local version = git.current_version()
if version then
vim.notify("Version: " .. version, "info", astronvim.base_notification)
end
end

function astronvim.updater.update()
for remote, entry in pairs(options.remotes and options.remotes or {}) do
local url = git.parse_remote_url(entry)
local current_url = git.remote_url(remote, false)
local check_needed = false
if not current_url then
git.remote_add(remote, url)
check_needed = true
elseif
current_url ~= url
and astronvim.prompt(
"Remote "
.. remote
.. " is currently set to "
.. current_url
.. "\nWould you like us to set it to "
.. url
.. "? (y to continue)"
)
then
git.remote_update(remote, url)
check_needed = true
end
if check_needed and git.remote_url(remote, false) ~= url then
vim.api.nvim_err_writeln("Error setting up remote " .. remote .. " to " .. url)
return
end
end
local is_stable = options.channel == "stable"
options.branch = is_stable and "main" or options.branch
if not git.fetch(options.remote) then
vim.api.nvim_err_writeln("Error fetching remote: " .. options.remote)
end
local local_branch = (options.remote == "origin" and "" or (options.remote .. "_")) .. options.branch
if not git.checkout(local_branch, false) then
git.checkout("-b " .. local_branch .. " " .. options.remote .. "/" .. options.branch, false)
end
if git.current_branch() ~= local_branch then
vim.api.nvim_err_writeln("Error checking out branch: " .. options.remote .. "/" .. options.branch)
return
end
local source = git.local_head() -- calculate current commit
local target -- calculate target commit
if is_stable then -- if stable get tag commit
options.version = git.latest_version(git.get_versions(options.version))
target = git.tag_commit(options.version)
elseif options.commit then -- if commit specified use it
target = git.branch_contains(options.remote, options.branch, options.commit) and options.commit or nil
else -- get most recent commit
target = git.remote_head(options.remote, options.branch)
end
if source and target then -- continue if current and target commits were found
if source == target then
vim.notify("No updates available", "info", astronvim.base_notification)
elseif -- prompt user if they want to accept update
not options.skip_prompts
and not astronvim.prompt("Update available! (y to continue):\n" .. source .. " to " .. target)
then
vim.notify("Update cancelled by user", "info", astronvim.base_notification)
return
else -- perform update
local changelog = git.get_commit_range(source, target)
local breaking = git.breaking_changes(changelog)
if
#breaking > 0
and not options.skip_prompts
and not astronvim.prompt("UPDATE HAS BREAKING CHANGES FOUND (y to continue):\n" .. table.concat(breaking, "\n"))
then
vim.notify("Update cancelled by user", "info", astronvim.base_notification)
return
end
local function attempt_update() -- helper function to attempt an update
if is_stable or options.commit then
return git.checkout(target, false)
else
return git.pull(false)
end
end
local updated = attempt_update()
if
not updated
and not options.skip_prompts
and not astronvim.prompt "Unable to pull due to local modifications, proceeding will reset any changes to internal files (y to continue):\n"
then
vim.notify("Update cancelled by user", "info", astronvim.base_notification)
return
elseif not updated then
git.hard_reset(source)
updated = attempt_update()
end
if not updated then
vim.api.nvim_err_writeln "Error ocurred performing update"
return
end
print(
"AstroNvim updated successfully to "
.. git.current_version()
.. "! Please restart and run PackerSync.\nChangelog:\n"
.. table.concat(changelog, "\n")
)
end
end
end
1 change: 1 addition & 0 deletions snapshots/v1.3.0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"telescope-media-files.nvim": {"commit": "513e4ee"}, "nvim-dap": {"commit": "60ffb68"}, "FixCursorHold.nvim": {"commit": "1bfb32e"}, "telescope-fzf-native.nvim": {"commit": "f0dba7d"}, "packer.nvim": {"commit": "4dedd3b"}, "nvim-notify": {"commit": "c6ca279"}, "nvim-lspconfig": {"commit": "c5dae15"}, "vim-table-mode": {"commit": "f47287d"}, "telescope-hop.nvim": {"commit": "337a1e9"}, "cmp-emoji": {"commit": "19075c3"}, "nvim-lastplace": {"commit": "30fe710"}, "null-ls.nvim": {"commit": "7b8560d"}, "which-key.nvim": {"commit": "bd4411a"}, "telescope-file-browser.nvim": {"commit": "4df59cc"}, "bufferline.nvim": {"commit": "e2b1e99"}, "nvim-autopairs": {"commit": "b9cc0a2"}, "zk-nvim": {"commit": "58fee43"}, "cmp_luasnip": {"commit": "a9de941"}, "friendly-snippets": {"commit": "974d792"}, "neovim-session-manager": {"commit": "f0b0501"}, "nvim-colorizer.lua": {"commit": "36c610a"}, "vim-simple-todo": {"commit": "e2eead5"}, "cmp-pandoc-references": {"commit": "2c808df"}, "gitsigns.nvim": {"commit": "27aeb2e"}, "SchemaStore.nvim": {"commit": "af73c24"}, "nvim-ts-autotag": {"commit": "044a05c"}, "sqls.nvim": {"commit": "6592b0c"}, "telescope.nvim": {"commit": "ad19bf6"}, "telescope-project.nvim": {"commit": "4658d78"}, "headlines.nvim": {"commit": "347ef03"}, "nvim-ts-context-commentstring": {"commit": "8834375"}, "nvim-toggleterm.lua": {"commit": "93c2f2c"}, "mini.nvim": {"commit": "2e209f3"}, "vim-wakatime": {"commit": "f86ca61"}, "nvim-treesitter-textobjects": {"commit": "b1e850b"}, "cmp-nvim-lsp": {"commit": "affe808"}, "LuaSnip": {"commit": "52f4aed"}, "neo-tree.nvim": {"commit": "a917174"}, "nvim-dap-ui": {"commit": "e5c3274"}, "popup.nvim": {"commit": "b7404d3"}, "nvim-web-devicons": {"commit": "8d2c533"}, "zen-mode.nvim": {"commit": "f1cc53d"}, "nvim-treesitter": {"commit": "889e901"}, "nui.nvim": {"commit": "abdbfab"}, "impatient.nvim": {"commit": "bcc2250"}, "feline.nvim": {"commit": "1ea4267"}, "hop.nvim": {"commit": "75f73d3"}, "neogen": {"commit": "a4b2fd5"}, "nabla.nvim": {"commit": "8d499bd"}, "nvim-lsp-installer": {"commit": "0d61e14"}, "nightfox.nvim": {"commit": "e602aca"}, "syntax-tree-surfer": {"commit": "2fe8d72"}, "indent-o-matic": {"commit": "0eff7e8"}, "cmp-calc": {"commit": "f7efc20"}, "smart-splits.nvim": {"commit": "8841720"}, "plenary.nvim": {"commit": "54b2e3d"}, "nvim-cmp": {"commit": "033a817"}, "aerial.nvim": {"commit": "ece90c4"}, "nvim-send-to-term": {"commit": "e0aa448"}, "telescope-bibtex.nvim": {"commit": "cd2640e"}, "cmp-latex-symbols": {"commit": "29dc9e5"}, "nvim-ts-rainbow": {"commit": "18cb3a4"}, "cmp-path": {"commit": "466b6b8"}, "cmp-buffer": {"commit": "12463cf"}}

0 comments on commit 759bb6f

Please sign in to comment.