Exemplo n.º 1
0
        /// <summary>
        /// Update the detailed status from the git status
        /// </summary>
        /// <param name="module">Current module</param>
        /// <param name="gitStatus">git status</param>
        /// <param name="cancelToken">Cancellation token</param>
        /// <returns>The task</returns>
        private async Task UpdateSubmodulesStatusAsync(VsrModule module, [CanBeNull] IReadOnlyList <GitItemStatus> gitStatus, CancellationToken cancelToken)
        {
            _previousSubmoduleUpdateTime = DateTime.Now;
            await TaskScheduler.Default;

            // TopModule is dirty if there are any changes in any module
            if (gitStatus != null &&
                gitStatus.Count > 0)
            {
                SetTopModuleAsDirty(module.GetTopModule().WorkingDir);
            }
            else if (module.GetTopModule() == module)
            {
                // status includes top module changes to files and 'dirty' can be cleared
                // (keep 'dirty' if unknown)
                _submoduleInfos[module.WorkingDir].Detailed = null;
            }

            var changedSubmodules = gitStatus.Where(i => i.IsSubmodule);

            foreach (var submoduleName in module.GetSubmodulesLocalPaths(false).Where(s => !changedSubmodules.Any(i => i.Name == s)))
            {
                SetSubmoduleEmptyDetailedStatus(module, submoduleName);
            }

            foreach (var submoduleName in changedSubmodules)
            {
                cancelToken.ThrowIfCancellationRequested();

                await GetSubmoduleDetailedStatusAsync(module, submoduleName.Name, cancelToken);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get the detailed submodule status for 'submoduleName' and below
        /// </summary>
        /// <param name="superModule">Module to compare to</param>
        /// <param name="submoduleName">Name of the submodule</param>
        /// <param name="cancelToken">Cancelation token</param>
        /// <returns>the task</returns>
        private async Task GetSubmoduleDetailedStatusAsync(VsrModule superModule, string submoduleName, CancellationToken cancelToken)
        {
            if (superModule == null || string.IsNullOrWhiteSpace(submoduleName))
            {
                return;
            }

            var path = superModule.GetSubmoduleFullPath(submoduleName);

            if (!_submoduleInfos.ContainsKey(path) || _submoduleInfos[path] == null)
            {
                return;
            }

            var info = _submoduleInfos[path];

            cancelToken.ThrowIfCancellationRequested();

            var submoduleStatus = await GitCommandHelpers.GetCurrentSubmoduleChangesAsync(superModule, submoduleName, noLocks : true)
                                  .ConfigureAwait(false);

            if (submoduleStatus != null && submoduleStatus.Commit != submoduleStatus.OldCommit)
            {
                submoduleStatus.CheckSubmoduleStatus(submoduleStatus.GetSubmodule(superModule));
            }

            info.Detailed = submoduleStatus == null ?
                            null :
                            new DetailedSubmoduleInfo()
            {
                Status              = submoduleStatus.Status,
                IsDirty             = submoduleStatus.IsDirty,
                AddedAndRemovedText = submoduleStatus.AddedAndRemovedString()
            };

            if (submoduleStatus != null)
            {
                SetTopModuleAsDirty(superModule.GetTopModule().WorkingDir);
            }

            // Recursively update submodules
            var module = new VsrModule(path);

            await GetSubmoduleDetailedStatusAsync(module, cancelToken);
        }
            private void AddNodesToTree(
                ref Nodes nodes,
                List <SubmoduleNode> submoduleNodes,
                VsrModule threadModule,
                SubmoduleInfo topProject)
            {
                // Create tree of SubmoduleFolderNode for each path directory and add input SubmoduleNodes as leaves.

                // Example of (SuperPath + LocalPath).ToPosixPath() for all nodes:
                //
                // C:/code/gitextensions2/Externals/conemu-inside
                // C:/code/gitextensions2/Externals/Git.hub
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor/gitextensions
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor/gitextensions/Externals/conemu-inside
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor/gitextensions/Externals/Git.hub
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor/gitextensions/Externals/ICSharpCode.TextEditor
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor/gitextensions/Externals/NBug
                // C:/code/gitextensions2/Externals/ICSharpCode.TextEditor/gitextensions/GitExtensionsDoc
                // C:/code/gitextensions2/Externals/NBug
                // C:/code/gitextensions2/GitExtensionsDoc
                //
                // What we want to do is first remove the topModule portion, "C:/code/gitextensions2/", and
                // then build our tree by breaking up each path into parts, separated by '/'.
                //
                // Note that when we break up the paths, some parts are just directories, the others are submodule nodes:
                //
                // Externals / ICSharpCode.TextEditor / gitextensions / Externals / Git.hub
                //  folder          submodule             submodule      folder     submodule
                //
                // Input 'nodes' is an array of SubmoduleNodes for all the submodules; now we need to create SubmoduleFolderNodes
                // and insert everything into a tree.

                var topModule = threadModule.GetTopModule();

                // Build a mapping of top-module-relative path to node
                var pathToNodes = new Dictionary <string, Node>();

                // Add existing SubmoduleNodes
                foreach (var node in submoduleNodes)
                {
                    pathToNodes[GetNodeRelativePath(topModule, node)] = node;
                }

                // Create and add missing SubmoduleFolderNodes
                foreach (var node in submoduleNodes)
                {
                    var parts = GetNodeRelativePath(topModule, node).Split('/');
                    for (int i = 0; i < parts.Length - 1; ++i)
                    {
                        var path = string.Join("/", parts.Take(i + 1));
                        if (!pathToNodes.ContainsKey(path))
                        {
                            pathToNodes[path] = new SubmoduleFolderNode(this, parts[i]);
                        }
                    }
                }

                // Now build the tree
                var rootNode    = new DummyNode();
                var nodesInTree = new HashSet <Node>();

                foreach (var node in submoduleNodes)
                {
                    Node parentNode = rootNode;
                    var  parts      = GetNodeRelativePath(topModule, node).Split('/');
                    for (int i = 0; i < parts.Length; ++i)
                    {
                        var path      = string.Join("/", parts.Take(i + 1));
                        var nodeToAdd = pathToNodes[path];

                        // If node is not already in the tree, add it
                        if (!nodesInTree.Contains(nodeToAdd))
                        {
                            parentNode.Nodes.AddNode(nodeToAdd);
                            nodesInTree.Add(nodeToAdd);
                        }

                        parentNode = nodeToAdd;
                    }
                }

                // Add top-module node, and move children of root to it
                var topModuleNode = new SubmoduleNode(this, topProject, topProject.Bold, "", topProject.Path);

                topModuleNode.Nodes.AddNodes(rootNode.Nodes);
                nodes.AddNode(topModuleNode);
            }
Exemplo n.º 4
0
        /// <inheritdoc />
        public void UpdateSubmodulesStructure(string workingDirectory, string noBranchText, bool updateStatus)
        {
            _submoduleInfoResult             = null;
            _gitStatusWhileUpdatingStructure = null;
            _submoduleInfos.Clear();
            ThreadHelper.JoinableTaskFactory.RunAsync(async() =>
            {
                // Cancel any previous async activities:
                var cancelToken = _submodulesStatusSequence.Next();

                // Do not throttle next status update
                _previousSubmoduleUpdateTime = DateTime.MinValue;

                OnStatusUpdating();

                await TaskScheduler.Default;

                // Start gathering new submodule structure asynchronously.
                var currentModule = new VsrModule(workingDirectory);
                var result        = new SubmoduleInfoResult
                {
                    Module = currentModule
                };

                // Add all submodules inside the current repository:
                GetRepositorySubmodulesStructure(result, noBranchText);
                GetSuperProjectRepositorySubmodulesStructure(currentModule, result, noBranchText);

                // Structure is updated
                OnStatusUpdated(result, cancelToken);

                // Prepare info for status updates (normally triggered by StatusMonitor)
                foreach (var info in result.OurSubmodules)
                {
                    _submoduleInfos[info.Path] = info;
                }

                foreach (var info in result.SuperSubmodules)
                {
                    _submoduleInfos[info.Path] = info;
                }

                if (!_submoduleInfos.ContainsKey(result.TopProject.Path))
                {
                    _submoduleInfos.Add(result.TopProject.Path, result.TopProject);
                }

                // Start update status for the submodules
                if (updateStatus)
                {
                    if (result.SuperProject != null)
                    {
                        // Update from top module (will stop at current)
                        await GetSubmoduleDetailedStatusAsync(currentModule.GetTopModule(), cancelToken);
                    }

                    if (_gitStatusWhileUpdatingStructure != null)
                    {
                        // Current module must be updated separately (not in _submoduleInfos)
                        await UpdateSubmodulesStatusAsync(currentModule, _gitStatusWhileUpdatingStructure, cancelToken);
                    }

                    OnStatusUpdated(result, cancelToken);
                }

                _submoduleInfoResult = result;
            }).FileAndForget();
        }