Skip to content

Commit 9f33f6b

Browse files
authored
Merge pull request #40 from dotTrench/fix/relative-path-resolution
Fix/relative path resolution
2 parents 726d30c + 04f1eaf commit 9f33f6b

19 files changed

+265
-212
lines changed

src/ProjectDiff.Core/BuildGraphDiff.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ public IEnumerable<DiffProject> Execute(BuildGraph previous, FrozenSet<string> m
7575
var existsInCurrent = _graph.Projects.Any(it => it.FullPath == previousProject.FullPath);
7676
if (!existsInCurrent)
7777
{
78-
_logger.LogDebug("Project {Path} not found in current graph, marking as removed", previousProject.FullPath);
78+
_logger.LogDebug(
79+
"Project {Path} not found in current graph, marking as removed",
80+
previousProject.FullPath
81+
);
7982
yield return new DiffProject
8083
{
8184
Path = previousProject.FullPath,

src/ProjectDiff.Core/BuildGraphFactory.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public void AddInputFile(string path, ProjectInstance projectInstance, string pr
6666
{
6767
path = Path.GetFullPath(path, projectInstance.Directory);
6868
}
69+
else
70+
{
71+
path = Path.GetFullPath(path);
72+
}
6973

7074
// Only include files that are part of this repository
7175
if (!path.StartsWith(_repository.Info.WorkingDirectory))
@@ -113,7 +117,7 @@ public BuildGraph Build()
113117

114118
return new BuildGraph
115119
{
116-
Projects = projects.OrderBy(it => it.References.Count).ToList(),
120+
Projects = projects.ToList(),
117121
};
118122
}
119123

@@ -132,7 +136,9 @@ private IEnumerable<BuildGraphProject> BuildGraphProjects()
132136
collector.AddReferences(references);
133137
}
134138

135-
return _collectors.Values.Select(it => it.ToBuildGraphProject());
139+
return _projectGraph.ProjectNodesTopologicallySorted
140+
.DistinctBy(it => it.ProjectInstance.FullPath)
141+
.Select(it => _collectors[it.ProjectInstance.FullPath].ToBuildGraphProject());
136142
}
137143
}
138144

src/ProjectDiff.Core/Entrypoints/DirectoryScanEntrypointProvider.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.Build.FileSystem;
2+
using Microsoft.Build.Graph;
3+
using Microsoft.Extensions.Logging;
4+
using Microsoft.Extensions.Logging.Abstractions;
5+
6+
namespace ProjectDiff.Core.Entrypoints;
7+
8+
public sealed class DirectoryScanProjectGraphEntryPointProvider : IProjectGraphEntryPointProvider
9+
{
10+
private readonly ILogger<DirectoryScanProjectGraphEntryPointProvider> _logger;
11+
private readonly string _repositoryWorkingDirectory;
12+
13+
14+
public DirectoryScanProjectGraphEntryPointProvider(
15+
string repositoryWorkingDirectory,
16+
ILogger<DirectoryScanProjectGraphEntryPointProvider>? logger = null
17+
)
18+
{
19+
_repositoryWorkingDirectory = repositoryWorkingDirectory;
20+
_logger = logger ?? NullLogger<DirectoryScanProjectGraphEntryPointProvider>.Instance;
21+
}
22+
23+
public Task<IEnumerable<ProjectGraphEntryPoint>> GetEntryPoints(
24+
MSBuildFileSystemBase fs,
25+
CancellationToken cancellationToken
26+
)
27+
{
28+
_logger.LogDebug("Scanning directory '{Directory}' for project files", _repositoryWorkingDirectory);
29+
var entrypoints = fs.EnumerateFiles(_repositoryWorkingDirectory, "*.csproj", SearchOption.AllDirectories)
30+
.Select(it => new ProjectGraphEntryPoint(it));
31+
32+
33+
return Task.FromResult(entrypoints);
34+
}
35+
}

src/ProjectDiff.Core/Entrypoints/IEntrypointProvider.cs renamed to src/ProjectDiff.Core/Entrypoints/IProjectGraphEntryPointProvider.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33

44
namespace ProjectDiff.Core.Entrypoints;
55

