public void GetAllChangedFilesCmd()
 {
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Default));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules --ignored",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: false, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Default));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files=no --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.No, IgnoreSubmodulesMode.Default));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files=normal --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Normal, IgnoreSubmodulesMode.Default));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files=all --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.All, IgnoreSubmodulesMode.Default));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules=none",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.None));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules=none",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules=untracked",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Untracked));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules=dirty",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Dirty));
     Assert.AreEqual(
         "status --porcelain -z --untracked-files --ignore-submodules=all",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.All));
 }
Exemple #2
0
        private static IReadOnlyList <GitItemStatus> GetStatusChangedFiles(IGitModule module)
        {
            var cmd    = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default, noLocks: true);
            var output = module.GitExecutable.GetOutput(cmd);

            return(new GetAllChangedFilesOutputParser(() => module).Parse(output));
        }
        private void Initialize()
        {
            EnableStageButtons(false);

            Cursor.Current = Cursors.WaitCursor;

            if (_gitGetUnstagedCommand == null)
            {
                _gitGetUnstagedCommand         = new GitCommandsInstance();
                _gitGetUnstagedCommand.Exited += GitCommandsExited;
            }

            // Load unstaged files
            var allChangedFilesCmd =
                GitCommandHelpers.GetAllChangedFilesCmd(
                    !showIgnoredFilesToolStripMenuItem.Checked,
                    showUntrackedFilesToolStripMenuItem.Checked);

            _gitGetUnstagedCommand.CmdStartProcess(Settings.GitCommand, allChangedFilesCmd);

            Loading.Visible       = true;
            LoadingStaged.Visible = true;

            Cursor.Current = Cursors.Default;
        }
Exemple #4
0
            private static IReadOnlyList <GitItemStatus> GetStatusChangedFiles(IVsrModule module)
            {
                var cmd    = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default, noLocks: true);
                var output = module.GitExecutable.GetOutput(cmd);

                return(GitCommandHelpers.GetStatusChangedFilesFromString(module, output));
            }
Exemple #5
0
        private void Update()
        {
            // If the previous status call hasn't exited yet, we'll wait until it is
            // so we don't queue up a bunch of commands
            if (gitGetUnstagedCommand.IsRunning)
            {
                hasDeferredUpdateRequests = true; // defer this update request
                return;
            }

            hasDeferredUpdateRequests = false;

            if (Environment.TickCount > nextUpdateTime)
            {
                string command = GitCommandHelpers.GetAllChangedFilesCmd(true, true);
                gitGetUnstagedCommand.CmdStartProcess(Settings.GitCommand, command);

                if (hasDeferredUpdateRequests)
                {
                    // New changes were detected while processing previous changes, schedule deferred update
                    ScheduleDeferredUpdate();
                }
                else
                {
                    // Always update every 5 min, even if we don't know anything changed
                    ScheduleNextJustInCaseUpdate();
                }
            }
        }
        private string RunStatusCommand()
        {
            _ignoredFilesPending = _ignoredFilesAreStale;
            // git-status with ignored files when needed only
            string command = GitCommandHelpers.GetAllChangedFilesCmd(!_ignoredFilesPending, UntrackedFilesMode.Default);

            return(Module.RunGitCmd(command));
        }
        public async Task <IEnumerable <AutoCompleteWord> > GetAutoCompleteWordsAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var autoCompleteWords = new HashSet <string>();

            IGitModule     module = GetModule();
            ArgumentString cmd    = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default, noLocks: true);
            var            output = await module.GitExecutable.GetOutputAsync(cmd).ConfigureAwait(false);

            IReadOnlyList <GitItemStatus> changedFiles = _getAllChangedFilesOutputParser.Parse(output);

            foreach (var file in changedFiles)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var regex = GetRegexForExtension(PathUtil.GetExtension(file.Name));

                if (regex is not null)
                {
                    // HACK: need to expose require methods at IGitModule level
                    var text = await GetChangedFileTextAsync((GitModule)module, file);

                    var matches = regex.Matches(text);
                    foreach (Match match in matches)
                    {
                        // Skip first group since it always contains the entire matched string (regardless of capture groups)
                        foreach (Group group in match.Groups.OfType <Group>().Skip(1))
                        {
                            foreach (Capture capture in group.Captures)
                            {
                                autoCompleteWords.Add(capture.Value);
                            }
                        }
                    }
                }

                autoCompleteWords.Add(Path.GetFileNameWithoutExtension(file.Name));
                autoCompleteWords.Add(Path.GetFileName(file.Name));
                if (!string.IsNullOrWhiteSpace(file.OldName))
                {
                    autoCompleteWords.Add(Path.GetFileNameWithoutExtension(file.OldName));
                    autoCompleteWords.Add(Path.GetFileName(file.OldName));
                }
            }

            return(autoCompleteWords.Select(w => new AutoCompleteWord(w)));
        }
        public async Task <IEnumerable <AutoCompleteWord> > GetAutoCompleteWordsAsync(CancellationToken cancellationToken)
        {
            await TaskScheduler.Default.SwitchTo(alwaysYield : true);

            cancellationToken.ThrowIfCancellationRequested();

            var autoCompleteWords = new HashSet <string>();

            var cmd          = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default, noLocks: true);
            var output       = _module.GitExecutable.GetOutput(cmd);
            var changedFiles = GitCommandHelpers.GetStatusChangedFilesFromString(_module, output);

            foreach (var file in changedFiles)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var regex = GetRegexForExtension(Path.GetExtension(file.Name));

                if (regex != null)
                {
                    var text    = GetChangedFileText(_module, file);
                    var matches = regex.Matches(text);
                    foreach (Match match in matches)
                    {
                        // Skip first group since it always contains the entire matched string (regardless of capture groups)
                        foreach (Group group in match.Groups.OfType <Group>().Skip(1))
                        {
                            foreach (Capture capture in group.Captures)
                            {
                                autoCompleteWords.Add(capture.Value);
                            }
                        }
                    }
                }

                autoCompleteWords.Add(Path.GetFileNameWithoutExtension(file.Name));
                autoCompleteWords.Add(Path.GetFileName(file.Name));
                if (!string.IsNullOrWhiteSpace(file.OldName))
                {
                    autoCompleteWords.Add(Path.GetFileNameWithoutExtension(file.OldName));
                    autoCompleteWords.Add(Path.GetFileName(file.OldName));
                }
            }

            return(autoCompleteWords.Select(w => new AutoCompleteWord(w)));
        }
