fix: git rebase --continue fail (#693)

* fix the exit code when start `SourceGit` as core editor (rebasing).
* redesign the layout of working copy page for in-progress states.

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2024-11-14 19:19:44 +08:00
parent bb90c86649
commit a53787c754
No known key found for this signature in database
6 changed files with 119 additions and 76 deletions

View file

@ -478,17 +478,20 @@ namespace SourceGit
if (args.Length <= 1 || !args[0].Equals("--rebase-message-editor", StringComparison.Ordinal)) if (args.Length <= 1 || !args[0].Equals("--rebase-message-editor", StringComparison.Ordinal))
return false; return false;
exitCode = 0;
var file = args[1]; var file = args[1];
var filename = Path.GetFileName(file); var filename = Path.GetFileName(file);
if (!filename.Equals("COMMIT_EDITMSG", StringComparison.OrdinalIgnoreCase)) if (!filename.Equals("COMMIT_EDITMSG", StringComparison.OrdinalIgnoreCase))
return true; return true;
var jobsFile = Path.Combine(Path.GetDirectoryName(file)!, "sourcegit_rebase_jobs.json"); var gitDir = Path.GetDirectoryName(file)!;
var jobsFile = Path.Combine(gitDir, "sourcegit_rebase_jobs.json");
if (!File.Exists(jobsFile)) if (!File.Exists(jobsFile))
return true; return true;
var collection = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.InteractiveRebaseJobCollection); var collection = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.InteractiveRebaseJobCollection);
var doneFile = Path.Combine(Path.GetDirectoryName(file)!, "rebase-merge", "done"); var doneFile = Path.Combine(gitDir, "rebase-merge", "done");
if (!File.Exists(doneFile)) if (!File.Exists(doneFile))
return true; return true;
@ -499,7 +502,6 @@ namespace SourceGit
var job = collection.Jobs[done.Length - 1]; var job = collection.Jobs[done.Length - 1];
File.WriteAllText(file, job.Message); File.WriteAllText(file, job.Message);
exitCode = 0;
return true; return true;
} }

View file

@ -512,6 +512,12 @@
<Style Selector="Button.flat.primary ToolTip TextBlock"> <Style Selector="Button.flat.primary ToolTip TextBlock">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/> <Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
</Style> </Style>
<Style Selector="Button.flat:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="Button.flat:disabled">
<Setter Property="Background" Value="{DynamicResource Brush.FlatButton.Background}"/>
</Style>
<Style Selector="aes|SearchPanel"> <Style Selector="aes|SearchPanel">
<Setter Property="Template"> <Setter Property="Template">

View file

