Skip to content

Commit

Permalink
feat: Add CustomHeaders to PushOptions
Browse files Browse the repository at this point in the history
Wires up CustomHeaders in PushOptions in the same vain as FetchOptions.
  • Loading branch information
James-LG committed Nov 3, 2023
1 parent 8c32b61 commit 714a426
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 6 deletions.
27 changes: 27 additions & 0 deletions LibGit2Sharp.Tests/PushFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,33 @@ public void CanForcePush()
}
}

[Fact]
public void CanPushWithCustomHeaders()
{
const string knownHeader = "X-Hello: mygit-201";
var options = new PushOptions { CustomHeaders = new string[] { knownHeader } };
AssertPush(repo =>
repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options));
}

[Fact]
public void CannotPushWithForbiddenCustomHeaders()
{
const string knownHeader = "User-Agent: mygit-201";
var options = new PushOptions { CustomHeaders = new string[] { knownHeader } };
Assert.Throws<LibGit2SharpException>(
() => AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options)));
}

[Fact]
public void CannotPushWithMalformedCustomHeaders()
{
const string knownHeader = "Hello world";
var options = new PushOptions { CustomHeaders = new string[] { knownHeader } };
Assert.Throws<LibGit2SharpException>(
() => AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options)));
}

private static void AssertRemoteHeadTipEquals(IRepository localRepo, string sha)
{
var remoteReferences = localRepo.Network.ListReferences(localRepo.Network.Remotes.Single());
Expand Down
36 changes: 36 additions & 0 deletions LibGit2Sharp/Core/GitPushOptionsWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;

namespace LibGit2Sharp.Core
{
/// <summary>
/// Git push options wrapper. Disposable wrapper for <see cref="GitPushOptions"/>.
/// </summary>
internal class GitPushOptionsWrapper : IDisposable
{
public GitPushOptionsWrapper() : this(new GitPushOptions()) { }

public GitPushOptionsWrapper(GitPushOptions pushOptions)
{
this.Options = pushOptions;
}

public GitPushOptions Options { get; private set; }

#region IDisposable
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (disposedValue)
return;

this.Options.CustomHeaders.Dispose();
disposedValue = true;
}

public void Dispose()
{
Dispose(true);
}
#endregion
}
}
21 changes: 15 additions & 6 deletions LibGit2Sharp/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,18 +365,27 @@ public virtual void Push(Remote remote, IEnumerable<string> pushRefSpecs, PushOp

// Load the remote.
using (RemoteHandle remoteHandle = Proxy.git_remote_lookup(repository.Handle, remote.Name, true))

// Create a git options wrapper so managed strings are disposed.
using (var pushOptionsWrapper = new GitPushOptionsWrapper())
{
var callbacks = new RemoteCallbacks(pushOptions);
GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();

var gitPushOptions = pushOptionsWrapper.Options;
gitPushOptions.PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism;
gitPushOptions.RemoteCallbacks = gitCallbacks;
gitPushOptions.ProxyOptions = new GitProxyOptions { Version = 1 };

// If there are custom headers, create a managed string array.
if (pushOptions.CustomHeaders != null && pushOptions.CustomHeaders.Length > 0)
{
gitPushOptions.CustomHeaders = GitStrArrayManaged.BuildFrom(pushOptions.CustomHeaders);
}

Proxy.git_remote_push(remoteHandle,
pushRefSpecs,
new GitPushOptions()
{
PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism,
RemoteCallbacks = gitCallbacks,
ProxyOptions = new GitProxyOptions { Version = 1 },
});
gitPushOptions);
}
}

Expand Down
20 changes: 20 additions & 0 deletions LibGit2Sharp/PushOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,25 @@ public sealed class PushOptions
/// information about what updates will be performed.
/// </summary>
public PrePushHandler OnNegotiationCompletedBeforePush { get; set; }

/// <summary>
/// Get/Set the custom headers.
/// <para>
/// This allows you to set custom headers (e.g. X-Forwarded-For,
/// X-Request-Id, etc),
/// </para>
/// </summary>
/// <remarks>
/// Libgit2 sets some headers for HTTP requests (User-Agent, Host,
/// Accept, Content-Type, Transfer-Encoding, Content-Length, Accept) that
/// cannot be overriden.
/// </remarks>
/// <example>
/// var pushOptions - new PushOptions() {
/// CustomHeaders = new String[] {"X-Request-Id: 12345"}
/// };
/// </example>
/// <value>The custom headers string array</value>
public string[] CustomHeaders { get; set; }
}
}

0 comments on commit 714a426

Please sign in to comment.