private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection) { NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); switch (message.Header) { case NamedPipeMessages.GetStatus.Request: this.HandleGetStatusRequest(connection); break; case NamedPipeMessages.Unmount.Request: this.HandleUnmountRequest(connection); break; case NamedPipeMessages.AcquireLock.AcquireRequest: this.HandleLockRequest(message.Body, connection); break; case NamedPipeMessages.ReleaseLock.Request: this.HandleReleaseLockRequest(message.Body, connection); break; case NamedPipeMessages.DownloadObject.DownloadRequest: this.HandleDownloadObjectRequest(message, connection); break; case NamedPipeMessages.ModifiedPaths.ListRequest: this.HandleModifiedPathsListRequest(message, connection); break; case NamedPipeMessages.PostIndexChanged.NotificationRequest: this.HandlePostIndexChangedRequest(message, connection); break; case NamedPipeMessages.RunPostFetchJob.PostFetchJob: this.HandlePostFetchJobRequest(message, connection); break; case NamedPipeMessages.DehydrateFolders.Dehydrate: this.HandleDehydrateFolders(message, connection); break; default: EventMetadata metadata = new EventMetadata(); metadata.Add("Area", "Mount"); metadata.Add("Header", message.Header); this.tracer.RelatedError(metadata, "HandleRequest: Unknown request"); connection.TrySendResponse(NamedPipeMessages.UnknownRequest); break; } }
/// <summary> /// Request that PrjFlt be enabled and attached to the volume of the enlistment root /// </summary> /// <param name="enlistmentRoot">Enlistment root. If string.Empty, PrjFlt will be enabled but not attached to any volumes</param> /// <param name="errorMessage">Error meesage (in the case of failure)</param> /// <returns>True is successful and false otherwise</returns> protected bool TryEnableAndAttachPrjFltThroughService(string enlistmentRoot, out string errorMessage) { errorMessage = string.Empty; NamedPipeMessages.EnableAndAttachProjFSRequest request = new NamedPipeMessages.EnableAndAttachProjFSRequest(); request.EnlistmentRoot = enlistmentRoot; using (NamedPipeClient client = new NamedPipeClient(this.ServicePipeName)) { if (!client.Connect()) { errorMessage = "GVFS.Service is not responding. " + GVFSVerb.StartServiceInstructions; return(false); } try { client.SendRequest(request.ToMessage()); NamedPipeMessages.Message response = client.ReadResponse(); if (response.Header == NamedPipeMessages.EnableAndAttachProjFSRequest.Response.Header) { NamedPipeMessages.EnableAndAttachProjFSRequest.Response message = NamedPipeMessages.EnableAndAttachProjFSRequest.Response.FromMessage(response); if (!string.IsNullOrEmpty(message.ErrorMessage)) { errorMessage = message.ErrorMessage; return(false); } if (message.State != NamedPipeMessages.CompletionState.Success) { errorMessage = $"Failed to attach ProjFS to volume."; return(false); } else { return(true); } } else { errorMessage = string.Format("GVFS.Service responded with unexpected message: {0}", response); return(false); } } catch (BrokenPipeException e) { errorMessage = "Unable to communicate with GVFS.Service: " + e.ToString(); return(false); } } }
protected virtual void HandleMessage( ITracer tracer, NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { switch (message.Header) { case NamedPipeMessages.RegisterRepoRequest.Header: this.requestDescription = MountRequestDescription; NamedPipeMessages.RegisterRepoRequest mountRequest = NamedPipeMessages.RegisterRepoRequest.FromMessage(message); RegisterRepoHandler mountHandler = new RegisterRepoHandler(tracer, this.repoRegistry, connection, mountRequest); mountHandler.Run(); break; case NamedPipeMessages.UnregisterRepoRequest.Header: this.requestDescription = UnmountRequestDescription; NamedPipeMessages.UnregisterRepoRequest unmountRequest = NamedPipeMessages.UnregisterRepoRequest.FromMessage(message); UnregisterRepoHandler unmountHandler = new UnregisterRepoHandler(tracer, this.repoRegistry, connection, unmountRequest); unmountHandler.Run(); break; case NamedPipeMessages.GetActiveRepoListRequest.Header: this.requestDescription = RepoListRequestDescription; NamedPipeMessages.GetActiveRepoListRequest repoListRequest = NamedPipeMessages.GetActiveRepoListRequest.FromMessage(message); GetActiveRepoListHandler excludeHandler = new GetActiveRepoListHandler(tracer, this.repoRegistry, connection, repoListRequest); excludeHandler.Run(); break; case NamedPipeMessages.EnableAndAttachProjFSRequest.Header: // This request is ignored on non Windows platforms. NamedPipeMessages.EnableAndAttachProjFSRequest.Response response = new NamedPipeMessages.EnableAndAttachProjFSRequest.Response(); response.State = NamedPipeMessages.CompletionState.Success; this.TrySendResponse(tracer, response.ToMessage().ToString(), connection); break; default: this.requestDescription = UnknownRequestDescription; EventMetadata metadata = new EventMetadata(); metadata.Add("Area", this.etwArea); metadata.Add("Header", message.Header); tracer.RelatedWarning(metadata, "HandleNewConnection: Unknown request", Keywords.Telemetry); this.TrySendResponse(tracer, NamedPipeMessages.UnknownRequest, connection); break; } }
private bool UnregisterRepo(string rootPath, out string errorMessage) { errorMessage = string.Empty; NamedPipeMessages.UnregisterRepoRequest request = new NamedPipeMessages.UnregisterRepoRequest(); request.EnlistmentRoot = rootPath; using (NamedPipeClient client = new NamedPipeClient(this.ServicePipeName)) { if (!client.Connect()) { errorMessage = "Unable to unregister repo because GVFS.Service is not responding. " + GVFSVerb.StartServiceInstructions; return(false); } try { client.SendRequest(request.ToMessage()); NamedPipeMessages.Message response = client.ReadResponse(); if (response.Header == NamedPipeMessages.UnregisterRepoRequest.Response.Header) { NamedPipeMessages.UnregisterRepoRequest.Response message = NamedPipeMessages.UnregisterRepoRequest.Response.FromMessage(response); if (message.State != NamedPipeMessages.CompletionState.Success) { errorMessage = message.ErrorMessage; return(false); } else { errorMessage = string.Empty; return(true); } } else { errorMessage = string.Format("GVFS.Service responded with unexpected message: {0}", response); return(false); } } catch (BrokenPipeException e) { errorMessage = "Unable to communicate with GVFS.Service: " + e.ToString(); return(false); } } }
private bool RequestUnmount(string rootPath, out string errorMessage) { errorMessage = string.Empty; NamedPipeMessages.UnmountRepoRequest request = new NamedPipeMessages.UnmountRepoRequest(); request.EnlistmentRoot = rootPath; using (NamedPipeClient client = new NamedPipeClient(this.ServicePipeName)) { if (!client.Connect()) { errorMessage = "Unable to unmount because GVFS.Service is not responding. Run 'sc start GVFS.Service' from an elevated command prompt to ensure it is running."; return(false); } try { client.SendRequest(request.ToMessage()); NamedPipeMessages.Message response = client.ReadResponse(); if (response.Header == NamedPipeMessages.UnmountRepoRequest.Response.Header) { NamedPipeMessages.UnmountRepoRequest.Response message = NamedPipeMessages.UnmountRepoRequest.Response.FromMessage(response); if (message.State != NamedPipeMessages.CompletionState.Success) { errorMessage = message.UserText; return(false); } else { errorMessage = string.Empty; return(true); } } else { errorMessage = string.Format("GVFS.Service responded with unexpected message: {0}", response); return(false); } } catch (BrokenPipeException e) { errorMessage = "Unable to communicate with GVFS.Service: " + e.ToString(); return(false); } } }
protected override void HandleMessage( ITracer tracer, NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { if (message.Header == NamedPipeMessages.EnableAndAttachProjFSRequest.Header) { this.requestDescription = EnableProjFSRequestDescription; NamedPipeMessages.EnableAndAttachProjFSRequest attachRequest = NamedPipeMessages.EnableAndAttachProjFSRequest.FromMessage(message); EnableAndAttachProjFSHandler attachHandler = new EnableAndAttachProjFSHandler(tracer, connection, attachRequest); attachHandler.Run(); } else { base.HandleMessage(tracer, message, connection); } }
protected virtual void HandleMessage( ITracer tracer, NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { switch (message.Header) { default: this.requestDescription = UnknownRequestDescription; EventMetadata metadata = new EventMetadata(); metadata.Add("Area", this.etwArea); metadata.Add("Header", message.Header); tracer.RelatedWarning(metadata, "HandleNewConnection: Unknown request", Keywords.Telemetry); this.TrySendResponse(tracer, NamedPipeMessages.UnknownRequest, connection); break; } }
private static void ReleaseLock(string enlistmentPipename, string enlistmentRoot) { using (NamedPipeClient pipeClient = new NamedPipeClient(enlistmentPipename)) { if (!pipeClient.Connect()) { throw new Exception("The repo does not appear to be mounted. Use 'gvfs status' to check."); } int pid = Process.GetCurrentProcess().Id; NamedPipeMessages.LockRequest request = new NamedPipeMessages.LockRequest(pid: pid, isElevated: false, checkAvailabilityOnly: false, parsedCommand: AcquireGVFSLockVerb.fullCommand, gitCommandSessionId: string.Empty); NamedPipeMessages.Message requestMessage = request.CreateMessage(NamedPipeMessages.ReleaseLock.Request); pipeClient.SendRequest(requestMessage); NamedPipeMessages.ReleaseLock.Response response = response = new NamedPipeMessages.ReleaseLock.Response(pipeClient.ReadResponse()); } }
/// <summary> /// Talk to the mount process across the named pipe to get a list of the modified paths /// </summary> /// <remarks>If/when modified paths are moved to SQLite go there instead</remarks> /// <param name="enlistment">The enlistment being operated on</param> /// <returns>An array containing all of the modified paths in string format</returns> private void GetModifiedPathsFromPipe(GVFSEnlistment enlistment, EnlistmentPathData pathData) { using (NamedPipeClient pipeClient = new NamedPipeClient(enlistment.NamedPipeName)) { string[] modifiedPathsList = Array.Empty <string>(); if (!pipeClient.Connect()) { this.ReportErrorAndExit("Unable to connect to GVFS. Try running 'gvfs mount'"); } try { NamedPipeMessages.Message modifiedPathsMessage = new NamedPipeMessages.Message(NamedPipeMessages.ModifiedPaths.ListRequest, NamedPipeMessages.ModifiedPaths.CurrentVersion); pipeClient.SendRequest(modifiedPathsMessage); NamedPipeMessages.Message modifiedPathsResponse = pipeClient.ReadResponse(); if (!modifiedPathsResponse.Header.Equals(NamedPipeMessages.ModifiedPaths.SuccessResult)) { this.Output.WriteLine("Bad response from modified path pipe: " + modifiedPathsResponse.Header); return; } modifiedPathsList = modifiedPathsResponse.Body.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); } catch (BrokenPipeException e) { this.ReportErrorAndExit("Unable to communicate with GVFS: " + e.ToString()); } foreach (string path in modifiedPathsList) { if (path.Last() == GVFSConstants.GitPathSeparator) { path.TrimEnd(GVFSConstants.GitPathSeparator); pathData.ModifiedFolderPaths.Add(path); } else { pathData.ModifiedFilePaths.Add(path); } } } }
private bool ExcludeFromAntiVirusThroughService(string path, out string errorMessage) { errorMessage = string.Empty; NamedPipeMessages.ExcludeFromAntiVirusRequest request = new NamedPipeMessages.ExcludeFromAntiVirusRequest(); request.ExclusionPath = path; using (NamedPipeClient client = new NamedPipeClient(this.ServicePipeName)) { if (!client.Connect()) { errorMessage = "Unable to exclude from antivirus because GVFS.Service is not responding. " + GVFSVerb.StartServiceInstructions; return(false); } try { client.SendRequest(request.ToMessage()); NamedPipeMessages.Message response = client.ReadResponse(); if (response.Header == NamedPipeMessages.ExcludeFromAntiVirusRequest.Response.Header) { NamedPipeMessages.ExcludeFromAntiVirusRequest.Response message = NamedPipeMessages.ExcludeFromAntiVirusRequest.Response.FromMessage(response); if (!string.IsNullOrEmpty(message.ErrorMessage)) { errorMessage = message.ErrorMessage; return(false); } return(message.State == NamedPipeMessages.CompletionState.Success); } else { errorMessage = string.Format("GVFS.Service responded with unexpected message: {0}", response); return(false); } } catch (BrokenPipeException e) { errorMessage = "Unable to communicate with GVFS.Service: " + e.ToString(); return(false); } } }
public static void ReleaseGVFSLock( bool unattended, NamedPipeClient pipeClient, string fullCommand, int pid, bool isElevated, bool isConsoleOutputRedirectedToFile, Action <NamedPipeMessages.ReleaseLock.Response> responseHandler, string gvfsEnlistmentRoot, string waitingMessage = "", int spinnerDelay = 0) { NamedPipeMessages.LockRequest request = new NamedPipeMessages.LockRequest(pid, isElevated, checkAvailabilityOnly: false, parsedCommand: fullCommand); NamedPipeMessages.Message requestMessage = request.CreateMessage(NamedPipeMessages.ReleaseLock.Request); pipeClient.SendRequest(requestMessage); NamedPipeMessages.ReleaseLock.Response response = null; Func <ConsoleHelper.ActionResult> releaseLock = () => { response = new NamedPipeMessages.ReleaseLock.Response(pipeClient.ReadResponse()); responseHandler(response); return(ConsoleHelper.ActionResult.Success); }; if (unattended || isConsoleOutputRedirectedToFile) { releaseLock(); } else { ConsoleHelper.ShowStatusWhileRunning( releaseLock, waitingMessage, output: Console.Out, showSpinner: true, gvfsLogEnlistmentRoot: gvfsEnlistmentRoot, initialDelayMs: spinnerDelay); } }
private static void HandleRequest(string request, NamedPipeServer.Connection connection) { NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); switch (message.Header) { case NamedPipeMessages.AcquireLock.AcquireRequest: NamedPipeMessages.AcquireLock.Response response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult); connection.TrySendResponse(response.CreateMessage()); break; case NamedPipeMessages.ReleaseLock.Request: connection.TrySendResponse(NamedPipeMessages.ReleaseLock.SuccessResult); break; default: connection.TrySendResponse(NamedPipeMessages.UnknownRequest); break; } }
private void HandlePostIndexChangedRequest(NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { NamedPipeMessages.PostIndexChanged.Response response; NamedPipeMessages.PostIndexChanged.Request request = new NamedPipeMessages.PostIndexChanged.Request(message); if (request == null) { response = new NamedPipeMessages.PostIndexChanged.Response(NamedPipeMessages.UnknownRequest); } else if (this.currentState != MountState.Ready) { response = new NamedPipeMessages.PostIndexChanged.Response(NamedPipeMessages.MountNotReadyResult); } else { this.fileSystemCallbacks.ForceIndexProjectionUpdate(request.UpdatedWorkingDirectory, request.UpdatedSkipWorktreeBits); response = new NamedPipeMessages.PostIndexChanged.Response(NamedPipeMessages.PostIndexChanged.SuccessResult); } connection.TrySendResponse(response.CreateMessage()); }
private void HandleDownloadObjectRequest(NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { NamedPipeMessages.DownloadObject.Response response; NamedPipeMessages.DownloadObject.Request request = new NamedPipeMessages.DownloadObject.Request(message); string objectSha = request.RequestSha; if (request == null) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.UnknownRequest); } else if (this.currentState != MountState.Ready) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.MountNotReadyResult); } else { if (!SHA1Util.IsValidShaFormat(objectSha)) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.InvalidSHAResult); } else { Stopwatch downloadTime = Stopwatch.StartNew(); if (this.gitObjects.TryDownloadAndSaveObject(objectSha, GVFSGitObjects.RequestSource.NamedPipeMessage) == GitObjects.DownloadAndSaveObjectResult.Success) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.SuccessResult); } else { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.DownloadFailed); } bool isBlob; this.context.Repository.TryGetIsBlob(objectSha, out isBlob); this.context.Repository.GVFSLock.RecordObjectDownload(isBlob, downloadTime.ElapsedMilliseconds); } } connection.TrySendResponse(response.CreateMessage()); }
private void HandlePostFetchJobRequest(NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { NamedPipeMessages.RunPostFetchJob.Request request = new NamedPipeMessages.RunPostFetchJob.Request(message); this.tracer.RelatedInfo("Received post-fetch job request with body {0}", message.Body); NamedPipeMessages.RunPostFetchJob.Response response; if (this.currentState == MountState.Ready) { List <string> packIndexes = JsonConvert.DeserializeObject <List <string> >(message.Body); this.fileSystemCallbacks.LaunchPostFetchJob(packIndexes); response = new NamedPipeMessages.RunPostFetchJob.Response(NamedPipeMessages.RunPostFetchJob.QueuedResult); } else { response = new NamedPipeMessages.RunPostFetchJob.Response(NamedPipeMessages.RunPostFetchJob.MountNotReadyResult); } connection.TrySendResponse(response.CreateMessage()); }
private void HandlePostFetchJobRequest(NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { NamedPipeMessages.RunPostFetchJob.Request request = new NamedPipeMessages.RunPostFetchJob.Request(message); this.tracer.RelatedInfo("Received post-fetch job request with body {0}", message.Body); NamedPipeMessages.RunPostFetchJob.Response response; if (this.currentState == MountState.Ready) { List <string> packIndexes = JsonConvert.DeserializeObject <List <string> >(message.Body); this.maintenanceScheduler.EnqueueOneTimeStep(new PostFetchStep(this.context, packIndexes)); response = new NamedPipeMessages.RunPostFetchJob.Response(NamedPipeMessages.RunPostFetchJob.QueuedResult); } else { response = new NamedPipeMessages.RunPostFetchJob.Response(NamedPipeMessages.RunPostFetchJob.MountNotReadyResult); } connection.TrySendResponse(response.CreateMessage()); }
public static void ReleaseGVFSLock( NamedPipeClient pipeClient, string fullCommand, int pid, Process parentProcess, Action <NamedPipeMessages.ReleaseLock.Response> responseHandler, string gvfsEnlistmentRoot, string waitingMessage = "", int spinnerDelay = 0) { NamedPipeMessages.LockRequest request = new NamedPipeMessages.LockRequest(pid, fullCommand); NamedPipeMessages.Message requestMessage = request.CreateMessage(NamedPipeMessages.ReleaseLock.Request); pipeClient.SendRequest(requestMessage); NamedPipeMessages.ReleaseLock.Response response = null; if (ConsoleHelper.IsConsoleOutputRedirectedToFile()) { // If output is redirected then don't show waiting message or it might be interpreted as error response = new NamedPipeMessages.ReleaseLock.Response(pipeClient.ReadResponse()); responseHandler(response); } else { ConsoleHelper.ShowStatusWhileRunning( () => { response = new NamedPipeMessages.ReleaseLock.Response(pipeClient.ReadResponse()); responseHandler(response); return(ConsoleHelper.ActionResult.Success); }, waitingMessage, output: Console.Out, showSpinner: true, gvfsLogEnlistmentRoot: gvfsEnlistmentRoot, initialDelayMs: spinnerDelay); } }
private void HandleConnection(NamedPipeServer.Connection connection) { while (connection.IsConnected) { string request = connection.ReadRequest(); if (request == null || !connection.IsConnected) { break; } NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); switch (message.Header) { case NamedPipeMessages.GetStatus.Request: this.HandleGetStatusRequest(connection); break; case NamedPipeMessages.Unmount.Request: this.HandleUnmountRequest(connection); break; case NamedPipeMessages.AcquireLock.AcquireRequest: this.HandleLockRequest(connection, message); break; case NamedPipeMessages.DownloadObject.DownloadRequest: this.HandleDownloadObjectRequest(connection, message); break; default: connection.TrySendResponse(NamedPipeMessages.UnknownRequest); break; } } }
private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection) { NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); switch (message.Header) { case NamedPipeMessages.GetStatus.Request: this.HandleGetStatusRequest(connection); break; case NamedPipeMessages.Unmount.Request: this.HandleUnmountRequest(connection); break; case NamedPipeMessages.AcquireLock.AcquireRequest: this.HandleLockRequest(message.Body, connection); break; case NamedPipeMessages.ReleaseLock.Request: this.HandleReleaseLockRequest(message.Body, connection); break; case NamedPipeMessages.DownloadObject.DownloadRequest: this.HandleDownloadObjectRequest(message, connection); break; default: EventMetadata metadata = new EventMetadata(); metadata.Add("Area", "Mount"); metadata.Add("Header", message.Header); metadata.Add("ErrorMessage", "HandleRequest: Unknown request"); this.tracer.RelatedError(metadata); connection.TrySendResponse(NamedPipeMessages.UnknownRequest); break; } }
private void HandleDownloadObjectRequest(NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { NamedPipeMessages.DownloadObject.Response response; NamedPipeMessages.DownloadObject.Request request = new NamedPipeMessages.DownloadObject.Request(message); string objectSha = request.RequestSha; if (request == null) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.UnknownRequest); } else if (this.currentState != MountState.Ready) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.MountNotReadyResult); } else { if (!GitHelper.IsValidFullSHA(objectSha)) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.InvalidSHAResult); } else { if (this.gitObjects.TryDownloadAndSaveObject(objectSha.Substring(0, 2), objectSha.Substring(2))) { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.SuccessResult); } else { response = new NamedPipeMessages.DownloadObject.Response(NamedPipeMessages.DownloadObject.DownloadFailed); } } } connection.TrySendResponse(response.CreateMessage()); }
private static void ReleaseGVFSLock(string fullCommand, int pid, Process parentProcess, NamedPipeClient pipeClient) { NamedPipeMessages.LockRequest request = new NamedPipeMessages.LockRequest(pid, fullCommand); NamedPipeMessages.Message requestMessage = request.CreateMessage(NamedPipeMessages.ReleaseLock.Request); pipeClient.SendRequest(requestMessage); NamedPipeMessages.ReleaseLock.Response response = null; if (!ConsoleHelper.IsConsoleOutputRedirectedToFile()) { // If output is redirected then don't show waiting message or it might be interpreted as error response = new NamedPipeMessages.ReleaseLock.Response(pipeClient.ReadResponse()); } else { ConsoleHelper.ShowStatusWhileRunning( () => { response = new NamedPipeMessages.ReleaseLock.Response(pipeClient.ReadResponse()); if (response.ResponseData == null) { return(ConsoleHelper.ActionResult.Failure); } return(response.ResponseData.HasFailures ? ConsoleHelper.ActionResult.CompletedWithErrors : ConsoleHelper.ActionResult.Success); }, "Waiting for GVFS to parse index and update placeholder files", output: Console.Out, showSpinner: true, suppressGvfsLogMessage: false, initialDelayMs: PostCommandSpinnerDelayMs); } if (response == null || response.ResponseData == null) { Console.WriteLine("\nError communicating with GVFS: Run 'git status' to check the status of your repo"); } else if (response.ResponseData.HasFailures) { if (response.ResponseData.FailureCountExceedsMaxFileNames) { Console.WriteLine( "\nGVFS failed to update {0} files, run 'git status' to check the status of files in the repo", response.ResponseData.FailedToDeleteCount + response.ResponseData.FailedToUpdateCount); } else { string deleteFailuresMessage = BuildUpdatePlaceholderFailureMessage(response.ResponseData.FailedToDeleteFileList, "delete", "git clean -f "); if (deleteFailuresMessage.Length > 0) { Console.WriteLine(deleteFailuresMessage); } string updateFailuresMessage = BuildUpdatePlaceholderFailureMessage(response.ResponseData.FailedToUpdateFileList, "update", "git checkout -- "); if (updateFailuresMessage.Length > 0) { Console.WriteLine(updateFailuresMessage); } } } }
public static bool TryAcquireGVFSLockForProcess( NamedPipeClient pipeClient, string fullCommand, int pid, Process parentProcess, string gvfsEnlistmentRoot, out string result) { NamedPipeMessages.LockRequest request = new NamedPipeMessages.LockRequest(pid, fullCommand); NamedPipeMessages.Message requestMessage = request.CreateMessage(NamedPipeMessages.AcquireLock.AcquireRequest); pipeClient.SendRequest(requestMessage); NamedPipeMessages.AcquireLock.Response response = new NamedPipeMessages.AcquireLock.Response(pipeClient.ReadResponse()); if (response.Result == NamedPipeMessages.AcquireLock.AcceptResult) { result = null; return(true); } else if (response.Result == NamedPipeMessages.AcquireLock.MountNotReadyResult) { result = "GVFS has not finished initializing, please wait a few seconds and try again."; return(false); } else { string message = string.Empty; switch (response.Result) { case NamedPipeMessages.AcquireLock.AcceptResult: break; case NamedPipeMessages.AcquireLock.DenyGVFSResult: message = "Waiting for GVFS to release the lock"; break; case NamedPipeMessages.AcquireLock.DenyGitResult: message = string.Format("Waiting for '{0}' to release the lock", response.ResponseData.ParsedCommand); break; default: result = "Error when acquiring the lock. Unrecognized response: " + response.CreateMessage(); return(false); } ConsoleHelper.ShowStatusWhileRunning( () => { while (response.Result != NamedPipeMessages.AcquireLock.AcceptResult) { Thread.Sleep(250); pipeClient.SendRequest(requestMessage); response = new NamedPipeMessages.AcquireLock.Response(pipeClient.ReadResponse()); } return(true); }, message, output: Console.Out, showSpinner: !ConsoleHelper.IsConsoleOutputRedirectedToFile(), gvfsLogEnlistmentRoot: gvfsEnlistmentRoot); result = null; return(true); } }
private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection) { NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); if (string.IsNullOrWhiteSpace(message.Header)) { return; } using (ITracer activity = this.tracer.StartActivity(message.Header, EventLevel.Informational, new EventMetadata { { "request", request } })) { switch (message.Header) { case NamedPipeMessages.MountRepoRequest.Header: try { NamedPipeMessages.MountRepoRequest mountRequest = NamedPipeMessages.MountRepoRequest.FromMessage(message); MountHandler mountHandler = new MountHandler(activity, this.repoRegistry, connection, mountRequest); mountHandler.Run(); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize mount request: {0}", ex.Message); } break; case NamedPipeMessages.UnmountRepoRequest.Header: try { NamedPipeMessages.UnmountRepoRequest unmountRequest = NamedPipeMessages.UnmountRepoRequest.FromMessage(message); UnmountHandler unmountHandler = new UnmountHandler(activity, this.repoRegistry, connection, unmountRequest); unmountHandler.Run(); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize unmount request: {0}", ex.Message); } break; case NamedPipeMessages.Notification.Request.Header: try { NamedPipeMessages.Notification.Request notificationRequest = NamedPipeMessages.Notification.Request.FromMessage(message); NotificationHandler.Instance.SendNotification(activity, notificationRequest); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize notification request: {0}", ex.Message); } break; default: EventMetadata metadata = new EventMetadata(); metadata.Add("Area", EtwArea); metadata.Add("Header", message.Header); metadata.Add("ErrorMessage", "HandleNewConnection: Unknown request"); this.tracer.RelatedError(metadata); connection.TrySendResponse(NamedPipeMessages.UnknownRequest); break; } } }
public static bool TryAcquireGVFSLockForProcess( bool unattended, NamedPipeClient pipeClient, string fullCommand, int pid, bool isElevated, bool checkAvailabilityOnly, string gvfsEnlistmentRoot, out string result) { NamedPipeMessages.LockRequest request = new NamedPipeMessages.LockRequest(pid, isElevated, checkAvailabilityOnly, fullCommand); NamedPipeMessages.Message requestMessage = request.CreateMessage(NamedPipeMessages.AcquireLock.AcquireRequest); pipeClient.SendRequest(requestMessage); NamedPipeMessages.AcquireLock.Response response = new NamedPipeMessages.AcquireLock.Response(pipeClient.ReadResponse()); string message = string.Empty; switch (response.Result) { case NamedPipeMessages.AcquireLock.AcceptResult: return(CheckAcceptResponse(response, checkAvailabilityOnly, out result)); case NamedPipeMessages.AcquireLock.AvailableResult: return(CheckAcceptResponse(response, checkAvailabilityOnly, out result)); case NamedPipeMessages.AcquireLock.MountNotReadyResult: result = "GVFS has not finished initializing, please wait a few seconds and try again."; return(false); case NamedPipeMessages.AcquireLock.UnmountInProgressResult: result = "GVFS is unmounting."; return(false); case NamedPipeMessages.AcquireLock.DenyGVFSResult: message = response.DenyGVFSMessage; break; case NamedPipeMessages.AcquireLock.DenyGitResult: message = string.Format("Waiting for '{0}' to release the lock", response.ResponseData.ParsedCommand); break; default: result = "Error when acquiring the lock. Unrecognized response: " + response.CreateMessage(); return(false); } Func <bool> waitForLock = () => { while (true) { Thread.Sleep(250); pipeClient.SendRequest(requestMessage); response = new NamedPipeMessages.AcquireLock.Response(pipeClient.ReadResponse()); switch (response.Result) { case NamedPipeMessages.AcquireLock.AcceptResult: return(CheckAcceptResponse(response, checkAvailabilityOnly, out _)); case NamedPipeMessages.AcquireLock.AvailableResult: return(CheckAcceptResponse(response, checkAvailabilityOnly, out _)); case NamedPipeMessages.AcquireLock.UnmountInProgressResult: return(false); default: break; } } }; if (unattended) { waitForLock(); } else { ConsoleHelper.ShowStatusWhileRunning( waitForLock, message, output: Console.Out, showSpinner: !ConsoleHelper.IsConsoleOutputRedirectedToFile(), gvfsLogEnlistmentRoot: gvfsEnlistmentRoot); } result = null; return(true); }
private void HandleDehydrateFolders(NamedPipeMessages.Message message, NamedPipeServer.Connection connection) { NamedPipeMessages.DehydrateFolders.Request request = new NamedPipeMessages.DehydrateFolders.Request(message); EventMetadata metadata = new EventMetadata(); metadata.Add(nameof(request.Folders), request.Folders); metadata.Add(TracingConstants.MessageKey.InfoMessage, "Received dehydrate folders request"); this.tracer.RelatedEvent(EventLevel.Informational, nameof(this.HandleDehydrateFolders), metadata); NamedPipeMessages.DehydrateFolders.Response response; if (this.currentState == MountState.Ready) { response = new NamedPipeMessages.DehydrateFolders.Response(NamedPipeMessages.DehydrateFolders.DehydratedResult); string[] folders = request.Folders.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); StringBuilder resetFolderPaths = new StringBuilder(); foreach (string folder in folders) { if (this.fileSystemCallbacks.TryDehydrateFolder(folder, out string errorMessage)) { response.SuccessfulFolders.Add(folder); } else { response.FailedFolders.Add($"{folder}\0{errorMessage}"); } resetFolderPaths.Append($"\"{folder.Replace(Path.DirectorySeparatorChar, GVFSConstants.GitPathSeparator)}\" "); } // Since modified paths could have changed with the dehydrate, the paths that were dehydrated need to be reset in the index string resetPaths = resetFolderPaths.ToString(); GitProcess gitProcess = new GitProcess(this.enlistment); EventMetadata resetIndexMetadata = new EventMetadata(); resetIndexMetadata.Add(nameof(resetPaths), resetPaths); GitProcess.Result refreshIndexResult; this.resetForDehydrateInProgress = true; try { // Because we've set resetForDehydrateInProgress to true, this call to 'git reset' will also force // the projection to be updated (required because 'git reset' will adjust the skip worktree bits in // the index). refreshIndexResult = gitProcess.Reset(GVFSConstants.DotGit.HeadName, resetPaths); } finally { this.resetForDehydrateInProgress = false; } resetIndexMetadata.Add(nameof(refreshIndexResult.ExitCode), refreshIndexResult.ExitCode); resetIndexMetadata.Add(nameof(refreshIndexResult.Output), refreshIndexResult.Output); resetIndexMetadata.Add(nameof(refreshIndexResult.Errors), refreshIndexResult.Errors); resetIndexMetadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(this.HandleDehydrateFolders)}: Reset git index"); this.tracer.RelatedEvent(EventLevel.Informational, $"{nameof(this.HandleDehydrateFolders)}_ResetIndex", resetIndexMetadata); } else { response = new NamedPipeMessages.DehydrateFolders.Response(NamedPipeMessages.DehydrateFolders.MountNotReadyResult); } connection.TrySendResponse(response.CreateMessage()); }
private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection) { NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); if (string.IsNullOrWhiteSpace(message.Header)) { return; } using (ITracer activity = this.tracer.StartActivity(message.Header, EventLevel.Informational, new EventMetadata { { "request", request } })) { switch (message.Header) { case NamedPipeMessages.RegisterRepoRequest.Header: try { NamedPipeMessages.RegisterRepoRequest mountRequest = NamedPipeMessages.RegisterRepoRequest.FromMessage(message); RegisterRepoHandler mountHandler = new RegisterRepoHandler(activity, this.repoRegistry, connection, mountRequest); mountHandler.Run(); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize mount request: {0}", ex.Message); } break; case NamedPipeMessages.UnregisterRepoRequest.Header: try { NamedPipeMessages.UnregisterRepoRequest unmountRequest = NamedPipeMessages.UnregisterRepoRequest.FromMessage(message); UnregisterRepoHandler unmountHandler = new UnregisterRepoHandler(activity, this.repoRegistry, connection, unmountRequest); unmountHandler.Run(); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize unmount request: {0}", ex.Message); } break; case NamedPipeMessages.EnableAndAttachProjFSRequest.Header: try { NamedPipeMessages.EnableAndAttachProjFSRequest attachRequest = NamedPipeMessages.EnableAndAttachProjFSRequest.FromMessage(message); EnableAndAttachProjFSHandler attachHandler = new EnableAndAttachProjFSHandler(activity, connection, attachRequest); attachHandler.Run(); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize attach volume request: {0}", ex.Message); } break; case NamedPipeMessages.GetActiveRepoListRequest.Header: try { NamedPipeMessages.GetActiveRepoListRequest repoListRequest = NamedPipeMessages.GetActiveRepoListRequest.FromMessage(message); GetActiveRepoListHandler excludeHandler = new GetActiveRepoListHandler(activity, this.repoRegistry, connection, repoListRequest); excludeHandler.Run(); } catch (SerializationException ex) { activity.RelatedError("Could not deserialize repo list request: {0}", ex.Message); } break; default: EventMetadata metadata = new EventMetadata(); metadata.Add("Area", EtwArea); metadata.Add("Header", message.Header); this.tracer.RelatedWarning(metadata, "HandleNewConnection: Unknown request", Keywords.Telemetry); connection.TrySendResponse(NamedPipeMessages.UnknownRequest); break; } } }
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 bool TrySendResponse(NamedPipeMessages.Message message) { return(TrySendResponse(message.ToString())); }