private static void AcquireGlobalLock(string[] args) { try { if (ShouldLock(args)) { GVFSEnlistment enlistment = GVFSEnlistment.CreateFromCurrentDirectory(null, GitProcess.GetInstalledGitBinPath()); if (enlistment == null) { ExitWithError("This hook must be run from a GVFS repo"); } if (EnlistmentIsReady(enlistment)) { string fullCommand = "git " + string.Join(" ", args.Skip(1)); int pid = ProcessHelper.GetParentProcessId("git.exe"); Process parentProcess = null; if (pid == GVFSConstants.InvalidProcessId || !ProcessHelper.TryGetProcess(pid, out parentProcess)) { ExitWithError("GVFS.Hooks: Unable to find parent git.exe process " + "(PID: " + pid + ")."); } using (NamedPipeClient pipeClient = new NamedPipeClient(enlistment.NamedPipeName)) { if (!pipeClient.Connect()) { ExitWithError("The enlistment does not appear to be mounted. Use 'gvfs status' to check."); } NamedPipeMessages.AcquireLock.Request request = new NamedPipeMessages.AcquireLock.Request(pid, fullCommand, ProcessHelper.GetCommandLine(parentProcess)); NamedPipeMessages.Message requestMessage = request.CreateMessage(); pipeClient.SendRequest(requestMessage); NamedPipeMessages.AcquireLock.Response response = new NamedPipeMessages.AcquireLock.Response(pipeClient.ReadResponse()); if (response.Result == NamedPipeMessages.AcquireLock.AcceptResult) { return; } else if (response.Result == NamedPipeMessages.AcquireLock.MountNotReadyResult) { ExitWithError("GVFS has not finished initializing, please wait a few seconds and try again."); } else { int retries = 0; char[] waiting = { '\u2014', '\\', '|', '/' }; string message = string.Empty; while (true) { if (response.Result == NamedPipeMessages.AcquireLock.AcceptResult) { if (!Console.IsOutputRedirected) { Console.WriteLine("\r{0}...", message); } return; } else if (response.Result == NamedPipeMessages.AcquireLock.DenyGVFSResult) { message = "Waiting for GVFS to release the lock"; } else if (response.Result == NamedPipeMessages.AcquireLock.DenyGitResult) { message = string.Format("Waiting for '{0}' to release the lock", response.ResponseData.ParsedCommand); } else { ExitWithError("Error when acquiring the lock. Unrecognized response: " + response.CreateMessage()); tracer.RelatedError("Unknown LockRequestResponse: " + response); } if (Console.IsOutputRedirected && retries == 0) { Console.WriteLine("{0}...", message); } else if (!Console.IsOutputRedirected) { Console.Write("\r{0}..{1}", message, waiting[retries % waiting.Length]); } Thread.Sleep(500); pipeClient.SendRequest(requestMessage); response = new NamedPipeMessages.AcquireLock.Response(pipeClient.ReadResponse()); retries++; } } } } } } catch (Exception e) { EventMetadata metadata = new EventMetadata(); metadata.Add("Error", e.ToString()); tracer.RelatedError(metadata); ExitWithError( "Unable to initialize Git command.", "Ensure that GVFS is running."); } }
public void Execute() { // CmdParser doesn't strip quotes, and Path.Combine will throw this.GitBinPath = this.GitBinPath.Replace("\"", string.Empty); if (!GitProcess.GitExists(this.GitBinPath)) { Console.WriteLine( "Could not find git.exe {0}", !string.IsNullOrWhiteSpace(this.GitBinPath) ? "at " + this.GitBinPath : "on %PATH%"); return; } if (this.Commit != null && this.Branch != null) { Console.WriteLine("Cannot specify both a commit sha and a branch name to checkout."); return; } this.CacheServerUrl = Enlistment.StripObjectsEndpointSuffix(this.CacheServerUrl); this.SearchThreadCount = this.SearchThreadCount > 0 ? this.SearchThreadCount : Environment.ProcessorCount; this.DownloadThreadCount = this.DownloadThreadCount > 0 ? this.DownloadThreadCount : Environment.ProcessorCount; this.IndexThreadCount = this.IndexThreadCount > 0 ? this.IndexThreadCount : Environment.ProcessorCount; this.CheckoutThreadCount = this.CheckoutThreadCount > 0 ? this.CheckoutThreadCount : Environment.ProcessorCount; this.GitBinPath = !string.IsNullOrWhiteSpace(this.GitBinPath) ? this.GitBinPath : GitProcess.GetInstalledGitBinPath(); Enlistment enlistment = (Enlistment)GVFSEnlistment.CreateFromCurrentDirectory(this.CacheServerUrl, this.GitBinPath) ?? GitEnlistment.CreateFromCurrentDirectory(this.CacheServerUrl, this.GitBinPath); if (enlistment == null) { Console.WriteLine("Must be run within a .git repo or GVFS enlistment"); return; } string commitish = this.Commit ?? this.Branch ?? DefaultBranch; EventLevel maxVerbosity = this.Silent ? EventLevel.LogAlways : EventLevel.Informational; using (JsonEtwTracer tracer = new JsonEtwTracer("Microsoft.Git.FastFetch", "FastFetch")) { tracer.AddConsoleEventListener(maxVerbosity, Keywords.Any); tracer.WriteStartEvent( enlistment.EnlistmentRoot, enlistment.RepoUrl, enlistment.CacheServerUrl, new EventMetadata { { "TargetCommitish", commitish }, }); FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment); fetchHelper.MaxRetries = this.MaxRetries; if (!FetchHelper.TryLoadPathWhitelist(this.PathWhitelist, this.PathWhitelistFile, tracer, fetchHelper.PathWhitelist)) { Environment.ExitCode = 1; return; } try { bool isBranch = this.Commit == null; fetchHelper.FastFetch(commitish, isBranch); if (fetchHelper.HasFailures) { Environment.ExitCode = 1; } } catch (AggregateException e) { Environment.ExitCode = 1; foreach (Exception ex in e.Flatten().InnerExceptions) { tracer.RelatedError(ex.ToString()); } } catch (Exception e) { Environment.ExitCode = 1; tracer.RelatedError(e.ToString()); } EventMetadata stopMetadata = new EventMetadata(); stopMetadata.Add("Success", Environment.ExitCode == 0); tracer.Stop(stopMetadata); } if (Debugger.IsAttached) { Console.ReadKey(); } }