diff options
author | Alan McGovern <alan.mcgovern@gmail.com> | 2012-02-06 04:57:06 +0400 |
---|---|---|
committer | Alan McGovern <alan.mcgovern@gmail.com> | 2012-02-06 04:57:06 +0400 |
commit | d578084f2dbdae8aa125865e0dcd9b6fe92a18c1 (patch) | |
tree | 424ed69da18f11a4ed2a6a611e14eb8d0858899e /main/src/addins/VersionControl/MonoDevelop.VersionControl.Git | |
parent | c19abc79e6ec513d276031f5169e9190cabef580 (diff) |
[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.
Diffstat (limited to 'main/src/addins/VersionControl/MonoDevelop.VersionControl.Git')
2 files changed, 15 insertions, 122 deletions
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<Annotation> annotations = new List<Annotation>(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<Annotation> list = new List<Annotation> (); + 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), "<uncommitted>", 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<RevCommit> commitHistory = new List<RevCommit>(); - 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<Hunk> 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<Hunk> GetDiffHunks (RawText curText, RawText ancestorText) { Dictionary<string, int> codeDictionary = new Dictionary<string, int> (); @@ -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<lines.Length; n++) { - if (lines [n] == null) { - lines [n] = commit; - lineCount++; - } - } - - return lineCount; - } - public static MergeCommandResult MergeTrees (NGit.ProgressMonitor monitor, NGit.Repository repo, RevCommit srcBase, RevCommit srcCommit, string sourceDisplayName, bool commitResult) { RevCommit newHead = null; |