public static async Task <Readme> GetReadme(GitHubClient client, string url) { SubmoduleInfo info = ParseURL(url); var readme = await client.Repository.Content.GetReadme(info.Name, info.Owner); return(readme); }
public SubmoduleNode(Tree tree, SubmoduleInfo submoduleInfo, bool isCurrent, string localPath, string superPath) : base(tree) { Info = submoduleInfo; IsCurrent = isCurrent; LocalPath = localPath; SuperPath = superPath; // Extract submodule name and branch // e.g. Info.Text = "Externals/conemu-inside [no branch]" // Note that the branch portion won't be there if the user hasn't yet init'd + updated the submodule. var pathAndBranch = Info.Text.Split(new char[] { ' ' }, 2); Trace.Assert(pathAndBranch.Length >= 1); SubmoduleName = pathAndBranch[0].SubstringAfterLast('/'); // Remove path BranchText = pathAndBranch.Length == 2 ? " " + pathAndBranch[1] : ""; }
public static SubmoduleInfo ParseURL(string url) { string str = url; if (url.EndsWith(".git")) { str = url.Substring(0, url.Length - 4); } var strings = str.Split('/'); SubmoduleInfo info = new SubmoduleInfo(); if (strings.Length >= 3) { info.Name = strings[strings.Length - 1].Trim(); info.Owner = strings[strings.Length - 2].Trim(); } return(info); }
private void UpdateSubmodulesList() { _previousUpdateTime = DateTime.Now; // Cancel any previous async activities: _submodulesStatusCTS.Cancel(); _submodulesStatusCTS.Dispose(); _submodulesStatusCTS = new CancellationTokenSource(); RemoveSubmoduleButtons(); toolStripButtonLevelUp.DropDownItems.Add(_loading.Text); // Start gathering new submodule information asynchronously. This makes a significant difference in UI // responsiveness if there are numerous submodules (e.g. > 100). var cancelToken = _submodulesStatusCTS.Token; string thisModuleDir = Module.WorkingDir; // First task: Gather list of submodules on a background thread. var updateTask = Task.Factory.StartNew(() => { // Don't access Module directly because it's not thread-safe. Use a thread-local version: GitModule threadModule = new GitModule(thisModuleDir); SubmoduleInfoResult result = new SubmoduleInfoResult(); // Add all submodules inside the current repository: foreach (var submodule in threadModule.GetSubmodulesLocalPaths().OrderBy(submoduleName => submoduleName)) { cancelToken.ThrowIfCancellationRequested(); var name = submodule; string path = threadModule.GetSubmoduleFullPath(submodule); if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); var smi = new SubmoduleInfo { Text = name, Path = path }; result.OurSubmodules.Add(smi); GetSubmoduleStatusAsync(smi, cancelToken); } if (threadModule.SuperprojectModule != null) { GitModule supersuperproject = threadModule.FindTopProjectModule(); if (threadModule.SuperprojectModule.WorkingDir != supersuperproject.WorkingDir) { var name = Path.GetFileName(Path.GetDirectoryName(supersuperproject.WorkingDir)); string path = supersuperproject.WorkingDir; if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); result.TopProject = new SubmoduleInfo { Text = name, Path = supersuperproject.WorkingDir }; GetSubmoduleStatusAsync(result.TopProject, cancelToken); } { string name; GitModule parentModule = threadModule.SuperprojectModule; string localpath = ""; if (threadModule.SuperprojectModule.WorkingDir != supersuperproject.WorkingDir) { parentModule = supersuperproject; localpath = threadModule.SuperprojectModule.WorkingDir.Substring(supersuperproject.WorkingDir.Length); localpath = PathUtil.GetDirectoryName(localpath.ToPosixPath()); name = localpath; } else name = Path.GetFileName(Path.GetDirectoryName(supersuperproject.WorkingDir)); string path = threadModule.SuperprojectModule.WorkingDir; if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); result.Superproject = new SubmoduleInfo { Text = name, Path = threadModule.SuperprojectModule.WorkingDir }; GetSubmoduleStatusAsync(result.Superproject, cancelToken); } var submodules = supersuperproject.GetSubmodulesLocalPaths().OrderBy(submoduleName => submoduleName); if (submodules.Any()) { string localpath = threadModule.WorkingDir.Substring(supersuperproject.WorkingDir.Length); localpath = PathUtil.GetDirectoryName(localpath.ToPosixPath()); foreach (var submodule in submodules) { cancelToken.ThrowIfCancellationRequested(); var name = submodule; string path = supersuperproject.GetSubmoduleFullPath(submodule); if (Settings.DashboardShowCurrentBranch && !GitModule.IsBareRepository(path)) name = name + " " + GetModuleBranch(path); bool bold = false; if (submodule == localpath) { result.CurrentSubmoduleName = threadModule.GetCurrentSubmoduleLocalPath(); bold = true; } var smi = new SubmoduleInfo { Text = name, Path = path, Bold = bold }; result.SuperSubmodules.Add(smi); GetSubmoduleStatusAsync(smi, cancelToken); } } } return result; }, cancelToken); // Second task: Populate toolbar menu on UI thread. Note further tasks are created by // CreateSubmoduleMenuItem to update images with submodule status. updateTask.ContinueWith((task) => { if (task.Result == null) return; RemoveSubmoduleButtons(); var newItems = new List<ToolStripItem>(); task.Result.OurSubmodules.ForEach(submodule => newItems.Add(CreateSubmoduleMenuItem(submodule))); if (task.Result.OurSubmodules.Count == 0) newItems.Add(new ToolStripMenuItem(_noSubmodulesPresent.Text)); if (task.Result.Superproject != null) { newItems.Add(new ToolStripSeparator()); if (task.Result.TopProject != null) newItems.Add(CreateSubmoduleMenuItem(task.Result.TopProject, _topProjectModuleFormat.Text)); newItems.Add(CreateSubmoduleMenuItem(task.Result.Superproject, _superprojectModuleFormat.Text)); task.Result.SuperSubmodules.ForEach(submodule => newItems.Add(CreateSubmoduleMenuItem(submodule))); } newItems.Add(new ToolStripSeparator()); var mi = new ToolStripMenuItem(updateAllSubmodulesToolStripMenuItem.Text); mi.Click += UpdateAllSubmodulesToolStripMenuItemClick; newItems.Add(mi); if (task.Result.CurrentSubmoduleName != null) { var usmi = new ToolStripMenuItem(_updateCurrentSubmodule.Text); usmi.Tag = task.Result.CurrentSubmoduleName; usmi.Click += UpdateSubmoduleToolStripMenuItemClick; newItems.Add(usmi); } // Using AddRange is critical: if you used Add to add menu items one at a // time, performance would be extremely slow with many submodules (> 100). toolStripButtonLevelUp.DropDownItems.AddRange(newItems.ToArray()); _previousUpdateTime = DateTime.Now; }, cancelToken, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext()); }
private static void GetSubmoduleStatusAsync(SubmoduleInfo info, CancellationToken cancelToken) { Task.Factory.StartNew(() => { var submodule = new GitModule(info.Path); var supermodule = submodule.SuperprojectModule; var submoduleName = submodule.GetCurrentSubmoduleLocalPath(); info.Status = null; if (String.IsNullOrEmpty(submoduleName) || supermodule == null) return; var submoduleStatus = GitCommandHelpers.GetCurrentSubmoduleChanges(supermodule, submoduleName); if (submoduleStatus != null && submoduleStatus.Commit != submoduleStatus.OldCommit) { submoduleStatus.CheckSubmoduleStatus(submoduleStatus.GetSubmodule(supermodule)); } if (submoduleStatus != null) { info.Status = submoduleStatus.Status; info.IsDirty = submoduleStatus.IsDirty; info.Text += submoduleStatus.AddedAndRemovedString(); } }, cancelToken, TaskCreationOptions.AttachedToParent, TaskScheduler.Default); }
private static Image GetItemImage(SubmoduleInfo info) { if (info.Status == null) return Resources.IconFolderSubmodule; if (info.Status == SubmoduleStatus.FastForward) return info.IsDirty ? Resources.IconSubmoduleRevisionUpDirty : Resources.IconSubmoduleRevisionUp; if (info.Status == SubmoduleStatus.Rewind) return info.IsDirty ? Resources.IconSubmoduleRevisionDownDirty : Resources.IconSubmoduleRevisionDown; if (info.Status == SubmoduleStatus.NewerTime) return info.IsDirty ? Resources.IconSubmoduleRevisionSemiUpDirty : Resources.IconSubmoduleRevisionSemiUp; if (info.Status == SubmoduleStatus.OlderTime) return info.IsDirty ? Resources.IconSubmoduleRevisionSemiDownDirty : Resources.IconSubmoduleRevisionSemiDown; return info.IsDirty ? Resources.IconSubmoduleDirty : Resources.Modified; }
private ToolStripMenuItem CreateSubmoduleMenuItem(SubmoduleInfo info) { return CreateSubmoduleMenuItem(info, "{0}"); }
private ToolStripMenuItem CreateSubmoduleMenuItem(SubmoduleInfo info, string textFormat) { var spmenu = new ToolStripMenuItem(string.Format(textFormat, info.Text)); spmenu.Click += SubmoduleToolStripButtonClick; spmenu.Width = 200; spmenu.Tag = info.Path; if (info.Bold) spmenu.Font = new Font(spmenu.Font, FontStyle.Bold); spmenu.Image = GetItemImage(info); return spmenu; }
private void AddNodesToTree( ref Nodes nodes, List <SubmoduleNode> submoduleNodes, GitModule threadModule, SubmoduleInfo topProject) { if (!UseFolderTree) { nodes.AddNodes(submoduleNodes); return; } // 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); }