Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix resetting selected lines for renamed files in index #10252

Merged
merged 13 commits into from Oct 19, 2022

Conversation

mdonatas
Copy link
Contributor

@mdonatas mdonatas commented Oct 13, 2022

Fixes

Fixes an issue where if you reset selected lines in a staged and renamed file then rename is undone too.

Proposed changes

  • Adjust the patch header to remove "reverse rename" part.

Screenshots

Before

reset-lines-on-renamed-before

After

reset-lines-on-renamed-after

Test methodology

  • Manual
  • Integration test

Test environment(s)

  • Git Extensions 33.33.33
  • Build 023b2d8 (Dirty)
  • Git 2.37.3.windows.1
  • Microsoft Windows NT 10.0.22000.0
  • .NET 6.0.10
  • DPI 192dpi (200% scaling)

Merge strategy

I agree that the maintainer squash merge this PR (if the commit message is clear).


✒️ I contribute this code under The Developer Certificate of Origin.

@ghost ghost assigned mdonatas Oct 13, 2022
@mdonatas
Copy link
Contributor Author

Related discussion that I've opened for integration tests part #10251

RescanChanges();
RescanChangesAsync();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The returned Task must be run, mustn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be awaited as it's fire-and-forget kind of task. I reverted this commit since I was returning this task because I didn't know about ThreadHelper.JoinPendingOperations(); and that it does exactly what I need - waits for background tasks to complete (at least that's my assumption).

Initialize();
InitializeAsync();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Comment on lines 887 to 890
return ThreadHelper.JoinableTaskFactory.RunAsync(() =>
{
return _unstagedLoader.LoadAsync(GetAllChangedFilesWithSubmodulesStatus, onComputed);
});
}).Task;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❔ just

await _unstagedLoader.LoadAsync(GetAllChangedFilesWithSubmodulesStatus, onComputed);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted this as it should only be awaited in tests and there is ThreadHelper.JoinPendingOperations(); for that.

string line = headerLines[i];
if (line.StartsWith("--- "))
{
line = $"--- a/{newName}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a risky check. I believe that a/, b/ is forced right now in GE, but Git could change the output format any time.

Copy link
Contributor Author

@mdonatas mdonatas Oct 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that would be a serious breaking change (and not just for GE). Also git documentation mentions these prefixes explicitly https://git-scm.com/docs/diff-format

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be changed with diff.mnemonicprefix=true. It was forced to false some time ago so a/b is likely stable.
But number of spaces etc are not porcelain and can be changed without notice.
It could be different in existing Git versions too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you approve of using regex here? Something like:
^---\s+(?<a>.+)/(?<aName>.+)$ and
^\+\+\+\s+(?<b>.+)/(?<bName>.+)$

to capture a prefix used and a file name as well as make it more resilient to spacing.

{
line = line.Replace($" {oldNameFull} ", $" a/{newName} ");
}
else if (line.StartsWith("rename from ") || line.StartsWith("rename to ") || line.StartsWith("similarity index "))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are any of these strings ever translated in Git?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are part of a diff format used by git and are called extended headers I think it's safe to assume that that wouldn't happen. At least documentation doesn't mention anything of that sort.
https://git-scm.com/docs/diff-format

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is described as a format, it is not even a 'requested' format, certainly not a porcelain interface.
Adding translations in Git will break too.
It could be OK anyway, if the consequences are low (like current behavior in master).
There need to be at least comments about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to push back if I may. Translation argument sounds almost like saying that translating browsers would mean translating HTTP Headers they send (custom ones, not covered by the standard).
These are headers added by the tools for the tools (at least I would assume so). They are meant to be parsable. Translating them would break older versions thus I can't imaging that ever happening. Although if you still insist, I'll add a comment.

@@ -73,6 +73,7 @@ private enum ViewMode
private Func<Task>? _deferShowFunc;
private readonly ContinuousScrollEventManager _continuousScrollEventManager;
private FileStatusItem? _viewItem;
private bool _confirmResetLines = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be marked as test specific, a proposal below
Even better would be to hide this in MessageBox.Show() instead with a test accessor
(assuming that there is no short term way to avoid this)

Suggested change
private bool _confirmResetLines = true;
// This variable is used by tests to avoid popups
private bool _unitTestConfirmResetLines = true;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageBox.Show() is not under our control and making a wrapper for it seems a daunting task for me at least :)
I like your suggested rename, thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap the call to MessageBox.Show() instead or rather switch to TaskDialog

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have a look at Use TaskDialog instead of MessageBox.Show for reset selected lines confirmation. Thoughts?

