Git / SSH hängt beim Aufruf von MVC WebApi

Ein Teil eines Projekts, an dem ich arbeite (Windows, C #, MVC4 WebAPI), erfordert eine gewisse Integration mit Git. Keine der vorhandenen C # git - Bibliotheken unterstützte das Klonen per Fernzugriff, daher habe ich die Teile des portiertJavaGit Projekt, das wir brauchten (checkout, fetch, status) und das ich selbst klonen konnte. Alles, was es wirklich ist, ist ein Wrapper für die ausführbare git-Befehlszeile. Der relevante Code, den es aufruft, ist hier:

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();
    }
}

Welches würde vom Code aufgerufen werden als:

// 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);

In der MVC-API wird der Identitätswechsel verwendet, um sicherzustellen, dass er als Benutzer mit einer gültigen Git-Anmeldung und einem gültigen Schlüssel (ohne Passphrase) ausgeführt wird. Der obige Befehl funktioniert perfekt über eine Befehlszeile wie ich selbst und auch in einem schnellen Unit-Test (ich weiß, dass es sich wirklich um einen Integrationstest handelt).

Wenn es jedoch wie oben gezeigt tatsächlich von der API aufgerufen wird, bleibt es hängen. Wenn Sie im Task-Manager nachsehen, wird "git.exe" ausgeführt. In der Befehlszeile wird der vollständige Pfad zu "git.exe" gefolgt von den obigen Argumenten angezeigt. Es verwendet keine Prozessorzeit und nur 2604 KB RAM, aber es behauptet, ausgeführt zu werden. Ebenso wird ein Prozess ssh.exe ohne Prozessorauslastung und mit 1212 KB RAM über die Befehlszeile ausgeführt:

ssh git@repo "git-upload-pack 'projectName'"

Beide Prozesse werden unter meinem Benutzernamen als ausgeführt aufgeführt, sodass der Identitätswechsel anscheinend ordnungsgemäß funktioniert.

Im localRepo-Verzeichnis erstellt es das .git-Verzeichnis und bleibt dann hängen. Es enthält etwa 13.000 Git-Dateien, aber keinen unserer Codes. Da ich dachte, dass unser Repo riesig ist, ließ ich es über Nacht laufen. Ab heute Morgen immer noch keine Bewegung.

Aufgebrachter LINQPad, lief:

Process.GetProcessById($gitPID).Dump()

Dasselbe gilt auch für den SSH-Prozess. Die Threads zeigten, dass sie sich im Wartezustand befanden, und WaitReason war Executive (Warten auf den Thread-Scheduler). Ich nahm anfangs an, dass es auf eine Passphrase wartete, da mein Schlüssel eine hatte. Ich habe auf einen funktionierenden Schlüssel ohne Passphrase gewechselt, das gleiche Ergebnis.

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

Die einzige Idee, die ich noch habe, ist, dass es möglicherweise nicht mit dem laufenden ssh-agent kommunizieren kann. Es verkörpert mich jedoch korrekt, sodass ich nicht weiß, warum es nicht mit dem WebApi-Framework funktioniert, sondern mit dem Unit-Test und der Git-Shell. Ich habe versucht, sicherzustellen, dass die Umgebungsvariablen HOME, PLINK_PROTOCOL, TERM, SSH_AUTH_SOCK und SSH_AGENT_PID festgelegt wurden, nachdem ich die Setup-Skripts von Github für Windows durchgesehen habe, um sicherzustellen, dass mir nichts entgangen ist.

Ich bin total ratlos. Hier ist ein Auszug aus der Protokolldatei mit einigen Kommentaren:

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 

I immer Holen Sie sich das "Verzeichnis 'h / .ssh' konnte nicht erstellt werden" und "Warnung: Permanent * zur Liste der bekannten Hosts hinzugefügt." Nachrichten, auch in der Befehlszeile. Mein H: .ssh \ known_hosts bleibt leer, aber meine Schlüssel befinden sich in diesem Verzeichnis und git findet diese gut. Der Fehler "Remote-Ende hat unerwartet aufgelegt" war, als ich die git- und ssh-Prozesse beendet habe.

Möglicherweise werde ich für die meisten meiner Bedürfnisse auf LibGit2Sharp umsteigen, aber das löst mein Klonproblem immer noch nicht. Ist etwas mit meinem Schlüssel-Setup nicht in Ordnung, das auch außerhalb des Prozesses w3wp.exe einwandfrei funktioniert? Muss es mit ssh-agent.exe kommunizieren können und kann es nicht? Hat jemand ein entferntes Git-Repository über System.Diagnostics.Process geklont und überlebt, um die Geschichte zu erzählen?

UPDATE (25.11.2012, 18:54 Uhr):

MVP wies zu Recht darauf hin, dass Identitätswechsel und zugeordnete Netzlaufwerke nicht gut zusammenspielen. Ich habe Folgendes hinzugefügt, bevor ich den Prozess gestartet habe:

var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
Environment.SetEnvironmentVariable("HOME", userProfile);

Ich habe es erneut ausgeführt und sehe jetzt zumindest einen neuen Git-Prozess im Task-Manager, der 0 Prozessorzeit in Anspruch nimmt, aber immer mehr Speicher benötigt, glaube ich, als Teil des Klonprozesses. Die Befehlszeile lautete:

git index-pack --stdin --fix-thin "--keep=fetch-pack 6024 on MACHINENAME"

Es ist nach 10 Minuten endlich fertig (es ist ein riesiges Repository) und hat die Ausnahme geworfen:

fatal: git checkout: updating paths is incompatible with switching branches.
Did you intend to checkout 'origin/8b243b8d9a5140673fc552ef7da8f0dfe9039d50' which can not be resolved as commit?

Sieht aber so aus, als hätte der Klon nach dem Wechsel ins Verzeichnis funktioniert! Das andere Problem hat etwas mit dem sofortigen Aufrufen von checkout nach Abschluss des Klonvorgangs zu tun, hängt jedoch nicht mit dem Problem des Aufhängens zusammen.

Ich muss nur die Lösung meines / mvps auf einem Produktionsserver überprüfen, dann werde ich die Prämie vergeben.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage