8000 Enumerate refspecs · apfunk/libgit2sharp@cc3197a · GitHub
[go: up one dir, main page]

Skip to content

Commit cc3197a

Browse files
committed
Enumerate refspecs
The Remote.RefSpecs property allows to enumerate over all refspecs defined for a specific remote.
1 parent 67433e1 commit cc3197a

File tree

9 files changed

+290
-1
lines changed

9 files changed

+290
-1
lines changed

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
</ItemGroup>
6060
<ItemGroup>
6161
<Compile Include="CheckoutFixture.cs" />
62+
<Compile Include="RefSpecFixture.cs" />
6263
<Compile Include="EqualityFixture.cs" />
6364
<Compile Include="SignatureFixture.cs" />
6465
<Compile Include="FilterBranchFixture.cs" />

LibGit2Sharp.Tests/RefSpecFixture.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Linq;
3+
using LibGit2Sharp.Tests.TestHelpers;
4+
using Xunit;
5+
6+
namespace LibGit2Sharp.Tests
7+
{
8+
public class RefSpecFixture : BaseFixture
9+
{
10+
[Fact]
11+
public void CanCountRefSpecs()
12+
{
13+
var path = CloneStandardTestRepo();
14+
using (var repo = new Repository(path))
15+
{
16+
var remote = repo.Network.Remotes["origin"];
17+
Assert.Equal(1, remote.RefSpecs.Count());
18+
}
19+
}
20+
21+
[Fact]
22+
public void CanIterateOverRefSpecs()
23+
{
24+
var path = CloneStandardTestRepo();
25+
using (var repo = new Repository(path))
26+
{
27+
var remote = repo.Network.Remotes["origin"];
28+
int count = 0;
29+
foreach (RefSpec refSpec in remote.RefSpecs)
30+
{
31+
Assert.NotNull(refSpec);
32+
count++;
33+
}
34+
Assert.Equal(1, count);
35+
}
36+
}
37+
38+
[Fact]
39+
public void CanReadRefSpecDetails()
40+
{
41+
var path = CloneStandardTestRepo();
42+
using (var repo = new Repository(path))
43+
{
44+
var remote = repo.Network.Remotes["origin"];
45+
46+
RefSpec refSpec = remote.RefSpecs.First();
47+
Assert.NotNull(refSpec);
48+
49+
Assert.Equal("refs/heads/*", refSpec.Source);
50+
Assert.Equal("refs/remotes/origin/*", refSpec.Destination);
51+
Assert.Equal(true, refSpec.ForceUpdate);
52+
}
53+
}
54+
}
55+
}

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,27 @@ internal static extern int git_refspec_rtransform(
800800
UIntPtr outlen,
801801
GitRefSpecHandle refSpec,
802802
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name);
803+
804+
[DllImport(libgit2)]
805+
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))]
806+
internal static extern string git_refspec_string(
807+
GitRefSpecHandle refSpec);
808+
809+
[DllImport(libgit2)]
810+
internal static extern RefSpecDirection git_refspec_direction(GitRefSpecHandle refSpec);
811+
812+
[DllImport(libgit2)]
813+
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))]
814+
internal static extern string git_refspec_dst(
815+
GitRefSpecHandle refSpec);
816+
817+
[DllImport(libgit2)]
818+
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))]
819+
internal static extern string git_refspec_src(
820+
GitRefSpecHandle refSpec);
821+
822+
[DllImport(libgit2)]
823+
internal static extern bool git_refspec_force(GitRefSpecHandle refSpec);
803824

804825
[DllImport(libgit2)]
805826
internal static extern int git_remote_autotag(RemoteSafeHandle remote);
@@ -827,6 +848,9 @@ internal static extern int git_remote_download(
827848
[DllImport(libgit2)]
828849
internal static extern GitRefSpecHandle git_remote_get_refspec(RemoteSafeHandle remote, UIntPtr n);
829850

851+
[DllImport(libgit2)]
852+
internal static extern UIntPtr git_remote_refspec_count(RemoteSafeHandle remote);
853+
830854
[DllImport(libgit2)]
831855
internal static extern int git_remote_is_valid_name(
832856
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string remote_name);

LibGit2Sharp/Core/Proxy.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,31 @@ public static string git_refspec_rtransform(GitRefSpecHandle refSpecPtr, string
14621462
}
14631463
}
14641464

