Git / SSH colgando cuando se llama desde MVC WebApi

Parte de un proyecto en el que estoy trabajando (Windows, C #, MVC4 WebAPI) requiere cierta integración con git. Ninguna de las bibliotecas existentes de Git C # admitía la clonación remota, así que terminé portando las partes del proyecto JavaGit que necesitábamos (pago, recuperación, estado) y escribiendo el clon por mi count. Todo lo que realmente es es un envoltorio para el ejecutable de la línea de command git. El código relevante que llama está aquí:

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 (eg "clone -- [email protected]: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(); } } 

Que sería llamado por el código como:

 // names changed to protect the innocent string localRepo = @"c:\repositories\repo_a8c0dd321f"; string gitArgs = "clone -- [email protected]:projectName c:\repositories\repo_a8c0dd321f"; GitConfiguration.RunGitCommand(localRepo, gitArgs); 

Desde dentro de la API de MVC, utilizamos la suplantación para asegurarnos de que se ejecuta como un usuario con un nombre de usuario y key válidos (sin frase de contraseña). El command anterior funciona perfectamente desde una línea de command como yo, y también en una testing rápida de unidad (sé que es realmente una testing de integración).

Sin embargo, cuando en realidad se llama desde la API como se muestra arriba, se cuelga. Al search en el Administrador de tareas, se muestra la ejecución de git.exe, con la command-line que muestra la ruta completa a git.exe seguida de los arguments anteriores. No está utilizando ningún time de procesador, y solo 2604K de RAM, pero dice que se está ejecutando. Del mismo modo, hay un process ssh.exe ejecutándose, también sin uso de procesador, y 1212K de RAM, con la línea de command:

 ssh [email protected] "git-upload-pack 'projectName'" 

Ambos processs aparecen como ejecutados bajo mi nombre de usuario, por lo que parece que la suplantación funciona correctamente.

Buscando en el directory localRepo, crea el directory .git, luego cuelga, dejando alnetworkingedor de 13K de files git, pero ninguno de nuestro código. Pensando que se debía a que nuestro repository era enorme, lo dejé correr durante la noche. Todavía no hay movimiento desde esta mañana.

Desarrollado LINQPad, funcionó:

 Process.GetProcessById($gitPID).Dump() 

Hizo lo mismo para el process de SSH también. Los subprocesss mostraban que estaban en el estado Esperar, y WaitReason era Ejecutivo (en espera del progtwigdor de subprocesss). Inicialmente asumí que estaba esperando una frase de contraseña, ya que mi key tenía una. Cambié a una key de trabajo sin una frase de contraseña, el mismo resultado.

 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 

La única idea que me queda es que tal vez no se pueda comunicar con ssh-agent, que se está ejecutando. Sin embargo, me está representando correctamente, así que no sé por qué no funcionaría desde el marco de WebApi, pero funciona bien desde la testing de "unidad" y Git Shell. Intenté asegurarme de que las variables de entorno HOME, PLINK_PROTOCOL, TERM, SSH_AUTH_SOCK y SSH_AGENT_PID estuvieran configuradas, después de mirar a través de las secuencias de commands de installation de Github para Windows, solo para asegurarme de que no me faltaba nada.

Estoy en una pérdida total. Aquí hay un fragment del file de logging, con algunos comentarios después:

 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: [email protected]: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 

Siempre obtengo el "No se pudo crear el directory 'h / .ssh'" y "Advertencia: agregado permanentemente * a la list de hosts conocidos". posts, incluso en la línea de command. Mi H: .ssh \ known_hosts permanece vacío, pero mis keys están en ese directory, y git las encuentra muy bien. El error "el extremo remoto colgó inesperadamente" fue cuando eliminé los processs de git y ssh.

Puede que termine cambiando a LibGit2Sharp para la mayoría de mis necesidades, pero eso aún no resuelve mi problema de clonación. ¿Hay algún problema con la configuration de mi key, que nuevamente funciona perfectamente fuera del process w3wp.exe? ¿Necesita poder comunicarse con ssh-agent.exe y no puede? ¿Alguien ha clonado un repository remoto de git a través de System.Diagnostics.Process y ha vivido para contarlo?

ACTUALIZACIÓN (25/11/2012 6:54 PM):

mvp estuvo en lo correcto al señalar que la suplantación y las unidades de networking asignadas no funcionan bien juntas. Agregué lo siguiente antes de comenzar el process:

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

Lo ejecuté de nuevo, y ahora estoy viendo al less un nuevo process de git en el Administrador de tareas que está tomando el time de 0 procesadores, pero está usando una cantidad creciente de memory, creo que como parte del process de clonación. La línea de command era:

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

Finalmente terminó después de 10 minutos (es un gran repository), y arrojó la exception:

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

¡Parece que el clon funcionó después de cambiar al directory! El otro problema tiene que ver con la ejecución inmediata de llamadas después de que finaliza la operación de clonación, pero no está relacionado con el problema de colgar.

Solo necesito verificar la solución de mi / mvp en un server de producción, luego otorgaré la recompensa.

Creo que su principal problema es que el directory principal para la count suplantada no es lo que usted cree que es, principalmente porque las unidades asignadas a la networking para las counts suplantadas realmente no funcionan .

Como solución alternativa, debe configurar la variable de entorno HOME para que el usuario suplantado señale algún directory local (por ejemplo, en la unidad C: que debe contener sus keys ssh (sin frases de contraseña). Debería probar esto ejecutando git clone manualmente (mientras tiene un HOME falso) y aceptar las keys de host_conocidas, para que no evite que el command git de background funcione automáticamente.

El hogar es h: \ es un poco amplio, pero aparte de eso, diría que su siguiente paso es crear un directory .ssh (h: .ssh) con los permissions correctos, debe ser solo para el usuario web y sin acceso para cualquier otro usuario.