Skip to content

Commit ca82701

Browse files
committed
Merge remote-tracking branch 'upstream/ethomson/inmemory_repo'
2 parents 2492eb8 + 665008a commit ca82701

File tree

4 files changed

+76
-13
lines changed

4 files changed

+76
-13
lines changed

LibGit2Sharp.Tests/RepositoryFixture.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public void CanCreateBareRepo()
2727
Assert.Null(repo.Info.WorkingDirectory);
2828
Assert.Equal(Path.GetFullPath(repoPath), repo.Info.Path);
2929
Assert.True(repo.Info.IsBare);
30+
Assert.Throws<BareRepositoryException>(() => { var idx = repo.Index; });
3031

3132
AssertInitializedRepository(repo, "refs/heads/master");
3233

@@ -673,6 +674,19 @@ public void CanDetectShallowness()
673674
}
674675
}
675676

677+
[Fact]
678+
public void CanCreateInMemoryRepository()
679+
{
680+
using (var repo = new Repository())
681+
{
682+
Assert.True(repo.Info.IsBare);
683+
Assert.Null(repo.Info.Path);
684+
Assert.Null(repo.Info.WorkingDirectory);
685+
686+
Assert.Throws<BareRepositoryException>(() => { var idx = repo.Index; });
687+
}
688+
}
689+
676690
[SkippableFact]
677691
public void CanListRemoteReferencesWithCredentials()
678692
{

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,10 @@ internal static extern unsafe int git_repository_message(
13851385
GitBuf buf,
13861386
git_repository* repository);
13871387

1388+
[DllImport(libgit2)]
1389+
internal static extern unsafe int git_repository_new(
1390+
out git_repository* repo);
1391+
13881392
[DllImport(libgit2)]
13891393
internal static extern unsafe int git_repository_odb(out git_odb* odb, git_repository* repo);
13901394

@@ -1454,9 +1458,6 @@ internal static extern unsafe int git_repository_state(
14541458
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))]
14551459
internal static extern unsafe FilePath git_repository_workdir(IntPtr repository);
14561460

1457-
[DllImport(libgit2)]
1458-
internal static extern unsafe int git_repository_new(out git_repository* repo);
1459-
14601461
[DllImport(libgit2)]
14611462
internal static extern unsafe int git_reset(
14621463
git_repository* repo,

LibGit2Sharp/Repository.cs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ public sealed class Repository : IRepository
3737
private readonly SubmoduleCollection submodules;
3838
private readonly Lazy<PathCase> pathCase;
3939

40+
private enum RepositoryRequiredParameter
41+
{
42+
None = 0,
43+
Path = 1,
44+
Options = 2,
45+
}
46+
47+
/// <summary>
48+
/// Initializes a new instance of the <see cref="Repository"/> class
49+
/// that does not point to an on-disk Git repository. This is
50+
/// suitable only for custom, in-memory Git repositories that are
51+
/// configured with custom object database, reference database and/or
52+
/// configuration backends.
53+
/// </summary>
54+
public Repository()
55+
: this(null, null, RepositoryRequiredParameter.None)
56+
{
57+
}
58+
4059
/// <summary>
4160
/// Initializes a new instance of the <see cref="Repository"/> class.
4261
/// <para>For a standard repository, <paramref name="path"/> should either point to the ".git" folder or to the working directory. For a bare repository, <paramref name="path"/> should directly point to the repository folder.</para>
@@ -45,31 +64,60 @@ public sealed class Repository : IRepository
4564
/// The path to the git repository to open, can be either the path to the git directory (for non-bare repositories this
4665
/// would be the ".git" folder inside the working directory) or the path to the working directory.
4766
/// </param>
48-
public Repository(string path) : this(path, null)
67+
public Repository(string path)
68+
: this(path, null, RepositoryRequiredParameter.Path)
4969
{ }
5070

5171
/// <summary>
52-
/// Initializes a new instance of the <see cref="Repository"/> class, providing optional behavioral overrides through <paramref name="options"/> parameter.
53-
/// <para>For a standard repository, <paramref name="path"/> should either point to the ".git" folder or to the working directory. For a bare repository, <paramref name="path"/> should directly point to the repository folder.</para>
72+
/// Initializes a new instance of the <see cref="Repository"/> class,
73+
/// providing optional behavioral overrides through the
74+
/// <paramref name="options"/> parameter.
75+
/// <para>For a standard repository, <paramref name="path"/> may
76+
/// either point to the ".git" folder or to the working directory.
77+
/// For a bare repository, <paramref name="path"/> should directly
78+
/// point to the repository folder.</para>
5479
/// </summary>
5580
/// <param name="path">
56-
/// The path to the git repository to open, can be either the path to the git directory (for non-bare repositories this
57-
/// would be the ".git" folder inside the working directory) or the path to the working directory.
81+
/// The path to the git repository to open, can be either the
82+
/// path to the git directory (for non-bare repositories this
83+
/// would be the ".git" folder inside the working directory)
84+
/// or the path to the working directory.
5885
/// </param>
5986
/// <param name="options">
6087
/// Overrides to the way a repository is opened.
6188
/// </param>
62-
public Repository(string path, RepositoryOptions options)
89+
public Repository(string path, RepositoryOptions options) :
90+
this(path, options, RepositoryRequiredParameter.Path | RepositoryRequiredParameter.Options)
6391
{
64-
Ensure.ArgumentNotNullOrEmptyString(path, "path");
92+
}
93+
94+
private Repository(string path, RepositoryOptions options, RepositoryRequiredParameter requiredParameter)
95+
{
96+
if ((requiredParameter & RepositoryRequiredParameter.Path) == RepositoryRequiredParameter.Path)
97+
{
98+
Ensure.ArgumentNotNullOrEmptyString(path, "path");
99+
}
100+
101+
if ((requiredParameter & RepositoryRequiredParameter.Options) == RepositoryRequiredParameter.Options)
102+
{
103+
Ensure.ArgumentNotNull(options, "options");
104+
}
65105

66106
try
67107
{
68-
handle = Proxy.git_repository_open(path);
108+
handle = (path != null) ? Proxy.git_repository_open(path) : Proxy.git_repository_new();
69109
RegisterForCleanup(handle);
70110

71111
isBare = Proxy.git_repository_is_bare(handle);
72112

113+
/* TODO: bug in libgit2, update when fixed by
114+
* https://github.com/libgit2/libgit2/pull/2970
115+
*/
116+
if (path == null)
117+
{
118+
isBare = true;
119+
}
120+
73121
Func<Index> indexBuilder = () => new Index(this);
74122

75123
string configurationGlobalFilePath = null;
@@ -252,7 +300,7 @@ public Index Index
252300
throw new BareRepositoryException("Index is not available in a bare repository.");
253301
}
254302

255-
return index.Value;
303+
return index != null ? index.Value : null;
256304
}
257305
}
258306

LibGit2Sharp/RepositoryInformation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal RepositoryInformation(Repository repo, bool isBare)
2323
FilePath path = Proxy.git_repository_path(repo.Handle);
2424
FilePath workingDirectoryPath = Proxy.git_repository_workdir(repo.Handle);
2525

26-
Path = path.Native;
26+
Path = path == null ? null : path.Native;
2727
WorkingDirectory = workingDirectoryPath == null ? null : workingDirectoryPath.Native;
2828
IsShallow = Proxy.git_repository_is_shallow(repo.Handle);
2929
}

0 commit comments

Comments
 (0)