6-
public interface IEntrypointProvider
6+
public interface IProjectGraphEntryPointProvider
77
{
8-
Task<IEnumerable<ProjectGraphEntryPoint>> GetEntrypoints(
9-
string repositoryWorkingDirectory,
8+
Task<IEnumerable<ProjectGraphEntryPoint>> GetEntryPoints(
109
MSBuildFileSystemBase fs,
1110
CancellationToken cancellationToken
1211
);

src/ProjectDiff.Core/Entrypoints/SolutionEntrypointProvider.cs renamed to src/ProjectDiff.Core/Entrypoints/SolutionProjectGraphEntryPointProvider.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@
55

66
namespace ProjectDiff.Core.Entrypoints;
77

8-
public sealed class SolutionEntrypointProvider : IEntrypointProvider
8+
public sealed class SolutionProjectGraphEntryPointProvider : IProjectGraphEntryPointProvider
99
{
1010
private readonly FileInfo _solution;
11-
private readonly ILogger<SolutionEntrypointProvider> _logger;
11+
private readonly ILogger<SolutionProjectGraphEntryPointProvider> _logger;
1212

13-
public SolutionEntrypointProvider(FileInfo solution, ILogger<SolutionEntrypointProvider> logger)
13+
public SolutionProjectGraphEntryPointProvider(
14+
FileInfo solution,
15+
ILogger<SolutionProjectGraphEntryPointProvider> logger
16+
)
1417
{
1518
_solution = solution;
1619
_logger = logger;
1720
}
1821

19-
public async Task<IEnumerable<ProjectGraphEntryPoint>> GetEntrypoints(
20-
string repositoryWorkingDirectory,
22+
public async Task<IEnumerable<ProjectGraphEntryPoint>> GetEntryPoints(
2123
MSBuildFileSystemBase fs,
2224
CancellationToken cancellationToken
2325
)

src/ProjectDiff.Core/ProjectDiffExecutionStatus.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ public enum ProjectDiffExecutionStatus
44
{
55
Success,
66

7-
RepositoryNotFound,
87
BaseCommitNotFound,
98
HeadCommitNotFound,
109
MergeBaseNotFound,

src/ProjectDiff.Core/ProjectDiffExecutor.cs

Lines changed: 58 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,20 @@ public ProjectDiffExecutor(ProjectDiffExecutorOptions options, ILoggerFactory? l
2121
}
2222

2323
public async Task<ProjectDiffResult> GetProjectDiff(
24-
string repositoryPath,
25-
IEntrypointProvider entrypointProvider,
24+
Repository repository,
25+
IProjectGraphEntryPointProvider projectGraphEntryPointProvider,
2626
string baseCommitRef = "HEAD",
2727
string? headCommitRef = null,
2828
CancellationToken cancellationToken = default
2929
)
3030
{
31-
_logger.LogDebug("Discovering repository from path '{Path}'", repositoryPath);
32-
var repoPath = Repository.Discover(repositoryPath);
33-
if (repoPath is null)
31+
if (repository.Info.IsShallow)
3432
{
35-
_logger.LogError("Could not find a Git repository for path '{Path}'", repositoryPath);
36-
return new ProjectDiffResult
37-
{
38-
Status = ProjectDiffExecutionStatus.RepositoryNotFound
39-
};
40-
}
41-
42-
_logger.LogDebug("Found repository at '{RepoPath}'", repoPath);
43-
44-
using var repo = new Repository(repoPath);
45-
if (repo.Info.IsShallow)
46-
{
47-
_logger.LogWarning("Repository at is shallow, some operations may not work as expected");
33+
_logger.LogWarning("Repository is shallow, some operations may not work as expected");
4834
}
4935

5036
_logger.LogDebug("Looking up base commit '{BaseCommitRef}'", baseCommitRef);
51-
var baseCommit = repo.Lookup<Commit>(baseCommitRef);
37+
var baseCommit = repository.Lookup<Commit>(baseCommitRef);
5238
if (baseCommit is null)
5339
{
5440
_logger.LogError("Base commit '{BaseCommitRef}' not found in repository", baseCommitRef);
@@ -62,7 +48,7 @@ public async Task<ProjectDiffResult> GetProjectDiff(
6248
if (headCommitRef is not null)
6349
{
6450
_logger.LogDebug("Looking up head commit '{HeadCommitRef}'", headCommitRef);
65-
headCommit = repo.Lookup<Commit>(headCommitRef);
51+
headCommit = repository.Lookup<Commit>(headCommitRef);
6652

6753
if (headCommit is null)
6854
{
@@ -86,13 +72,14 @@ public async Task<ProjectDiffResult> GetProjectDiff(
8672
baseCommitRef,
8773
headCommitRef
8874
);
89-
var mergeBaseCommit = repo.ObjectDatabase.FindMergeBase(baseCommit, headCommit ?? repo.Head.Tip);
75+
var head = headCommit ?? repository.Head.Tip;
76+
var mergeBaseCommit = repository.ObjectDatabase.FindMergeBase(baseCommit, head);
9077
if (mergeBaseCommit is null)
9178
{
9279
_logger.LogError(
9380
"Could not find merge base between base commit '{BaseCommitRef}' and head commit '{HeadCommitRef}'",
9481
baseCommitRef,
95-
headCommitRef
82+
head.Sha
9683
);
9784
return new ProjectDiffResult
9885
{
@@ -113,11 +100,10 @@ public async Task<ProjectDiffResult> GetProjectDiff(
113100
baseCommitRef,
114101
headCommitRef ?? "working directory"
115102
);
116-
var changedFiles = GetGitModifiedFiles(repo, baseCommit, headCommit)
103+
var changedFiles = GetGitModifiedFiles(repository, baseCommit, headCommit)
117104
.Where(ShouldIncludeFile)
118105
.ToList();
119106

120-
121107
if (changedFiles.Count == 0)
122108
{
123109
_logger.LogInformation(
@@ -133,7 +119,6 @@ public async Task<ProjectDiffResult> GetProjectDiff(
133119
};
134120
}
135121

136-
137122
_logger.LogInformation("Found {NumChangedFiles} changed files", changedFiles.Count);
138123
if (_logger.IsEnabled(LogLevel.Debug))
139124
{
@@ -142,56 +127,32 @@ public async Task<ProjectDiffResult> GetProjectDiff(
142127

143128
var projectGraphFactory = new ProjectGraphFactory(_loggerFactory);
144129

145-
var baseGraph = await projectGraphFactory.BuildForGitTree(
146-
repo,
147-
baseCommit.Tree,
148-
entrypointProvider,
149-
cancellationToken
150-
);
151-
_logger.LogInformation(
152-
"Base project graph built with {NumProjects} projects",
153-
baseGraph.ProjectNodes.Count
154-
);
155-
156-
ProjectGraph headGraph;
157-
if (headCommit is null)
130+
BuildGraph baseBuildGraph;
131+
using (_logger.BeginScope("Building base graph"))
158132
{
159-
headGraph = await projectGraphFactory.BuildForWorkingDirectory(
160-
repo,
161-
entrypointProvider,
133+
baseBuildGraph = await CreateBuildGraph(
134+
repository,
135+
projectGraphFactory,
136+
projectGraphEntryPointProvider,
137+
baseCommit,
162138
cancellationToken
163139
);
164140
}
165-
else
141+
142+
BuildGraph headBuildGraph;
143+
using (_logger.BeginScope("Building head graph"))
166144
{
167-
headGraph = await projectGraphFactory.BuildForGitTree(
168-
repo,
169-
headCommit.Tree,
170-
entrypointProvider,
145+
headBuildGraph = await CreateBuildGraph(
146+
repository,
147+
projectGraphFactory,
148+
projectGraphEntryPointProvider,
149+
headCommit,
171150
cancellationToken
172151
);
173152
}
174153

175-
_logger.LogInformation(
176-
"Head project graph built with {NumProjects} projects",
177-
headGraph.ProjectNodes.Count
178-
);
179-
180-
181-
var headBuildGraph = BuildGraphFactory.CreateForProjectGraph(
182-
headGraph,
183-
repo,
184-
_options.IgnoreChangedFiles
185-
);
186-
var baseBuildGraph = BuildGraphFactory.CreateForProjectGraph(
187-
baseGraph,
188-
repo,
189-
_options.IgnoreChangedFiles
190-
);
191154

192-
var projects = BuildGraphDiff.Diff(baseBuildGraph, headBuildGraph, changedFiles, _loggerFactory)
193-
.OrderBy(it => it.ReferencedProjects.Count)
194-
.ThenBy(it => it.Name);
155+
var projects = BuildGraphDiff.Diff(baseBuildGraph, headBuildGraph, changedFiles, _loggerFactory);
195156
return new ProjectDiffResult
196157
{
197158
Status = ProjectDiffExecutionStatus.Success,
@@ -203,6 +164,38 @@ bool ShouldIncludeFile(string file) =>
203164
_options.IgnoreChangedFiles.Length == 0 || _options.IgnoreChangedFiles.All(it => it.FullName != file);
204165
}
205166

167+
private async Task<BuildGraph> CreateBuildGraph(
168+
Repository repository,
169+
ProjectGraphFactory projectGraphFactory,
170+
IProjectGraphEntryPointProvider projectGraphEntryPointProvider,
171+
Commit? headCommit,
172+
CancellationToken cancellationToken
173+
)
174+
{
175+
ProjectGraph projectGraph;
176+
if (headCommit is null)
177+
{
178+
projectGraph = await projectGraphFactory.BuildForWorkingDirectory(
179+
projectGraphEntryPointProvider,
180+
cancellationToken
181+
);
182+
}
183+
else
184+
{
185+
projectGraph = await projectGraphFactory.BuildForGitTree(
186+
repository,
187+
headCommit.Tree,
188+
projectGraphEntryPointProvider,
189+
cancellationToken
190+
);
191+
}
192+
193+
return BuildGraphFactory.CreateForProjectGraph(
194+
projectGraph,
195+
repository,
196+
_options.IgnoreChangedFiles
197+
);
198+
}
206199

207200
private static IEnumerable<string> GetGitModifiedFiles(
208201
Repository repository,

src/ProjectDiff.Core/ProjectDiffExecutorOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ public sealed class ProjectDiffExecutorOptions
44
{
55
public bool FindMergeBase { get; init; }
66
public FileInfo[] IgnoreChangedFiles { get; init; } = [];
7+
public IReadOnlyDictionary<string, string> GlobalProperties { get; init; } = new Dictionary<string, string>(0);
78
}

src/ProjectDiff.Core/ProjectDiffResult.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ public sealed record ProjectDiffResult
55
public required ProjectDiffExecutionStatus Status { get; init; }
66
public IEnumerable<DiffProject> Projects { get; init; } = [];
77
public IReadOnlyCollection<string> ChangedFiles { get; init; } = [];
8+
9+
public bool IsSuccessful => Status == ProjectDiffExecutionStatus.Success;
810
}

0 commit comments

Comments
 (0)