예제 #1
0
        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;
            }
        }
예제 #2
0
        /// <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);
                }
            }
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        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);
                }
            }
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
 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);
     }
 }
예제 #7
0
        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;
            }
        }
예제 #8
0
        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());
            }
        }
예제 #9
0
        /// <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);
                    }
                }
            }
        }
예제 #10
0
파일: MountVerb.cs 프로젝트: smodin/GVFS
        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);
                }
            }
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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;
            }
        }
예제 #13
0
        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());
        }
예제 #14
0
        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());
        }
예제 #15
0
        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());
        }
예제 #16
0
        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());
        }
예제 #17
0
        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);
            }
        }
예제 #18
0
        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;
                }
            }
        }
예제 #19
0
        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;
            }
        }
예제 #20
0
        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());
        }
예제 #21
0
        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);
                    }
                }
            }
        }
예제 #22
0
        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);
            }
        }
예제 #23
0
        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;
                }
            }
        }
예제 #24
0
        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);
        }
예제 #25
0
        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());
        }
예제 #26
0
        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;
                }
            }
        }
예제 #27
0
        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.");
            }
        }
예제 #28
0
 public bool TrySendResponse(NamedPipeMessages.Message message)
 {
     return(TrySendResponse(message.ToString()));
 }