Skip to content

Commit e7538b5

Browse files
fix(deps): respect special GIT_xxx env vars that affecting Git actions
Details: - Environment variables `GIT_DIR` and `GIT_WORK_TREE` can affect any Git operation that is meant to be done inside specific Git repo. They need to be manually handled in 'mini.deps' for any Git action it want to do. Resolve #1968 Co-authored-by: Diego Velez <diego.velez.dev@gmail.com>
1 parent ddb70da commit e7538b5

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

lua/mini/deps.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,12 @@ H.cli_run = function(jobs)
14891489
-- Prepare data for `vim.loop.spawn`
14901490
local executable, args = command[1], vim.list_slice(command, 2, #command)
14911491
local process, stdout, stderr = nil, vim.loop.new_pipe(), vim.loop.new_pipe()
1492-
local spawn_opts = { args = args, cwd = cwd, stdio = { nil, stdout, stderr } }
1492+
1493+
-- - Unset special `GIT_xxx` variables that can affect `git` commands
1494+
local env = vim.fn.environ()
1495+
env.GIT_DIR, env.GIT_WORK_TREE = nil, nil
1496+
1497+
local spawn_opts = { args = args, cwd = cwd, env = env, clear_env = true, stdio = { nil, stdout, stderr } }
14931498

14941499
local on_exit = function(code)
14951500
-- Process only not already closing job

tests/test_deps.lua

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ local mock_timestamp = function(timestamp)
8585
child.lua(lua_cmd)
8686
end
8787

88+
local mock_bad_env_vars = function()
89+
child.fn.setenv('GIT_DIR', test_dir_absolute .. '/.git')
90+
child.fn.setenv('GIT_WORK_TREE', test_dir_absolute)
91+
end
92+
8893
local mock_hide_path = function(path)
8994
path = path or test_dir_absolute
9095
-- NOTE: use "^" as pattern separator because "/" can cause troubles
@@ -103,6 +108,10 @@ local get_spawn_log = function() return child.lua_get('_G.spawn_log') end
103108
local validate_git_spawn_log = function(ref_log)
104109
local spawn_log = get_spawn_log()
105110

111+
local ref_env = child.fn.environ()
112+
-- Should never include environment variables that can affect Git operations
113+
ref_env.GIT_DIR, ref_env.GIT_WORK_TREE = nil, nil
114+
106115
local n = math.max(#spawn_log, #ref_log)
107116
for i = 1, n do
108117
local real, ref = spawn_log[i], ref_log[i]
@@ -114,23 +123,25 @@ local validate_git_spawn_log = function(ref_log)
114123
-- Assume default `git` options
115124
local args = { '-c', 'gc.auto=0' }
116125
vim.list_extend(args, ref)
117-
eq(real, { executable = 'git', options = { args = args, cwd = real.options.cwd } })
126+
local opts = { args = args, cwd = real.options.cwd, env = ref_env, clear_env = true }
127+
local ref_val = { executable = 'git', options = opts }
128+
eq(real, ref_val)
118129
else
119130
local opts = vim.deepcopy(ref)
120131
-- Assume default `git` options
121132
local args = { '-c', 'gc.auto=0' }
122133
opts.args = vim.list_extend(args, opts.args)
134+
if opts.env == nil then
135+
opts.env = opts.env or ref_env
136+
opts.clear_env = true
137+
end
123138
eq(real, { executable = 'git', options = opts })
124139
end
125140
end
126141
end
127142

128-
local clear_spawn_log = function() child.lua('_G.spawn_log = {}') end
129-
130143
local get_process_log = function() return child.lua_get('_G.process_log') end
131144

132-
local clear_process_log = function() child.lua('_G.process_log = {}') end
133-
134145
-- Work with notifications
135146
local mock_notify = function()
136147
child.lua([[
@@ -541,6 +552,9 @@ T['add()']['Install'] = new_set({
541552
})
542553

543554
T['add()']['Install']['works'] = function()
555+
mock_bad_env_vars()
556+
local ref_environ = child.fn.environ()
557+
544558
child.lua([[
545559
_G.stdio_queue = {
546560
{ out = 'git version 2.43.0'}, -- Check Git executable
@@ -596,6 +610,9 @@ T['add()']['Install']['works'] = function()
596610
{ '(mini.deps) (1/1) Installed `new_plugin`', 'INFO' },
597611
}
598612
validate_notifications(ref_notify_log)
613+
614+
-- Should not affect any environment variables
615+
eq(child.fn.environ(), ref_environ)
599616
end
600617

601618
T['add()']['Install']['checks for executable Git'] = function()
@@ -1222,6 +1239,8 @@ local update = forward_lua('MiniDeps.update')
12221239

12231240
T['update()']['works'] = function()
12241241
child.set_size(40, 80)
1242+
mock_bad_env_vars()
1243+
local ref_environ = child.fn.environ()
12251244

12261245
-- By default should update all plugins in session
12271246
add('plugin_1')
@@ -1310,6 +1329,9 @@ T['update()']['works'] = function()
13101329
mock_hide_path(test_dir_absolute)
13111330
child.expect_screenshot()
13121331
validate_confirm_buf('confirm-update')
1332+
1333+
-- Should not affect any environment variables
1334+
eq(child.fn.environ(), ref_environ)
13131335
end
13141336

13151337
T['update()']['checks for executable Git'] = function()
@@ -1371,6 +1393,9 @@ T['update()']['Confirm buffer'] = new_set({
13711393
})
13721394

13731395
T['update()']['Confirm buffer']['can apply changes'] = function()
1396+
mock_bad_env_vars()
1397+
local ref_environ = child.fn.environ()
1398+
13741399
-- Should run `update()` on buffer write with only valid plugin names
13751400
-- Remove 'plugin_1' from being updated
13761401
child.cmd('g/^+++ plugin_1/normal! dd/')
@@ -1379,6 +1404,9 @@ T['update()']['Confirm buffer']['can apply changes'] = function()
13791404
-- Should update and close confirmation buffer
13801405
eq(child.lua_get('_G.update_args'), { { 'plugin_2' }, { force = true, offline = true } })
13811406
validate_not_confirm_buf()
1407+
1408+
-- Should not affect any environment variables
1409+
eq(child.fn.environ(), ref_environ)
13821410
end
13831411

13841412
T['update()']['Confirm buffer']['can cancel'] = function()

0 commit comments

Comments
 (0)