Skip to content

Commit

Permalink
Allow line patching for new worktree/index files
Browse files Browse the repository at this point in the history
Cherry picked from 7ff040e (gitextensions#9281)
  • Loading branch information
gerhardol committed Jun 20, 2021
1 parent 4f27b8a commit b7ff4e0
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 46 deletions.
2 changes: 1 addition & 1 deletion GitUI/CommandsDialogs/FormFileHistory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ private void UpdateSelectedFileViewers(bool force = false)
IsTracked = true,
IsSubmodule = GitModule.IsValidGitWorkingDir(_fullPathResolver.Resolve(fileName))
};
_ = View.ViewGitItemRevisionAsync(file, revision.ObjectId);
_ = View.ViewGitItemAsync(file, revision.ObjectId);
}
else if (tabControl1.SelectedTab == DiffTab)
{
Expand Down
3 changes: 2 additions & 1 deletion GitUI/CommandsDialogs/RevisionFileTreeControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using GitUI.CommandsDialogs.BrowseDialog;
using GitUI.Hotkey;
using GitUI.Properties;
using GitUI.UserControls;
using GitUIPluginInterfaces;
using Microsoft;
using ResourceManager;
Expand Down Expand Up @@ -368,7 +369,7 @@ Task ViewGitItemAsync(GitItem gitItem)
IsSubmodule = gitItem.ObjectType == GitObjectType.Commit
};

return FileText.ViewGitItemAsync(file);
return FileText.ViewGitItemAsync(file, gitItem.ObjectId);
}

default:
Expand Down
96 changes: 53 additions & 43 deletions GitUI/Editor/FileViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ public Task ViewRangeDiffAsync(string fileName, string text)
Action? openWithDifftool = null)
{
ThreadHelper.JoinableTaskFactory.Run(
() => ViewTextAsync(fileName, text, openWithDifftool));
() => ViewTextAsync(fileName, text, openWithDifftool: openWithDifftool));
}

/// <summary>
Expand All @@ -444,14 +444,17 @@ public Task ViewRangeDiffAsync(string fileName, string text)
/// <param name="text">The patch text.</param>
/// <param name="openWithDifftool">The action to open the difftool.</param>
/// <param name="checkGitAttributes">Check Git attributes to check for binary files.</param>
public Task ViewTextAsync(string? fileName, string text,
Action? openWithDifftool = null, bool checkGitAttributes = false)
public Task ViewTextAsync(string? fileName,
string text,
FileStatusItem? item = null,
Action? openWithDifftool = null,
bool checkGitAttributes = false)
{
return ShowOrDeferAsync(
text.Length,
() =>
{
ResetView(ViewMode.Text, fileName);
ResetView(ViewMode.Text, fileName, item: item);
// Check for binary file. Using gitattributes could be misleading for a changed file,
// but not much other can be done
Expand Down Expand Up @@ -489,27 +492,34 @@ public Task ViewRangeDiffAsync(string fileName, string text)
});
}

public Task ViewGitItemRevisionAsync(GitItemStatus file, ObjectId revision, Action? openWithDifftool = null)
public Task ViewGitItemAsync(FileStatusItem item, Action? openWithDifftool = null)
{
if (revision == ObjectId.WorkTreeId)
{
// No blob exists for worktree, present contents from file system
return ViewFileAsync(file.Name, file.IsSubmodule, openWithDifftool);
}

file.TreeGuid ??= Module.GetFileBlobHash(file.Name, revision);
return ViewGitItemAsync(item.Item, item.SecondRevision.ObjectId, item, openWithDifftool);
}

return ViewGitItemAsync(file, openWithDifftool);
public Task ViewGitItemAsync(GitItemStatus file, ObjectId objectId, Action? openWithDifftool = null)
{
return ViewGitItemAsync(file, objectId, null, openWithDifftool);
}