Exemple #9
0
        private void update()
        {
            // If the previous status call hasn't exited yet, we'll wait until it is
            // so we don't queue up a bunch of commands.
            if (gitGetUnstagedCommand.IsRunning)
            {
                return;
            }

            if (Environment.TickCount > nextUpdate)
            {
                string command = GitCommandHelpers.GetAllChangedFilesCmd(true, true);
                gitGetUnstagedCommand.CmdStartProcess(Settings.GitCommand, command);

                // Always update every 5 min, even if we don't know anything changed
                nextUpdate = Environment.TickCount + MAX_UPDATE_PERIOD;
            }
        }
 public void GetAllChangedFilesCmd()
 {
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Default).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files --ignored --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: false, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Default).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files=no --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.No, IgnoreSubmodulesMode.Default).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files=normal --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Normal, IgnoreSubmodulesMode.Default).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files=all --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.All, IgnoreSubmodulesMode.Default).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.None).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files --ignore-submodules=untracked",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Untracked).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files --ignore-submodules=dirty",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Dirty).Arguments);
     Assert.AreEqual(
         "-c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files --ignore-submodules=all",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.All).Arguments);
     Assert.AreEqual(
         "--no-optional-locks -c diff.ignoreSubmodules=none status --porcelain=2 -z --untracked-files --ignore-submodules",
         GitCommandHelpers.GetAllChangedFilesCmd(excludeIgnoredFiles: true, UntrackedFilesMode.Default, IgnoreSubmodulesMode.Default, noLocks: true).Arguments);
 }
        private String RunStatusCommand()
        {
            string command = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default);

            return(Module.RunGitCmd(command));
        }
