From d578084f2dbdae8aa125865e0dcd9b6fe92a18c1 Mon Sep 17 00:00:00 2001 From: Alan McGovern Date: Mon, 6 Feb 2012 01:57:06 +0100 Subject: [Git] Use a *much* faster method of generating the blame information NGit now has a built in way to generate blame information which is billions of times faster than the current method, so use it! Fixes bug #411. --- .../GitRepository.cs | 41 ++++----- .../MonoDevelop.VersionControl.Git/GitUtil.cs | 96 ---------------------- 2 files changed, 15 insertions(+), 122 deletions(-) (limited to 'main/src/addins/VersionControl/MonoDevelop.VersionControl.Git') diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs index a15c51a785..2850a1f95c 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs @@ -1282,35 +1282,24 @@ namespace MonoDevelop.VersionControl.Git RevCommit hc = GetHeadCommit (); if (hc == null) return new Annotation [0]; - RevCommit[] lineCommits = GitUtil.Blame (repo, hc, repositoryPath); - int lineCount = lineCommits.Length; - List annotations = new List(lineCount); - for (int n = 0; n < lineCount; n++) { - RevCommit c = lineCommits[n]; - Annotation annotation = new Annotation (c.Name, c.GetAuthorIdent ().GetName () + "<" + c.GetAuthorIdent ().GetEmailAddress () + ">", c.GetCommitterIdent ().GetWhen ()); - annotations.Add(annotation); - } - - Document baseDocument = new Document (GetCommitTextContent (hc, repositoryPath)); - Document workingDocument = new Document (File.ReadAllText (repositoryPath)); - Annotation uncommittedRev = new Annotation("0000000000000000000000000000000000000000", "", new DateTime()); - // Based on Subversion code until we support blame on things other than commits - foreach (var hunk in baseDocument.Diff (workingDocument)) { - annotations.RemoveRange (hunk.RemoveStart, hunk.Removed); - int start = hunk.InsertStart - 1; //Line number - 1 = index - bool insert = (start < annotations.Count); - - for (int i = 0; i < hunk.Inserted; ++i) { - if (insert) { - annotations.Insert (start, uncommittedRev); - } else { - annotations.Add (uncommittedRev); - } + var git = new NGit.Api.Git (repo); + var result = git.Blame ().SetFilePath (ToGitPath (repositoryPath)).Call (); + result.ComputeAll (); + + List list = new List (); + for (int i = 0; i < result.GetResultContents ().Size (); i++) { + var commit = result.GetSourceCommit (i); + var author = result.GetSourceCommitter (i); + if (commit != null && author != null) { + string name = string.Format ("{0} <{1}>", author.GetName (), author.GetEmailAddress ()); + var commitTime = new DateTime (1970, 1, 1).AddSeconds (commit.CommitTime); + list.Add (new Annotation (commit.Name, name, commitTime)); + } else { + list.Add (new Annotation (new string ('0', 20), "", DateTime.Now)); } } - - return annotations.ToArray(); + return list.ToArray (); } internal GitRevision GetPreviousRevisionFor (GitRevision revision) diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs index c4a6f5b855..2466c2de45 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs @@ -351,69 +351,6 @@ namespace MonoDevelop.VersionControl.Git return repo; } - public static RevCommit[] Blame (NGit.Repository repo, RevCommit commit, string file) - { - string localFile = ToGitPath (repo, file); - TreeWalk tw = TreeWalk.ForPath (repo, localFile, commit.Tree); - if (tw == null) - return new RevCommit [0]; - int totalLines = GetFileLineCount (repo, tw); - int lineCount = totalLines; - RevCommit[] lines = new RevCommit [lineCount]; - RevWalk revWalker = new RevWalk (repo); - revWalker.MarkStart (commit); - List commitHistory = new List(); - FilePath localCpath = FromGitPath (repo, localFile); - - foreach (RevCommit ancestorCommit in revWalker) { - foreach (Change change in GetCommitChanges (repo, ancestorCommit)) { - FilePath cpath = FromGitPath (repo, change.Path); - if (change.ChangeType != ChangeType.Deleted && (localCpath == cpath || cpath.IsChildPathOf (localCpath))) - { - commitHistory.Add(ancestorCommit); - break; - } - } - } - - int historySize = commitHistory.Count; - - if (historySize > 1) { - RevCommit recentCommit = commitHistory[0]; - RawText latestRawText = GetRawText (repo, localFile, recentCommit); - - for (int i = 1; i < historySize; i++) { - RevCommit ancestorCommit = commitHistory[i]; - RawText ancestorRawText = GetRawText (repo, localFile, ancestorCommit); - lineCount -= SetBlameLines(repo, lines, recentCommit, latestRawText, ancestorRawText); - recentCommit = ancestorCommit; - - if (lineCount <= 0) - { - break; - } - } - - if (lineCount > 0) { - RevCommit firstCommit = commitHistory[historySize - 1]; - - for (int i = 0; i < totalLines; i++) { - if (lines[i] == null) { - lines[i] = firstCommit; - } - } - } - } else if (historySize == 1) { - RevCommit firstCommit = commitHistory[0]; - - for (int i = 0; i < totalLines; i++) { - lines[i] = firstCommit; - } - } - - return lines; - } - static int GetFileLineCount (NGit.Repository repo, TreeWalk tw) { ObjectId id = tw.GetObjectId (0); byte[] data = repo.ObjectDatabase.Open (id).GetBytes (); @@ -429,25 +366,6 @@ namespace MonoDevelop.VersionControl.Git return new RawText (data); } - static int SetBlameLines (NGit.Repository repo, RevCommit[] lines, RevCommit commit, RawText curText, RawText ancestorText) - { - int lineCount = 0; - IEnumerable diffHunks = GetDiffHunks (curText, ancestorText); - - foreach (Hunk e in diffHunks) { - int basePosition = e.InsertStart - 1; - for (int i = 0; i < e.Inserted; i++) { - int lineNum = basePosition + i; - if (lines [lineNum] == null) { - lines [lineNum] = commit; - lineCount++; - } - } - } - - return lineCount; - } - static IEnumerable GetDiffHunks (RawText curText, RawText ancestorText) { Dictionary codeDictionary = new Dictionary (); @@ -485,20 +403,6 @@ namespace MonoDevelop.VersionControl.Git return lines; } - static int FillRemainingBlame (RevCommit[] lines, RevCommit commit) - { - int lineCount = 0; - - for (int n=0; n