Skip to content

Commit 7765c12

Browse files
committed
Use a callback for credentials
Instead of making the user choose beforehand, use a callback to let the user ask a database or human about the credentials. If desired, a hard-coded value can still be provided via a lambda, e.g. (_url, _user, _types) => new UsernamePasswordCredentials() { ... }
1 parent 5dab358 commit 7765c12

12 files changed

+76
-22
lines changed

LibGit2Sharp.Tests/CloneFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public void CanCloneWithCredentials()
151151
string clonedRepoPath = Repository.Clone(Constants.PrivateRepoUrl, scd.DirectoryPath,
152152
new CloneOptions()
153153
{
154-
Credentials = Constants.PrivateRepoCredentials
154+
CredentialsProvider = (_url, _user, _cred) => Constants.PrivateRepoCredentials
155155
});
156156

157157

LibGit2Sharp.Tests/FetchFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void CanFetchIntoAnEmptyRepositoryWithCredentials()
6060
// Perform the actual fetch
6161
repo.Network.Fetch(remote, new FetchOptions
6262
{
63-
Credentials = Constants.PrivateRepoCredentials
63+
CredentialsProvider = (_url, _user, _credtype) => Constants.PrivateRepoCredentials
6464
});
6565
}
6666
}

LibGit2Sharp.Tests/NetworkFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public void CanListRemoteReferencesWithCredentials()
121121
{
122122
Remote remote = repo.Network.Remotes.Add(remoteName, Constants.PrivateRepoUrl);
123123

124-
var references = repo.Network.ListReferences(remote, Constants.PrivateRepoCredentials);
124+
var references = repo.Network.ListReferences(remote, (_url, _user, _credtype) => Constants.PrivateRepoCredentials);
125125

126126
foreach (var directReference in references)
127127
{

LibGit2Sharp/CloneOptions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using LibGit2Sharp.Core;
1+
using System;
2+
using LibGit2Sharp.Core;
23
using LibGit2Sharp.Handlers;
34

45
namespace LibGit2Sharp
@@ -40,7 +41,7 @@ public CloneOptions()
4041
/// <summary>
4142
/// Credentials to use for user/pass authentication
4243
/// </summary>
43-
public Credentials Credentials { get; set; }
44+
public CredentialsHandler CredentialsProvider { get; set; }
4445

4546
#region IConvertableToGitCheckoutOpts
4647

LibGit2Sharp/FetchOptions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using LibGit2Sharp.Handlers;
1+
using System;
2+
using LibGit2Sharp.Handlers;
23

34
namespace LibGit2Sharp
45
{
@@ -41,6 +42,6 @@ public sealed class FetchOptions
4142
/// <summary>
4243
/// Credentials to use for username/password authentication.
4344
/// </summary>
44-
public Credentials Credentials { get; set; }
45+
public CredentialsHandler CredentialsProvider { get; set; }
4546
}
4647
}

LibGit2Sharp/Handlers.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222
/// <returns>True to continue, false to cancel.</returns>
2323
public delegate bool UpdateTipsHandler(string referenceName, ObjectId oldId, ObjectId newId);
2424

25+
/// <summary>
26+
/// Delegate definition for the credentials retrieval callback
27+
/// </summary>
28+
/// <param name="usernameFromUrl">Username which was extracted form the url, if any</param>
29+
/// <param name="url">The url</param>
30+
/// <param name="types">Credential types which the server accepts</param>
31+
public delegate Credentials CredentialsHandler(string url, string usernameFromUrl, SupportedCredentialTypes types);
32+
2533
/// <summary>
2634
/// Delegate definition for transfer progress callback.
2735
/// </summary>

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@
317317
<Compile Include="VoidReference.cs" />
318318
<Compile Include="Core\RawContentStream.cs" />
319319
<Compile Include="Core\Handles\OdbStreamSafeHandle.cs" />
320+
<Compile Include="SupportedCredentialTypes.cs" />
320321
</ItemGroup>
321322
<ItemGroup>
322323
<CodeAnalysisDictionary Include="CustomDictionary.xml" />

LibGit2Sharp/Network.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,17 @@ public virtual RemoteCollection Remotes
4646
/// </para>
4747
/// </summary>
4848
/// <param name="remote">The <see cref="Remote"/> to list from.</param>
49-
/// <param name="credentials">The optional <see cref="Credentials"/> used to connect to remote repository.</param>
49+
/// <param name="credentials">The optional <see cref="Func<Credentials>"/> used to connect to remote repository.</param>
5050
/// <returns>The references in the <see cref="Remote"/> repository.</returns>
51-
public virtual IEnumerable<DirectReference> ListReferences(Remote remote, Credentials credentials = null)
51+
public virtual IEnumerable<DirectReference> ListReferences(Remote remote, CredentialsHandler credentialsProvider = null)
5252
{
5353
Ensure.ArgumentNotNull(remote, "remote");
5454

5555
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
5656
{
57-
if (credentials != null)
57+
if (credentialsProvider != null)
5858
{
59-
var callbacks = new RemoteCallbacks(null, null, null, credentials);
59+
var callbacks = new RemoteCallbacks(null, null, null, credentialsProvider);
6060
GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();
6161
Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);
6262
}
@@ -272,7 +272,7 @@ public virtual void Push(
272272
// Load the remote.
273273
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
274274
{
275-
var callbacks = new RemoteCallbacks(null, null, null, pushOptions.Credentials);
275+
var callbacks = new RemoteCallbacks(null, null, null, pushOptions.CredentialsProvider);
276276
GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();
277277
Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);
278278

LibGit2Sharp/PushOptions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using LibGit2Sharp.Handlers;
1+
using System;
2+
using LibGit2Sharp.Handlers;
23

34
namespace LibGit2Sharp
45
{
@@ -10,7 +11,7 @@ public sealed class PushOptions
1011
/// <summary>
1112
/// The <see cref="Credentials"/> to authenticate with during the push.
1213
/// </summary>
13-
public Credentials Credentials { get; set; }
14+
public CredentialsHandler CredentialsProvider { get; set; }
1415

1516
/// <summary>
1617
/// If the transport being used to push to the remote requires the creation

LibGit2Sharp/RemoteCallbacks.cs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ internal RemoteCallbacks(
1616
ProgressHandler onProgress = null,
1717
TransferProgressHandler onDownloadProgress = null,
1818
UpdateTipsHandler onUpdateTips = null,
19-
Credentials credentials = null)
19+
CredentialsHandler credentialsProvider = null)
2020
{
2121
Progress = onProgress;
2222
DownloadTransferProgress = onDownloadProgress;
2323
UpdateTips = onUpdateTips;
24-
Credentials = credentials;
24+
CredentialsProvider = credentialsProvider;
2525
}
2626

2727
internal RemoteCallbacks(FetchOptions fetchOptions)
@@ -30,7 +30,7 @@ internal RemoteCallbacks(FetchOptions fetchOptions)
3030
Progress = fetchOptions.OnProgress;
3131
DownloadTransferProgress = fetchOptions.OnTransferProgress;
3232
UpdateTips = fetchOptions.OnUpdateTips;
33-
Credentials = fetchOptions.Credentials;
33+
CredentialsProvider = fetchOptions.CredentialsProvider;
3434
}
3535

3636
#region Delegates
@@ -54,9 +54,9 @@ internal RemoteCallbacks(FetchOptions fetchOptions)
5454
#endregion
5555

5656
/// <summary>
57-
/// The credentials to use for the credential callback.
57+
/// The credentials to use for authentication.
5858
/// </summary>
59-
Credentials Credentials;
59+
private readonly CredentialsHandler CredentialsProvider;
6060

6161
internal GitRemoteCallbacks GenerateCallbacks()
6262
{
@@ -72,9 +72,9 @@ internal GitRemoteCallbacks GenerateCallbacks()
7272
callbacks.update_tips = GitUpdateTipsHandler;
7373
}
7474

75-
if (Credentials != null)
75+
if (CredentialsProvider != null)
7676
{
77-
callbacks.acquire_credentials = Credentials.GitCredentialHandler;
77+
callbacks.acquire_credentials = GitCredentialHandler;
7878
}
7979

8080
if (DownloadTransferProgress != null)
@@ -153,6 +153,26 @@ private int GitDownloadTransferProgressHandler(ref GitTransferProgress progress,
153153
return Proxy.ConvertResultToCancelFlag(shouldContinue);
154154
}
155155

156+
private int GitCredentialHandler(out IntPtr ptr, IntPtr cUrl, IntPtr usernameFromUrl, GitCredentialType credTypes, IntPtr payload)
157+
{
158+
string url = LaxUtf8Marshaler.FromNative(cUrl);
159+
string username = LaxUtf8Marshaler.FromNative(usernameFromUrl);
160+
161+
SupportedCredentialTypes types = default(SupportedCredentialTypes);
162+
if (credTypes.HasFlag(GitCredentialType.UserPassPlaintext))
163+
{
164+
types |= SupportedCredentialTypes.UsernamePassword;
165+
}
166+
if (credTypes.HasFlag(GitCredentialType.Default))
167+
{
168+
types |= SupportedCredentialTypes.Default;
169+
}
170+
171+
var cred = CredentialsProvider(url, username, types);
172+
173+
return cred.GitCredentialHandler(out ptr, cUrl, usernameFromUrl, credTypes, payload);
174+
}
175+
156176
#endregion
157177
}
158178
}

LibGit2Sharp/Repository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ public static string Clone(string sourceUrl, string workdirPath,
545545
{
546546
var gitCheckoutOptions = checkoutOptionsWrapper.Options;
547547

548-
var remoteCallbacks = new RemoteCallbacks(null, options.OnTransferProgress, null, options.Credentials);
548+
var remoteCallbacks = new RemoteCallbacks(null, options.OnTransferProgress, null, options.CredentialsProvider);
549549
var gitRemoteCallbacks = remoteCallbacks.GenerateCallbacks();
550550

551551
var cloneOpts = new GitCloneOptions
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
3+
namespace LibGit2Sharp
4+
{
5+
/// <summary>
6+
/// Credential types supported by the server. If the server supports a particular type of
7+
/// authentication, it will be set to true.
8+
/// </summary>
9+
[Flags]
10+
public enum SupportedCredentialTypes
11+
{
12+
/// <summary>
13+
/// Plain username and password combination
14+
/// </summary>
15+
UsernamePassword = (1 << 0),
16+
17+
/// <summary>
18+
/// Ask Windows to provide its default credentials for the current user (e.g. NTLM)
19+
/// </summary>
20+
Default = (1 << 1),
21+
}
22+
}

0 commit comments

Comments
 (0)