diff --git a/LibGit2Sharp.Tests/BranchFixture.cs b/LibGit2Sharp.Tests/BranchFixture.cs index 8208305dd..1fe0e8e47 100644 --- a/LibGit2Sharp.Tests/BranchFixture.cs +++ b/LibGit2Sharp.Tests/BranchFixture.cs @@ -518,7 +518,7 @@ public void CanSetUpstreamBranch() Branch trackedBranch = repo.Branches[trackedBranchName]; Branch updatedBranch = repo.Branches.Update(branch, b => b.Remote = remoteName, - b => b.UpstreamBranch = upstreamBranchName); + b => b.UpstreamBranch = upstreamBranchName); // Verify the immutability of the branch. Assert.False(branch.IsTracking); diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index f40dcd667..a484b48cb 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using System.Linq; using LibGit2Sharp.Tests.TestHelpers; +using Xunit; using Xunit.Extensions; namespace LibGit2Sharp.Tests @@ -95,5 +97,31 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) expectedFetchState.CheckUpdatedReferences(repo); } } + + [Theory] + [InlineData(TagFetchMode.All, 4)] + [InlineData(TagFetchMode.None, 0)] + [InlineData(TagFetchMode.Auto, 3)] + public void FetchRespectsConfiguredAutoTagSetting(TagFetchMode tagFetchMode, int expectedTagCount) + { + string url = "https://github.com/libgit2/TestGitRepository"; + + var scd = BuildSelfCleaningDirectory(); + using (var repo = Repository.Init(scd.RootedDirectoryPath)) + { + Remote remote = repo.Network.Remotes.Add(remoteName, url); + Assert.NotNull(remote); + + // Update the configured autotag setting. + repo.Network.Remotes.Update(remote, + r => r.TagFetchMode = tagFetchMode); + + // Perform the actual fetch. + repo.Network.Fetch(remote); + + // Verify the number of fetched tags. + Assert.Equal(expectedTagCount, repo.Tags.Count()); + } + } } } diff --git a/LibGit2Sharp.Tests/RemoteFixture.cs b/LibGit2Sharp.Tests/RemoteFixture.cs index 7aa842893..02a293b27 100644 --- a/LibGit2Sharp.Tests/RemoteFixture.cs +++ b/LibGit2Sharp.Tests/RemoteFixture.cs @@ -44,6 +44,29 @@ public void CanEnumerateTheRemotes() } } + [Theory] + [InlineData(TagFetchMode.All)] + [InlineData(TagFetchMode.Auto)] + [InlineData(TagFetchMode.None)] + public void CanSetTagFetchMode(TagFetchMode tagFetchMode) + { + string path = CloneBareTestRepo(); + using (var repo = new Repository(path)) + { + const string name = "upstream"; + const string url = "https://github.com/libgit2/libgit2sharp.git"; + + repo.Network.Remotes.Add(name, url); + Remote remote = repo.Network.Remotes[name]; + Assert.NotNull(remote); + + Remote updatedremote = repo.Network.Remotes.Update(remote, + r => r.TagFetchMode = tagFetchMode); + + Assert.Equal(tagFetchMode, updatedremote.TagFetchMode); + } + } + [Fact] public void CanCheckEqualityOfRemote() { diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 7074d95e0..62a6e1ab8 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -756,6 +756,9 @@ internal static extern int git_refspec_rtransform( GitRefSpecHandle refSpec, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(Utf8Marshaler))] string name); + [DllImport(libgit2)] + internal static extern int git_remote_autotag(RemoteSafeHandle remote); + [DllImport(libgit2)] internal static extern int git_remote_connect(RemoteSafeHandle remote, GitDirection direction); diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index d9ebbacc6..ac2c3ba98 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -1368,6 +1368,11 @@ public static string git_refspec_rtransform(GitRefSpecHandle refSpecPtr, string #region git_remote_ + public static TagFetchMode git_remote_autotag(RemoteSafeHandle remote) + { + return (TagFetchMode) NativeMethods.git_remote_autotag(remote); + } + public static RemoteSafeHandle git_remote_create(RepositorySafeHandle repo, string name, string url) { using (ThreadAffinity()) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 0da4df39c..fa61f12e6 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -74,6 +74,7 @@ + diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index 628f9f45e..7d52ef463 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -102,7 +102,7 @@ public virtual IEnumerable ListReferences(Remote remote) /// Credentials to use for username/password authentication. public virtual void Fetch( Remote remote, - TagFetchMode tagFetchMode = TagFetchMode.Auto, + TagFetchMode? tagFetchMode = null, ProgressHandler onProgress = null, CompletionHandler onCompletion = null, UpdateTipsHandler onUpdateTips = null, @@ -121,7 +121,10 @@ public virtual void Fetch( var callbacks = new RemoteCallbacks(onProgress, onCompletion, onUpdateTips); GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); - Proxy.git_remote_set_autotag(remoteHandle, tagFetchMode); + if (tagFetchMode.HasValue) + { + Proxy.git_remote_set_autotag(remoteHandle, tagFetchMode.Value); + } if (credentials != null) { diff --git a/LibGit2Sharp/Remote.cs b/LibGit2Sharp/Remote.cs index 8c402fe35..a0365c92d 100644 --- a/LibGit2Sharp/Remote.cs +++ b/LibGit2Sharp/Remote.cs @@ -23,19 +23,21 @@ public class Remote : IEquatable protected Remote() { } - private Remote(Repository repository, string name, string url) + private Remote(Repository repository, string name, string url, TagFetchMode tagFetchMode) { this.repository = repository; Name = name; Url = url; + TagFetchMode = tagFetchMode; } internal static Remote BuildFromPtr(RemoteSafeHandle handle, Repository repo) { string name = Proxy.git_remote_name(handle); string url = Proxy.git_remote_url(handle); + TagFetchMode tagFetchMode = Proxy.git_remote_autotag(handle); - var remote = new Remote(repo, name, url); + var remote = new Remote(repo, name, url, tagFetchMode); return remote; } @@ -50,6 +52,11 @@ internal static Remote BuildFromPtr(RemoteSafeHandle handle, Repository repo) /// public virtual string Url { get; private set; } + /// + /// Gets the Tag Fetch Mode of the remote - indicating how tags are fetched. + /// + public virtual TagFetchMode TagFetchMode { get; private set; } + /// /// Transform a reference to its source reference using the 's default fetchspec. /// diff --git a/LibGit2Sharp/RemoteCollection.cs b/LibGit2Sharp/RemoteCollection.cs index 05715fb7d..79a027472 100644 --- a/LibGit2Sharp/RemoteCollection.cs +++ b/LibGit2Sharp/RemoteCollection.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -47,6 +48,24 @@ internal Remote RemoteForName(string name, bool shouldThrowIfNotFound = true) } } + /// + /// Update properties of a remote. + /// + /// The remote to update. + /// Delegate to perform updates on the remote. + /// The updated remote. + public virtual Remote Update(Remote remote, params Action[] actions) + { + var updater = new RemoteUpdater(this.repository, remote); + + foreach (Action action in actions) + { + action(updater); + } + + return this[remote.Name]; + } + /// /// Returns an enumerator that iterates through the collection. /// diff --git a/LibGit2Sharp/RemoteUpdater.cs b/LibGit2Sharp/RemoteUpdater.cs new file mode 100644 index 000000000..84da1e2cc --- /dev/null +++ b/LibGit2Sharp/RemoteUpdater.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Handles; + +namespace LibGit2Sharp +{ + /// + /// Exposes properties of a remote that can be updated. + /// + public class RemoteUpdater + { + private readonly Repository repo; + private readonly Remote remote; + + /// + /// Needed for mocking purposes. + /// + protected RemoteUpdater() + { } + + internal RemoteUpdater(Repository repo, Remote remote) + { + Ensure.ArgumentNotNull(repo, "repo"); + Ensure.ArgumentNotNull(remote, "remote"); + + this.repo = repo; + this.remote = remote; + } + + /// + /// Set the default TagFetchMode value for the remote. + /// + public virtual TagFetchMode TagFetchMode + { + set + { + using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repo.Handle, remote.Name, true)) + { + Proxy.git_remote_set_autotag(remoteHandle, value); + Proxy.git_remote_save(remoteHandle); + } + } + } + } +}