1465+
public static string git_refspec_string(GitRefSpecHandle refSpec)
1466+
{
1467+
return NativeMethods.git_refspec_string(refSpec);
1468+
}
1469+
1470+
public static string git_refspec_src(GitRefSpecHandle refSpec)
1471+
{
1472+
return NativeMethods.git_refspec_src(refSpec);
1473+
}
1474+
1475+
public static string git_refspec_dst(GitRefSpecHandle refSpec)
1476+
{
1477+
return NativeMethods.git_refspec_dst(refSpec);
1478+
}
1479+
1480+
public static RefSpecDirection git_refspec_direction(GitRefSpecHandle refSpec)
1481+
{
1482+
return NativeMethods.git_refspec_direction(refSpec);
1483+
}
1484+
1485+
public static bool git_refspec_force(GitRefSpecHandle refSpec)
1486+
{
1487+
return NativeMethods.git_refspec_force(refSpec);
1488+
}
1489+
14651490
#endregion
14661491

14671492
#region git_remote_
@@ -1505,6 +1530,11 @@ public static GitRefSpecHandle git_remote_get_refspec(RemoteSafeHandle remote, i
15051530
return NativeMethods.git_remote_get_refspec(remote, (UIntPtr)n);
15061531
}
15071532

1533+
public static int git_remote_refspec_count(RemoteSafeHandle remote)
1534+
{
1535+
return (int)NativeMethods.git_remote_refspec_count(remote);
1536+
}
1537+
15081538
public static void git_remote_download(RemoteSafeHandle remote)
15091539
{
15101540
using (ThreadAffinity())

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
<Compile Include="CommitFilter.cs" />
7272
<Compile Include="CommitSortStrategies.cs" />
7373
<Compile Include="CompareOptions.cs" />
74+
<Compile < 57AE span class="pl-e">Include="RefSpec.cs" />
75+
<Compile Include="RefSpecCollection.cs" />
7476
<Compile Include="Core\EncodingMarshaler.cs" />
7577
<Compile Include="Core\Handles\BranchIteratorSafeHandle.cs" />
7678
<Compile Include="Core\PushTransferProgressCallbacks.cs" />
@@ -80,6 +82,7 @@
8082
<Compile Include="FilteringOptions.cs" />
8183
<Compile Include="ResetMode.cs" />
8284
<Compile Include="NoteCollectionExtensions.cs" />
85+
<Compile Include="RefSpecDirection.cs" />
8386
<Compile Include="UnbornBranchException.cs" />
8487
<Compile Include="LockedFileException.cs" />
8588
<Compile Include="Core\GitRepositoryInitOptions.cs" />

LibGit2Sharp/RefSpec.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using LibGit2Sharp.Core;
3+
using LibGit2Sharp.Core.Handles;
4+
5+
namespace LibGit2Sharp
6+
{
7+
/// <summary>
8+
/// A push or fetch reference specification
9+
/// </summary>
10+
public class RefSpec
11+
{
12+
private RefSpec(string refSpec, RefSpecDirection direction, string source, string destination, bool forceUpdate)
13+
{
14+
Ensure.ArgumentNotNullOrEmptyString(refSpec, "refSpec");
15+
Ensure.ArgumentNotNull(source, "source");
16+
Ensure.ArgumentNotNull(destination, "destination");
17+
18+
Specification = refSpec;
19+
Direction = direction;
20+
Source = source;
21+
Destination = destination;
22+
ForceUpdate = forceUpdate;
23+
}
24+
25+
/// <summary>
26+
/// Needed for mocking purposes.
27+
/// </summary>
28+
protected RefSpec()
29+
{ }
30+
31+
internal static RefSpec BuildFromPtr(GitRefSpecHandle handle)
32+
{
33+
Ensure.ArgumentNotNull(handle, "handle");
34+
35+
return new RefSpec(Proxy.git_refspec_string(handle), Proxy.git_refspec_direction(handle),
36+
Proxy.git_refspec_src(handle), Proxy.git_refspec_dst(handle), Proxy.git_refspec_force(handle));
37+
}
38+
39+
/// <summary>
40+
/// Gets the pattern describing the mapping between remote and local references
41+
/// </summary>
42+
public virtual string Specification { get; private set; }
43+
44+
/// <summary>
45+
/// Indicates whether this <see cref="RefSpec"/> is intended to be used during a Push or Fetch operation
46+
/// </summary>
47+
public virtual RefSpecDirection Direction { get; private set; }
48+
49+
/// <summary>
50+
/// The source reference specifier
51+
/// </summary>
52+
public virtual string Source { get; private set; }
53+
54+
/// <summary>
55+
/// The target reference specifier
56+
/// </summary>
57+
public virtual string Destination { get; private set; }
58+
59+
/// <summary>
60+
/// Indicates whether the destination will be force-updated if fast-forwarding is not possible
61+
/// </summary>
62+
public virtual bool ForceUpdate { get; private set; }
63+
}
64+
}

LibGit2Sharp/RefSpecCollection.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Diagnostics;
6+
using System.Globalization;
7+
using LibGit2Sharp.Core;
8+
using LibGit2Sharp.Core.Handles;
9+
using LibGit2Sharp.Core.Compat;
10+
11+
namespace LibGit2Sharp
12+
{
13+
/// <summary>
14+
/// The collection of <see cref="RefSpec"/>s in a <see cref="Remote"/>
15+
/// </summary>
16+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
17+
public class RefSpecCollection : IEnumerable<RefSpec>
18+
{
19+
private readonly Lazy<IList<RefSpec>> refSpecsLazy;
20+
21+
/// <summary>
22+
/// Needed for mocking purposes.
23+
/// </summary>
24+
protected RefSpecCollection()
25+
{ }
26+
27+
internal RefSpecCollection(Remote remote)
28+
{
29+
Ensure.ArgumentNotNull(remote, "remote");
30+
31+
refSpecsLazy = new Lazy<IList<RefSpec>>(() => RetrieveRefSpecs(remote));
32+
}
33+
34+
private static IList<RefSpec> RetrieveRefSpecs(Remote remote)
35+
{
36+
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(remote.repository.Handle, remote.Name, true))
37+
{
38+
int count = Proxy.git_remote_refspec_count(remoteHandle);
39+
List<RefSpec> refSpecs = new List<RefSpec>();
40+
41+
for (int i = 0; i < count; i++)
42+
{
43+
using (GitRefSpecHandle handle = Proxy.git_remote_get_refspec(remoteHandle, i))
44+
{
45+
refSpecs.Add(RefSpec.BuildFromPtr(handle));
46+
}
47+
}
48+
49+
return refSpecs;
50+
}
51+
}
52+
53+
/// <summary>
54+
/// Returns an enumerator that iterates through the collection.
55+
/// </summary>
56+
/// <returns>An <see cref="IEnumerator{T}"/> object that can be used to iterate through the collection.</returns>
57+
public virtual IEnumerator<RefSpec> GetEnumerator()
58+
{
59+
return refSpecsLazy.Value.GetEnumerator();
60+
}
61+
62+
/// <summary>
63+
/// Returns an enumerator that iterates through the collection.
64+
/// </summary>
65+
/// <returns>An <see cref="IEnumerator"/> object that can be used to iterate through the collection.</returns>
66+
IEnumerator IEnumerable.GetEnumerator()
67+
{
68+
return GetEnumerator();
69+
}
70+
71+
private string DebuggerDisplay
72+
{
73+
get
74+
{
75+
return string.Format(CultureInfo.InvariantCulture,
76+
"Count = {0}", this.Count());
77+
}
78+
}
79+
}
80+
}