/// <summary>
/// View the git item with the TreeGuid.
/// </summary>
/// <param name="file">GitItem file, with TreeGuid.</param>
/// <param name="openWithDifftool">difftool command.</param>
/// <returns>Task to view the item.</returns>
public Task ViewGitItemAsync(GitItemStatus file, Action? openWithDifftool = null)
/// <param name="objectId">Revision to present. Can be null if file.TreeGuid is set.</param>
/// <param name="item">Metadata for line patching and presentation.</param>
/// <param name="openWithDifftool">difftool command</param>
/// <returns>Task to view the item</returns>
private Task ViewGitItemAsync(GitItemStatus file, ObjectId? objectId, FileStatusItem? item, Action? openWithDifftool)
{
if (objectId == ObjectId.WorkTreeId || file.Staged == StagedStatus.WorkTree)
{
// No blob exists for worktree, present contents from file system
return ViewFileAsync(file.Name, file.IsSubmodule, item, openWithDifftool);
}

file.TreeGuid ??= Module.GetFileBlobHash(file.Name, objectId);

Validates.NotNull(file.TreeGuid);
var sha = file.TreeGuid.ToString();
var isSubmodule = file.IsSubmodule;
Expand All @@ -531,6 +541,7 @@ public Task ViewGitItemAsync(GitItemStatus file, Action? openWithDifftool = null
getImage: GetImage,
getFileText: GetFileTextIfBlobExists,
getSubmoduleText: () => LocalizationHelpers.GetSubmoduleText(Module, file.Name.TrimEnd('/'), sha, cache: true),
item: item,
openWithDifftool: openWithDifftool);

string GetFileTextIfBlobExists()
Expand Down Expand Up @@ -562,9 +573,10 @@ string GetFileTextIfBlobExists()
/// </summary>
/// <param name="fileName">The file/submodule path.</param>
/// <param name="isSubmodule">If submodule.</param>
/// <param name="item">Metadata for line patching and presentation.</param>
/// <param name="openWithDifftool">Diff action.</param>
/// <returns>Task.</returns>
public Task ViewFileAsync(string fileName, bool isSubmodule = false, Action? openWithDifftool = null)
public Task ViewFileAsync(string fileName, bool isSubmodule = false, FileStatusItem? item = null, Action? openWithDifftool = null)
{
string? fullPath = _fullPathResolver.Resolve(fileName);
Validates.NotNull(fullPath);
Expand Down Expand Up @@ -599,6 +611,7 @@ public Task ViewFileAsync(string fileName, bool isSubmodule = false, Action? ope
getImage: GetImage,
getFileText: GetFileText,
getSubmoduleText: () => LocalizationHelpers.GetSubmoduleText(Module, fileName.TrimEnd('/'), "", cache: false),
item: item,
openWithDifftool));

Image? GetImage()
Expand Down Expand Up @@ -766,32 +779,22 @@ private StagedStatus ViewItemStagedStatus()
stagedStatus = GitModule.GetStagedStatus(_viewItem?.FirstRevision?.ObjectId,
_viewItem?.SecondRevision?.ObjectId,
_viewItem?.SecondRevision?.FirstParentId);
if (_viewItem?.Item is not null)
{
_viewItem.Item.Staged = stagedStatus;
}
}

return stagedStatus;
}

private bool ViewItemIsWorkTree()
{
return _viewMode == ViewMode.Diff
&& ViewItemStagedStatus() == StagedStatus.WorkTree
&& SupportLinePatching;
}

private bool ViewItemIsIndex()
{
return _viewMode == ViewMode.Diff
&& ViewItemStagedStatus() == StagedStatus.Index
&& SupportLinePatching;
}

private void SetVisibilityDiffContextMenu(ViewMode viewMode)
{
// stage and reset has different implementation depending on the viewItem
// For the user it looks the same and they expect the same menu item (and hotkey)
var isIndex = ViewItemIsIndex();
var isIndex = ViewItemStagedStatus() == StagedStatus.Index;
stageSelectedLinesToolStripMenuItem.Visible = SupportLinePatching && !isIndex;
unstageSelectedLinesToolStripMenuItem.Visible = isIndex;
unstageSelectedLinesToolStripMenuItem.Visible = SupportLinePatching && isIndex;
resetSelectedLinesToolStripMenuItem.Visible = SupportLinePatching;

// RangeDiff patch is undefined, could be new/old commit or to parents
Expand Down Expand Up @@ -937,6 +940,13 @@ private void OnIgnoreWhitespaceChanged()
AppSettings.IgnoreWhitespaceKind = IgnoreWhitespace;
}

