Skip to content

Commit ce4ccc9

Browse files
committed
Config architecture and Git integration testing (#3)
* quick test * started working on YAML file * adding configuration structure * adding some testing tools * verified that GitDiff works as expected for adding files * verified that Diff detection works in all cases
1 parent 627702f commit ce4ccc9

16 files changed

+409
-30
lines changed

src/Incrementalist.Cmd/Program.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,14 @@
55
using System.Linq;
66
using System.Runtime.InteropServices;
77
using System.Threading.Tasks;
8-
using Incrementalist.FileSystem;
98
using Incrementalist.Git;
9+
using Incrementalist.ProjectSystem;
1010
using LibGit2Sharp;
1111
using Microsoft.Build.Locator;
1212
using Microsoft.CodeAnalysis.MSBuild;
1313

1414
namespace Incrementalist.Cmd
1515
{
16-
enum FileType
17-
{
18-
Code,
19-
Project,
20-
Solution,
21-
Other
22-
}
2316

2417
class Program
2518
{
@@ -60,11 +53,11 @@ static async Task<int> Main(string[] args)
6053
//if (insideRepo)
6154
//{
6255
var repoFolder = Repository.Discover(Directory.GetCurrentDirectory());
63-
var repository = new Repository(repoFolder);
56+
var repository = new Repository(repoFolder);
6457
Console.WriteLine("Repo base is located in {0}", repoFolder);
6558
var workingFolder = Directory.GetParent(repoFolder).Parent;
6659

67-
var affectedFiles = DiffHelper.ChangedFiles(repository, "master").Select(x => Path.GetFullPath(x, workingFolder.FullName)).ToList();
60+
var affectedFiles = DiffHelper.ChangedFiles(repository, "dev").Select(x => Path.GetFullPath(x, workingFolder.FullName)).ToList();
6861
foreach (var file in affectedFiles)
6962
Console.WriteLine("Modified file: {0}", file);
7063
//}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using FluentAssertions;
7+
using Incrementalist.Git;
8+
using Incrementalist.Tests.Helpers;
9+
using Xunit;
10+
11+
namespace Incrementalist.Tests.Git
12+
{
13+
public class GitDiffDetectionSpecs : IDisposable
14+
{
15+
public DisposableRepository Repository { get; }
16+
17+
public GitDiffDetectionSpecs()
18+
{
19+
Repository = new DisposableRepository();
20+
}
21+
22+
[Fact(DisplayName = "Should detect files that have been added to git repo")]
23+
public void Should_detect_added_files_to_bare_Repo()
24+
{
25+
Repository.CreateBranch("foo").CheckoutBranch("foo").WriteFile("fuber.txt", "fuber").Commit("Fuberized file");
26+
var diffedFiles = DiffHelper.ChangedFiles(Repository.Repository, "master").ToList();
27+
diffedFiles.Count.Should().Be(1);
28+
var file = diffedFiles[0];
29+
Path.GetFileName(file).Should().Be("fuber.txt");
30+
}
31+
32+
[Fact(DisplayName = "Should detect files that have been modified in existing repo")]
33+
public void Should_detect_changes_to_existing_files_in_Repo()
34+
{
35+
Repository.WriteFile("fuber.txt", "fuber")
36+
.Commit("Fuberized file")
37+
.CreateBranch("foo")
38+
.CheckoutBranch("foo")
39+
.WriteFile("fuber.txt", "fuber2")
40+
.Commit("Updated fuberized file");
41+
42+
var diffedFiles = DiffHelper.ChangedFiles(Repository.Repository, "master").ToList();
43+
diffedFiles.Count.Should().Be(1);
44+
var file = diffedFiles[0];
45+
Path.GetFileName(file).Should().Be("fuber.txt");
46+
}
47+
48+
[Fact(DisplayName = "Should detect files that have been deleted in existing repo")]
49+
public void Should_detect_delete_of_existing_file_in_Repo()
50+
{
51+
Repository.WriteFile("fuber.txt", "fuber")
52+
.Commit("Fuberized file")
53+
.CreateBranch("foo")
54+
.CheckoutBranch("foo")
55+
.DeleteFile("fuber.txt")
56+
.Commit("Delete fuberized file");
57+
58+
var diffedFiles = DiffHelper.ChangedFiles(Repository.Repository, "master").ToList();
59+
diffedFiles.Count.Should().Be(1);
60+
var file = diffedFiles[0];
61+
Path.GetFileName(file).Should().Be("fuber.txt");
62+
}
63+
64+
[Fact(DisplayName = "Should not detect any changes when none are present")]
65+
public void Should_not_detect_any_changes_when_none_present()
66+
{
67+
Repository.CreateBranch("foo").CheckoutBranch("foo");
68+
69+
var diffedFiles = DiffHelper.ChangedFiles(Repository.Repository, "master").ToList();
70+
diffedFiles.Count.Should().Be(0);
71+
}
72+
73+
public void Dispose()
74+
{
75+
Repository?.Dispose();
76+
}
77+
}
78+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Text;
5+
using System.Threading;
6+
using LibGit2Sharp;
7+
8+
namespace Incrementalist.Tests.Helpers
9+
{
10+
public class DisposableRepository : IDisposable
11+
{
12+
/// <summary>
13+
/// Since it might take a few tries to delete the Git repository.
14+
/// </summary>
15+
private const int MaxDeleteAttempts = 5;
16+
17+
/// <summary>
18+
/// Needed to create repositories in random, temporary directories.
19+
/// </summary>
20+
/// <returns>The path to a temporary, random directory.</returns>
21+
public static string CreateTempDirectory()
22+
{
23+
var dirPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Path.GetFileNameWithoutExtension(System.IO.Path.GetRandomFileName()));
24+
Directory.CreateDirectory(dirPath);
25+
return dirPath;
26+
}
27+
28+
public DisposableRepository() : this(CreateTempDirectory()) { }
29+
30+
public DisposableRepository(string basePath)
31+
{
32+
BasePath = basePath;
33+
Init();
34+
}
35+
36+
private void Init()
37+
{
38+
var repoPath = Repository.Init(BasePath);
39+
Repository = new Repository(repoPath);
40+
var sig = CreateSignature();
41+
Repository.Commit("First", sig, sig);
42+
//Repository.CreateBranch("master"); // setup the master branch initially
43+
}
44+
45+
public string BasePath { get; }
46+
47+
public Repository Repository { get; private set; }
48+
49+
/// <summary>
50+
/// Create a new branch inside this repository.
51+
/// </summary>
52+
/// <param name="branchName">The name of the branch to be created.</param>
53+
/// <returns>The current <see cref="DisposableRepository"/>.</returns>
54+
public DisposableRepository CreateBranch(string branchName)
55+
{
56+
Repository.CreateBranch(branchName);
57+
return this;
58+
}
59+
60+
/// <summary>
61+
/// Checks out the specified branch, assuming it exists.
62+
/// </summary>
63+
/// <param name="branchName">The name of the branch to be checked out.</param>
64+
/// <returns>The current <see cref="DisposableRepository"/>.</returns>
65+
public DisposableRepository CheckoutBranch(string branchName)
66+
{
67+
var branch = Repository.Branches[branchName];
68+
var currentBranch = Commands.Checkout(Repository, branch);
69+
return this;
70+
}
71+
72+
/// <summary>
73+
/// Add a new file to the repository.
74+
/// </summary>
75+
/// <param name="fileName">The name of the file to add or overwrite.</param>
76+
/// <param name="fileText">The content of the file.</param>
77+
/// <returns>The current <see cref="DisposableRepository"/>.</returns>
78+
public DisposableRepository WriteFile(string fileName, string fileText)
79+
{
80+
var filePath = Path.Combine(BasePath, fileName);
81+
File.WriteAllText(filePath, fileText);
82+
Commands.Stage(Repository, filePath);
83+
return this;
84+
}
85+
86+
/// <summary>
87+
/// Delete an existing file from the repository.
88+
/// </summary>
89+
/// <param name="fileName">The name of the file to delete.</param>
90+
/// <returns>The current <see cref="DisposableRepository"/>.</returns>
91+
public DisposableRepository DeleteFile(string fileName)
92+
{
93+
var filePath = Path.Combine(BasePath, fileName);
94+
File.Delete(fileName);
95+
Commands.Remove(Repository, filePath);
96+
return this;
97+
}
98+
99+
/// <summary>
100+
/// Create a new commit inside the <see cref="Repository"/>.
101+
/// </summary>
102+
/// <param name="commitMessage">The commit message.</param>
103+
/// <param name="author">Optional. The signature of the author performing the commit.</param>
104+
/// <returns>The current <see cref="DisposableRepository"/>.</returns>
105+
public DisposableRepository Commit(string commitMessage, Signature author = null)
106+
{
107+
var committer = author ?? CreateSignature();
108+
Repository.Commit(commitMessage, committer, committer);
109+
return this;
110+
}
111+
112+
public static Signature CreateSignature(string name = null, string email = null)
113+
{
114+
return new Signature(name ?? "Fuber", email ?? "fuber@petabridge.com", DateTimeOffset.UtcNow);
115+
}
116+
117+
public void Dispose()
118+
{
119+
Repository?.Dispose();
120+
for (var attempt = 1; attempt <= MaxDeleteAttempts; attempt++)
121+
{
122+
try
123+
{
124+
Directory.Delete(BasePath, true);
125+
return;
126+
}
127+
catch (Exception ex)
128+
{
129+
if (attempt < MaxDeleteAttempts)
130+
{
131+
// some exponential backoff here
132+
Thread.Sleep(100 + (int)Math.Pow(10, attempt - 1));
133+
}
134+
}
135+
}
136+
137+
}
138+
}
139+
}

src/Incrementalist.Tests/Incrementalist.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9+
<PackageReference Include="FluentAssertions" Version="5.6.0" />
910
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
1011
<PackageReference Include="xunit" Version="$(XunitVersion)" />
1112
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />

src/Incrementalist.Tests/UnitTest1.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/Incrementalist/AffectedFile.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace Incrementalist
6+
{
7+
/// <summary>
8+
/// The types of files that can be detected automatically by Roslyn.
9+
/// </summary>
10+
public enum FileType
11+
{
12+
Code,
13+
Project,
14+
Solution,
15+
Script,
16+
Other
17+
}
18+
19+
20+
/// <summary>
21+
/// Used to document a file that was affected by the current commit.
22+
/// </summary>
23+
public sealed class AffectedFile
24+
{
25+
public AffectedFile(string path, FileType fileType, string project)
26+
{
27+
Path = path;
28+
FileType = fileType;
29+
Project = project;
30+
}
31+
32+
/// <summary>
33+
/// The absolute path to the file.
34+
/// </summary>
35+
public string Path { get; }
36+
37+
/// <summary>
38+
/// The type of file detected in the diff.
39+
/// </summary>
40+
public FileType FileType { get; }
41+
42+
/// <summary>
43+
/// The name of the affected project.
44+
/// </summary>
45+
public string Project { get; }
46+
}
47+
}

src/Incrementalist/BuildStep.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace Incrementalist
2+
{
3+
/// <summary>
4+
/// Used to define a build step, which may or may not be used
5+
/// depending on whether or not one of the affected projects requires it.
6+
/// </summary>
7+
public sealed class BuildStep
8+
{
9+
public BuildStep(string stepName, string commandText, IBuildStepApplicator applicator)
10+
{
11+
StepName = stepName;
12+
CommandText = commandText;
13+
Applicator = applicator;
14+
}
15+
16+
/// <summary>
17+
/// The name of this build step.
18+
/// </summary>
19+
public string StepName { get; }
20+
21+
/// <summary>
22+
/// The text to emit when this build step is used.
23+
///
24+
/// Some supported format strings:
25+
/// - "{fileName}" will swap in the name of the file, with the extension
26+
/// - "{filePath}" will swap in the absolute path of the file
27+
/// - "{projectName}" will swap in the name of the project, without the extension
28+
/// - "{projectPath}" will swap in the full path of the project including the extension
29+
/// </summary>
30+
public string CommandText { get; }
31+
32+
/// <summary>
33+
/// The applicator used to evaluate whether or not this build step applies to a particular path.
34+
/// </summary>
35+
public IBuildStepApplicator Applicator { get; }
36+
}
37+
}

src/Incrementalist/Git/DiffHelper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ namespace Incrementalist.Git
1212
/// </summary>
1313
public static class DiffHelper
1414
{
15-
public static IEnumerable<string> ChangedFiles(Repository repo, string targetBranch)
15+
public static IEnumerable<string> ChangedFiles(Repository repo, string targetBranch, string workingDirectory = null)
1616
{
17-
return repo.Diff.Compare<TreeChanges>(repo.Branches[targetBranch].Tip.Tree, DiffTargets.Index).Select(x => x.Path);
17+
var finalDir = workingDirectory ?? Directory.GetCurrentDirectory();
18+
return repo.Diff.Compare<TreeChanges>(repo.Branches[targetBranch].Tip.Tree, DiffTargets.Index).Select(x => Path.GetFullPath(x.Path));
1819
}
1920
}
2021
}

0 commit comments

Comments
 (0)