私が取り組んでいるプロジェクトの一部 (Windows、C#、MVC4 WebAPI) には、git との統合が必要です。既存の C# git ライブラリはいずれもリモート クローン作成をサポートしていませんでした。そのため、JavaGitプロジェクトの必要な部分 (チェックアウト、フェッチ、ステータス) を移植し、クローンを自分で作成することになりました。実際には、git コマンドライン実行可能ファイルのラッパーだけです。それが呼び出す関連コードは次のとおりです。
public static void RunGitCommand(string repositoryPath, string gitArguments)
{
// GitCommand is the full path to git.exe (currently using Github for Windows)
if (null == GitCommand || String.IsNullOrWhiteSpace(GitCommand))
{
throw new FileNotFoundException("Unable to find git.exe on your system PATH.");
}
// gitArguments contains the command to run (e.g. "clone -- git@repo:projectName c:\repositories\repo_a8c0dd321f")
var startInfo = new ProcessStartInfo(GitCommand, gitArguments)
{
WorkingDirectory = (null != repositoryPath && Directory.Exists(repositoryPath)) ? repositoryPath : String.Empty,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true
};
using (var p = new Process
{
EnableRaisingEvents = true,
StartInfo = startInfo
})
{
p.OutputDataReceived += (sender, args) => Log.Debug(args.Data);
p.ErrorDataReceived += (sender, args) => Log.Debug(args.Data);
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
}
}
これは、コードによって次のように呼び出されます。
// names changed to protect the innocent
string localRepo = @"c:\repositories\repo_a8c0dd321f";
string gitArgs = "clone -- git@repo:projectName c:\repositories\repo_a8c0dd321f";
GitConfiguration.RunGitCommand(localRepo, gitArgs);
MVC API 内から、偽装を使用して、有効な git ログインとキー (パスフレーズなし) を持つユーザーとして実行されていることを確認します。上記のコマンドは、私自身のようにコマンド ラインから完全に機能し、簡単な単体テストでも機能します (実際には統合テストであることはわかっています)。
しかし、実際に上記のように API から呼び出すと、ハングします。タスク マネージャーを見ると、git.exe が実行されていることがわかります。コマンド ラインには、git.exe へのフル パスが示され、その後に上記の引数が続きます。プロセッサ時間をまったく使用しておらず、2604K の RAM しか使用していませんが、実行中であると主張しています。同様に、ssh.exe プロセスが実行されており、これもプロセッサは使用されておらず、1212K の RAM がコマンド ラインで使用されています。
ssh git@repo "git-upload-pack 'projectName'"
両方のプロセスが私のユーザー名で実行されていると表示されているため、偽装が正しく機能しているようです。
localRepo ディレクトリを見ると、.git ディレクトリが作成されてハングし、そこに約 13K 相当の git ファイルが残りますが、コードは何もありません。私たちのレポが巨大だからだと思って、一晩実行させました。今朝もまだ動きがありません。
LINQPad を起動し、実行しました:
Process.GetProcessById($gitPID).Dump()
SSHプロセスについても同じことをしました。スレッドは待機状態であると示し、WaitReason は Executive (スレッド スケジューラを待機中) でした。私のキーにはパスフレーズがあったので、最初はパスフレーズを待っていると思いました。パスフレーズなしで有効なキーに切り替えましたが、同じ結果でした。
Git/SSH versions (from latest GitHub for Windows):
git version
git version 1.7.11.msysgit.1
ssh -v
OpenSSH_4.6p1, OpenSSL 0.9.8e 23 Feb 2007
私が残した唯一の考えは、実行中の ssh-agent と通信できない可能性があるということです。ただし、適切に偽装しているため、WebApi フレームワークからは機能しない理由はわかりませんが、「単体」テストと Git Shell からは正常に機能します。Windowsセットアップスクリプト用のGithubを調べた後、HOME、PLINK_PROTOCOL、TERM、SSH_AUTH_SOCK、およびSSH_AGENT_PID環境変数が設定されていることを確認して、何も欠けていないことを確認しました。
私は完全に途方に暮れています。以下は、ログ ファイルの抜粋で、その後にいくつかのコメントがあります。
2012-11-20 13:42:59.5898 Info Initializing repo at path: c:\repositories\repo_a8c0dd321f
2012-11-20 13:42:59.5898 Debug Working Directory: c:\repositories\repo_a8c0dd321f
2012-11-20 13:42:59.6053 Debug C:\Users\christian.doggett\AppData\Local\GitHub\PortableGit_8810fd5c2c79c73adcc73fd0825f3b32fdb816e7\bin\git.exe status --branch
2012-11-20 13:42:59.6209 Debug HOME=H:\
2012-11-20 13:42:59.6209 Debug PLINK_PROTOCOL=ssh
2012-11-20 13:42:59.6365 Debug TERM=msys
2012-11-20 13:42:59.6365 Debug SSH_AGENT_PID=58416
2012-11-20 13:42:59.6365 Debug SSH_AUTH_SOCK=/tmp/ssh-IgTHj19056/agent.19056
2012-11-20 13:42:59.6521 Info git status --branch
Exit code: 128
2012-11-20 13:42:59.6521 Error
2012-11-20 13:42:59.6677 Info Cloning repo from origin: git@repo:projectName
2012-11-20 13:43:01.8674 Debug Cloning into 'c:\repositories\repo_a8c0dd321f'...
2012-11-20 13:43:03.2090 Debug Could not create directory 'h/.ssh'.
2012-11-20 13:43:03.2870 Debug Warning: Permanently added 'repo,359.33.9.234' (RSA) to the list of known hosts.
2012-11-20 13:44:41.4593 Debug fatal: The remote end hung up unexpectedly
「ディレクトリ 'h/.ssh'を作成できませんでした」と「警告: 既知のホストのリストに * を永続的に追加しました」というメッセージが常に表示されます。コマンドラインでもメッセージ。私の H:.ssh\known_hosts は空のままですが、私のキーはそのディレクトリにあり、git はそれらを問題なく見つけます。「リモートエンドが予期せずハングアップしました」というエラーは、git および ssh プロセスを強制終了したときに発生しました。
ほとんどのニーズに対して LibGit2Sharp に切り替えることになるかもしれませんが、それでもクローンの問題は解決しません。w3wp.exe プロセスの外部で完全に機能する、キーのセットアップに問題があるのでしょうか? ssh-agent.exe と通信できる必要があるのにできないのですか? System.Diagnostics.Process を介してリモートの git リポジトリのクローンを作成し、生き残った人はいますか?
更新 (2012 年 11 月 25 日午後 6 時 54 分):
偽装とマップされたネットワーク ドライブがうまく連携しないという mvp の指摘は正しかった。プロセスを開始する前に、次を追加しました。
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
Environment.SetEnvironmentVariable("HOME", userProfile);
私はそれをもう一度実行しましたが、少なくともタスク マネージャーで新しい git プロセスが表示され、プロセッサ時間は 0 ですが、メモリの使用量が増加しています。これは、クローン プロセスの一部であると考えられます。コマンドラインは次のとおりです。
git index-pack --stdin --fix-thin "--keep=fetch-pack 6024 on MACHINENAME"
10分後にようやく終了し(巨大なリポジトリです)、例外をスローしました:
fatal: git checkout: updating paths is incompatible with switching branches.
Did you intend to checkout 'origin/8b243b8d9a5140673fc552ef7da8f0dfe9039d50' which can not be resolved as commit?
ただし、ディレクトリに変更した後、クローンは機能したようです。もう 1 つの問題は、クローン操作が終了した直後に checkout を呼び出すことと関係がありますが、ハングの問題とは関係ありません。
実稼働サーバーで my/mvp のソリューションを検証する必要があるだけです。その後、報奨金を授与します。