Skip to content

Get default remote branch & add init options #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
1 commit merged into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions LibGit2Sharp/Core/GitRepositoryInitOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,46 @@ internal class GitRepositoryInitOptions : IDisposable
public IntPtr InitialHead;
public IntPtr OriginUrl;

public static GitRepositoryInitOptions BuildFrom(FilePath workdirPath, bool isBare)
public static GitRepositoryInitOptions BuildFrom(InitOptions initOptions)
{
var opts = new GitRepositoryInitOptions
{
Flags = GitRepositoryInitFlags.GIT_REPOSITORY_INIT_MKPATH,
Mode = 0 /* GIT_REPOSITORY_INIT_SHARED_UMASK */
};

if (workdirPath != null)
if (initOptions == null)
{
Debug.Assert(!isBare);
return opts;
}

if (initOptions.WorkdirPath != null)
{
Debug.Assert(!initOptions.IsBare);

opts.WorkDirPath = StrictFilePathMarshaler.FromManaged(workdirPath);
opts.WorkDirPath = StrictFilePathMarshaler.FromManaged(initOptions.WorkdirPath);
}

if (isBare)
if (initOptions.IsBare)
{
opts.Flags |= GitRepositoryInitFlags.GIT_REPOSITORY_INIT_BARE;
}

if (initOptions.InitialHead != null)
{
opts.InitialHead = StrictUtf8Marshaler.FromManaged(initOptions.InitialHead);
}

return opts;
}

public void Dispose()
{
EncodingMarshaler.Cleanup(WorkDirPath);
WorkDirPath = IntPtr.Zero;

EncodingMarshaler.Cleanup(InitialHead);
InitialHead = IntPtr.Zero;
}
}

Expand Down
5 changes: 5 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,11 @@ internal static extern unsafe int git_remote_create_with_fetchspec(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refspec);

[DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int git_remote_default_branch(
GitBuf res,
git_remote* remote);

[DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int git_remote_delete(
git_repository* repo,
Expand Down
25 changes: 16 additions & 9 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,17 @@ public static unsafe void git_remote_connect(RemoteHandle remote, GitDirection d
}
}

public static unsafe string git_remote_default_branch(RemoteHandle remote)
{
using (var buf = new GitBuf())
{
int res = NativeMethods.git_remote_default_branch(buf, remote);
Ensure.ZeroResult(res);

return LaxUtf8Marshaler.FromNative(buf.ptr);
}
}

public static unsafe void git_remote_delete(RepositoryHandle repo, string name)
{
int res = NativeMethods.git_remote_delete(repo, name);
Expand Down Expand Up @@ -2470,18 +2481,14 @@ public static unsafe IndexHandle git_repository_index(RepositoryHandle repo)
}

public static unsafe RepositoryHandle git_repository_init_ext(
FilePath workdirPath,
FilePath gitdirPath,
bool isBare)
GitRepositoryInitOptions opts)
{
using (var opts = GitRepositoryInitOptions.BuildFrom(workdirPath, isBare))
{
git_repository* repo;
int res = NativeMethods.git_repository_init_ext(out repo, gitdirPath, opts);
Ensure.ZeroResult(res);
git_repository* repo;
int res = NativeMethods.git_repository_init_ext(out repo, gitdirPath, opts);
Ensure.ZeroResult(res);

return new RepositoryHandle(repo, true);
}
return new RepositoryHandle(repo, true);
}

public static unsafe bool git_repository_is_bare(RepositoryHandle repo)
Expand Down
41 changes: 41 additions & 0 deletions LibGit2Sharp/InitOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace LibGit2Sharp
{
/// <summary>
/// Options controlling Repository Init behavior.
/// </summary>
public sealed class InitOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="InitOptions"/> class.
/// <para>
/// Default behavior:
/// The workdirPath is null.
/// Not a bare repository.
/// Default initial head.
/// </para>
/// </summary>
public InitOptions()
{
WorkdirPath = null;
IsBare = false;
InitialHead = null;
}

/// <summary>
/// The path to the working directory. Null if it's the same directory where ".git" repository is created.
/// </summary>
public string WorkdirPath { get; set; }

/// <summary>
/// True to initialize a bare repository. False otherwise, to initialize a standard ".git" repository.
/// </summary>
public bool IsBare { get; set; }

/// <summary>
/// The name of the head to point HEAD at.
/// If null, then this will be treated as "master" and the HEAD ref will be set to "refs/heads/master".
/// If this begins with "refs/" it will be used verbatim; otherwise "refs/heads/" will be prefixed.
/// </summary>
public string InitialHead { get; set; }
}
}
74 changes: 58 additions & 16 deletions LibGit2Sharp/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -495,11 +495,9 @@ public static string Init(string path, bool isBare)
{
Ensure.ArgumentNotNullOrEmptyString(path, "path");

using (RepositoryHandle repo = Proxy.git_repository_init_ext(null, path, isBare))
{
FilePath repoPath = Proxy.git_repository_path(repo);
return repoPath.Native;
}
var initOptions = new InitOptions { IsBare = isBare };

return Init(path, initOptions);
}

