diff --git a/LibGit2Sharp/Core/GitRepositoryInitOptions.cs b/LibGit2Sharp/Core/GitRepositoryInitOptions.cs index f639a0d8..1b7b0e66 100644 --- a/LibGit2Sharp/Core/GitRepositoryInitOptions.cs +++ b/LibGit2Sharp/Core/GitRepositoryInitOptions.cs @@ -16,7 +16,7 @@ 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 { @@ -24,18 +24,28 @@ public static GitRepositoryInitOptions BuildFrom(FilePath workdirPath, bool isBa 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; } @@ -43,6 +53,9 @@ public void Dispose() { EncodingMarshaler.Cleanup(WorkDirPath); WorkDirPath = IntPtr.Zero; + + EncodingMarshaler.Cleanup(InitialHead); + InitialHead = IntPtr.Zero; } } diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 7dd99ac3..9fdd5db7 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -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, diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index fd070f45..b9b0db93 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -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); @@ -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) diff --git a/LibGit2Sharp/InitOptions.cs b/LibGit2Sharp/InitOptions.cs new file mode 100644 index 00000000..6b3f3486 --- /dev/null +++ b/LibGit2Sharp/InitOptions.cs @@ -0,0 +1,41 @@ +namespace LibGit2Sharp +{ + /// + /// Options controlling Repository Init behavior. + /// + public sealed class InitOptions + { + /// + /// Initializes a new instance of the class. + /// + /// Default behavior: + /// The workdirPath is null. + /// Not a bare repository. + /// Default initial head. + /// + /// + public InitOptions() + { + WorkdirPath = null; + IsBare = false; + InitialHead = null; + } + + /// + /// The path to the working directory. Null if it's the same directory where ".git" repository is created. + /// + public string WorkdirPath { get; set; } + + /// + /// True to initialize a bare repository. False otherwise, to initialize a standard ".git" repository. + /// + public bool IsBare { get; set; } + + /// + /// 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. + /// + public string InitialHead { get; set; } + } +} diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index b6399af4..e67fca74 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -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); } /// @@ -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); + } + + /// + /// Initialize a repository at the specified , + /// providing optional behavioral overrides through the parameter. + /// + /// 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. + /// Options controlling init behavior. + /// The path to the created repository. + 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; @@ -656,7 +673,24 @@ internal Commit LookupCommit(string committish) /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url) { - return ListRemoteReferences(url, null); + string _defaultBranch; + return ListRemoteReferences(url, null, out _defaultBranch); + } + + /// + /// Lists the Remote Repository References. + /// + /// + /// Does not require a local Repository. The retrieved + /// + /// throws in this case. + /// + /// The url to list from. + /// The name of the Repository's default branch. + /// The references in the remote repository. + public static IEnumerable ListRemoteReferences(string url, out string defaultBranch) + { + return ListRemoteReferences(url, null, out defaultBranch); } /// @@ -671,6 +705,24 @@ public static IEnumerable ListRemoteReferences(string url) /// The used to connect to remote repository. /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider) + { + string _defaultBranch; + return ListRemoteReferences(url, credentialsProvider, out _defaultBranch); + } + + /// + /// Lists the Remote Repository References. + /// + /// + /// Does not require a local Repository. The retrieved + /// + /// throws in this case. + /// + /// The url to list from. + /// The used to connect to remote repository. + /// The name of the Repository's default branch. + /// The references in the remote repository. + public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider, out string defaultBranch) { Ensure.ArgumentNotNull(url, "url"); @@ -687,7 +739,11 @@ public static IEnumerable ListRemoteReferences(string url, Credential } Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions); - return Proxy.git_remote_ls(null, remoteHandle); + + var remoteReferences = Proxy.git_remote_ls(null, remoteHandle); + defaultBranch = Proxy.git_remote_default_branch(remoteHandle); + + return remoteReferences; } } diff --git a/version.json b/version.json index 36406d69..762c232a 100644 --- a/version.json +++ b/version.json @@ -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.3", "cloudBuild": { "buildNumber": { "enabled": true