1

我正在使用 MSYS2/git,并为 Windows SDK 正确安装了git 在 MSYS2 中正确安装 git

git.exe 位于/mingw64/bin目录中(已添加到 $PATH),但 git 需要的其他包(特别是sh.exeless.exe)位于/usr/bin我不想放入 $PATH 的目录中,以避免其他可执行文件污染我的环境,例如mkdir并且dir,...

目前,一些 git 命令需要那些包,比如git config -lwhich needsless以及任何会打开EDITORwill need的 git 命令sh.exe

我想要实现的是在不添加整个目录的情况下添加less和到 PATH。sh


我尝试使用HEREHERE方法添加它们。它们中的大多数都允许我直接从终端使用shless但它们都没有使依赖的 git 命令工作。

例如,在目录中创建and的符号链接将使命令提示符识别这些可执行文件,但 using将不会给出任何输出,除非将目录添加到.lesssh/mingw64/bingit config -lless$PATH

但是,其他方法(创建脚本和快捷方式,..)将使 git 抱怨"Unable to spawn sh/less",altgoughcmd并且powershell会识别lessand sh


为什么可执行文件可以从终端运行,但不能使用 git?特别是git 没有抱怨缺少 EXE 但仍然无法正常运行的符号链接案例?

4

2 回答 2

1

我解决这类问题的诀窍是将“git.exe”替换为“git.bat”,它会执行类似于set PATH=my\extra\dir;%PATHpass-all-args 调用 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 文件后面(我也偶然发现了这种情况),我使用了类似的解决方案——我使用了.gitrc文件并将我的修复程序放在那里。你可以在这里看到一个更复杂的 gitrc 的例子,基本上它只是一个像 bashrc/etc 这样的 shell 脚本。然而,奇怪的是,我在互联网上找不到任何关于提供运行gitrc.. 的内容的提及。我认为它是 git 本身,但我找不到任何支持参考。奇怪的。

于 2019-04-29T17:36:34.467 回答
1

听起来你想在 MSYS2 之外为 Windows 运行 Git,并且你想避免将所有 MSYS2 的/usr/bin目录放在你的 PATH 上。避免/mingw64/bin使用 PATH 也可能是一个好主意。

我建议为 git 本身制作一个包装程序。它会知道 git.exe 的位置,并知道在运行 git.exe 之前将哪些目录放在 PATH 上。它会简单地修改 PATH,然后将其所有参数传递给正确的 git.exe。由于您可能正在使用无法识别 Bash shell 脚本的 Windows 命令提示符之类的 shell,因此您可能只需要制作一个使用 Win32 API 的静态链接的本机 Windows 可执行文件来执行此操作。然后将它放在它自己的目录中,并将该目录添加到您的 PATH 中。

这是一些适合您的代码。但是,您必须进行编辑MSYS2_DIR以指向安装 MSYS2 的目录,并且您也必须编辑该target字符串。(大多数 MSYS2 用户都使用 pacman 安装了 git,它存在于/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。这应该创建一个不依赖于任何 MSYS2 DLL 的本机 Windows 可执行文件。

于 2019-04-29T17:21:53.387 回答