/// <summary>
Expand All @@ -518,9 +516,28 @@ public static string Init(string workingDirectoryPath, string gitDirectoryPath)
// to pass a path relatively to his current directory.
string wd = Path.GetFullPath(workingDirectoryPath);

var initOptions = new InitOptions { WorkdirPath = wd };

// TODO: Shouldn't we ensure that the working folder isn't under the gitDir?

using (RepositoryHandle repo = Proxy.git_repository_init_ext(wd, gitDirectoryPath, false))
return Init(gitDirectoryPath, initOptions);
}

/// <summary>
/// Initialize a repository at the specified <paramref name="path"/>,
/// providing optional behavioral overrides through the <paramref name="options"/> parameter.
/// </summary>
/// <param name="path">The path to the working folder when initializing a standard ".git" repository. Otherwise, when initializing a bare repository, the path to the expected location of this later.</param>
/// <param name="options">Options controlling init behavior.</param>
/// <returns>The path to the created repository.</returns>
public static string Init(string path, InitOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(path, "path");

options = options ?? new InitOptions();

using (var opts = GitRepositoryInitOptions.BuildFrom(options))
using (RepositoryHandle repo = Proxy.git_repository_init_ext(path, opts))
{
FilePath repoPath = Proxy.git_repository_path(repo);
return repoPath.Native;
Expand Down Expand Up @@ -675,22 +692,47 @@ public static IEnumerable<Reference> ListRemoteReferences(string url, Credential
Ensure.ArgumentNotNull(url, "url");

using (RepositoryHandle repositoryHandle = Proxy.git_repository_new())
using (RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url))
using (RemoteHandle remoteHandle = ConnectToAnonymousRemote(repositoryHandle, url, credentialsProvider))
{
var gitCallbacks = new GitRemoteCallbacks { version = 1 };
var proxyOptions = new GitProxyOptions { Version = 1 };
return Proxy.git_remote_ls(null, remoteHandle);
}
}

if (credentialsProvider != null)
{
var callbacks = new RemoteCallbacks(credentialsProvider);
gitCallbacks = callbacks.GenerateCallbacks();
}
/// <summary>
/// Retrieves the name of the Remote Repository's default branch.
/// </summary>
/// <param name="url">The url to retrieve from.</param>
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
/// <returns>The reference name.</returns>
public static string GetRemoteDefaultBranch(string url, CredentialsHandler credentialsProvider)
{
Ensure.ArgumentNotNull(url, "url");

Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions);
return Proxy.git_remote_ls(null, remoteHandle);
using (RepositoryHandle repositoryHandle = Proxy.git_repository_new())
using (RemoteHandle remoteHandle = ConnectToAnonymousRemote(repositoryHandle, url, credentialsProvider))
{
return Proxy.git_remote_default_branch(remoteHandle);
}
}

private static RemoteHandle ConnectToAnonymousRemote(RepositoryHandle repositoryHandle, string url, CredentialsHandler credentialsProvider)
{
RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url);

var gitCallbacks = new GitRemoteCallbacks { version = 1 };
var proxyOptions = new GitProxyOptions { Version = 1 };

if (credentialsProvider != null)
{
var callbacks = new RemoteCallbacks(credentialsProvider);
gitCallbacks = callbacks.GenerateCallbacks();
}

Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions);

return remoteHandle;
}

/// <summary>
/// Probe for a git repository.
/// <para>The lookup start from <paramref name="startingPath"/> and walk upward parent directories if nothing has been found.</para>
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "1.110.2",
"version": "1.110.10",
"cloudBuild": {
"buildNumber": {
"enabled": true
Expand Down