Skip to content

#977 - Discarded changes should be saved in a dated file in the Trash #1516

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

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/Commands/SaveDiscardOnTrash.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace SourceGit.Commands
{
public static class SaveDiscardOnTrash
{
public static async Task<bool> ProcessSaveDiscardOnTrash(string repo, List<Models.Change> changes)
{
changes ??= await new QueryLocalChanges(repo).GetResultAsync().ConfigureAwait(false);

string tempFolder = Path.GetTempPath();
string fileName = $"discard_{DateTime.Now.Ticks}.patch";
string fileNameTemp = Path.Combine(tempFolder, fileName);

// Save the patch in the Temp Folder
var succ = await SaveChangesAsPatch.ProcessLocalChangesAsync(repo, changes, true, fileNameTemp);
if (succ) return false;

// Move the file in the Trash
if(!Native.OS.MoveFileToTrash(fileNameTemp)) return false;

return false;
}
}
}
5 changes: 5 additions & 0 deletions src/Native/Linux.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,10 @@ private string FindJetBrainsFleet()
var path = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox/apps/fleet/bin/Fleet";
return File.Exists(path) ? path : FindExecutable("fleet");
}

public bool MoveFileToTrash(string file)
{
return true;
}
}
}
5 changes: 5 additions & 0 deletions src/Native/MacOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,10 @@ public void OpenWithDefaultEditor(string file)
{
Process.Start("open", $"\"{file}\"");
}

public bool MoveFileToTrash(string file)
{
return true;
}
}
}
6 changes: 6 additions & 0 deletions src/Native/OS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public interface IBackend
string FindGitExecutable();
string FindTerminal(Models.ShellOrTerminal shell);
List<Models.ExternalTool> FindExternalTools();
bool MoveFileToTrash(string file);

void OpenTerminal(string workdir);
void OpenInFileManager(string path, bool select);
Expand Down Expand Up @@ -162,6 +163,11 @@ public static void OpenBrowser(string url)
_backend.OpenBrowser(url);
}

public static bool MoveFileToTrash(string file)
{
return _backend.MoveFileToTrash(file);
}

public static void OpenTerminal(string workdir)
{
if (string.IsNullOrEmpty(ShellOrTerminal))
Expand Down
42 changes: 42 additions & 0 deletions src/Native/Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ internal struct MARGINS
public int cyBottomHeight;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public uint wFunc;
public string pFrom;
public string pTo;
public ushort fFlags;
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
public string lpszProgressTitle;
}

[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);

Expand All @@ -48,6 +61,9 @@ internal struct MARGINS
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = false)]
private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags);

[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);

[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

Expand Down Expand Up @@ -253,6 +269,28 @@ public void OpenWithDefaultEditor(string file)
Process.Start(start);
}

public bool MoveFileToTrash(string file)
{
SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT
{
wFunc = FO_DELETE,
pFrom = file + '\0',
pTo = null,
fFlags = (ushort)(FOF_ALLOWUNDO | FOF_NOCONFIRMATION),
fAnyOperationsAborted = false,
hNameMappings = IntPtr.Zero,
lpszProgressTitle = null
};

// Move the file in the Trash
bool result = SHFileOperation(ref fileOp) == 0;

// If move ok delete the temp file
if (result) File.Delete(file);

return result;
}

private void FixWindowFrameOnWin10(Window w)
{
// Schedule the DWM frame extension to run in the next render frame
Expand Down Expand Up @@ -431,5 +469,9 @@ private string FindVSSolutionFile(DirectoryInfo dir, int leftDepth)

return null;
}

private const uint FO_DELETE = 0x0003; // Delete operation
private const uint FOF_ALLOWUNDO = 0x0040; // Put in Trash
private const uint FOF_NOCONFIRMATION = 0x0010; // No confirmation
}
}
1 change: 1 addition & 0 deletions src/Resources/Locales/en_US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Date Format</x:String>
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Language</x:String>
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
<x:String x:Key="Text.Preferences.General.SaveDiscardChanges" xml:space="preserve">Save discard in Trash</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Show author time instead of commit time in graph</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Show children in the commit details</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Show tags in commit graph</x:String>
Expand Down
1 change: 1 addition & 0 deletions src/Resources/Locales/fr_FR.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@
<x:String x:Key="Text.Preferences.General.DateFormat" xml:space="preserve">Format de date</x:String>
<x:String x:Key="Text.Preferences.General.Locale" xml:space="preserve">Language</x:String>
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Historique de commits</x:String>
<x:String x:Key="Text.Preferences.General.SaveDiscardChanges" xml:space="preserve">Enregistre les rejets dans la Corbeille</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Afficher l'heure de l'auteur au lieu de l'heure de validation dans le graphique</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Afficher les enfants dans les détails du commit</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Afficher les tags dans le graphique des commits</x:String>
Expand Down
3 changes: 3 additions & 0 deletions src/ViewModels/Discard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public override async Task<bool> Sure()
var log = _repo.CreateLog("Discard all");
Use(log);

if (Preferences.Instance.DiscardChangedOnBin)
await Commands.SaveDiscardOnTrash.ProcessSaveDiscardOnTrash(_repo.FullPath, _changes);

if (Mode is DiscardAllMode all)
await Commands.Discard.AllAsync(_repo.FullPath, all.IncludeIgnored, log);
else
Expand Down
7 changes: 7 additions & 0 deletions src/ViewModels/Preferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ public bool Check4UpdatesOnStartup
set => SetProperty(ref _check4UpdatesOnStartup, value);
}

public bool DiscardChangedOnBin
{
get => _discardChangedOnBin;
set => SetProperty(ref _discardChangedOnBin, value);
}

public bool ShowAuthorTimeInGraph
{
get => _showAuthorTimeInGraph;
Expand Down Expand Up @@ -682,6 +688,7 @@ private bool RemoveInvalidRepositoriesRecursive(List<RepositoryNode> collection)
private bool _check4UpdatesOnStartup = true;
private double _lastCheckUpdateTime = 0;
private string _ignoreUpdateTag = string.Empty;
private bool _discardChangedOnBin = false;

private bool _showTagsInGraph = true;
private bool _useTwoColumnsLayoutInHistories = false;
Expand Down
7 changes: 6 additions & 1 deletion src/Views/Preferences.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.General}"/>
</TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preferences.General.Locale}"
HorizontalAlignment="Right"
Expand Down Expand Up @@ -152,6 +152,11 @@
Content="{DynamicResource Text.Preferences.General.Check4UpdatesOnStartup}"
IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"
IsChecked="{Binding Check4UpdatesOnStartup, Mode=TwoWay}"/>

<CheckBox Grid.Row="9" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preferences.General.SaveDiscardChanges}"
IsChecked="{Binding DiscardChangedOnBin, Mode=TwoWay}"/>
</Grid>
</TabItem>

Expand Down