-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDiff.cs
More file actions
160 lines (136 loc) · 6.12 KB
/
Diff.cs
File metadata and controls
160 lines (136 loc) · 6.12 KB
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
using LibGit2Sharp;
namespace EyePatch
{
internal class Diff : Command
{
public override void Execute(Settings settings, string? arg = null)
{
var repo = FindRepository();
ExecuteWithRepo(
settings,
repo);
}
internal void ExecuteWithRepo(
Settings settings,
IRepository repo)
{
// Get the current branch
var currentBranch = repo.Head;
ConsoleWriter.WriteInfo($"Current Branch: {currentBranch.FriendlyName}");
// Find the commit where the current branch diverged from its parent branch
var parentCommit = repo.ObjectDatabase.FindMergeBase(
currentBranch.Tip,
repo.Branches["origin/main"].Tip);
if (null == parentCommit)
{
throw new EyePatchException("Could not determine the parent commit.");
}
ConsoleWriter.WriteInfo($"Parent Commit: {parentCommit.Sha}");
// Create a temporary folder to store original files
var tempFolder = CreateTempFolder();
Dictionary<string, ChangeKind> changes = new Dictionary<string, ChangeKind>();
try
{
// Find the list of modified files in the current branch
var changesFromTip = repo.Diff.Compare<TreeChanges>(
parentCommit.Tree,
currentBranch.Tip.Tree);
if (changesFromTip != null)
{
foreach (var change in changesFromTip)
{
changes.Add(change.Path, change.Status);
}
}
// Get all modified, added, or deleted files in the working directory (staged or unstaged)
var statusEntries = repo.RetrieveStatus(new StatusOptions());
if (statusEntries != null)
{
foreach (var entry in statusEntries)
{
if (entry.State.HasFlag(FileStatus.ModifiedInWorkdir) ||
entry.State.HasFlag(FileStatus.ModifiedInIndex))
{
changes[entry.FilePath] = ChangeKind.Modified;
}
else if (entry.State.HasFlag(FileStatus.NewInIndex))
{
changes.Add(entry.FilePath, ChangeKind.Added);
}
else if (entry.State.HasFlag(FileStatus.DeletedFromWorkdir) ||
entry.State.HasFlag(FileStatus.DeletedFromIndex))
{
changes[entry.FilePath] = ChangeKind.Deleted;
}
}
}
if (changes.Count == 0)
{
ConsoleWriter.WriteWarning("No changes to diff.");
return;
}
ConsoleWriter.WriteInfo($"\nFiles ({changes.Count}):\n");
ConsoleWriter.WriteNewLine();
List<string> diffFilePairs = [];
foreach (var change in changes)
{
if (change.Value is ChangeKind.Modified or ChangeKind.Added or ChangeKind.Deleted)
{
ConsoleWriter.WriteInfo($"{change.Key} ({change.Value})");
try
{
var tempFilePath =
Path.Combine(tempFolder, change.Key.Replace("/", "_"));
var currentFilePath =
Path.Combine(repo.Info.WorkingDirectory, change.Key.Replace("/", "\\"));
// Extract the original file content to a temp file
var originalBlob = parentCommit[change.Key]?.Target as Blob;
if (originalBlob != null)
{
WriteBlobAsFile(tempFilePath, originalBlob);
}
else
{
ConsoleWriter.WriteWarning($"Skipping {change.Key}, as no original version found.");
continue;
}
if (AreFilesIdentical(currentFilePath, originalBlob, change.Key))
{
ConsoleWriter.WriteWarning(
$"Skipping {change.Key} as it is identical (changesFromTip were reverted).");
continue;
}
diffFilePairs.Add($"{tempFilePath} {currentFilePath}");
}
catch (Exception e)
{
throw new EyePatchException($"Error processing diff for {change.Key}: {e.Message}", e);
}
}
}
LaunchDiffTool(settings, tempFolder, diffFilePairs);
}
finally
{
DeleteTempFolder(tempFolder);
}
}
internal virtual bool AreFilesIdentical(string currentFilePath, Blob originalBlob, string modifiedFile)
{
// Check if the two files are identical
if (File.Exists(currentFilePath))
{
var currentFileContent = File.ReadAllText(currentFilePath);
if (originalBlob.GetContentText() == currentFileContent)
{
return true;
}
}
return false;
}
internal virtual void WriteBlobAsFile(string tempFilePath, Blob originalBlob)
{
File.WriteAllText(tempFilePath, originalBlob.GetContentText());
}
}
}