diff --git a/LibGit2Sharp/Core/FileHistory.cs b/LibGit2Sharp/Core/FileHistory.cs index 5775d0ab8..9f3b4e9fd 100644 --- a/LibGit2Sharp/Core/FileHistory.cs +++ b/LibGit2Sharp/Core/FileHistory.cs @@ -163,6 +163,16 @@ private static void DetermineParentPaths(IRepository repo, Commit currentCommit, private static string ParentPath(IRepository repo, Commit currentCommit, string currentPath, Commit parentCommit) { + // optimization: if the SHA of the parent commit's TreeEntry is the same as this commit's TreeEntry then + // they are the same and there is no need to diff the commit + TreeEntry parentTreeEntry = parentCommit.Tree[currentPath]; + TreeEntry thisTreeEntry = currentCommit.Tree[currentPath]; + if (parentTreeEntry != null && parentTreeEntry.Target.Sha == thisTreeEntry.Target.Sha) + { + return currentPath; + } + + // something in the tree is different, so we need to diff the commits to look for renames using (var treeChanges = repo.Diff.Compare(parentCommit.Tree, currentCommit.Tree)) { var treeEntryChanges = treeChanges.FirstOrDefault(c => c.Path == currentPath); diff --git a/LibGit2Sharp/Tree.cs b/LibGit2Sharp/Tree.cs index 30f534a99..45afaddb4 100644 --- a/LibGit2Sharp/Tree.cs +++ b/LibGit2Sharp/Tree.cs @@ -43,6 +43,8 @@ internal Tree(Repository repo, ObjectId id, string path) /// Throws if tree is missing public virtual int Count => lazyCount.Value; + private Dictionary _treeCache; + /// /// Gets the pointed at by the in this instance. /// @@ -51,9 +53,19 @@ internal Tree(Repository repo, ObjectId id, string path) /// Throws if tree is missing public virtual TreeEntry this[string relativePath] { - get { return RetrieveFromPath(relativePath); } + get + { + TreeEntry ret; + if (_treeCache == null) _treeCache = new Dictionary(); + else if (_treeCache.TryGetValue(relativePath, out ret)) return ret; + + ret = RetrieveFromPath(relativePath); + _treeCache[relativePath] = ret; + return ret; + } } + private unsafe TreeEntry RetrieveFromPath(string relativePath) { if (string.IsNullOrEmpty(relativePath))