Exemple #12
0
        private String RunStatusCommand()
        {
            string command = GitCommandHelpers.GetAllChangedFilesCmd(true, true);

            return(Module.RunGitCmd(command));
        }
        private void Update()
        {
            if (CurrentStatus != GitStatusMonitorState.Running)
            {
                return;
            }

            if (Environment.TickCount < _nextUpdateTime && (Environment.TickCount >= 0 || _nextUpdateTime <= 0))
            {
                return;
            }

            // If the previous status call hasn't exited yet, we'll wait until it is
            // so we don't queue up a bunch of commands
            if (_commandIsRunning ||

                // don't update status while repository is being modified by GitExt
                // or while any git process is running, mostly repository status will change
                // after these actions. Moreover, calling git status while other git command is performed
                // can cause repository crash
                UICommandsSource.UICommands.RepoChangedNotifier.IsLocked ||
                (GitVersion.Current.RaceConditionWhenGitStatusIsUpdatingIndex && Module.IsRunningGitProcess()))
            {
                _statusIsUpToDate = false; // tell that computed status isn't up to date
                return;
            }

            _commandIsRunning   = true;
            _statusIsUpToDate   = true;
            _previousUpdateTime = Environment.TickCount;

            ThreadHelper.JoinableTaskFactory.RunAsync(
                async() =>
            {
                try
                {
                    await TaskScheduler.Default;

                    _ignoredFilesPending = _ignoredFilesAreStale;

                    // git-status with ignored files when needed only
                    var cmd          = GitCommandHelpers.GetAllChangedFilesCmd(!_ignoredFilesPending, UntrackedFilesMode.Default, noLocks: true);
                    var output       = Module.RunGitCmd(cmd);
                    var changedFiles = GitCommandHelpers.GetStatusChangedFilesFromString(Module, output);

                    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                    UpdatedStatusReceived(changedFiles);
                }
                catch
                {
                    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                    _commandIsRunning = false;
                    CurrentStatus     = GitStatusMonitorState.Stopped;
                }
            })
            .FileAndForget();

            // Schedule update every 5 min, even if we don't know that anything changed
            CalculateNextUpdateTime(MaxUpdatePeriod);

            return;

            void UpdatedStatusReceived(IReadOnlyList <GitItemStatus> changedFiles)
            {
                // Adjust the interval between updates. (This does not affect an update already scheduled).
                _currentUpdateInterval = Math.Max(MinUpdateInterval, 3 * (Environment.TickCount - _previousUpdateTime));
                _commandIsRunning      = false;

                if (CurrentStatus != GitStatusMonitorState.Running)
                {
                    return;
                }

                GitWorkingDirectoryStatusChanged?.Invoke(this, new GitWorkingDirectoryStatusEventArgs(changedFiles.Where(item => !item.IsIgnored)));
                if (_ignoredFilesPending)
                {
                    _ignoredFilesPending = false;
                    _ignoredFiles        = new HashSet <string>(changedFiles.Where(item => item.IsIgnored).Select(item => item.Name));
                    if (_statusIsUpToDate)
                    {
                        _ignoredFilesAreStale = false;
                    }
                }

                if (!_statusIsUpToDate)
                {
                    // Still not up-to-date, but present what received, GetAllChangedFilesCmd() is the heavy command
                    CalculateNextUpdateTime(UpdateDelay);
                }
            }
        }
