Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 510bd7f

Browse files
gerhardolRussKie
authored andcommittedDec 6, 2017
Compare artificial commits to all other commits (gitextensions#4157)
* Restructure OpenWithDifftool() so it can handle artificial diff and add unit tests * Update diff options so 'from' is always first in the list * Compare artificial commits to all other commits Handled in gitextensions#4031, several other PRs are required first, see the issue for merge order. It is possible to compare a normal commit to any other commit, but staged/unstaged has until know just been comparable to its immediate parent This commit removes that limitation. In order to do that, the diff handling has been cleaned up some too. There are maybe not less code related to artificial commits, but the normal flow has less special handling
1 parent aec560b commit 510bd7f

File tree

16 files changed

+248
-265
lines changed

16 files changed

+248
-265
lines changed
 

‎GitCommands/Git/GitModule.cs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ public sealed class GitModule : IGitModule
9191
private readonly IIndexLockManager _indexLockManager;
9292
private static readonly IGitDirectoryResolver GitDirectoryResolverInstance = new GitDirectoryResolver();
9393
private readonly IGitTreeParser _gitTreeParser = new GitTreeParser();
94+
private readonly IRevisionDiffProvider _revisionDiffProvider = new RevisionDiffProvider();
95+
9496

9597
public const string NoNewLineAtTheEnd = "\\ No newline at end of file";
9698
private const string DiffCommandWithStandardArgs = " -c diff.submodule=short diff --no-color ";
@@ -2201,13 +2203,8 @@ public Patch GetSingleDiff(string @from, string to, string fileName, string oldF
22012203

22022204
//fix refs slashes
22032205
from = from.ToPosixPath();
2204-
to = to.ToPosixPath();
2205-
string commitRange = string.Empty;
2206-
if (!to.IsNullOrEmpty())
2207-
commitRange = "\"" + to + "\"";
2208-
if (!from.IsNullOrEmpty())
2209-
commitRange = string.Join(" ", commitRange, "\"" + from + "\"");
2210-
2206+
to = to == null ? "":to.ToPosixPath();
2207+
string commitRange = _revisionDiffProvider.Get(from, to);
22112208
if (AppSettings.UsePatienceDiffAlgorithm)
22122209
extraDiffArguments = string.Concat(extraDiffArguments, " --patience");
22132210

@@ -2250,7 +2247,7 @@ public string GetDiffFilesText(string from, string to)
22502247

22512248
public string GetDiffFilesText(string from, string to, bool noCache)
22522249
{
2253-
string cmd = DiffCommandWithStandardArgs + "-M -C --name-status \"" + to + "\" \"" + from + "\"";
2250+
string cmd = DiffCommandWithStandardArgs + "-M -C --name-status " + _revisionDiffProvider.Get(from, to);
22542251
return noCache ? RunGitCmd(cmd) : this.RunCacheableCmd(AppSettings.GitCommand, cmd, SystemEncoding);
22552252
}
22562253

@@ -2263,14 +2260,35 @@ public List<GitItemStatus> GetDiffFilesWithSubmodulesStatus(string from, string
22632260

22642261
public List<GitItemStatus> GetDiffFiles(string from, string to, bool noCache = false)
22652262
{
2266-
string cmd = DiffCommandWithStandardArgs + "-M -C -z --name-status \"" + to + "\" \"" + from + "\"";
2263+
noCache = noCache || GitRevision.IsArtificial(from) || GitRevision.IsArtificial(to);
2264+
string cmd = DiffCommandWithStandardArgs + "-M -C -z --name-status " + _revisionDiffProvider.Get(from, to);
22672265
string result = noCache ? RunGitCmd(cmd) : this.RunCacheableCmd(AppSettings.GitCommand, cmd, SystemEncoding);
2268-
return GitCommandHelpers.GetAllChangedFilesFromString(this, result, true);
2266+
var resultCollection = GitCommandHelpers.GetAllChangedFilesFromString(this, result, true);
2267+
if (from == GitRevision.UnstagedGuid || to == GitRevision.UnstagedGuid)
2268+
{
2269+
//For unstaged the untracked must be added too
2270+
var files = GetUnstagedFilesWithSubmodulesStatus().Where(item => item.IsNew);
2271+
if (from == GitRevision.UnstagedGuid)
2272+
{
2273+
//The file is seen as "deleted" in 'to' revision
2274+
foreach (var item in files)
2275+
{
2276+
item.IsNew = false;
2277+
item.IsDeleted = true;
2278+
resultCollection.Add(item);
2279+
}
2280+
}
2281+
else
2282+
{
2283+
resultCollection.AddRange(files);
2284+
}
2285+
}
2286+
return resultCollection;
22692287
}
22702288

22712289
public IList<GitItemStatus> GetStashDiffFiles(string stashName)
22722290
{
2273-
var resultCollection = GetDiffFiles(stashName, stashName + "^", true);
2291+
var resultCollection = GetDiffFiles(stashName + "^", stashName, true);
22742292

22752293
// shows untracked files
22762294
string untrackedTreeHash = RunGitCmd("log " + stashName + "^3 --pretty=format:\"%T\" --max-count=1");
@@ -3035,12 +3053,8 @@ public IEnumerable<string> GetPreviousCommitMessages(string revision, int count)
30353053
public string OpenWithDifftool(string filename, string oldFileName = "", string revision1 = null, string revision2 = null, string extraDiffArguments = "")
30363054
{
30373055
var output = "";
3038-
if (!filename.IsNullOrEmpty())
3039-
filename = filename.Quote();
3040-
if (!oldFileName.IsNullOrEmpty())
3041-
oldFileName = oldFileName.Quote();
30423056

3043-
string args = string.Join(" ", extraDiffArguments, revision1.QuoteNE(), revision2.QuoteNE(), "--", filename, oldFileName);
3057+
string args = string.Join(" ", extraDiffArguments, _revisionDiffProvider.Get(revision1, revision2), "--", filename.QuoteNE(), oldFileName.QuoteNE());
30443058
RunGitCmdDetached("difftool --gui --no-prompt " + args);
30453059
return output;
30463060
}

‎GitCommands/Git/RevisionDiffProvider.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
11
using System;
22
using System.Diagnostics;
33

4-
namespace GitCommands
4+
namespace GitCommands.Git
55
{
6+
public interface IRevisionDiffProvider
7+
{
8+
/// <summary>
9+
/// options to git-diff from GE arguments, including artificial commits
10+
/// This is an instance class to not have static dependencies in GitModule
11+
/// </summary>
12+
/// <param name="from">The first revision</param>
13+
/// <param name="to">The second "current" revision</param>
14+
/// <returns></returns>
15+
string Get(string from, string to);
16+
}
17+
618
/// <summary>
719
/// Translate GitRevision including artificial commits to diff options
820
/// Closely related to GitRevision.cs
921
/// </summary>
10-
public class RevisionDiffProvider
22+
public sealed class RevisionDiffProvider : IRevisionDiffProvider
1123
{
24+
private static readonly string StagedOpt = "--cached";
25+
1226
/// <summary>
1327
/// options to git-diff from GE arguments, including artificial commits
28+
/// This is an instance class to not have static dependencies in GitModule
1429
/// </summary>
1530
/// <param name="from">The first revision</param>
1631
/// <param name="to">The second "current" revision</param>
1732
/// <returns></returns>
18-
public static string Get(string from, string to)
33+
public string Get(string from, string to)
1934
{
2035
string extra = string.Empty;
2136
from = ArtificialToDiffOptions(from);
@@ -60,7 +75,7 @@ public static string Get(string from, string to)
6075
/// </summary>
6176
/// <param name="rev"></param>
6277
/// <returns></returns>
63-
private static string ArtificialToDiffOptions(string rev)
78+
private string ArtificialToDiffOptions(string rev)
6479
{
6580
if (rev.IsNullOrEmpty() || rev == GitRevision.UnstagedGuid) { rev = string.Empty; }
6681
else if (rev == "^" || rev == GitRevision.UnstagedGuid + "^" || rev == GitRevision.IndexGuid) { rev = StagedOpt; }
@@ -74,7 +89,5 @@ private static string ArtificialToDiffOptions(string rev)
7489

7590
return rev;
7691
}
77-
78-
private const string StagedOpt = "--cached";
7992
}
8093
}

‎GitUI/CommandsDialogs/FormArchive.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,19 @@ private string GetPathArgumentFromGui()
154154
{
155155
if (checkBoxPathFilter.Checked)
156156
{
157-
// 1. get all lines from text box which are not empty
158-
// 2. wrap lines with ""
157+
// 1. get all lines (paths) from text box
158+
// 2. wrap lines that are not empty with ""
159159
// 3. join together with space as separator
160-
return string.Join(" ", textBoxPaths.Lines.Where(a => !a.IsNullOrEmpty()).Select(a => string.Format("\"{0}\"", a)));
160+
return string.Join(" ", textBoxPaths.Lines.Select(a => a.QuoteNE()));
161161
}
162162
else if (checkboxRevisionFilter.Checked)
163163
{
164164

165-
// 1. get all files changed between current revision and selected revision from diff
166-
var files = UICommands.Module.GetDiffFiles(this.SelectedRevision.Guid, this.DiffSelectedRevision.Guid);
167-
// 2. wrap names with ""
165+
// 1. get all changed (and not deleted files) from selected to current revision
166+
var files = UICommands.Module.GetDiffFiles(this.DiffSelectedRevision.Guid, this.SelectedRevision.Guid).Where(f => !f.IsDeleted);
167+
// 2. wrap file names with ""
168168
// 3. join together with space as separator
169-
return string.Join(" ", files.Where(f => !f.IsDeleted).Select(f => string.Format("\"{0}\"", f.Name)));
169+
return string.Join(" ", files.Select(f => f.Name.QuoteNE()));
170170
}
171171
else
172172
{

‎GitUI/CommandsDialogs/FormCommit.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,19 +1960,19 @@ private void FilenameToClipboardToolStripMenuItemClick(object sender, EventArgs
19601960
Clipboard.SetText(fileNames.ToString());
19611961
}
19621962

1963-
private void OpenFilesWithDiffTool(IEnumerable<GitItemStatus> items, bool staged)
1963+
private void OpenFilesWithDiffTool(IEnumerable<GitItemStatus> items, string from, string to)
19641964
{
19651965
foreach (var item in items)
19661966
{
1967-
string output = Module.OpenWithDifftool(item.Name, null, null, null, staged ? "--cached" : "");
1967+
string output = Module.OpenWithDifftool(item.Name, null, from, to);
19681968
if (!string.IsNullOrEmpty(output))
19691969
MessageBox.Show(this, output);
19701970
}
19711971
}
19721972

19731973
private void OpenWithDifftoolToolStripMenuItemClick(object sender, EventArgs e)
19741974
{
1975-
OpenFilesWithDiffTool(Unstaged.SelectedItems, staged: false);
1975+
OpenFilesWithDiffTool(Unstaged.SelectedItems, GitRevision.IndexGuid, GitRevision.UnstagedGuid);
19761976
}
19771977

19781978
private void ResetPartOfFileToolStripMenuItemClick(object sender, EventArgs e)
@@ -2634,7 +2634,7 @@ private void OpenContainingFolder(FileStatusList list)
26342634

26352635
private void stagedOpenDifftoolToolStripMenuItem9_Click(object sender, EventArgs e)
26362636
{
2637-
OpenFilesWithDiffTool(Staged.SelectedItems, staged: true);
2637+
OpenFilesWithDiffTool(Staged.SelectedItems, "HEAD", GitRevision.IndexGuid);
26382638
}
26392639

26402640
private void openFolderToolStripMenuItem10_Click(object sender, EventArgs e)

‎GitUI/CommandsDialogs/FormDiff.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,20 @@ private void openWithDifftoolToolStripMenuItem_Click(object sender, EventArgs e)
119119
if (DiffFiles.SelectedItem == null)
120120
return;
121121

122-
GitUIExtensions.DiffWithRevisionKind diffKind;
122+
GitUI.RevisionDiffKind diffKind;
123123

124124
if (sender == aLocalToolStripMenuItem)
125-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffALocal;
125+
diffKind = GitUI.RevisionDiffKind.DiffALocal;
126126
else if (sender == bLocalToolStripMenuItem)
127-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffBLocal;
127+
diffKind = GitUI.RevisionDiffKind.DiffBLocal;
128128
else if (sender == parentOfALocalToolStripMenuItem)
129-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffAParentLocal;
129+
diffKind = GitUI.RevisionDiffKind.DiffAParentLocal;
130130
else if (sender == parentOfBLocalToolStripMenuItem)
131-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffBParentLocal;
131+
diffKind = GitUI.RevisionDiffKind.DiffBParentLocal;
132132
else
133133
{
134134
Debug.Assert(sender == aBToolStripMenuItem, "Not implemented DiffWithRevisionKind: " + sender);
135-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffAB;
135+
diffKind = GitUI.RevisionDiffKind.DiffAB;
136136
}
137137

138138
foreach (var selectedItem in DiffFiles.SelectedItems)
@@ -157,12 +157,7 @@ private void fileHistoryDiffToolstripMenuItem_Click(object sender, EventArgs e)
157157

158158
if (item.IsTracked)
159159
{
160-
IList<GitRevision> revisions = RevisionGrid.GetSelectedRevisions();
161-
162-
if (revisions.Count == 0 || GitRevision.IsArtificial(revisions[0].Guid))
163-
UICommands.StartFileHistoryDialog(this, item.Name);
164-
else
165-
UICommands.StartFileHistoryDialog(this, item.Name, revisions[0], false);
160+
UICommands.StartFileHistoryDialog(this, item.Name, _baseRevision, false);
166161
}
167162
}
168163

@@ -172,12 +167,7 @@ private void blameToolStripMenuItem_Click(object sender, EventArgs e)
172167

173168
if (item.IsTracked)
174169
{
175-
IList<GitRevision> revisions = RevisionGrid.GetSelectedRevisions();
176-
177-
if (revisions.Count == 0 || GitRevision.IsArtificial(revisions[0].Guid))
178-
UICommands.StartFileHistoryDialog(this, item.Name, null, false, true);
179-
else
180-
UICommands.StartFileHistoryDialog(this, item.Name, revisions[0], true, true);
170+
UICommands.StartFileHistoryDialog(this, item.Name, _baseRevision, true, true);
181171
}
182172
}
183173

@@ -261,7 +251,7 @@ private void PickAnotherBranch(GitRevision preSelectCommit, ref string displaySt
261251

262252
private void PickAnotherCommit(GitRevision preSelect, ref string displayStr, ref GitRevision revision)
263253
{
264-
using (var form = new FormChooseCommit(UICommands, preselectCommit: preSelect.Guid))
254+
using (var form = new FormChooseCommit(UICommands, preselectCommit: preSelect.Guid, showArtificial: true))
265255
{
266256
if (form.ShowDialog(this) == DialogResult.OK)
267257
{

‎GitUI/CommandsDialogs/FormFileHistory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ private void OpenWithDifftoolToolStripMenuItemClick(object sender, EventArgs e)
328328
{
329329
orgFileName = selectedRows[0].Name;
330330
}
331-
FileChanges.OpenWithDifftool(FileName, orgFileName, GitUIExtensions.DiffWithRevisionKind.DiffAB);
331+
FileChanges.OpenWithDifftool(FileName, orgFileName, GitUI.RevisionDiffKind.DiffAB);
332332
}
333333

334334
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
@@ -442,7 +442,7 @@ public override void TranslateItems(ITranslation translation)
442442

443443
private void diffToolremotelocalStripMenuItem_Click(object sender, EventArgs e)
444444
{
445-
FileChanges.OpenWithDifftool(FileName, string.Empty, GitUIExtensions.DiffWithRevisionKind.DiffBLocal);
445+
FileChanges.OpenWithDifftool(FileName, string.Empty, GitUI.RevisionDiffKind.DiffBLocal);
446446
}
447447

448448
private void toolStripSplitLoad_ButtonClick(object sender, EventArgs e)

‎GitUI/CommandsDialogs/RevisionDiff.cs

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,7 @@ public string GetTabText()
140140
break;
141141

142142
case 2: // diff "first clicked revision" --> "second clicked revision"
143-
bool artificialRevSelected = revisions[0].IsArtificial() || revisions[1].IsArtificial();
144-
if (!artificialRevSelected)
145-
return _diffTwoSelected.Text;
146-
break;
147-
143+
return _diffTwoSelected.Text;
148144
}
149145
return _diffNotSupported.Text;
150146
}
@@ -414,12 +410,8 @@ private void blameToolStripMenuItem_Click(object sender, EventArgs e)
414410

415411
if (item.IsTracked)
416412
{
417-
IList<GitRevision> revisions = _revisionGrid.GetSelectedRevisions();
418-
419-
if (revisions.Count == 0 || GitRevision.IsArtificial(revisions[0].Guid))
420-
UICommands.StartFileHistoryDialog(this, item.Name, null, false, true);
421-
else
422-
UICommands.StartFileHistoryDialog(this, item.Name, revisions[0], true, true);
413+
GitRevision revision = _revisionGrid.GetSelectedRevisions().FirstOrDefault();
414+
UICommands.StartFileHistoryDialog(this, item.Name, revision, true, true);
423415
}
424416
}
425417

@@ -509,12 +501,8 @@ private void fileHistoryDiffToolstripMenuItem_Click(object sender, EventArgs e)
509501

510502
if (item.IsTracked)
511503
{
512-
IList<GitRevision> revisions = _revisionGrid.GetSelectedRevisions();
513-
514-
if (revisions.Count == 0 || GitRevision.IsArtificial(revisions[0].Guid))
515-
UICommands.StartFileHistoryDialog(this, item.Name);
516-
else
517-
UICommands.StartFileHistoryDialog(this, item.Name, revisions[0], false);
504+
GitRevision revision = _revisionGrid.GetSelectedRevisions().FirstOrDefault();
505+
UICommands.StartFileHistoryDialog(this, item.Name, revision, false);
518506
}
519507
}
520508

@@ -528,20 +516,19 @@ private void openWithDifftoolToolStripMenuItem_Click(object sender, EventArgs e)
528516
if (DiffFiles.SelectedItem == null)
529517
return;
530518

531-
GitUIExtensions.DiffWithRevisionKind diffKind;
519+
GitUI.RevisionDiffKind diffKind;
532520

533521
if (sender == aLocalToolStripMenuItem)
534-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffALocal;
522+
diffKind = GitUI.RevisionDiffKind.DiffALocal;
535523
else if (sender == bLocalToolStripMenuItem)
536-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffBLocal;
524+
diffKind = GitUI.RevisionDiffKind.DiffBLocal;
537525
else if (sender == parentOfALocalToolStripMenuItem)
538-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffAParentLocal;
526+
diffKind = GitUI.RevisionDiffKind.DiffAParentLocal;
539527
else if (sender == parentOfBLocalToolStripMenuItem)
540-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffBParentLocal;
528+
diffKind = GitUI.RevisionDiffKind.DiffBParentLocal;
541529
else
542530
{
543-
Debug.Assert(sender == aBToolStripMenuItem, "Not implemented DiffWithRevisionKind: " + sender);
544-
diffKind = GitUIExtensions.DiffWithRevisionKind.DiffAB;
531+
diffKind = GitUI.RevisionDiffKind.DiffAB;
545532
}
546533

547534
foreach (var itemWithParent in DiffFiles.SelectedItemsWithParent)
@@ -582,7 +569,6 @@ private ContextMenuDiffToolInfo GetContextMenuDiffToolInfo()
582569
}
583570

584571
//enable *<->Local items only when local file exists
585-
//no simple way to check if A (or A/B parents) is normal, ignore that some menus should be disabled
586572
foreach (var item in DiffFiles.SelectedItems)
587573
{
588574
bIsNormal = bIsNormal || !(item.IsNew || item.IsDeleted);

‎GitUI/CommandsDialogs/RevisionFileTree.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,7 @@ private void blameMenuItem_Click(object sender, EventArgs e)
363363
if (gitItem == null)
364364
return;
365365

366-
if (GitRevision.IsArtificial(_revision.Guid))
367-
UICommands.StartFileHistoryDialog(this, gitItem.FileName, null, false, true);
368-
else
369-
UICommands.StartFileHistoryDialog(this, gitItem.FileName, _revision, true, true);
366+
UICommands.StartFileHistoryDialog(this, gitItem.FileName, _revision, true, true);
370367
}
371368

372369
private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e)
@@ -390,10 +387,7 @@ private void fileHistoryItem_Click(object sender, EventArgs e)
390387
if (gitItem == null)
391388
return;
392389

393-
if (GitRevision.IsArtificial(_revision.Guid))
394-
UICommands.StartFileHistoryDialog(this, gitItem.FileName);
395-
else
396-
UICommands.StartFileHistoryDialog(this, gitItem.FileName, _revision, false, false);
390+
UICommands.StartFileHistoryDialog(this, gitItem.FileName, _revision, false, false);
397391
}
398392

399393
private void findToolStripMenuItem_Click(object sender, EventArgs e)

‎GitUI/GitUI.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@
253253
<Compile Include="CommandsDialogs\SettingsDialog\Pages\FormBrowseRepoSettingsPage.Designer.cs">
254254
<DependentUpon>FormBrowseRepoSettingsPage.cs</DependentUpon>
255255
</Compile>
256+
<Compile Include="RevisionDiffInfoProvider.cs" />
257+
<Compile Include="RevisionDiffKind.cs" />
256258
<Compile Include="FormStatusOutputLog.cs" />
257259
<Compile Include="CommandsDialogs\WorktreeDialog\FormCreateWorktree.cs">
258260
<SubType>Form</SubType>

0 commit comments

Comments
 (0)
Please sign in to comment.