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

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

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

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 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