summaryrefslogtreecommitdiff
path: root/lua/lvim/utils/git.lua
blob: 73ba7c9611d75c3e05d0b20384f6b4560ac1abe8 (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
local M = {}

local Log = require "lvim.core.log"

local function git_cmd(opts)
  local plenary_loaded, Job = pcall(require, "plenary.job")
  if not plenary_loaded then
    vim.cmd "packadd plenary.nvim"
  end

  opts = opts or {}
  opts.cwd = opts.cwd or get_lvim_base_dir()

  local stderr = {}
  local stdout, ret = Job
    :new({
      command = "git",
      args = opts.args,
      cwd = opts.cwd,
      on_stderr = function(_, data)
        table.insert(stderr, data)
      end,
    })
    :sync()

  if not vim.tbl_isempty(stderr) then
    Log:debug(stderr)
  end

  if not vim.tbl_isempty(stdout) then
    Log:debug(stdout)
  end

  return ret, stdout
end

local function safe_deep_fetch()
  local ret, result = git_cmd { args = { "rev-parse", "--is-shallow-repository" } }
  if ret ~= 0 then
    Log:error "Git fetch failed! Check the log for further information"
    return
  end
  -- git fetch --unshallow will cause an error on a a complete clone
  local fetch_mode = result[1] == "true" and "--unshallow" or "--all"
  ret = git_cmd { args = { "fetch", fetch_mode } }
  if ret ~= 0 then
    Log:error "Git fetch failed! Check the log for further information"
    return
  end
  return true
end

---pulls the latest changes from github
function M.update_base_lvim()
  Log:info "Checking for updates"

  local ret = git_cmd { args = { "fetch" } }
  if ret ~= 0 then
    Log:error "Update failed! Check the log for further information"
    return
  end

  ret = git_cmd { args = { "diff", "--quiet", "@{upstream}" } }
  if ret == 0 then
    Log:info "LunarVim is already up-to-date"
    return
  end

  ret = git_cmd { args = { "merge", "--ff-only", "--progress" } }
  if ret ~= 0 then
    Log:error "Update failed! Please pull the changes manually instead."
    return
  end
end

---Switch Lunarvim to the specified development branch
---@param branch string
function M.switch_lvim_branch(branch)
  if not safe_deep_fetch() then
    return
  end
  local ret = git_cmd { args = { "switch", branch } }
  if ret ~= 0 then
    Log:error "Unable to switch branches! Check the log for further information"
    return
  end
end

---Get the current Lunarvim development branch
---@return string|nil
function M.get_lvim_branch()
  local ret, branch = git_cmd { args = { "branch", "--show-current" } }
  if ret ~= 0 or (not branch or branch[1] == "") then
    Log:error "Unable to retrieve the name of the current branch. Check the log for further information"
    return
  end
  return branch[1]
end

---Get currently checked-out tag of Lunarvim
---@param type string can be "short"
---@return string|nil
function M.get_lvim_tag(type)
  type = type or ""
  local ret, results = git_cmd { args = { "describe", "--tags" } }
  local lvim_full_ver = results[1] or ""

  if ret ~= 0 or string.match(lvim_full_ver, "%d") == nil then
    Log:error "Unable to retrieve current tag. Check the log for further information"
    return nil
  end
  if type == "short" then
    return vim.fn.split(lvim_full_ver, "-")[1]
  else
    return string.sub(lvim_full_ver, 1, #lvim_full_ver - 1)
  end
end

---Get the commit hash of currently checked-out commit of Lunarvim
---@param type string can be "short"
---@return string|nil
function M.get_lvim_version(type)
  type = type or ""
  local branch = M.get_lvim_branch()
  if branch == "master" then
    return M.get_lvim_tag(type)
  end
  local ret, log_results = git_cmd { args = { "log", "--pretty=format:%h", "-1" } }
  local abbrev_version = log_results[1] or ""
  if ret ~= 0 or string.match(abbrev_version, "%d") == nil then
    Log:error "Unable to retrieve current version. Check the log for further information"
    return nil
  end
  if type == "short" then
    return abbrev_version
  end
  return branch .. "-" .. abbrev_version
end

function M.generate_plugins_sha(output)
  local list = {}
  output = output or "commits.lua"

  local core_plugins = require "lvim.plugins"
  for _, plugin in pairs(core_plugins) do
    local name = plugin[1]:match "/(%S*)"
    local url = "https://github.com/" .. plugin[1]
    print("checking: " .. name .. ", at: " .. url)
    local retval, latest_sha = git_cmd { args = { "ls-remote", url, "origin", "HEAD" } }
    if retval == 0 then
      -- replace dashes, remove postfixes and use lowercase
      local normalize_name = (name:gsub("-", "_"):gsub("%.%S+", "")):lower()
      list[normalize_name] = latest_sha[1]:gsub("\tHEAD", "")
    end
  end
  require("lvim.utils").write_file(output, "local commit = " .. vim.inspect(list), "w")
end
return M