@ -336,14 +336,7 @@ namespace SourceGit.ViewModels
public InProgressContext InProgressContext public InProgressContext InProgressContext
{ {
get => _inProgressContext; get => _workingCopy?.InProgressContext;
private set => SetProperty(ref _inProgressContext, value);
}
public bool HasUnsolvedConflicts
{
get => _hasUnsolvedConflicts;
private set => SetProperty(ref _hasUnsolvedConflicts, value);
} }
public Models.Commit SearchResultSelectedCommit public Models.Commit SearchResultSelectedCommit
@ -395,8 +388,6 @@ namespace SourceGit.ViewModels
_stashesPage = new StashesPage(this); _stashesPage = new StashesPage(this);
_selectedView = _histories; _selectedView = _histories;
_selectedViewIndex = 0; _selectedViewIndex = 0;
_inProgressContext = null;
_hasUnsolvedConflicts = false;
_autoFetchTimer = new Timer(AutoFetchImpl, null, 5000, 5000); _autoFetchTimer = new Timer(AutoFetchImpl, null, 5000, 5000);
RefreshAll(); RefreshAll();
@ -429,7 +420,6 @@ namespace SourceGit.ViewModels
_histories = null; _histories = null;
_workingCopy = null; _workingCopy = null;
_stashesPage = null; _stashesPage = null;
_inProgressContext = null;
_localChangesCount = 0; _localChangesCount = 0;
_stashesCount = 0; _stashesCount = 0;
@ -732,40 +722,9 @@ namespace SourceGit.ViewModels
SelectedViewIndex = 1; SelectedViewIndex = 1;
} }
public async void ContinueMerge() public void AbortMerge()
{ {
if (_inProgressContext != null) _workingCopy?.AbortMerge();
{
SetWatcherEnabled(false);
var succ = await Task.Run(_inProgressContext.Continue);
if (succ && _workingCopy != null)
{
_workingCopy.CommitMessage = string.Empty;
}
SetWatcherEnabled(true);
}
else
{
MarkWorkingCopyDirtyManually();
}
}
public async void AbortMerge()
{
if (_inProgressContext != null)
{
SetWatcherEnabled(false);
var succ = await Task.Run(_inProgressContext.Abort);
if (succ && _workingCopy != null)
{
_workingCopy.CommitMessage = string.Empty;
}
SetWatcherEnabled(true);
}
else
{
MarkWorkingCopyDirtyManually();
}
} }
public void RefreshBranches() public void RefreshBranches()
@ -869,23 +828,12 @@ namespace SourceGit.ViewModels
if (_workingCopy == null) if (_workingCopy == null)
return; return;
var hasUnsolvedConflict = _workingCopy.SetData(changes); _workingCopy.SetData(changes);
var inProgress = null as InProgressContext;
if (File.Exists(Path.Combine(_gitDir, "CHERRY_PICK_HEAD")))
inProgress = new CherryPickInProgress(_fullpath);
else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD")) && Directory.Exists(Path.Combine(_gitDir, "rebase-merge")))
inProgress = new RebaseInProgress(this);
else if (File.Exists(Path.Combine(_gitDir, "REVERT_HEAD")))
inProgress = new RevertInProgress(_fullpath);
else if (File.Exists(Path.Combine(_gitDir, "MERGE_HEAD")))
inProgress = new MergeInProgress(_fullpath);
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
InProgressContext = inProgress;
HasUnsolvedConflicts = hasUnsolvedConflict;
LocalChangesCount = changes.Count; LocalChangesCount = changes.Count;
OnPropertyChanged(nameof(InProgressContext));
}); });
} }
@ -2173,10 +2121,7 @@ namespace SourceGit.ViewModels
private List<Models.Submodule> _visibleSubmodules = new List<Models.Submodule>(); private List<Models.Submodule> _visibleSubmodules = new List<Models.Submodule>();
private bool _includeUntracked = true; private bool _includeUntracked = true;
private InProgressContext _inProgressContext = null;
private bool _hasUnsolvedConflicts = false;
private Models.Commit _searchResultSelectedCommit = null; private Models.Commit _searchResultSelectedCommit = null;
private Timer _autoFetchTimer = null; private Timer _autoFetchTimer = null;
private DateTime _lastFetchTime = DateTime.MinValue; private DateTime _lastFetchTime = DateTime.MinValue;
} }

View file

