3

私が取り組んでいるプロジェクトの一部 (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 のソリューションを検証する必要があるだけです。その後、報奨金を授与します。

4

2 に答える 2

2

あなたの主な問題は、なりすましアカウントのホーム ディレクトリが、あなたが思っているものではないことだと思います。これは主に、なりすましアカウントのネットワーク マップ ドライブが実際には機能しないためです。

C:回避策として、なりすましユーザーの HOME 環境変数を、ssh キー (パスフレーズなし) を含むローカル ディレクトリ (たとえば drive ) を指すように設定する必要があります。これを手動で実行してテストしgit clone(偽の HOME が有効な状態で)、known_host キーを受け入れて、バックグラウンドの git コマンドが自動的に機能するのを妨げないようにする必要があります。

于 2012-11-25T09:02:16.090 に答える
1

ホームが h:\ であることは少し広いですが、それ以外は、次のステップは、正しいアクセス許可を持つ .ssh ディレクトリ (h:.ssh) を作成することだと思います。このディレクトリは、Web ユーザーに対して読み取り専用であり、アクセスできません。他のユーザーの場合。

于 2012-11-20T21:14:58.150 に答える