-
Notifications
You must be signed in to change notification settings - Fork 899
Win http fetch #213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Win http fetch #213
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using LibGit2Sharp.Tests.TestHelpers; | ||
|
@@ -120,6 +121,39 @@ private static void AssertIsHidden(string repoPath) | |
Assert.Equal(FileAttributes.Hidden, (attribs & FileAttributes.Hidden)); | ||
} | ||
|
||
|
||
[Theory] | ||
[InlineData("http://github.com/nulltoken/TestGitRepository")] | ||
[InlineData("https://github.com/nulltoken/TestGitRepository")] | ||
//[InlineData("[email protected]:nulltoken/TestGitRepository")] | ||
public void CanFetchFromEmptyRepository(string url) | ||
{ | ||
var scd = BuildSelfCleaningDirectory(); | ||
using (var repo = Repository.Init(scd.RootedDirectoryPath)) | ||
{ | ||
string remoteName = "testRepository"; | ||
|
||
TestRemoteExpectedInfo expectedResults = new TestRemoteExpectedInfo(remoteName); | ||
RemoteUpdateTipsCallbackHelper helper = new RemoteUpdateTipsCallbackHelper(expectedResults.ExpectedReferenceCallbacks); | ||
|
||
Remote remote = repo.Remotes.Add(remoteName, url); | ||
|
||
FetchProgress progress = new FetchProgress(); | ||
progress.RemoteCallbacks.UpdateTipsChanged += new System.EventHandler<UpdateTipsChangedEventArgs>(helper.RemoteUpdateTipsHandler); | ||
repo.Fetch(remote, progress); | ||
|
||
Assert.Equal(expectedResults.ExpectedBranchTips.Count, repo.Branches.Count()); | ||
foreach (KeyValuePair<string, string> kvp in expectedResults.ExpectedBranchTips) | ||
{ | ||
Branch branch = repo.Branches[kvp.Key]; | ||
Assert.NotNull(branch); | ||
Assert.Equal(kvp.Value, branch.Tip.Sha); | ||
} | ||
|
||
helper.CheckUpdatedReferences(); | ||
} | ||
} | ||
|
||
[Fact(Skip = "This is fixed on libgit2's development tip")] | ||
public void CanReinitARepository() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,7 +83,10 @@ public void Dispose() | |
{ | ||
foreach (string directory in directories) | ||
{ | ||
DirectoryHelper.DeleteDirectory(directory); | ||
if (Directory.Exists(directory)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please give me some more context about this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had hit an issue running the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks a lot for your answer. Indeed, that makes sense. However, I'm afraid this check could hide that something may have went wrong earlier (a wrongly written test for instance). Could you think of a way to let the user know about this not expected state? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now (especially as the clone is no longer part of the test suite) I will remove this change so we can concentrate on the core Fetch changes. |
||
{ | ||
DirectoryHelper.DeleteDirectory(directory); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System.Collections.Generic; | ||
using LibGit2Sharp.Core.Compat; | ||
using Xunit; | ||
|
||
namespace LibGit2Sharp.Tests.TestHelpers | ||
{ | ||
/// <summary> | ||
/// Class to verify the update_tips callback of the git_remote_callbacks structure. | ||
/// </summary> | ||
public class RemoteUpdateTipsCallbackHelper | ||
{ | ||
private Dictionary<string, Tuple<ObjectId, ObjectId>> ExpectedReferenceUpdates; | ||
private Dictionary<string, Tuple<ObjectId, ObjectId>> ObservedReferenceUpdates; | ||
|
||
/// <summary> | ||
/// Constructor. | ||
/// </summary> | ||
/// <param name="expectedCallbacks">Dictionary of expected reference name => tuple of (old ObjectId, new ObjectID) that should be updated.</param> | ||
public RemoteUpdateTipsCallbackHelper(Dictionary<string, Tuple<ObjectId, ObjectId>> expectedCallbacks) | ||
{ | ||
ExpectedReferenceUpdates = new Dictionary<string, Tuple<ObjectId, ObjectId>>(expectedCallbacks); | ||
ObservedReferenceUpdates = new Dictionary<string, Tuple<ObjectId, ObjectId>>(); | ||
} | ||
|
||
/// <summary> | ||
/// Handler to hook up to UpdateTips callback. | ||
/// </summary> | ||
/// <param name="sender"></param> | ||
/// <param name="e"></param> | ||
public void RemoteUpdateTipsHandler(object sender, UpdateTipsChangedEventArgs e) | ||
{ | ||
// assert that we have not seen this reference before | ||
Assert.DoesNotContain(e.ReferenceName, ObservedReferenceUpdates.Keys); | ||
ObservedReferenceUpdates.Add(e.ReferenceName, new Tuple<ObjectId,ObjectId>(e.OldId, e.NewId)); | ||
|
||
|
||
// verify that this reference is in the list of expected references | ||
Tuple<ObjectId, ObjectId> reference; | ||
bool referenceFound = ExpectedReferenceUpdates.TryGetValue(e.ReferenceName, out reference); | ||
Assert.True(referenceFound, string.Format("Could not find reference {0} in list of expected reference updates.", e.ReferenceName)); | ||
|
||
// verify that the old / new Object IDs | ||
if(referenceFound) | ||
{ | ||
Assert.Equal(reference.Item1, e.OldId); | ||
Assert.Equal(reference.Item2, e.NewId); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Check that all expected references have been updated. | ||
/// </summary> | ||
public void CheckUpdatedReferences() | ||
{ | ||
// we have already verified that all observed reference updates are expected, | ||
// verify that we have seen all expected reference updates | ||
Assert.Equal(ExpectedReferenceUpdates.Count, ObservedReferenceUpdates.Count); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using LibGit2Sharp.Core.Compat; | ||
|
||
namespace LibGit2Sharp.Tests.TestHelpers | ||
{ | ||
/// <summary> | ||
/// This is the expected information based on the test repository at: | ||
/// github.com/nulltoken/TestGitRepository | ||
/// </summary> | ||
public class TestRemoteExpectedInfo | ||
{ | ||
public Dictionary<string, string> ExpectedBranchTips = new Dictionary<string, string>(); | ||
|
||
public Dictionary<string, string> ExpectedTags = new Dictionary<string, string>(); | ||
|
||
public Dictionary<string, Tuple<ObjectId, ObjectId>> ExpectedReferenceCallbacks = new Dictionary<string, Tuple<ObjectId, ObjectId>>(); | ||
|
||
public TestRemoteExpectedInfo(string remoteName) | ||
{ | ||
ExpectedBranchTips.Add(remoteName + "/" + "master", "49322bb17d3acc9146f98c97d078513228bbf3c0"); | ||
ExpectedBranchTips.Add(remoteName + "/" + "first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6"); | ||
ExpectedBranchTips.Add(remoteName + "/" + "no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"); | ||
|
||
ExpectedTags.Add("annotated_tag", "c070ad8c08840c8116da865b2d65593a6bb9cd2a"); | ||
ExpectedTags.Add("blob", "55a1a760df4b86a02094a904dfa511deb5655905"); | ||
ExpectedTags.Add("commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee"); | ||
ExpectedTags.Add("nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e"); | ||
|
||
string referenceUpdateBase = "refs/remotes/" + remoteName + "/"; | ||
ExpectedReferenceCallbacks.Add(referenceUpdateBase + "master", new Tuple<ObjectId, ObjectId>(new ObjectId("0000000000000000000000000000000000000000"), new ObjectId("49322bb17d3acc9146f98c97d078513228bbf3c0"))); | ||
ExpectedReferenceCallbacks.Add(referenceUpdateBase + "first-merge", new Tuple<ObjectId, ObjectId>(new ObjectId("0000000000000000000000000000000000000000"), new ObjectId("0966a434eb1a025db6b71485ab63a3bfbea520b6"))); | ||
ExpectedReferenceCallbacks.Add(referenceUpdateBase + "no-parent", new Tuple<ObjectId, ObjectId>(new ObjectId("0000000000000000000000000000000000000000"), new ObjectId("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"))); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,9 +136,31 @@ public virtual ICommitLog Commits | |
get { return repo.Commits.QueryBy(new Filter { Since = this }); } | ||
} | ||
|
||
/// <summary> | ||
/// Gets the <see cref="Remote"/> tracking this branch | ||
/// </summary> | ||
/// <returns>The <see cref="Remote"/> tracking this branch if one exists, otherwise returns null.</returns> | ||
public virtual Remote ResolveTrackedRemote() | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather be in favor of exposing a property Could you please cover with test how this would behave when dealing with a local tracking branch (there's one in the StandardTestRepository named "track-local" IIRC)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will expose this as a new property. I was not aware of local tracking tracking branches ... I covered this behavior in a test, In this case, there is no "Remote" for the local machine that I could see, so this would return "null"... Maybe we should add a property indicating that this is a "local tracking" branch? |
||
if (IsTracking) | ||
{ | ||
string trackedRemoteName = ResolveTrackedRemoteName(); | ||
if (string.IsNullOrEmpty(trackedRemoteName)) | ||
{ | ||
return null; | ||
} | ||
|
||
return repo.Remotes[trackedRemoteName]; | ||
} | ||
else | ||
{ | ||
return null; | ||
} | ||
} | ||
|
||
private Branch ResolveTrackedBranch() | ||
{ | ||
var trackedRemote = repo.Config.Get<string>("branch", Name, "remote", null); | ||
string trackedRemote = ResolveTrackedRemoteName(); | ||
if (trackedRemote == null) | ||
{ | ||
return null; | ||
|
@@ -154,6 +176,11 @@ private Branch ResolveTrackedBranch() | |
return repo.Branches[remoteRefName]; | ||
} | ||
|
||
private string ResolveTrackedRemoteName() | ||
{ | ||
return repo.Config.Get<string>("branch", Name, "remote", null) as string; | ||
} | ||
|
||
private static string ResolveTrackedReference(string trackedRemote, string trackedRefName) | ||
{ | ||
if (trackedRemote == ".") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System; | ||
|
||
namespace LibGit2Sharp.Core | ||
{ | ||
internal enum GitDirection | ||
{ | ||
Fetch = 0, | ||
Push = 1 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,10 +3,10 @@ | |
namespace LibGit2Sharp.Core | ||
{ | ||
[StructLayout(LayoutKind.Sequential)] | ||
public class GitIndexerStats | ||
internal class GitIndexerStats | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❤️ ! |
||
{ | ||
public int Total; | ||
public int Processed; | ||
public int Received; | ||
public uint Total; | ||
public uint Processed; | ||
public uint Received; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
|
||
namespace LibGit2Sharp.Core | ||
{ | ||
/// <summary> | ||
/// Structure for git_remote_callbacks | ||
/// </summary> | ||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct GitRemoteCallbacks | ||
{ | ||
internal NativeMethods.remote_progress_callback progress; | ||
|
||
internal NativeMethods.remote_completion_callback completion; | ||
|
||
internal NativeMethods.remote_update_tips_callback update_tips; | ||
|
||
internal IntPtr data; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using LibGit2Sharp.Core; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace LibGit2Sharp | ||
{ | ||
/// <summary> | ||
/// Contains data regarding fetch progress. | ||
/// </summary> | ||
public class FetchProgress : IndexerStats | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick... From a semantic standpoint, I don't think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will split this out so FetchProgress no longer derives from IndexerStats. |
||
{ | ||
/// <summary> | ||
/// Fetch progress constructor. | ||
/// </summary> | ||
public FetchProgress() | ||
{ | ||
RemoteCallbacks = new RemoteCallbacks(); | ||
} | ||
|
||
/// <summary> | ||
/// Bytes received. | ||
/// </summary> | ||
public long Bytes | ||
{ | ||
get | ||
{ | ||
return bytes; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// The events fired in response to callbacks from libgit2. | ||
/// </summary> | ||
public RemoteCallbacks RemoteCallbacks { get; set; } | ||
|
||
internal override void Reset() | ||
{ | ||
base.Reset(); | ||
bytes = 0; | ||
} | ||
|
||
#region Fields | ||
|
||
internal long bytes; | ||
|
||
#endregion | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the use of this assert?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct - I will update this test to cover what I meant for it to test.