Exemple #14
0
        public override bool Execute(GitUIBaseEventArgs args)
        {
            var       module        = (GitModule)args.GitModule;
            var       allChangesCmd = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.All, IgnoreSubmodulesMode.All);;
            CmdResult cmdResult;
            var       exitCode = args.GitModule.RunGitCmdResult("submodule update --init --recursive").ExitCode;

            // öncelikle bekleyen hiçbir değişiklik olmadığından emin oluyoruz
            var status       = args.GitModule.RunGitCmdResult(allChangesCmd);
            var statusString = status.StdOutput;

            exitCode = status.ExitCode;
            var changedFiles = GitCommandHelpers.GetAllChangedFilesFromString(module, statusString);

            if (changedFiles.Count != 0)
            {
                MessageBox.Show("Commit edilmeyi bekleyen dosyalarınız var. Lütfen TEST işleminden önce bu dosyaları commit ediniz!");
                return(false);
            }

            // bunun bir feature branch i olmasını kontrol et
            var featureBranch = (args.GitModule.GetSelectedBranch() ?? "").ToLowerInvariant();

            if (featureBranch.IsNullOrEmpty() || featureBranch == "master" || featureBranch == "test")
            {
                MessageBox.Show("Bu işlem master ya da test branch lerinde yapılamaz!");
                return(false);
            }

            // son kez onay alalım
            if (!Dialogs.Confirm("Bulunduğunuz branch, TEST'e gönderilecek.\n\n" +
                                 "Devam etmek istiyor musunuz?"))
            {
                return(true);
            }

            // origin deki son değişikliklerden haberdar ol
            var fetchCmd     = module.FetchCmd("origin", "", "");
            var fetchResultX = args.GitModule.RunGitCmdResult(fetchCmd);

            exitCode = fetchResultX.ExitCode;
            if (exitCode != 0)
            {
                MessageBox.Show("Fetch işlemi esnasında şu hata alındı:\n" +
                                fetchResultX.StdError + "\nExitCode:" + exitCode);
                return(false);
            }

            // remote branch varsa, son değişiklikleri pull edelim
            var remoteBranchExists = module.GetRefs(false, true).Any(x => x.Name == featureBranch & x.IsRemote);

            if (remoteBranchExists)
            {
                var pullFeatureCmd = module.PullCmd("origin", featureBranch, featureBranch, false);
                cmdResult = args.GitModule.RunGitCmdResult(pullFeatureCmd);
                var pullFeatureResult = cmdResult.StdError;
                exitCode = cmdResult.ExitCode;

                if (exitCode != 0)
                {
                    MessageBox.Show("Feature pull işlemi esnasında şu hata alındı:\n" +
                                    pullFeatureResult + "\nExitCode:" + exitCode);
                    return(true);
                }
            }

            // test branch ine geçiş yap
            var switchBranchCmd = GitCommandHelpers.CheckoutCmd("test", LocalChangesAction.DontChange);

            exitCode = args.GitModule.RunGitCmdResult(switchBranchCmd).ExitCode;

            var currentBranch = args.GitModule.GetSelectedBranch().ToLowerInvariant();

            if (currentBranch != "test")
            {
                MessageBox.Show("Test branch'ine geçiş yapılamadı. İşleme devam edilemiyor!");
                return(true);
            }

            // varsa test teki son değişiklikleri al
            // test e direk commit olmayacağı varsayıldığından rebase e gerek yok.
            var pullCmd = module.PullCmd("origin", "test", "test", false);

            cmdResult = args.GitModule.RunGitCmdResult(pullCmd);
            var pullResult = cmdResult.StdError;

            exitCode = cmdResult.ExitCode;

            if (exitCode != 0)
            {
                MessageBox.Show("Test'ten pull işlemi esnasında şu hata alındı:\n" +
                                pullResult + "\nExitCode:" + exitCode);
                return(true);
            }

            // feature branch i test e birleştir
            var mergeCmd = GitCommandHelpers.MergeBranchCmd(featureBranch, allowFastForward: false, squash: false, noCommit: false, strategy: "");

            cmdResult = args.GitModule.RunGitCmdResult(mergeCmd);
            var mergeResult = cmdResult.StdError;

            exitCode = cmdResult.ExitCode;

            if (exitCode != 0)
            {
                MessageBox.Show("Merge işlemi esnasında şu hata alındı:\n" +
                                mergeResult + "\nExitCode:" + exitCode);
                return(true);
            }

            MessageBox.Show(String.Format("{0} feature branch'i başarıyla TEST'e merge edildi.\n\nLütfen projeyi son haliyle TEST'teyken " +
                                          "build edip, PUSH işlemi yapınız.", featureBranch));

            Clipboard.SetText("Gerekli kontroller yapılmıştır, gerçek ortama çıkarılabilir mi?");

            return(true);
        }
        private void Update()
        {
            ThreadHelper.AssertOnUIThread();

            if (CurrentStatus != GitStatusMonitorState.Running)
            {
                return;
            }

            if (Environment.TickCount < _nextUpdateTime && (Environment.TickCount >= 0 || _nextUpdateTime <= 0))
            {
                return;
            }

            // If the previous status call hasn't exited yet, we'll wait until it is
            // so we don't queue up a bunch of commands
            if (_commandIsRunning ||

                // don't update status while repository is being modified by GitExt,
                // repository status will change after these actions.
                UICommandsSource.UICommands.RepoChangedNotifier.IsLocked ||
                (GitVersion.Current.RaceConditionWhenGitStatusIsUpdatingIndex && Module.IsRunningGitProcess()))
            {
                _statusIsUpToDate = false; // schedule new update when command is finished
                return;
            }

            _workTreeWatcher.EnableRaisingEvents = true;
            _commandIsRunning   = true;
            _statusIsUpToDate   = true;
            _previousUpdateTime = Environment.TickCount;

            // Schedule update every 5 min, even if we don't know that anything changed
            CalculateNextUpdateTime(PeriodicUpdateInterval);

            // capture a consistent state in the main thread
            IGitModule module = Module;

            ThreadHelper.JoinableTaskFactory.RunAsync(
                async() =>
            {
                try
                {
                    try
                    {
                        await TaskScheduler.Default;

                        var cmd          = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default, noLocks: true);
                        var output       = module.RunGitCmd(cmd);
                        var changedFiles = GitCommandHelpers.GetStatusChangedFilesFromString(module, output);

                        await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                        if (!ModuleHasChanged())
                        {
                            UpdatedStatusReceived(changedFiles);
                        }
                    }
                    catch
                    {
                        try
                        {
                            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                            // Avoid possible popups on every file changes
                            CurrentStatus = GitStatusMonitorState.Stopped;
                        }
                        catch
                        {
                            // No action
                        }

                        throw;
                    }
                }
                finally
                {
                    _commandIsRunning = false;
                }
            })
            .FileAndForget();

            return;

            bool ModuleHasChanged()
            {
                return(module != Module);
            }

            void UpdatedStatusReceived(IEnumerable <GitItemStatus> changedFiles)
            {
                // Adjust the interval between updates. (This does not affect an update already scheduled).
                _currentUpdateInterval = Math.Max(MinUpdateInterval, 3 * (Environment.TickCount - _previousUpdateTime));

                GitWorkingDirectoryStatusChanged?.Invoke(this, new GitWorkingDirectoryStatusEventArgs(changedFiles));

                if (!_statusIsUpToDate)
                {
                    // Command was requested when this command was running
                    // Will always be scheduled as background update (even if requested interactively orignally)
                    CalculateNextUpdateTime();
                }
            }
        }