@ -56,6 +56,18 @@ namespace SourceGit.ViewModels
} }
} }
public bool HasUnsolvedConflicts
{
get => _hasUnsolvedConflicts;
set => SetProperty(ref _hasUnsolvedConflicts, value);
}
public InProgressContext InProgressContext
{
get => _inProgressContext;
private set => SetProperty(ref _inProgressContext, value);
}
public bool IsStaging public bool IsStaging
{ {
get => _isStaging; get => _isStaging;
@ -191,6 +203,7 @@ namespace SourceGit.ViewModels
public void Cleanup() public void Cleanup()
{ {
_repo = null; _repo = null;
_inProgressContext = null;
_selectedUnstaged.Clear(); _selectedUnstaged.Clear();
OnPropertyChanged(nameof(SelectedUnstaged)); OnPropertyChanged(nameof(SelectedUnstaged));
@ -208,7 +221,7 @@ namespace SourceGit.ViewModels
_commitMessage = string.Empty; _commitMessage = string.Empty;
} }
public bool SetData(List<Models.Change> changes) public void SetData(List<Models.Change> changes)
{ {
if (!IsChanged(_cached, changes)) if (!IsChanged(_cached, changes))
{ {
@ -221,9 +234,22 @@ namespace SourceGit.ViewModels
SetDetail(_selectedStaged[0], false); SetDetail(_selectedStaged[0], false);
else else
SetDetail(null, false); SetDetail(null, false);
var inProgress = null as InProgressContext;
if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD")))
inProgress = new CherryPickInProgress(_repo.FullPath);
else if (File.Exists(Path.Combine(_repo.GitDir, "REBASE_HEAD")) && Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")))
inProgress = new RebaseInProgress(_repo);
else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD")))
inProgress = new RevertInProgress(_repo.FullPath);
else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD")))
inProgress = new MergeInProgress(_repo.FullPath);
HasUnsolvedConflicts = _cached.Find(x => x.IsConflit) != null;
InProgressContext = inProgress;
}); });
return _cached.Find(x => x.IsConflit) != null; return;
} }
_cached = changes; _cached = changes;
@ -268,6 +294,7 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
_isLoadingData = true; _isLoadingData = true;
HasUnsolvedConflicts = hasConflict;
Unstaged = unstaged; Unstaged = unstaged;
Staged = staged; Staged = staged;
SelectedUnstaged = selectedUnstaged; SelectedUnstaged = selectedUnstaged;
@ -281,6 +308,18 @@ namespace SourceGit.ViewModels
else else
SetDetail(null, false); SetDetail(null, false);
var inProgress = null as InProgressContext;
if (File.Exists(Path.Combine(_repo.GitDir, "CHERRY_PICK_HEAD")))
inProgress = new CherryPickInProgress(_repo.FullPath);
else if (File.Exists(Path.Combine(_repo.GitDir, "REBASE_HEAD")) && Directory.Exists(Path.Combine(_repo.GitDir, "rebase-merge")))
inProgress = new RebaseInProgress(_repo);
else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD")))
inProgress = new RevertInProgress(_repo.FullPath);
else if (File.Exists(Path.Combine(_repo.GitDir, "MERGE_HEAD")))
inProgress = new MergeInProgress(_repo.FullPath);
InProgressContext = inProgress;
// Try to load merge message from MERGE_MSG // Try to load merge message from MERGE_MSG
if (string.IsNullOrEmpty(_commitMessage)) if (string.IsNullOrEmpty(_commitMessage))
{ {
@ -289,8 +328,6 @@ namespace SourceGit.ViewModels
CommitMessage = File.ReadAllText(mergeMsgFile); CommitMessage = File.ReadAllText(mergeMsgFile);
} }
}); });
return hasConflict;
} }
public void OpenAssumeUnchanged() public void OpenAssumeUnchanged()
@ -403,6 +440,52 @@ namespace SourceGit.ViewModels
} }
} }
public void ContinueMerge()
{
if (_inProgressContext != null)
{
_repo.SetWatcherEnabled(false);
Task.Run(() =>
{
var succ = _inProgressContext.Continue();
Dispatcher.UIThread.Invoke(() =>
{
if (succ)
CommitMessage = string.Empty;
_repo.SetWatcherEnabled(true);
});
});
}
else
{
_repo.MarkWorkingCopyDirtyManually();
}
}
public void AbortMerge()
{
if (_inProgressContext != null)
{
_repo.SetWatcherEnabled(false);
Task.Run(() =>
{
var succ = _inProgressContext.Abort();
Dispatcher.UIThread.Invoke(() =>
{
if (succ)
CommitMessage = string.Empty;
_repo.SetWatcherEnabled(true);
});
});
}
else
{
_repo.MarkWorkingCopyDirtyManually();
}
}
public void Commit() public void Commit()
{ {
DoCommit(false, false, false); DoCommit(false, false, false);
@ -1475,5 +1558,8 @@ namespace SourceGit.ViewModels
private int _count = 0; private int _count = 0;
private object _detailContext = null; private object _detailContext = null;
private string _commitMessage = string.Empty; private string _commitMessage = string.Empty;
private bool _hasUnsolvedConflicts = false;
private InProgressContext _inProgressContext = null;
} }
} }

