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 vein as FetchOptions.
  • Loading branch information
James-LG committed Jul 25, 2023
1 parent 8c32b61 commit 0ddf3a2
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 6 deletions.
22 changes: 22 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM mcr.microsoft.com/devcontainers/base:debian

# Install .net 6 and .net 7
# https://learn.microsoft.com/en-us/dotnet/core/install/linux-debian
RUN wget https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \
dpkg -i packages-microsoft-prod.deb && \
rm packages-microsoft-prod.deb
RUN apt-get update -yq && \
apt-get install -yq --no-install-recommends \
dotnet-sdk-6.0 dotnet-sdk-7.0

# Install mono framework
# https://www.mono-project.com/download/stable/#download-lin-debian
RUN apt-get install -yq --no-install-recommends \
dirmngr ca-certificates gnupg
RUN gpg --keyserver keyserver.ubuntu.com --recv 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \
gpg --export 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF | tee /usr/share/keyrings/mono.gpg >/dev/null && \
gpg --batch --yes --delete-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \
echo "deb [signed-by=/usr/share/keyrings/mono.gpg] https://download.mono-project.com/repo/debian stable-buster main" | tee /etc/apt/sources.list.d/mono-official-stable.list
RUN apt-get update -yq && \
apt-get install -yq --no-install-recommends \
mono-devel
28 changes: 28 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
{
"name": "C# (.NET)",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"dockerFile": "Dockerfile",
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [5000, 5001],
// "portsAttributes": {
// "5001": {
// "protocol": "https"
// }
// }
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "dotnet restore",
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"ms-dotnettools.csharp"
]
}
}
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
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 0ddf3a2

Please sign in to comment.