Exemple #16
0
        private void Update()
        {
            ThreadHelper.AssertOnUIThread();

            if (CurrentStatus != GitStatusMonitorState.Running)
            {
                return;
            }

            if (Environment.TickCount < _nextUpdateTime)
            {
                return;
            }

            // If the previous status call hasn't exited yet,
            // schedule new update when command is finished
            if (_commandIsRunning)
            {
                ScheduleNextUpdateTime(0);
                return;
            }

            // don't update status while repository is being modified by GitExt,
            // repository status will change after these actions.
            if (UICommandsSource.UICommands.RepoChangedNotifier.IsLocked ||
                (GitVersion.Current.RaceConditionWhenGitStatusIsUpdatingIndex && Module.IsRunningGitProcess()))
            {
                ScheduleNextUpdateTime(0);
                return;
            }

            _commandIsRunning  = true;
            _nextIsInteractive = false;
            var commandStartTime = Environment.TickCount;

            _workTreeWatcher.EnableRaisingEvents = true;

            // Schedule update every 5 min, even if we don't know that anything changed
            ScheduleNextUpdateTime(PeriodicUpdateInterval);

            // capture a consistent state in the main thread
            IGitModule module = Module;

            ThreadHelper.JoinableTaskFactory.RunAsync(
                async() =>
            {
                try
                {
                    await TaskScheduler.Default;

                    var cmd = GitCommandHelpers.GetAllChangedFilesCmd(true, UntrackedFilesMode.Default,
                                                                      noLocks: true);
                    var output       = module.RunGitCmd(cmd);
                    var changedFiles = GitCommandHelpers.GetStatusChangedFilesFromString(module, output);

                    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                    if (!ModuleHasChanged())
                    {
                        UpdatedStatusReceived(changedFiles);
                    }
                }
                catch
                {
                    try
                    {
                        await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                        // Avoid possible popups on every file changes
                        CurrentStatus = GitStatusMonitorState.Stopped;
                    }
                    catch
                    {
                        // No action
                    }

                    throw;
                }
                finally
                {
                    _commandIsRunning = false;
                }
            })
            .FileAndForget();

            return;

            bool ModuleHasChanged()
            {
                return(module != Module);
            }

            void UpdatedStatusReceived(IEnumerable <GitItemStatus> changedFiles)
            {
                // Adjust the interval between updates, schedule new to recalculate
                _nextEarliestTime = commandStartTime +
                                    Math.Max(MinUpdateInterval, 3 * (Environment.TickCount - commandStartTime));
                ScheduleNextUpdateTime(PeriodicUpdateInterval);

                GitWorkingDirectoryStatusChanged?.Invoke(this, new GitWorkingDirectoryStatusEventArgs(changedFiles));
            }
        }