LibGit2Sharp/RefSpecDirection.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace LibGit2Sharp
7+
{
8+
/// <summary>
9+
/// Indicates whether a refspec is a push refspec or a fetch refspec
10+
/// </summary>
11+
public enum RefSpecDirection
12+
{
13+
/// <summary>
14+
/// Indicates that the refspec is a fetch refspec
15+
/// </summary>
16+
Fetch,
17+
18+
/// <summary>
19+
/// Indicates that the refspec is a push refspec
20+
/// </summary>
21+
Push
22+
}
23+
}

LibGit2Sharp/Remote.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.Globalization;
45
using LibGit2Sharp.Core;
@@ -15,7 +16,9 @@ public class Remote : IEquatable<Remote>
1516
private static readonly LambdaEqualityHelper<Remote> equalityHelper =
1617
new LambdaEqualityHelper<Remote>(x => x.Name, x => x.Url);
1718

18-
private readonly Repository repository;
19+
internal readonly Repository repository;
20+
21+
private readonly RefSpecCollection refSpecs;
1922

2023
/// <summary>
2124
/// Needed for mocking purposes.
@@ -29,6 +32,7 @@ private Remote(Repository repository, string name, string url, TagFetchMode tagF
2932
Name = name;
3033
Url = url;
3134
TagFetchMode = tagFetchMode;
35+
refSpecs = new RefSpecCollection(this);
3236
}
3337

3438
internal static Remote BuildFromPtr(RemoteSafeHandle handle, Repository repo)
@@ -57,6 +61,11 @@ internal static Remote BuildFromPtr(RemoteSafeHandle handle, Repository repo)
5761
/// </summary>
5862
public virtual TagFetchMode TagFetchMode { get; private set; }
5963

64+
/// <summary>
65+
/// Gets the list of <see cref="RefSpec"/>s defined for this <see cref="Remote"/>
66+
/// </summary>
67+
public virtual IEnumerable<RefSpec> RefSpecs { get { return refSpecs; } }
68+
6069
/// <summary>
6170
/// Transform a reference to its source reference using the <see cref="Remote"/>'s default fetchspec.
6271
/// </summary>

0 commit comments

Comments
 (0)
0