View file

@ -524,7 +524,7 @@
<!-- Right --> <!-- Right -->
<Grid Grid.Column="2" RowDefinitions="Auto,Auto,*"> <Grid Grid.Column="2" RowDefinitions="Auto,Auto,*">
<Grid Grid.Row="0" Height="28" ColumnDefinitions="*,Auto,Auto,Auto" Background="{DynamicResource Brush.Conflict}" IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNotNull}}"> <Grid Grid.Row="0" Height="28" ColumnDefinitions="*,Auto,Auto" Background="{DynamicResource Brush.Conflict}" IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNotNull}}">
<ContentControl Grid.Column="0" Margin="8,0" Content="{Binding InProgressContext}"> <ContentControl Grid.Column="0" Margin="8,0" Content="{Binding InProgressContext}">
<ContentControl.DataTemplates> <ContentControl.DataTemplates>
<DataTemplate DataType="vm:CherryPickInProgress"> <DataTemplate DataType="vm:CherryPickInProgress">
@ -557,14 +557,6 @@
</Button.IsVisible> </Button.IsVisible>
</Button> </Button>
<Button Grid.Column="2" <Button Grid.Column="2"
Classes="flat primary"
FontWeight="Regular"
BorderThickness="0"
Content="{DynamicResource Text.Repository.Continue}"
Padding="8,0" Margin="4,0"
Command="{Binding ContinueMerge}"
IsVisible="{Binding !HasUnsolvedConflicts}"/>
<Button Grid.Column="3"
Classes="flat" Classes="flat"
FontWeight="Regular" FontWeight="Regular"
BorderThickness="0" BorderThickness="0"

View file

@ -239,10 +239,21 @@
Margin="8,0,0,0" Margin="8,0,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
IsChecked="{Binding UseAmend, Mode=TwoWay}" IsChecked="{Binding UseAmend, Mode=TwoWay}"
IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNull}}"
Content="{DynamicResource Text.WorkingCopy.Amend}"/> Content="{DynamicResource Text.WorkingCopy.Amend}"/>
<v:LoadingIcon Grid.Column="5" Width="18" Height="18" IsVisible="{Binding IsCommitting}"/> <v:LoadingIcon Grid.Column="5" Width="18" Height="18" IsVisible="{Binding IsCommitting}"/>
<Button Grid.Column="6"
Classes="flat primary"
Content="{DynamicResource Text.Repository.Continue}"
Height="28"
Margin="8,0,0,0"
Padding="8,0"
Command="{Binding ContinueMerge}"
IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNotNull}}"
IsEnabled="{Binding !HasUnsolvedConflicts}"/>
<Button Grid.Column="6" <Button Grid.Column="6"
Classes="flat primary" Classes="flat primary"
Content="{DynamicResource Text.WorkingCopy.Commit}" Content="{DynamicResource Text.WorkingCopy.Commit}"
@ -251,6 +262,7 @@
Padding="8,0" Padding="8,0"
Command="{Binding Commit}" Command="{Binding Commit}"
HotKey="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}" HotKey="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"
IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNull}}"
ToolTip.Placement="Top" ToolTip.Placement="Top"
ToolTip.VerticalOffset="0"> ToolTip.VerticalOffset="0">
<ToolTip.Tip> <ToolTip.Tip>