/// <summary>
/// Reset internal status for the new file.
/// </summary>
/// <param name="viewMode">Requested mode to view.</param>
/// <param name="fileName">Filename to present, for highlighting etc.</param>
/// <param name="item">Metadata for linepatching.</param>
/// <param name="text">Metadata for linepatching.</param>
private void ResetView(ViewMode viewMode, string? fileName, FileStatusItem? item = null, string? text = null)
{
_viewMode = viewMode;
Expand All @@ -949,10 +959,10 @@ private void ResetView(ViewMode viewMode, string? fileName, FileStatusItem? item
_viewMode = ViewMode.FixedDiff;
}

SupportLinePatching = IsDiffView(_viewMode)
SupportLinePatching = ((IsDiffView(_viewMode) && (text?.Contains("@@") ?? false))
|| (item is not null && item.Item.IsNew && (item.Item.Staged is StagedStatus.WorkTree or StagedStatus.Index)))
&& !Module.IsBareRepository()
&& File.Exists(_fullPathResolver.Resolve(fileName))
&& (text?.Contains("@@") ?? false);
&& File.Exists(_fullPathResolver.Resolve(fileName));

SetVisibilityDiffContextMenu(_viewMode);
ClearImage();
Expand Down Expand Up @@ -984,7 +994,7 @@ void ClearImage()
}
}

private Task ViewItemAsync(string fileName, bool isSubmodule, Func<Image?> getImage, Func<string> getFileText, Func<string> getSubmoduleText, Action? openWithDifftool)
private Task ViewItemAsync(string fileName, bool isSubmodule, Func<Image?> getImage, Func<string> getFileText, Func<string> getSubmoduleText, FileStatusItem? item, Action? openWithDifftool)
{
FilePreamble = null;

Expand All @@ -994,7 +1004,7 @@ private Task ViewItemAsync(string fileName, bool isSubmodule, Func<Image?> getIm
getSubmoduleText,
text =>
{
ThreadHelper.JoinableTaskFactory.Run(() => ViewTextAsync(fileName, text, openWithDifftool));
ThreadHelper.JoinableTaskFactory.Run(() => ViewTextAsync(fileName, text, item, openWithDifftool));
});
}
else if (FileHelper.IsImage(fileName))
Expand All @@ -1018,7 +1028,7 @@ private Task ViewItemAsync(string fileName, bool isSubmodule, Func<Image?> getIm
return;
}
ResetView(ViewMode.Image, fileName);
ResetView(ViewMode.Image, fileName, item);
var size = DpiUtil.Scale(image.Size);
if (size.Height > PictureBox.Size.Height || size.Width > PictureBox.Size.Width)
{
Expand All @@ -1038,7 +1048,7 @@ private Task ViewItemAsync(string fileName, bool isSubmodule, Func<Image?> getIm
return _async.LoadAsync(
getFileText,
text => ThreadHelper.JoinableTaskFactory.Run(
() => ViewTextAsync(fileName, text, openWithDifftool, checkGitAttributes: true)));
() => ViewTextAsync(fileName, text, item, openWithDifftool, checkGitAttributes: true)));
}
}

Expand Down Expand Up @@ -1328,7 +1338,7 @@ private bool StageSelectedLines()
return false;
}

if (ViewItemIsWorkTree())
if (ViewItemStagedStatus() == StagedStatus.WorkTree)
{
StageSelectedLines(stage: true);
return true;
Expand All @@ -1340,7 +1350,7 @@ private bool StageSelectedLines()

private bool UnstageSelectedLines()
{
if (!ViewItemIsIndex())
if (!SupportLinePatching || ViewItemStagedStatus() != StagedStatus.Index)
{
// Hotkey executed when menu is disabled
return false;
Expand All @@ -1358,7 +1368,7 @@ private bool ResetSelectedLines()
return false;
}

if (ViewItemIsWorkTree() || ViewItemIsIndex())
if (ViewItemStagedStatus() is StagedStatus.WorkTree or StagedStatus.Index)
{
ResetNoncommittedSelectedLines();
return true;
Expand Down
2 changes: 1 addition & 1 deletion GitUI/GitUIExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static class GitUIExtensions
if (item.Item.IsNew || firstId is null || (!item.Item.IsDeleted && FileHelper.IsImage(item.Item.Name)))
{
// View blob guid from revision, or file for worktree
await fileViewer.ViewGitItemRevisionAsync(item.Item, item.SecondRevision.ObjectId, openWithDiffTool);
await fileViewer.ViewGitItemAsync(item, openWithDiffTool);
return;
}

Expand Down

0 comments on commit b7ff4e0

Please sign in to comment.