@mdonatas mdonatas requested review from gerhardol and mstv and removed request for gerhardol and mstv October 15, 2022 01:16
Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 modulo other comments

@@ -1476,7 +1481,7 @@ public void ResetNoncommittedSelectedLines()
return;
}

if (MessageBox.Show(this, TranslatedStrings.ResetSelectedLinesConfirmation, TranslatedStrings.ResetChangesCaption,
if (_unitTestConfirmResetLines && MessageBox.Show(this, TranslatedStrings.ResetSelectedLinesConfirmation, TranslatedStrings.ResetChangesCaption,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should change MessageBox.Show to TaskDialog and then we won't have test-only code outside the TestAccessor.

Copy link
Contributor Author

@mdonatas mdonatas Oct 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have a look at Use TaskDialog instead of MessageBox.Show for reset selected lines confirmation commit. I've tried to look for examples of manipulating TaskDialogPage in the tests but couldn't find any. I am not sure if this is a correct approach.

@RussKie RussKie added the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Oct 16, 2022
@ghost ghost removed the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Oct 16, 2022
@RussKie
Copy link
Member

RussKie commented Oct 16, 2022 via email

@mdonatas
Copy link
Contributor Author

A task dialog page can be autoclosed, IIRC

Thanks for the pointers!

https://github.com/dotnet/winforms/blob/main/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/TaskDialogSamples.cs#L217-L233 uses a timer to call PerformClick on a desired button to auto-close while I do it immediately upon creation of the dialog. Having looked at examples I think what I've got is correct.

@mdonatas mdonatas force-pushed the reset-renamed-from-index branch 2 times, most recently from 0873181 to 562f4e7 Compare October 16, 2022 16:53
@mdonatas
Copy link
Contributor Author

mdonatas commented Oct 16, 2022

Update: The fix was to call Application.EnableVisualStyles(); in a GlobalSetupOnce.cs where this call would be made once per assembly

AppVeyor is failing because of TaskDialogPage and I've been hitting my head against the problem for quite some time now... @RussKie it seems you are somewhat familiar with the root cause dotnet/wpf#6810 any ideas how to solve this here?

p.s. Works on my machine™
p.s.s. Although locally I needed to add

public FormCommitTests()
{
    Application.EnableVisualStyles();
}

Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, have not run

UnitTests/CommonTestUtils/ReferenceRepository.cs Outdated Show resolved Hide resolved
GitCommands/Patches/PatchManager.cs Outdated Show resolved Hide resolved
@mdonatas mdonatas requested review from mstv and removed request for gerhardol October 18, 2022 18:20
Caption = TranslatedStrings.ResetChangesCaption,
Icon = TaskDialogIcon.Warning,
Buttons = { TaskDialogButton.Yes, TaskDialogButton.No },
DefaultButton = TaskDialogButton.Yes,
Copy link
Member

@RussKie RussKie Oct 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a good idea? I think the default button for destructive operations should be the one that doesn't lead to data loss.
Which button is selected by default now (in the message box)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes is currently the default in the MessageBox and because I use it a lot in my daily work (select text, r, enter, repeat) I didn't want to change the behavior even though I agree with what you said.

using NUnit.Framework;

[SetUpFixture]
public class GlobalSetupOnce
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this class get used?

Copy link
Contributor Author

@mdonatas mdonatas Oct 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the NUnit docs

This is the attribute that marks a class that contains the one-time setup or teardown methods for all the test fixtures in a given namespace.

Since GlobalSetupOnce is in no namespace it's executed once per assembly. I've followed Answer 2 from this article.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@RussKie RussKie added the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Oct 19, 2022
@ghost ghost removed the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Oct 19, 2022
Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you

@RussKie RussKie merged commit 69a8570 into gitextensions:master Oct 19, 2022
@ghost ghost added this to the vNext milestone Oct 19, 2022
@mdonatas mdonatas deleted the reset-renamed-from-index branch October 20, 2022 09:20
RussKie pushed a commit that referenced this pull request Oct 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants