private void SetActiveBranchCommits(MRepository repository) { IEnumerable <MSubBranch> branches = repository.SubBranches.Values .Where(b => b.TipCommit.BranchId == null && b.IsActive); foreach (MSubBranch branch in branches) { MCommit branchTip = branch.TipCommit; MCommit last = TryFindFirstAncestorWithSameName(branchTip, branch.Name); if (last == null) { // Could not find first ancestor commit with branch name continue; } foreach (MCommit current in branchTip.CommitAndFirstAncestors()) { current.SetBranchName(branch.Name); current.SubBranchId = branch.SubBranchId; if (current == last) { break; } } } }
private static void SetBranchCommitsOfParents(MRepository repository) { bool found; do { found = false; foreach (var commit in repository.Commits.Values) { if (commit.BranchId == null && !commit.HasBranchName && commit.HasFirstChild) { MCommit firstChild = commit.FirstChildren.ElementAt(0); if (firstChild.HasBranchName) { if (commit.FirstChildren.All(c => c.BranchName == firstChild.BranchName)) { commit.SetBranchName(firstChild.BranchName); commit.SubBranchId = firstChild.SubBranchId; found = true; } } } } } while (found); }
private static void SetMasterBranchCommits(MRepository repository, MSubBranch subBranch) { CommitId commitId = subBranch.TipCommitId; while (commitId != CommitId.None) { MCommit commit = repository.Commits[commitId]; if (commit.BranchName == subBranch.Name && commit.SubBranchId != null) { // Do not break if commit is the tip if (!(commit.Id == subBranch.TipCommitId && commit.SubBranchId == subBranch.SubBranchId)) { break; } } if (commit.HasBranchName && commit.BranchName != subBranch.Name) { Log.Warn($"commit {commit} already has branch {commit.BranchName} != {subBranch.Name}"); break; } commit.SetBranchName(subBranch.Name); commit.SubBranchId = subBranch.SubBranchId; commitId = commit.FirstParentId; } }
private static void AddEmptyBranchesVirtualTipCommits(MRepository repository) { IEnumerable <MBranch> emptyBranches = repository.Branches.Values .Where(b => !b.Commits.Any() && !b.IsLocalPart); foreach (MBranch branch in emptyBranches) { string virtualShaText = (Guid.NewGuid() + Guid.NewGuid().ToString()).Replace("-", "") .Substring(0, 40); CommitSha virtualSha = new CommitSha(virtualShaText); CommitId virtualId = new CommitId(virtualShaText); MCommit commit = AddVirtualCommit(repository, virtualId); commit.IsVirtual = true; commit.BranchId = branch.Id; commit.SetBranchName(branch.Name); CopyToVirtualCommit(repository, branch, commit, virtualSha); SetChildOfParents(commit); //repository.Commits[commit.Id] = commit; branch.CommitIds.Add(commit.Id); branch.TipCommitId = commit.Id; branch.FirstCommitId = commit.Id; branch.TipCommit.BranchTips = $"{branch.Name} branch tip"; } }
private MCommit TryFindFirstAncestorWithSameName(MCommit startCommit, BranchName branchName) { foreach (MCommit commit in startCommit.CommitAndFirstAncestors()) { BranchName commitBranchName = GetBranchName(commit); if (commitBranchName != null) { if (commitBranchName == branchName) { // Found an ancestor, which has branch name we are searching fore return(commit); } else { // Fond an ancestor with another different name break; } } if (commit != startCommit && commit.BranchTipBranches.Count == 1 && commit.BranchTipBranches[0].Name == branchName) { // Found a commit with a branch tip of a branch with same name, // this can happen for local/remote pairs. Lets assume the commit is the on that branch return(commit); } } // Could not find an ancestor with the branch name we a searching for return(null); }
private static int CompareCommitsDescending(MCommit c1, MCommit c2) { if (c1 == c2) { return(0); } if (c1.CommitDate < c2.CommitDate) { return(1); } else if (c1.CommitDate > c2.CommitDate) { return(-1); } else { if (c2.Parents.Any(c => c.Id == c1.Id)) { return(1); } else if (c1.Parents.Any(c => c.Id == c2.Id)) { return(-1); } return(0); } }
private static void SetParentCommitId(MRepository repository) { foreach (var subBranch in repository.SubBranches.Values) { MCommit tipCommit = subBranch.TipCommit; if (tipCommit.BranchId != null) { if (tipCommit.BranchName == subBranch.Name) { subBranch.ParentCommitId = repository.Branches[tipCommit.BranchId].ParentCommitId; } else { // This is a branch with no commits subBranch.ParentCommitId = tipCommit.Id; } } else { IEnumerable <MCommit> commits = subBranch.TipCommit.CommitAndFirstAncestors() .TakeWhile(c => c.BranchName == subBranch.Name); bool foundParent = false; MCommit currentcommit = null; foreach (MCommit commit in commits) { if (commit.BranchId != null) { subBranch.ParentCommitId = repository.Branches[commit.BranchId].ParentCommitId; foundParent = true; break; } currentcommit = commit; } if (!foundParent) { if (currentcommit != null) { // Sub branch has at least one commit MCommit firstCommit = currentcommit; subBranch.ParentCommitId = firstCommit.FirstParentId; } else { // Sub branch has no commits of its own, setting parent commit to same as branch tip subBranch.ParentCommitId = tipCommit.Id; } } } } }
public IEnumerable <MCommit> FirstAncestors() { MCommit current = FirstParent; while (current != null) { yield return(current); current = current.FirstParent; } }
private MCommit AddNewCommit(CommitId commitId) { MCommit commit = new MCommit() { Repository = this, Id = commitId, }; Commits[commitId] = commit; return(commit); }
private void AddCommit(MCommit commit, GitCommit gitCommit) { //string subject = gitCommit.Subject; string tickets = ""; // GetTickets(subject); commit.Tickets = tickets; // Pre-create all parents commit.ParentIds.ForEach(pid => commit.Repository.Commit(pid)); SetChildOfParents(commit); commit.IsSet = true; }
private static MCommit AddVirtualCommit( MRepository repository, CommitId virtualId) { MCommit commit = new MCommit() { Repository = repository, Id = virtualId, }; repository.Commits[virtualId] = commit; return(commit); }
private async Task SetSpecifiedCommitBranchNamesAsync(MRepository repository) { MCommit rootCommit = GetRootCommit(repository); repository.RootCommitId = rootCommit.RealCommitId; IReadOnlyList <CommitBranchName> gitSpecifiedNames = await gitCommitBranchNameService.GetEditedBranchNamesAsync( rootCommit.Sha); IReadOnlyList <CommitBranchName> commitBranches = await gitCommitBranchNameService.GetCommitBranchNamesAsync( rootCommit.Sha); commitBranchNameService.SetSpecifiedCommitBranchNames(gitSpecifiedNames, repository); commitBranchNameService.SetCommitBranchNames(commitBranches, repository); }
private static MCommit GetRootCommit(MRepository repository) { MSubBranch mSubBranch = repository.SubBranches .FirstOrDefault(b => b.Value.IsActive && b.Value.Name == BranchName.Master).Value; if (mSubBranch == null) { Asserter.FailFast($"Repository {repository.WorkingFolder} does not have a master branch"); } IEnumerable <MCommit> firstAncestors = mSubBranch.TipCommit.FirstAncestorsAnSelf(); MCommit rootCommit = firstAncestors.Last(); return(rootCommit); }
public BranchName GetBranchName(MCommit commit) { if (commit.BranchName != null) { return(commit.BranchName); } else if (commit.SpecifiedBranchName != null) { return(commit.SpecifiedBranchName); } else if (commit.FromSubjectBranchName != null) { return(commit.FromSubjectBranchName); } return(null); }
private static void CopyToVirtualCommit (MRepository repository, MBranch branch, MCommit commit, CommitSha virtualSha) { GitCommit gitCommit = new GitCommit( virtualSha, branch.ParentCommit.Subject, branch.ParentCommit.Message, branch.ParentCommit.Author, branch.ParentCommit.AuthorDate, branch.ParentCommit.CommitDate + TimeSpan.FromSeconds(1), new List <CommitId> { branch.ParentCommitId }); repository.GitCommits[commit.Id] = gitCommit; // commit.Id = GetId(); }
public IEnumerable <MCommit> Ancestors(Func <MCommit, bool> predicate) { Stack <MCommit> commits = new Stack <MCommit>(); Parents .Where(predicate) .ForEach(parent => commits.Push(parent)); while (commits.Any()) { MCommit commit = commits.Pop(); yield return(commit); commit.Parents .Where(predicate) .ForEach(parent => commits.Push(parent)); } }
public void SetBranchTipCommitsNames(MRepository repository) { IEnumerable <MSubBranch> branches = repository.SubBranches.Values .Where(b => b.TipCommit.BranchId == null && b.TipCommit.SubBranchId == null); foreach (MSubBranch branch in branches) { MCommit branchTip = branch.TipCommit; if (!branchTip.HasFirstChild && !branches.Any(b => b.Name != branch.Name && b.TipCommitId == branch.TipCommitId)) { branchTip.SetBranchName(branch.Name); branchTip.SubBranchId = branch.SubBranchId; } } }
private static void CopyToUncommitedCommit( GitBranch currentBranch, MRepository repository, GitStatus status, MCommit commit, CommitId parentId) { int modifiedCount = status.AllChanges; int conflictCount = status.Conflicted; string subject = $"{modifiedCount} uncommitted changes in working folder"; if (conflictCount > 0) { subject = $"{conflictCount} conflicts and {modifiedCount} changes, {ShortSubject(status)}"; commit.HasConflicts = true; } else if (status.IsMerging) { subject = $"{modifiedCount} changes, {ShortSubject(status)}"; commit.IsMerging = true; } GitCommit gitCommit = new GitCommit( CommitSha.Uncommitted, subject, subject, "", DateTime.Now, DateTime.Now, new List <CommitId> { parentId }); repository.GitCommits[CommitId.Uncommitted] = gitCommit; commit.SetBranchName(currentBranch?.Name ?? "master"); commit.Tickets = ""; commit.BranchId = null; }
private BranchName TryFindBranchName(MCommit root) { BranchName branchName = commitBranchNameService.GetBranchName(root); if (branchName == null) { // Could not find a branch name from the commit, lets try it ancestors foreach (MCommit commit in root.FirstAncestors() .TakeWhile(c => c.HasSingleFirstChild)) { branchName = commitBranchNameService.GetBranchName(commit); if (branchName != null) { return(branchName); } } } return(branchName); }
private void AddVirtualUncommitted(GitBranch currentBranch, GitStatus status, MRepository repository) { MCommit commit = repository.Commit(CommitId.Uncommitted); repository.Uncommitted = commit; commit.IsVirtual = true; CommitId headCommitId = CommitId.NoCommits; if (currentBranch != null) { CommitId headId = new CommitId(currentBranch.TipSha.Sha); MCommit headCommit = repository.Commit(headId); headCommitId = headCommit.Id; } CopyToUncommitedCommit(currentBranch, repository, status, commit, headCommitId); SetChildOfParents(commit); }
private void SetEmptyParentCommits(MRepository repository) { // All commits, which do have a name, but first parent commit does not have a name bool isFound; do { isFound = false; IEnumerable <MCommit> commitsWithBranchName = repository.Commits.Values .Where(commit => commit.BranchId == null && commit.HasBranchName && commit.HasFirstParent && !commit.FirstParent.HasBranchName); foreach (MCommit commit in commitsWithBranchName) { BranchName branchName = commit.BranchName; string subBranchId = commit.SubBranchId; MCommit last = TryFindFirstAncestorWithSameName(commit.FirstParent, branchName); if (last != null) { isFound = true; foreach (MCommit current in commit.FirstAncestors()) { current.SetBranchName(branchName); current.SubBranchId = subBranchId; if (current == last) { break; } } } } } while (isFound); }
private static void SetChildOfParents(MCommit commit) { bool isFirstParent = true; foreach (MCommit parent in commit.Parents) { IList <CommitId> childIds = parent.ChildIds; if (!childIds.Contains(commit.Id)) { childIds.Add(commit.Id); } if (isFirstParent) { isFirstParent = false; IList <CommitId> firstChildIds = parent.FirstChildIds; if (!firstChildIds.Contains(commit.Id)) { firstChildIds.Add(commit.Id); } } } }
public static Commit ToCommit(Repository repository, MCommit commit) { try { return(new Commit( repository, commit.Id, commit.RealCommitId, commit.RealCommitSha, commit.Subject, commit.Message, commit.Author, commit.AuthorDate, commit.CommitDate, commit.Tags, commit.Tickets, commit.BranchTips, commit.ParentIds.ToList(), commit.ChildIds.ToList(), commit.BranchId, commit.SpecifiedBranchName, commit.CommitBranchName, commit.IsLocalAhead, commit.IsRemoteAhead, commit.IsCommon, commit.IsUncommitted, commit.IsVirtual, commit.HasConflicts, commit.IsMerging, commit.HasFirstChild)); } catch (Exception e) { Log.Exception(e, $"Failed to convert {commit.Id}"); throw; } }
private static bool TryGetCommit( MRepository repository, string id, out MCommit commit) { if (CommitId.TryParse(id, out CommitId commitId)) { return(repository.Commits.TryGetValue(commitId, out commit)); } else { foreach (var pair in repository.GitCommits.ToList()) { if (pair.Value.Sha.Sha.StartsWithOic(id)) { commitId = new CommitId(pair.Value.Sha); return(repository.Commits.TryGetValue(commitId, out commit)); } } } commit = null; return(false); }
public void AddBranchCommits(IReadOnlyList <GitBranch> branches, MRepository repository) { GitStatus status = repository.Status; Timing t = new Timing(); IEnumerable <CommitSha> rootCommits = branches.Select(b => b.TipSha); if (branches.TryGetCurrent(out GitBranch current) && current.IsDetached) { rootCommits = rootCommits.Concat(new[] { current.TipSha }); } if (!rootCommits.Any()) { AddVirtualEmptyCommit(repository); rootCommits = new[] { CommitSha.NoCommits }; } rootCommits = rootCommits.ToList(); t.Log("Root commit ids"); Dictionary <CommitSha, object> added = new Dictionary <CommitSha, object>(); Dictionary <CommitId, BranchName> branchNameByCommitId = new Dictionary <CommitId, BranchName>(); Dictionary <CommitId, BranchName> subjectBranchNameByCommitId = new Dictionary <CommitId, BranchName>(); Stack <CommitSha> commitShas = new Stack <CommitSha>(); rootCommits.ForEach(sha => commitShas.Push(sha)); rootCommits.ForEach(sha => added[sha] = null); t.Log("Pushed roots on stack"); while (commitShas.Any()) { CommitSha commitSha = commitShas.Pop(); CommitId commitId = new CommitId(commitSha.Sha); GitCommit gitCommit; IEnumerable <CommitSha> parentIds = null; if (!repository.GitCommits.TryGetValue(commitId, out gitCommit)) { Log.Warn($"Unknown commit {commitSha}"); continue; } if (IsMergeCommit(gitCommit)) { TrySetBranchNameFromSubject(commitId, gitCommit, branchNameByCommitId, subjectBranchNameByCommitId); } MCommit commit = repository.Commit(commitId); if (!commit.IsSet) { if (commit.Id == CommitId.NoCommits) { commit.IsVirtual = true; commit.SetBranchName("master"); } AddCommit(commit, gitCommit); if (parentIds == null) { parentIds = gitCommit.ParentIds.Select(id => repository.GitCommits[id].Sha); } AddParents(parentIds, commitShas, added); } BranchName branchName; if (branchNameByCommitId.TryGetValue(commitId, out branchName)) { // Branch name set by a child commit (pull merge commit) commit.SetBranchName(branchName); } BranchName subjectBranchName; if (subjectBranchNameByCommitId.TryGetValue(commitId, out subjectBranchName)) { // Subject branch name set by a child commit (merge commit) gitCommit.SetBranchNameFromSubject(subjectBranchName); } } if (!status.OK) { // Adding a virtual "uncommitted" commit since current working folder status has changes AddVirtualUncommitted(current, status, repository); } }
private void SetLocalAndRemoteAhead(MRepository repository) { IEnumerable <MBranch> unsynkedBranches = repository.Branches.Values .Where(b => b.IsActive && b.IsLocal && b.IsRemote && b.LocalTipCommitId != b.RemoteTipCommitId) .ToList(); foreach (MBranch branch in unsynkedBranches) { MCommit localTipCommit = repository.Commits[branch.LocalTipCommitId]; MCommit remoteTipCommit = repository.Commits[branch.RemoteTipCommitId]; if (localTipCommit.Id == CommitId.Uncommitted) { localTipCommit = localTipCommit.FirstParent; } branch.Commits.ForEach(commit => { commit.IsLocalAhead = false; commit.IsRemoteAhead = false; commit.IsLocal = false; commit.IsRemote = false; commit.IsCommon = false; }); localTipCommit .CommitAndAncestors(c => c.BranchId == branch.Id && c.IsLocal != true) .ForEach(c => c.IsLocal = true); remoteTipCommit .CommitAndAncestors(c => c.BranchId == branch.Id && c.IsRemote != true) .ForEach(c => c.IsRemote = true); branch.Commits.ForEach(commit => { commit.IsCommon = commit.IsLocal && commit.IsRemote; }); MCommit commonCommit = localTipCommit .CommitAndAncestors(c => c.BranchId == branch.Id) .FirstOrDefault(c => c.IsCommon); if (commonCommit == null) { if (branch.HasParentBranch) { commonCommit = branch.ParentCommit; } else { commonCommit = branch.FirstCommit; } } if (commonCommit.Sha != localTipCommit.Sha || (repository.Commits[branch.LocalTipCommitId].IsUncommitted && !repository.Commits[branch.FirstCommitId].IsUncommitted)) { MakeLocalBranch(repository, branch, localTipCommit.Id, commonCommit.Id); } if (branch.IsLocal) { HashSet <CommitId> marked = new HashSet <CommitId>(); int localCount = 0; Stack <MCommit> commits = new Stack <MCommit>(); commits.Push(localTipCommit); while (commits.Any()) { MCommit commit = commits.Pop(); if (!marked.Contains(commit.Id) && !commit.IsCommon && commit.Branch == branch) { commit.IsLocalAhead = true; localCount++; marked.Add(commit.Id); commit.Parents .Where(p => p.Branch == branch) .ForEach(p => commits.Push(p)); } } branch.LocalAheadCount = localCount; } if (branch.IsRemote) { HashSet <CommitId> marked = new HashSet <CommitId>(); int remoteCount = 0; Stack <MCommit> commits = new Stack <MCommit>(); commits.Push(remoteTipCommit); while (commits.Any()) { MCommit commit = commits.Pop(); if (!marked.Contains(commit.Id) && !commit.IsCommon && commit.Branch == branch) { commit.IsRemoteAhead = true; remoteCount++; marked.Add(commit.Id); commit.Parents .Where(p => p.Branch == branch) .ForEach(p => commits.Push(p)); } } branch.RemoteAheadCount = remoteCount; } } }
private static void MakeLocalBranch( MRepository repository, MBranch branch, CommitId localTip, CommitId commonTip) { string name = $"{branch.Name}"; string branchId = name + "(local)-" + commonTip; MBranch localBranch; if (!repository.Branches.TryGetValue(branchId, out localBranch)) { localBranch = new MBranch { IsLocalPart = true, Repository = branch.Repository, Name = name, IsMultiBranch = false, IsActive = true, IsLocal = true, ParentCommitId = commonTip, }; localBranch.Id = branchId; repository.Branches[localBranch.Id] = localBranch; } localBranch.TipCommitId = localTip; localBranch.LocalTipCommitId = localTip; localBranch.IsCurrent = branch.IsCurrent; localBranch.IsActive = branch.IsActive; Stack <MCommit> commits = new Stack <MCommit>(); commits.Push(repository.Commits[localTip]); while (commits.Any()) { MCommit commit = commits.Pop(); if (!commit.IsCommon && commit.Branch == branch) { commit.IsLocalAhead = true; localBranch.CommitIds.Add(commit.Id); branch.CommitIds.Remove(commit.Id); commit.BranchId = localBranch.Id; commit.Parents .Where(p => p.Branch == branch) .ForEach(p => commits.Push(p)); } } localBranch.LocalAheadCount = localBranch.Commits.Count(); localBranch.RemoteAheadCount = 0; if (repository.Commits.TryGetValue(CommitId.Uncommitted, out MCommit uncommitted) && branch.TipCommitId == CommitId.Uncommitted) { localBranch.TipCommitId = uncommitted.Id; localBranch.LocalTipCommitId = uncommitted.Id; localBranch.CommitIds.Insert(0, uncommitted.Id); branch.CommitIds.Remove(uncommitted.Id); branch.TipCommitId = uncommitted.FirstParentId; uncommitted.BranchId = localBranch.Id; } localBranch.FirstCommitId = localBranch.Commits.Last().Id; branch.IsMainPart = true; branch.LocalSubBranchId = localBranch.Id; localBranch.MainBranchId = branch.Id; if (branch.IsCurrent) { branch.IsCurrent = false; } branch.IsLocal = false; branch.TipCommitId = branch.RemoteTipCommitId; if (!branch.CommitIds.Any()) { branch.FirstCommitId = branch.TipCommitId; } }