-
-
Notifications
You must be signed in to change notification settings - Fork 167
/
RepoTestBase.cs
213 lines (177 loc) · 7.6 KB
/
RepoTestBase.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using LibGit2Sharp;
using Nerdbank.GitVersioning;
using Nerdbank.GitVersioning.LibGit2;
using Validation;
using Xunit.Abstractions;
public abstract partial class RepoTestBase : IDisposable
{
private readonly List<string> repoDirectories = new List<string>();
public RepoTestBase(ITestOutputHelper logger)
{
Requires.NotNull(logger, nameof(logger));
this.Logger = logger;
this.RepoPath = this.CreateDirectoryForNewRepo();
this.Context = this.CreateGitContext(this.RepoPath);
}
protected ITestOutputHelper Logger { get; }
protected GitContext? Context { get; set; }
protected string RepoPath { get; set; }
protected Signature Signer => new Signature("a", "a@a.com", new DateTimeOffset(2015, 8, 2, 0, 0, 0, TimeSpan.Zero));
protected Repository? LibGit2Repository { get; private set; }
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract GitContext CreateGitContext(string path, string? committish = null);
protected void SetContextToHead() => Assumes.True(this.Context?.TrySelectCommit("HEAD") ?? false);
protected VersionOptions? GetVersionOptions(string? path = null, string? committish = null)
{
Debug.Assert(path?.Length != 40, "commit passed as path");
using var context = this.CreateGitContext(path is null ? this.RepoPath : Path.Combine(this.RepoPath, path), committish);
return context.VersionFile.GetVersion();
}
protected VersionOracle GetVersionOracle(string? path = null, string? committish = null)
{
using var context = this.CreateGitContext(path is null ? this.RepoPath : Path.Combine(this.RepoPath, path), committish);
return new VersionOracle(context);
}
protected System.Version GetVersion(string? path = null, string? committish = null) => this.GetVersionOracle(path, committish).Version;
protected string CreateDirectoryForNewRepo()
{
string repoPath;
do
{
repoPath = Path.Combine(Path.GetTempPath(), this.GetType().Name + "_" + Path.GetRandomFileName());
} while (Directory.Exists(repoPath));
Directory.CreateDirectory(repoPath);
this.repoDirectories.Add(repoPath);
return repoPath;
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.LibGit2Repository?.Dispose();
this.Context?.Dispose();
foreach (string dir in this.repoDirectories)
{
try
{
TestUtilities.DeleteDirectory(dir);
}
catch (IOException)
{
// This happens in AppVeyor a lot.
}
}
}
}
protected virtual void InitializeSourceControl(bool withInitialCommit = true)
{
this.Context?.Dispose();
this.Context = this.InitializeSourceControl(this.RepoPath, withInitialCommit);
this.LibGit2Repository = new Repository(this.RepoPath);
}
protected virtual GitContext InitializeSourceControl(string repoPath, bool withInitialCommit = true)
{
Repository.Init(repoPath);
var repo = new Repository(repoPath);
repo.Config.Set("user.name", this.Signer.Name, ConfigurationLevel.Local);
repo.Config.Set("user.email", this.Signer.Email, ConfigurationLevel.Local);
foreach (var file in repo.RetrieveStatus().Untracked)
{
if (!Path.GetFileName(file.FilePath).StartsWith("_git2_", StringComparison.Ordinal))
{
Commands.Stage(repo, file.FilePath);
}
}
if (repo.Index.Count > 0 && withInitialCommit)
{
repo.Commit("initial commit", this.Signer, this.Signer);
}
repo.Dispose();
return this.CreateGitContext(repoPath);
}
protected void Ignore_git2_UntrackedFile()
{
string gitIgnoreFilePath = Path.Combine(this.RepoPath, ".gitignore");
File.WriteAllLines(gitIgnoreFilePath, new[] { "_git2_*" });
Commands.Stage(this.LibGit2Repository, gitIgnoreFilePath);
this.LibGit2Repository.Commit("Ignore _git2_ files.", this.Signer, this.Signer);
}
protected void AddCommits(int count = 1)
{
Verify.Operation(this.LibGit2Repository is object, "Repo has not been created yet.");
for (int i = 1; i <= count; i++)
{
this.LibGit2Repository.Commit($"filler commit {i}", this.Signer, this.Signer, new CommitOptions { AllowEmptyCommit = true });
}
this.SetContextToHead();
}
protected Commit? WriteVersionTxtFile(string version = "1.2", string prerelease = "", string? relativeDirectory = null)
{
if (relativeDirectory is null)
{
relativeDirectory = string.Empty;
}
string versionFilePath = Path.Combine(this.RepoPath, relativeDirectory, "version.txt");
File.WriteAllText(versionFilePath, $"{version}\r\n{prerelease}");
return this.CommitVersionFile(versionFilePath, $"{version}{prerelease}");
}
protected Commit? WriteVersionFile(string version = "1.2", string prerelease = "", string? relativeDirectory = null)
{
var versionData = VersionOptions.FromVersion(new System.Version(version), prerelease);
return this.WriteVersionFile(versionData, relativeDirectory);
}
protected Commit? WriteVersionFile(VersionOptions versionData, string? relativeDirectory = null)
{
Requires.NotNull(versionData, nameof(versionData));
if (relativeDirectory is null)
{
relativeDirectory = string.Empty;
}
bool localContextCreated = this.Context is null;
var context = this.Context ?? GitContext.Create(this.RepoPath, writable: true);
try
{
string versionFilePath = context.VersionFile.SetVersion(Path.Combine(this.RepoPath, relativeDirectory), versionData);
return this.CommitVersionFile(versionFilePath, versionData.Version?.ToString());
}
finally
{
if (localContextCreated)
{
context.Dispose();
}
}
}
protected Commit? CommitVersionFile(string versionFilePath, string? version)
{
Requires.NotNullOrEmpty(versionFilePath, nameof(versionFilePath));
Requires.NotNullOrEmpty(versionFilePath, nameof(versionFilePath));
if (this.LibGit2Repository is object)
{
Assumes.True(versionFilePath.StartsWith(this.RepoPath, StringComparison.OrdinalIgnoreCase));
var relativeFilePath = versionFilePath.Substring(this.RepoPath.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
Commands.Stage(this.LibGit2Repository, relativeFilePath);
if (Path.GetExtension(relativeFilePath) == ".json")
{
string txtFilePath = relativeFilePath.Substring(0, relativeFilePath.Length - 4) + "txt";
if (!File.Exists(Path.Combine(this.RepoPath, txtFilePath)) && this.LibGit2Repository.Index[txtFilePath] is not null)
{
this.LibGit2Repository.Index.Remove(txtFilePath);
}
}
Commit? result = this.LibGit2Repository.Commit($"Add/write {relativeFilePath} set to {version ?? "Inherited"}", this.Signer, this.Signer, new CommitOptions { AllowEmptyCommit = true });
this.SetContextToHead();
return result;
}
return null;
}
}