Beispiel #1
0
        private static bool CheckAcceptResponse(NamedPipeMessages.AcquireLock.Response response, bool checkAvailabilityOnly, out string message)
        {
            switch (response.Result)
            {
            case NamedPipeMessages.AcquireLock.AcceptResult:
                if (!checkAvailabilityOnly)
                {
                    message = null;
                    return(true);
                }
                else
                {
                    message = "Error when acquiring the lock. Unexpected response: " + response.CreateMessage();
                    return(false);
                }

            case NamedPipeMessages.AcquireLock.AvailableResult:
                if (checkAvailabilityOnly)
                {
                    message = null;
                    return(true);
                }
                else
                {
                    message = "Error when acquiring the lock. Unexpected response: " + response.CreateMessage();
                    return(false);
                }

            default:
                message = "Error when acquiring the lock. Not an Accept result: " + response.CreateMessage();
                return(false);
            }
        }
Beispiel #2
0
        private void HandleLockRequest(NamedPipeServer.Connection connection, NamedPipeMessages.Message message)
        {
            NamedPipeMessages.AcquireLock.Response response;
            NamedPipeMessages.AcquireLock.Data     externalHolder;

            NamedPipeMessages.AcquireLock.Request request   = new NamedPipeMessages.AcquireLock.Request(message);
            NamedPipeMessages.AcquireLock.Data    requester = request.RequestData;
            if (request == null)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.UnknownRequest, requester);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool lockAcquired = this.gvfsLock.TryAcquireLock(requester, out externalHolder);

                if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                }
                else if (externalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, externalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Beispiel #3
0
        private static void AcquireGVFSLockForProcess(string fullCommand, int pid, Process parentProcess, NamedPipeClient pipeClient)
        {
            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)
            {
                return;
            }
            else if (response.Result == NamedPipeMessages.AcquireLock.MountNotReadyResult)
            {
                ExitWithError("GVFS has not finished initializing, please wait a few seconds and try again.");
            }
            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:
                    ExitWithError("Error when acquiring the lock. Unrecognized response: " + response.CreateMessage());
                    break;
                }

                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());
            }
        }
Beispiel #4
0
        private void HandleLockRequest(string messageBody, NamedPipeServer.Connection connection)
        {
            NamedPipeMessages.AcquireLock.Response response;

            NamedPipeMessages.LockRequest request   = new NamedPipeMessages.LockRequest(messageBody);
            NamedPipeMessages.LockData    requester = request.RequestData;
            if (this.currentState == MountState.Unmounting)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.UnmountInProgressResult);

                EventMetadata metadata = new EventMetadata();
                metadata.Add("LockRequest", requester.ToString());
                metadata.Add(TracingConstants.MessageKey.InfoMessage, "Request denied, unmount in progress");
                this.tracer.RelatedEvent(EventLevel.Informational, "HandleLockRequest_UnmountInProgress", metadata);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool lockAcquired = false;

                NamedPipeMessages.LockData existingExternalHolder = null;
                string denyGVFSMessage = null;

                bool lockAvailable = this.context.Repository.GVFSLock.IsLockAvailableForExternalRequestor(out existingExternalHolder);
                bool isReadyForExternalLockRequests = this.fileSystemCallbacks.IsReadyForExternalAcquireLockRequests(requester, out denyGVFSMessage);

                if (!requester.CheckAvailabilityOnly && isReadyForExternalLockRequests)
                {
                    lockAcquired = this.context.Repository.GVFSLock.TryAcquireLockForExternalRequestor(requester, out existingExternalHolder);
                }

                if (requester.CheckAvailabilityOnly && lockAvailable && isReadyForExternalLockRequests)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AvailableResult);
                }
                else if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                    this.tracer.SetGitCommandSessionId(requester.GitCommandSessionId);
                }
                else if (existingExternalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult, responseData: null, denyGVFSMessage: denyGVFSMessage);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, existingExternalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Beispiel #5
0
        private void HandleLockRequest(string messageBody, NamedPipeServer.Connection connection)
        {
            NamedPipeMessages.AcquireLock.Response response;
            NamedPipeMessages.LockData             externalHolder;

            NamedPipeMessages.LockRequest request   = new NamedPipeMessages.LockRequest(messageBody);
            NamedPipeMessages.LockData    requester = request.RequestData;
            if (request == null)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.UnknownRequest, requester);
            }
            else if (this.currentState == MountState.Unmounting)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.UnmountInProgressResult);

                EventMetadata metadata = new EventMetadata();
                metadata.Add("LockRequest", requester.ToString());
                metadata.Add(TracingConstants.MessageKey.InfoMessage, "Request denied, unmount in progress");
                this.tracer.RelatedEvent(EventLevel.Informational, "HandleLockRequest_UnmountInProgress", metadata);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool   lockAcquired = false;
                string denyMessage;
                if (this.gvfltCallbacks.IsReadyForExternalAcquireLockRequests(requester, out denyMessage))
                {
                    lockAcquired = this.context.Repository.GVFSLock.TryAcquireLock(requester, out externalHolder);
                }
                else
                {
                    // There might be an external lock holder, and it should be reported to the user
                    externalHolder = this.context.Repository.GVFSLock.GetExternalLockHolder();
                }

                if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                }
                else if (externalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult, responseData: null, denyGVFSMessage: denyMessage);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, externalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Beispiel #6
0
        private void HandleLockRequest(string messageBody, NamedPipeServer.Connection connection)
        {
            NamedPipeMessages.AcquireLock.Response response;
            NamedPipeMessages.LockData             externalHolder;

            NamedPipeMessages.LockRequest request   = new NamedPipeMessages.LockRequest(messageBody);
            NamedPipeMessages.LockData    requester = request.RequestData;
            if (request == null)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.UnknownRequest, requester);
            }
            else if (this.currentState != MountState.Ready)
            {
                response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.MountNotReadyResult);
            }
            else
            {
                bool lockAcquired = false;
                if (this.gvfltCallbacks.IsReadyForExternalAcquireLockRequests())
                {
                    lockAcquired = this.gvfsLock.TryAcquireLock(requester, out externalHolder);
                }
                else
                {
                    // There might be an external lock holder, and it should be reported to the user
                    externalHolder = this.gvfsLock.GetExternalLockHolder();
                }

                if (lockAcquired)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.AcceptResult);
                }
                else if (externalHolder == null)
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGVFSResult);
                }
                else
                {
                    response = new NamedPipeMessages.AcquireLock.Response(NamedPipeMessages.AcquireLock.DenyGitResult, externalHolder);
                }
            }

            connection.TrySendResponse(response.CreateMessage());
        }
Beispiel #7
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;
            }
        }
Beispiel #8
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);
        }
Beispiel #9
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.");
            }
        }