mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-24 20:57:19 -08:00
refactor: rewrite amend behaviour (#300)
* toggle amend will show changes in HEAD commit * since discard is not compatible with staged changes in `amend` mode, we only allows user to discard unstaged changes
This commit is contained in:
parent
3c5a661fa0
commit
f55a576013
9 changed files with 261 additions and 86 deletions
|
@ -11,7 +11,7 @@ namespace SourceGit.Commands
|
||||||
new Clean(repo).Exec();
|
new Clean(repo).Exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ChangesInWorkTree(string repo, List<Models.Change> changes)
|
public static void Changes(string repo, List<Models.Change> changes)
|
||||||
{
|
{
|
||||||
var needClean = new List<string>();
|
var needClean = new List<string>();
|
||||||
var needCheckout = new List<string>();
|
var needCheckout = new List<string>();
|
||||||
|
@ -19,14 +19,10 @@ namespace SourceGit.Commands
|
||||||
foreach (var c in changes)
|
foreach (var c in changes)
|
||||||
{
|
{
|
||||||
if (c.WorkTree == Models.ChangeState.Untracked || c.WorkTree == Models.ChangeState.Added)
|
if (c.WorkTree == Models.ChangeState.Untracked || c.WorkTree == Models.ChangeState.Added)
|
||||||
{
|
|
||||||
needClean.Add(c.Path);
|
needClean.Add(c.Path);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
needCheckout.Add(c.Path);
|
needCheckout.Add(c.Path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < needClean.Count; i += 10)
|
for (int i = 0; i < needClean.Count; i += 10)
|
||||||
{
|
{
|
||||||
|
@ -40,17 +36,5 @@ namespace SourceGit.Commands
|
||||||
new Restore(repo, needCheckout.GetRange(i, count), "--worktree --recurse-submodules").Exec();
|
new Restore(repo, needCheckout.GetRange(i, count), "--worktree --recurse-submodules").Exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ChangesInStaged(string repo, List<Models.Change> changes)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < changes.Count; i += 10)
|
|
||||||
{
|
|
||||||
var count = Math.Min(10, changes.Count - i);
|
|
||||||
var files = new List<string>();
|
|
||||||
for (int j = 0; j < count; j++)
|
|
||||||
files.Add(changes[i + j].Path);
|
|
||||||
new Restore(repo, files, "--staged --worktree --recurse-submodules").Exec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
90
src/Commands/QueryStagedChangesWithAmend.cs
Normal file
90
src/Commands/QueryStagedChangesWithAmend.cs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace SourceGit.Commands
|
||||||
|
{
|
||||||
|
public partial class QueryStagedChangesWithAmend : Command
|
||||||
|
{
|
||||||
|
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMTUX])\d{0,6}\t(.*)$")]
|
||||||
|
private static partial Regex REG_FORMAT1();
|
||||||
|
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} R\d{0,6}\t(.*\t.*)$")]
|
||||||
|
private static partial Regex REG_FORMAT2();
|
||||||
|
|
||||||
|
public QueryStagedChangesWithAmend(string repo)
|
||||||
|
{
|
||||||
|
WorkingDirectory = repo;
|
||||||
|
Context = repo;
|
||||||
|
Args = "diff-index --cached -M HEAD^";
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Models.Change> Result()
|
||||||
|
{
|
||||||
|
var rs = ReadToEnd();
|
||||||
|
if (rs.IsSuccess)
|
||||||
|
{
|
||||||
|
var changes = new List<Models.Change>();
|
||||||
|
var lines = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
var match = REG_FORMAT2().Match(line);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var change = new Models.Change() {
|
||||||
|
Path = match.Groups[3].Value,
|
||||||
|
DataForAmend = new Models.ChangeDataForAmend()
|
||||||
|
{
|
||||||
|
FileMode = match.Groups[1].Value,
|
||||||
|
ObjectHash = match.Groups[2].Value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
change.Set(Models.ChangeState.Renamed);
|
||||||
|
changes.Add(change);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = REG_FORMAT1().Match(line);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var change = new Models.Change() {
|
||||||
|
Path = match.Groups[4].Value,
|
||||||
|
DataForAmend = new Models.ChangeDataForAmend()
|
||||||
|
{
|
||||||
|
FileMode = match.Groups[1].Value,
|
||||||
|
ObjectHash = match.Groups[2].Value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var type = match.Groups[3].Value;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "A":
|
||||||
|
change.Set(Models.ChangeState.Added);
|
||||||
|
break;
|
||||||
|
case "C":
|
||||||
|
change.Set(Models.ChangeState.Copied);
|
||||||
|
break;
|
||||||
|
case "D":
|
||||||
|
change.Set(Models.ChangeState.Deleted);
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
change.Set(Models.ChangeState.Modified);
|
||||||
|
break;
|
||||||
|
case "T":
|
||||||
|
change.Set(Models.ChangeState.TypeChanged);
|
||||||
|
break;
|
||||||
|
case "U":
|
||||||
|
change.Set(Models.ChangeState.Unmerged);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
changes.Add(change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
97
src/Commands/UnstageChangesForAmend.cs
Normal file
97
src/Commands/UnstageChangesForAmend.cs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
namespace SourceGit.Commands
|
||||||
|
{
|
||||||
|
public class UnstageChangesForAmend
|
||||||
|
{
|
||||||
|
public UnstageChangesForAmend(string repo, List<Models.Change> changes)
|
||||||
|
{
|
||||||
|
_repo = repo;
|
||||||
|
|
||||||
|
foreach (var c in changes)
|
||||||
|
{
|
||||||
|
if (c.Index == Models.ChangeState.Renamed)
|
||||||
|
{
|
||||||
|
_patchBuilder.Append("0 0000000000000000000000000000000000000000\t");
|
||||||
|
_patchBuilder.Append(c.Path);
|
||||||
|
_patchBuilder.Append("\0100644 ");
|
||||||
|
_patchBuilder.Append(c.DataForAmend.ObjectHash);
|
||||||
|
_patchBuilder.Append("\t");
|
||||||
|
_patchBuilder.Append(c.OriginalPath);
|
||||||
|
_patchBuilder.Append("\n");
|
||||||
|
}
|
||||||
|
else if (c.Index == Models.ChangeState.Added)
|
||||||
|
{
|
||||||
|
_patchBuilder.Append("0 0000000000000000000000000000000000000000\t");
|
||||||
|
_patchBuilder.Append(c.Path);
|
||||||
|
_patchBuilder.Append("\n");
|
||||||
|
}
|
||||||
|
else if (c.Index == Models.ChangeState.Deleted)
|
||||||
|
{
|
||||||
|
_patchBuilder.Append("100644 ");
|
||||||
|
_patchBuilder.Append(c.DataForAmend.ObjectHash);
|
||||||
|
_patchBuilder.Append("\t");
|
||||||
|
_patchBuilder.Append(c.Path);
|
||||||
|
_patchBuilder.Append("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_patchBuilder.Append(c.DataForAmend.FileMode);
|
||||||
|
_patchBuilder.Append(" ");
|
||||||
|
_patchBuilder.Append(c.DataForAmend.ObjectHash);
|
||||||
|
_patchBuilder.Append("\t");
|
||||||
|
_patchBuilder.Append(c.Path);
|
||||||
|
_patchBuilder.Append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Exec()
|
||||||
|
{
|
||||||
|
var starter = new ProcessStartInfo();
|
||||||
|
starter.WorkingDirectory = _repo;
|
||||||
|
starter.FileName = Native.OS.GitExecutable;
|
||||||
|
starter.Arguments = "-c core.editor=true update-index --index-info";
|
||||||
|
starter.UseShellExecute = false;
|
||||||
|
starter.CreateNoWindow = true;
|
||||||
|
starter.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
starter.RedirectStandardInput = true;
|
||||||
|
starter.RedirectStandardOutput = false;
|
||||||
|
starter.RedirectStandardError = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var proc = new Process() { StartInfo = starter };
|
||||||
|
proc.Start();
|
||||||
|
proc.StandardInput.Write(_patchBuilder.ToString());
|
||||||
|
proc.StandardInput.Close();
|
||||||
|
|
||||||
|
var err = proc.StandardError.ReadToEnd();
|
||||||
|
proc.WaitForExit();
|
||||||
|
var rs = proc.ExitCode == 0;
|
||||||
|
proc.Close();
|
||||||
|
|
||||||
|
if (!rs)
|
||||||
|
Dispatcher.UIThread.Invoke(() => App.RaiseException(_repo, err));
|
||||||
|
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
|
{
|
||||||
|
App.RaiseException(_repo, "Failed to unstage changes: " + e.Message);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _repo = "";
|
||||||
|
private StringBuilder _patchBuilder = new StringBuilder();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,12 +22,19 @@ namespace SourceGit.Models
|
||||||
Untracked
|
Untracked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ChangeDataForAmend
|
||||||
|
{
|
||||||
|
public string FileMode { get; set; } = "";
|
||||||
|
public string ObjectHash { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
public class Change
|
public class Change
|
||||||
{
|
{
|
||||||
public ChangeState Index { get; set; }
|
public ChangeState Index { get; set; } = ChangeState.None;
|
||||||
public ChangeState WorkTree { get; set; } = ChangeState.None;
|
public ChangeState WorkTree { get; set; } = ChangeState.None;
|
||||||
public string Path { get; set; } = "";
|
public string Path { get; set; } = "";
|
||||||
public string OriginalPath { get; set; } = "";
|
public string OriginalPath { get; set; } = "";
|
||||||
|
public ChangeDataForAmend DataForAmend { get; set; } = null;
|
||||||
|
|
||||||
public bool IsConflit
|
public bool IsConflit
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,11 @@ namespace SourceGit.Models
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (change.DataForAmend != null)
|
||||||
|
_extra = "--cached HEAD^";
|
||||||
|
else
|
||||||
_extra = "--cached";
|
_extra = "--cached";
|
||||||
|
|
||||||
_path = change.Path;
|
_path = change.Path;
|
||||||
_orgPath = change.OriginalPath;
|
_orgPath = change.OriginalPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,10 @@ namespace SourceGit.ViewModels
|
||||||
View = new Views.Discard { DataContext = this };
|
View = new Views.Discard { DataContext = this };
|
||||||
}
|
}
|
||||||
|
|
||||||
public Discard(Repository repo, List<Models.Change> changes, bool isUnstaged)
|
public Discard(Repository repo, List<Models.Change> changes)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_changes = changes;
|
_changes = changes;
|
||||||
_isUnstaged = isUnstaged;
|
|
||||||
|
|
||||||
if (_changes == null)
|
if (_changes == null)
|
||||||
Mode = new Models.Null();
|
Mode = new Models.Null();
|
||||||
|
@ -44,10 +43,8 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
if (_changes == null)
|
if (_changes == null)
|
||||||
Commands.Discard.All(_repo.FullPath);
|
Commands.Discard.All(_repo.FullPath);
|
||||||
else if (_isUnstaged)
|
|
||||||
Commands.Discard.ChangesInWorkTree(_repo.FullPath, _changes);
|
|
||||||
else
|
else
|
||||||
Commands.Discard.ChangesInStaged(_repo.FullPath, _changes);
|
Commands.Discard.Changes(_repo.FullPath, _changes);
|
||||||
|
|
||||||
CallUIThread(() =>
|
CallUIThread(() =>
|
||||||
{
|
{
|
||||||
|
@ -61,6 +58,5 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
private readonly Repository _repo = null;
|
private readonly Repository _repo = null;
|
||||||
private readonly List<Models.Change> _changes = null;
|
private readonly List<Models.Change> _changes = null;
|
||||||
private readonly bool _isUnstaged = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,9 @@ namespace SourceGit.ViewModels
|
||||||
get => _useAmend;
|
get => _useAmend;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (SetProperty(ref _useAmend, value) && value)
|
if (SetProperty(ref _useAmend, value))
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
{
|
{
|
||||||
var currentBranch = _repo.CurrentBranch;
|
var currentBranch = _repo.CurrentBranch;
|
||||||
if (currentBranch == null)
|
if (currentBranch == null)
|
||||||
|
@ -102,9 +104,12 @@ namespace SourceGit.ViewModels
|
||||||
CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, currentBranch.Head).Result();
|
CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, currentBranch.Head).Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Staged = GetStagedChanges();
|
||||||
|
SelectedStaged = [];
|
||||||
OnPropertyChanged(nameof(IsCommitWithPushVisible));
|
OnPropertyChanged(nameof(IsCommitWithPushVisible));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsCommitWithPushVisible
|
public bool IsCommitWithPushVisible
|
||||||
{
|
{
|
||||||
|
@ -216,6 +221,8 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public bool SetData(List<Models.Change> changes)
|
public bool SetData(List<Models.Change> changes)
|
||||||
{
|
{
|
||||||
|
_cached = changes;
|
||||||
|
|
||||||
var unstaged = new List<Models.Change>();
|
var unstaged = new List<Models.Change>();
|
||||||
var staged = new List<Models.Change>();
|
var staged = new List<Models.Change>();
|
||||||
var selectedUnstaged = new List<Models.Change>();
|
var selectedUnstaged = new List<Models.Change>();
|
||||||
|
@ -237,17 +244,6 @@ namespace SourceGit.ViewModels
|
||||||
var hasConflict = false;
|
var hasConflict = false;
|
||||||
foreach (var c in changes)
|
foreach (var c in changes)
|
||||||
{
|
{
|
||||||
if (c.Index == Models.ChangeState.Modified
|
|
||||||
|| c.Index == Models.ChangeState.Added
|
|
||||||
|| c.Index == Models.ChangeState.Deleted
|
|
||||||
|| c.Index == Models.ChangeState.Renamed)
|
|
||||||
{
|
|
||||||
staged.Add(c);
|
|
||||||
|
|
||||||
if (lastSelectedStaged.Contains(c.Path))
|
|
||||||
selectedStaged.Add(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.WorkTree != Models.ChangeState.None)
|
if (c.WorkTree != Models.ChangeState.None)
|
||||||
{
|
{
|
||||||
unstaged.Add(c);
|
unstaged.Add(c);
|
||||||
|
@ -258,6 +254,13 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
staged = GetStagedChanges();
|
||||||
|
foreach (var c in staged)
|
||||||
|
{
|
||||||
|
if (lastSelectedStaged.Contains(c.Path))
|
||||||
|
selectedStaged.Add(c);
|
||||||
|
}
|
||||||
|
|
||||||
_count = changes.Count;
|
_count = changes.Count;
|
||||||
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
|
@ -358,7 +361,11 @@ namespace SourceGit.ViewModels
|
||||||
SetDetail(null);
|
SetDetail(null);
|
||||||
IsUnstaging = true;
|
IsUnstaging = true;
|
||||||
_repo.SetWatcherEnabled(false);
|
_repo.SetWatcherEnabled(false);
|
||||||
if (changes.Count == _staged.Count)
|
if (_useAmend)
|
||||||
|
{
|
||||||
|
await Task.Run(() => new Commands.UnstageChangesForAmend(_repo.FullPath, changes).Exec());
|
||||||
|
}
|
||||||
|
else if (changes.Count == _staged.Count)
|
||||||
{
|
{
|
||||||
await Task.Run(() => new Commands.Reset(_repo.FullPath).Exec());
|
await Task.Run(() => new Commands.Reset(_repo.FullPath).Exec());
|
||||||
}
|
}
|
||||||
|
@ -376,24 +383,14 @@ namespace SourceGit.ViewModels
|
||||||
IsUnstaging = false;
|
IsUnstaging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Discard(List<Models.Change> changes, bool isUnstaged)
|
public void Discard(List<Models.Change> changes)
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
{
|
|
||||||
if (isUnstaged)
|
|
||||||
{
|
{
|
||||||
if (changes.Count == _unstaged.Count && _staged.Count == 0)
|
if (changes.Count == _unstaged.Count && _staged.Count == 0)
|
||||||
PopupHost.ShowPopup(new Discard(_repo));
|
PopupHost.ShowPopup(new Discard(_repo));
|
||||||
else
|
else
|
||||||
PopupHost.ShowPopup(new Discard(_repo, changes, true));
|
PopupHost.ShowPopup(new Discard(_repo, changes));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (changes.Count == _staged.Count && _unstaged.Count == 0)
|
|
||||||
PopupHost.ShowPopup(new Discard(_repo));
|
|
||||||
else
|
|
||||||
PopupHost.ShowPopup(new Discard(_repo, changes, false));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,7 +488,7 @@ namespace SourceGit.ViewModels
|
||||||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
||||||
discard.Click += (_, e) =>
|
discard.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
Discard(_selectedUnstaged, true);
|
Discard(_selectedUnstaged);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -815,7 +812,7 @@ namespace SourceGit.ViewModels
|
||||||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
||||||
discard.Click += (_, e) =>
|
discard.Click += (_, e) =>
|
||||||
{
|
{
|
||||||
Discard(_selectedUnstaged, true);
|
Discard(_selectedUnstaged);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -904,15 +901,6 @@ namespace SourceGit.ViewModels
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var discard = new MenuItem();
|
|
||||||
discard.Header = App.Text("FileCM.Discard");
|
|
||||||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
|
||||||
discard.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
Discard(_selectedStaged, false);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var stash = new MenuItem();
|
var stash = new MenuItem();
|
||||||
stash.Header = App.Text("FileCM.Stash");
|
stash.Header = App.Text("FileCM.Stash");
|
||||||
stash.Icon = App.CreateMenuIcon("Icons.Stashes");
|
stash.Icon = App.CreateMenuIcon("Icons.Stashes");
|
||||||
|
@ -971,7 +959,6 @@ namespace SourceGit.ViewModels
|
||||||
menu.Items.Add(openWith);
|
menu.Items.Add(openWith);
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
menu.Items.Add(unstage);
|
menu.Items.Add(unstage);
|
||||||
menu.Items.Add(discard);
|
|
||||||
menu.Items.Add(stash);
|
menu.Items.Add(stash);
|
||||||
menu.Items.Add(patch);
|
menu.Items.Add(patch);
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
@ -1071,15 +1058,6 @@ namespace SourceGit.ViewModels
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var discard = new MenuItem();
|
|
||||||
discard.Header = App.Text("FileCM.DiscardMulti", _selectedStaged.Count);
|
|
||||||
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
|
||||||
discard.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
Discard(_selectedStaged, false);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var stash = new MenuItem();
|
var stash = new MenuItem();
|
||||||
stash.Header = App.Text("FileCM.StashMulti", _selectedStaged.Count);
|
stash.Header = App.Text("FileCM.StashMulti", _selectedStaged.Count);
|
||||||
stash.Icon = App.CreateMenuIcon("Icons.Stashes");
|
stash.Icon = App.CreateMenuIcon("Icons.Stashes");
|
||||||
|
@ -1118,7 +1096,6 @@ namespace SourceGit.ViewModels
|
||||||
};
|
};
|
||||||
|
|
||||||
menu.Items.Add(unstage);
|
menu.Items.Add(unstage);
|
||||||
menu.Items.Add(discard);
|
|
||||||
menu.Items.Add(stash);
|
menu.Items.Add(stash);
|
||||||
menu.Items.Add(patch);
|
menu.Items.Add(patch);
|
||||||
}
|
}
|
||||||
|
@ -1162,6 +1139,25 @@ namespace SourceGit.ViewModels
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Models.Change> GetStagedChanges()
|
||||||
|
{
|
||||||
|
if (_useAmend)
|
||||||
|
{
|
||||||
|
return new Commands.QueryStagedChangesWithAmend(_repo.FullPath).Result();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rs = new List<Models.Change>();
|
||||||
|
foreach (var c in _cached)
|
||||||
|
{
|
||||||
|
if (c.Index != Models.ChangeState.None &&
|
||||||
|
c.Index != Models.ChangeState.Untracked)
|
||||||
|
rs.Add(c);
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetDetail(Models.Change change)
|
private void SetDetail(Models.Change change)
|
||||||
{
|
{
|
||||||
if (_isLoadingData)
|
if (_isLoadingData)
|
||||||
|
@ -1287,6 +1283,7 @@ namespace SourceGit.ViewModels
|
||||||
private bool _isCommitting = false;
|
private bool _isCommitting = false;
|
||||||
private bool _useAmend = false;
|
private bool _useAmend = false;
|
||||||
private bool _canCommitWithPush = false;
|
private bool _canCommitWithPush = false;
|
||||||
|
private List<Models.Change> _cached = [];
|
||||||
private List<Models.Change> _unstaged = [];
|
private List<Models.Change> _unstaged = [];
|
||||||
private List<Models.Change> _staged = [];
|
private List<Models.Change> _staged = [];
|
||||||
private List<Models.Change> _selectedUnstaged = [];
|
private List<Models.Change> _selectedUnstaged = [];
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
<StackPanel x:Name="Popup" IsVisible="False" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" Effect="drop-shadow(0 0 6 #40000000)">
|
<StackPanel x:Name="Popup" IsVisible="False" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" Effect="drop-shadow(0 0 6 #40000000)">
|
||||||
<Button Classes="flat" Content="{DynamicResource Text.Hunk.Stage}" Click="OnStageChunk" IsVisible="{Binding #ThisControl.IsUnstagedChange}"/>
|
<Button Classes="flat" Content="{DynamicResource Text.Hunk.Stage}" Click="OnStageChunk" IsVisible="{Binding #ThisControl.IsUnstagedChange}"/>
|
||||||
<Button Classes="flat" Content="{DynamicResource Text.Hunk.Unstage}" Click="OnUnstageChunk" IsVisible="{Binding #ThisControl.IsUnstagedChange, Converter={x:Static BoolConverters.Not}}"/>
|
<Button Classes="flat" Content="{DynamicResource Text.Hunk.Unstage}" Click="OnUnstageChunk" IsVisible="{Binding #ThisControl.IsUnstagedChange, Converter={x:Static BoolConverters.Not}}"/>
|
||||||
<Button Classes="flat" Content="{DynamicResource Text.Hunk.Discard}" Margin="8,0,0,0" Click="OnDiscardChunk"/>
|
<Button Classes="flat" Content="{DynamicResource Text.Hunk.Discard}" Margin="8,0,0,0" Click="OnDiscardChunk" IsVisible="{Binding #ThisControl.IsUnstagedChange}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -1273,7 +1273,7 @@ namespace SourceGit.Views
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var workcopy = workcopyView.DataContext as ViewModels.WorkingCopy;
|
var workcopy = workcopyView.DataContext as ViewModels.WorkingCopy;
|
||||||
workcopy?.Discard(new List<Models.Change> { change }, diff.Option.IsUnstaged);
|
workcopy?.Discard(new List<Models.Change> { change });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1303,7 +1303,7 @@ namespace SourceGit.Views
|
||||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
|
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", diff.Option.IsUnstaged ? "--reverse" : "--index --reverse").Exec();
|
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--reverse").Exec();
|
||||||
File.Delete(tmpFile);
|
File.Delete(tmpFile);
|
||||||
|
|
||||||
repo.MarkWorkingCopyDirtyManually();
|
repo.MarkWorkingCopyDirtyManually();
|
||||||
|
|
Loading…
Reference in a new issue