From 5118bcde728a80f8ef1f9910c5a60dab29274838 Mon Sep 17 00:00:00 2001 From: idealist1508 Date: Thu, 25 Sep 2014 07:53:35 +0200 Subject: [PATCH 1/3] Fix for QueryHistory throws ItemNotFoundException --- GitTfs/Util/ChangeSieve.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/GitTfs/Util/ChangeSieve.cs b/GitTfs/Util/ChangeSieve.cs index 6f615dc9..bb366d7d 100644 --- a/GitTfs/Util/ChangeSieve.cs +++ b/GitTfs/Util/ChangeSieve.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Sep.Git.Tfs.Core; @@ -180,16 +181,19 @@ namespace Sep.Git.Tfs.Util var oldItem = item.VersionControlServer.GetItem(item.ItemId, previousChangeset); if (null == oldItem) { - var history = item.VersionControlServer.QueryHistory(item.ServerItem, item.ChangesetId, 0, + try + { + var history = item.VersionControlServer.QueryHistory(item.ServerItem, item.ChangesetId, 0, TfsRecursionType.None, null, 1, previousChangeset, 1, true, false, false); - var previousChange = history.FirstOrDefault(); - if (previousChange == null) + var previousChange = history.First(); + oldItem = previousChange.Changes[0].Item; + } + catch { Trace.WriteLine(string.Format("No history found for item {0} changesetId {1}", item.ServerItem, item.ChangesetId)); return null; } - oldItem = previousChange.Changes[0].Item; } return oldItem.ServerItem; } From 9d01a022fa3ac53d7caa738b420cf13cf0153d0a Mon Sep 17 00:00:00 2001 From: Matt Burke Date: Thu, 25 Sep 2014 09:30:31 -0400 Subject: [PATCH 2/3] Add test for #645. --- GitTfsTest/Core/ChangeSieveTests.cs | 113 ++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/GitTfsTest/Core/ChangeSieveTests.cs b/GitTfsTest/Core/ChangeSieveTests.cs index d7c29f5c..59b42625 100644 --- a/GitTfsTest/Core/ChangeSieveTests.cs +++ b/GitTfsTest/Core/ChangeSieveTests.cs @@ -635,5 +635,118 @@ namespace Sep.Git.Tfs.Test.Core Assert.Equal(new string[] { "$/Project/file1.txt" }, Subject.GetChangesToFetch().Select(c => c.Item.ServerItem)); } } + + public class RenamedFromDeleted : Base + { + public class Fixture : BaseFixture + { + public Fixture() + { + Changeset.Changes = new IChange[] { + new RenamedFromDeletedChange("$/Project/file1.txt"), + }; + } + } + + [Fact] + public void FetchesItemRenamedAfterDelete() + { + AssertChanges(Subject.GetChangesToApply(), + ApplicableChange.Update("file1.txt")); + } + + // A Change/Item that only throws an exception when you try to query its history. + public class RenamedFromDeletedChange : IChange, IItem, IVersionControlServer + { + // This is the interesting part of this implementation. + // The TFS client throws an exception of type Microsoft.TeamFoundation.VersionControl.Client.ItemNotFoundException. + // ChangeSieve doesn't have a reference to the TFS client libs, so it can't catch that exact exception. + // This class, therefore, throws an exception that is of a type that ChangeSieve can't specifically catch. + IEnumerable IVersionControlServer.QueryHistory(string path, int version, int deletionId, TfsRecursionType recursion, string user, int versionFrom, int versionTo, int maxCount, bool includeChanges, bool slotMode, bool includeDownloadInfo) + { + throw new AnExceptionTypeThatYouCannotCatch(); + } + + class AnExceptionTypeThatYouCannotCatch : Exception + { + } + + // The rest of the implementation is pretty straight-forward. + + readonly string _serverItem; + + // Accept a name so that the name is more obviously matched between the Fixture + // and the assertion. + public RenamedFromDeletedChange(string serverItem) + { + _serverItem = serverItem; + } + + TfsChangeType IChange.ChangeType + { + get { return TfsChangeType.Rename; } + } + + IItem IChange.Item + { + get { return this; } + } + + IVersionControlServer IItem.VersionControlServer + { + get { return this; } + } + + int IItem.ChangesetId + { + get { return 100; } + } + + string IItem.ServerItem + { + get { return _serverItem; } + } + + int IItem.DeletionId + { + get { throw new NotImplementedException(); } + } + + TfsItemType IItem.ItemType + { + get { return TfsItemType.File; } + } + + int IItem.ItemId + { + get { return 200; } + } + + long IItem.ContentLength + { + get { return 0; } + } + + TemporaryFile IItem.DownloadFile() + { + return null; + } + + IItem IVersionControlServer.GetItem(int itemId, int changesetNumber) + { + return null; + } + + IItem IVersionControlServer.GetItem(string itemPath, int changesetNumber) + { + return null; + } + + IItem[] IVersionControlServer.GetItems(string itemPath, int changesetNumber, TfsRecursionType recursionType) + { + return null; + } + } + } } } From 45621291c7d82b15e99678818516b1da606749aa Mon Sep 17 00:00:00 2001 From: idealist1508 Date: Wed, 10 Dec 2014 00:19:36 +0100 Subject: [PATCH 3/3] Make Test happy --- GitTfsTest/Core/ChangeSieveTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GitTfsTest/Core/ChangeSieveTests.cs b/GitTfsTest/Core/ChangeSieveTests.cs index 59b42625..b7bc6246 100644 --- a/GitTfsTest/Core/ChangeSieveTests.cs +++ b/GitTfsTest/Core/ChangeSieveTests.cs @@ -22,7 +22,7 @@ namespace Sep.Git.Tfs.Test.Core // Make this remote act like it's mapped to $/Project Remote.Stub(r => r.GetPathInGitRepo(null)) .Constraints(Is.Anything()) - .Do(new Function(path => path.StartsWith("$/Project/") ? path.Replace("$/Project/", "") : null)); + .Do(new Function(path => path != null && path.StartsWith("$/Project/") ? path.Replace("$/Project/", "") : null)); // Make this remote ignore any path that includes "ignored". Remote.Stub(r => r.ShouldSkip(null)) .Constraints(Is.Anything()) @@ -575,6 +575,7 @@ namespace Sep.Git.Tfs.Test.Core ApplicableChange.Update("file10.txt")); } } + public class WithDeleteMainFolderBranchAndSubItems : Base { public class Fixture : BaseFixture @@ -709,7 +710,7 @@ namespace Sep.Git.Tfs.Test.Core int IItem.DeletionId { - get { throw new NotImplementedException(); } + get { return 0; } } TfsItemType IItem.ItemType