如何在不将整个目录添加到环境 $PATH 的情况下授予 "git" 对特定 EXE 的访问权限?
How to give "git" access to specific EXEs without adding the whole directory to environment $PATH?
我正在使用 MSYS2/git 并为 windows SDK Install git inside MSYS2 proper
正确安装了 git
git.exe 位于 /mingw64/bin
目录(已添加到 $PATH),但 git 需要的其他包(特别是 sh.exe
和 less.exe
) 位于 /usr/bin
目录中,我不想将其放入 $PATH 以避免其他可执行文件污染我的环境,例如 mkdir
和 dir
,...
目前,一些 git 命令需要像 git config -l
这样需要 less
的包,任何 git 命令打开 EDITOR
都需要sh.exe
.
我想要实现的是在不添加整个目录的情况下将 less
和 sh
添加到 PATH。
我尝试使用方法 HERE and HERE 添加它们。它们中的大多数允许我直接从终端使用 sh
和 less
,但是它们中的 none 使依赖的 git 命令起作用。
例如,在 /mingw64/bin
目录中创建 less
和 sh
的 符号链接 将使命令提示符识别这些可执行文件,但是使用 git config -l
将不会给出任何输出,除非 less
的目录被添加到 $PATH
.
然而,其他方法(创建脚本和快捷方式,..)将使 git 抱怨 "Unable to spawn sh/less",altgough cmd
和 powershell
会识别 less
和 sh
.
为什么可执行文件可以从终端运行,而不是 git?
尤其是 symlink 的情况 git 没有抱怨缺少 EXE 但仍然无法正常运行?
听起来您想 运行 Git for Windows 在 MSYS2 之外并且您想避免将 MSYS2 的所有 /usr/bin
目录放在您的 PATH 上。避免将 /mingw64/bin
也放在您的 PATH 上也可能是个好主意。
我建议为 git 本身制作一个包装程序。它会知道 git.exe 的位置,并知道在 运行 宁 git.exe 之前将哪些目录放在 PATH 上。它会简单地修改 PATH,然后将其所有参数传递给正确的 git.exe。由于您可能正在使用无法识别 Bash shell 脚本的 shell 之类的 Windows 命令提示符,因此您可能只需要进行静态链接使用 Win32 API 执行此操作的本机 Windows 可执行文件。然后将它放在自己的目录中,并将该目录添加到您的 PATH。
下面是一些适合您的代码。但是,您必须编辑 MSYS2_DIR
以指向安装 MSYS2 的目录,并且还必须编辑 target
字符串。 (大多数 MSYS2 用户 git 安装了 pacman 并且它存在于 /usr/bin
中,所以我不想将不同的东西硬编码到这段代码中。)
#include <windows.h>
#include <stdio.h>
#define MSYS2_DIR "C:/msys64"
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
const char * target = MSYS2_DIR "/usr/bin/git.exe";
BOOL success = SetEnvironmentVariable(
"PATH", MSYS2_DIR "/mingw64/bin;" MSYS2_DIR "/usr/bin/");
if (!success)
{
DWORD error = GetLastError();
fprintf(stderr, "Failed to set PATH: error %ld.\n", error);
return 1;
}
PROCESS_INFORMATION info;
STARTUPINFOA startup_info = {
sizeof(startup_info),
.hStdInput = GetStdHandle(STD_INPUT_HANDLE),
.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE),
.hStdError = GetStdHandle(STD_ERROR_HANDLE),
};
success = CreateProcessA(target, GetCommandLine(),
NULL, NULL, 1, 0, NULL, NULL, &startup_info, &info);
if (!success)
{
DWORD error = GetLastError();
fprintf(stderr, "Failed to start git: error %ld.\n", error);
return 1;
}
DWORD result = WaitForSingleObject(info.hProcess, INFINITE);
if (result)
{
fprintf(stderr, "Unexpected wait result: 0x%lx\n", result);
return 1;
}
DWORD code;
success = GetExitCodeProcess(info.hProcess, &code);
if (!success)
{
fprintf(stderr, "Failed to get child exit code.\n");
return 1;
}
return code;
}
您可以使用 MSYS2 提供的 32 位或 64 位 MinGW 工具链编译它。只是 运行 gcc wrapper.c -o git
。这应该创建一个本机 Windows 可执行文件,不依赖于任何 MSYS2 DLL。
我解决这类问题的诀窍是用 "git.bat" 替换 "git.exe" ,它执行类似 set PATH=my\extra\dir;%PATH
的操作,然后传递所有参数调用 git.exe __git.exe %*
。创建这样一个 BAT 文件后,我将它放在与 git.exe 相同的位置,将 git.exe 重命名为 __git.exe 就完成了。每当我写 "git checkout foo" 它实际上调用带有 "checkout foo" 参数的 BAT 文件并且 BAT 句柄临时扩展 PATH 变量,或者我想要的任何其他准备工作。
当然,它不适用于想直接调用git.exe
的外部程序。如果外部程序调用 git.exe
它将失败。如果它在没有扩展名的情况下调用 git
,它将成功,因为它将命中 BAT 文件(前提是 BAT 本身在 PATH 上)。
如果 git.exe 不能在 BAT 文件后面 'hid'(我也已经偶然发现了这种情况),我使用了类似的解决方案——我使用了 .gitrc
文件并将我的修正放在那里。你可以看到一个更复杂的 gitrc here 的例子,基本上它只是一个像 bashrc/etc 这样的 shell 脚本。然而,奇怪的是,我 在互联网上找不到 关于提供 运行 和 gitrc
的任何提及。我认为它是 git 本身,但我找不到任何支持参考。奇数
我正在使用 MSYS2/git 并为 windows SDK Install git inside MSYS2 proper
正确安装了 gitgit.exe 位于 /mingw64/bin
目录(已添加到 $PATH),但 git 需要的其他包(特别是 sh.exe
和 less.exe
) 位于 /usr/bin
目录中,我不想将其放入 $PATH 以避免其他可执行文件污染我的环境,例如 mkdir
和 dir
,...
目前,一些 git 命令需要像 git config -l
这样需要 less
的包,任何 git 命令打开 EDITOR
都需要sh.exe
.
我想要实现的是在不添加整个目录的情况下将 less
和 sh
添加到 PATH。
我尝试使用方法 HERE and HERE 添加它们。它们中的大多数允许我直接从终端使用 sh
和 less
,但是它们中的 none 使依赖的 git 命令起作用。
例如,在 /mingw64/bin
目录中创建 less
和 sh
的 符号链接 将使命令提示符识别这些可执行文件,但是使用 git config -l
将不会给出任何输出,除非 less
的目录被添加到 $PATH
.
然而,其他方法(创建脚本和快捷方式,..)将使 git 抱怨 "Unable to spawn sh/less",altgough cmd
和 powershell
会识别 less
和 sh
.
为什么可执行文件可以从终端运行,而不是 git? 尤其是 symlink 的情况 git 没有抱怨缺少 EXE 但仍然无法正常运行?
听起来您想 运行 Git for Windows 在 MSYS2 之外并且您想避免将 MSYS2 的所有 /usr/bin
目录放在您的 PATH 上。避免将 /mingw64/bin
也放在您的 PATH 上也可能是个好主意。
我建议为 git 本身制作一个包装程序。它会知道 git.exe 的位置,并知道在 运行 宁 git.exe 之前将哪些目录放在 PATH 上。它会简单地修改 PATH,然后将其所有参数传递给正确的 git.exe。由于您可能正在使用无法识别 Bash shell 脚本的 shell 之类的 Windows 命令提示符,因此您可能只需要进行静态链接使用 Win32 API 执行此操作的本机 Windows 可执行文件。然后将它放在自己的目录中,并将该目录添加到您的 PATH。
下面是一些适合您的代码。但是,您必须编辑 MSYS2_DIR
以指向安装 MSYS2 的目录,并且还必须编辑 target
字符串。 (大多数 MSYS2 用户 git 安装了 pacman 并且它存在于 /usr/bin
中,所以我不想将不同的东西硬编码到这段代码中。)
#include <windows.h>
#include <stdio.h>
#define MSYS2_DIR "C:/msys64"
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
const char * target = MSYS2_DIR "/usr/bin/git.exe";
BOOL success = SetEnvironmentVariable(
"PATH", MSYS2_DIR "/mingw64/bin;" MSYS2_DIR "/usr/bin/");
if (!success)
{
DWORD error = GetLastError();
fprintf(stderr, "Failed to set PATH: error %ld.\n", error);
return 1;
}
PROCESS_INFORMATION info;
STARTUPINFOA startup_info = {
sizeof(startup_info),
.hStdInput = GetStdHandle(STD_INPUT_HANDLE),
.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE),
.hStdError = GetStdHandle(STD_ERROR_HANDLE),
};
success = CreateProcessA(target, GetCommandLine(),
NULL, NULL, 1, 0, NULL, NULL, &startup_info, &info);
if (!success)
{
DWORD error = GetLastError();
fprintf(stderr, "Failed to start git: error %ld.\n", error);
return 1;
}
DWORD result = WaitForSingleObject(info.hProcess, INFINITE);
if (result)
{
fprintf(stderr, "Unexpected wait result: 0x%lx\n", result);
return 1;
}
DWORD code;
success = GetExitCodeProcess(info.hProcess, &code);
if (!success)
{
fprintf(stderr, "Failed to get child exit code.\n");
return 1;
}
return code;
}
您可以使用 MSYS2 提供的 32 位或 64 位 MinGW 工具链编译它。只是 运行 gcc wrapper.c -o git
。这应该创建一个本机 Windows 可执行文件,不依赖于任何 MSYS2 DLL。
我解决这类问题的诀窍是用 "git.bat" 替换 "git.exe" ,它执行类似 set PATH=my\extra\dir;%PATH
的操作,然后传递所有参数调用 git.exe __git.exe %*
。创建这样一个 BAT 文件后,我将它放在与 git.exe 相同的位置,将 git.exe 重命名为 __git.exe 就完成了。每当我写 "git checkout foo" 它实际上调用带有 "checkout foo" 参数的 BAT 文件并且 BAT 句柄临时扩展 PATH 变量,或者我想要的任何其他准备工作。
当然,它不适用于想直接调用git.exe
的外部程序。如果外部程序调用 git.exe
它将失败。如果它在没有扩展名的情况下调用 git
,它将成功,因为它将命中 BAT 文件(前提是 BAT 本身在 PATH 上)。
如果 git.exe 不能在 BAT 文件后面 'hid'(我也已经偶然发现了这种情况),我使用了类似的解决方案——我使用了 .gitrc
文件并将我的修正放在那里。你可以看到一个更复杂的 gitrc here 的例子,基本上它只是一个像 bashrc/etc 这样的 shell 脚本。然而,奇怪的是,我 在互联网上找不到 关于提供 运行 和 gitrc
的任何提及。我认为它是 git 本身,但我找不到任何支持参考。奇数