mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-28 23:54:59 +00:00
feature<WorkingCopy>: gitee issue #I54W26 - toggle untracked files in working copy changes
This commit is contained in:
parent
b04c94ccc1
commit
35235df7bc
10 changed files with 3432 additions and 3370 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,253 +1,262 @@
|
|||
<UserControl x:Class="SourceGit.Views.Widgets.WorkingCopy"
|
||||
x:Name="me"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
|
||||
xmlns:converter="clr-namespace:SourceGit.Views.Converters"
|
||||
xmlns:models="clr-namespace:SourceGit.Models"
|
||||
xmlns:widgets="clr-namespace:SourceGit.Views.Widgets"
|
||||
xmlns:validations="clr-namespace:SourceGit.Views.Validations"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converter:BoolToCollapsed x:Key="BoolToCollapsed"/>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="300" MinWidth="300"/>
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left -->
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="26"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="26"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Unstaged Toolbar -->
|
||||
<Border Grid.Row="0" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:ChangeDisplaySwitcher
|
||||
Grid.Column="0"
|
||||
x:Name="unstagedMode"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0,0,0"
|
||||
Mode="{Binding Source={x:Static models:Preference.Instance}, Path=Window.ChangeInUnstaged, Mode=TwoWay}"/>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="6,0"
|
||||
Text="{DynamicResource Text.WorkingCopy.Unstaged}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
FontWeight="Bold"/>
|
||||
<controls:Loading
|
||||
Grid.Column="2"
|
||||
Width="12" Height="12"
|
||||
x:Name="iconStaging"
|
||||
IsAnimating="{Binding ElementName=unstagedContainer, Path=IsStaging}"
|
||||
Visibility="{Binding ElementName=unstagedContainer, Path=IsStaging, Converter={StaticResource BoolToCollapsed}}"/>
|
||||
<controls:IconButton
|
||||
Grid.Column="4"
|
||||
Click="StageSelected"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.Down}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Unstaged.Stage}"/>
|
||||
<controls:IconButton
|
||||
Grid.Column="5"
|
||||
Click="StageAll"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.DoubleDown}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Unstaged Changes -->
|
||||
<Border Grid.Row="1" Background="{DynamicResource Brush.Contents}">
|
||||
<widgets:WorkingCopyChanges
|
||||
x:Name="unstagedContainer"
|
||||
IsUnstaged="True"
|
||||
Mode="{Binding ElementName=unstagedMode, Path=Mode}"
|
||||
DiffTargetChanged="OnDiffTargetChanged"/>
|
||||
</Border>
|
||||
|
||||
<!-- Staged Toolbar -->
|
||||
<Border Grid.Row="2" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:ChangeDisplaySwitcher
|
||||
Grid.Column="0"
|
||||
x:Name="stagedMode"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0,0,0"
|
||||
Mode="{Binding Source={x:Static models:Preference.Instance}, Path=Window.ChangeInStaged, Mode=TwoWay}"/>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="6,0"
|
||||
Text="{DynamicResource Text.WorkingCopy.Staged}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
FontWeight="Bold"/>
|
||||
|
||||
<controls:IconButton
|
||||
Grid.Column="2"
|
||||
Click="UnstageSelected"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.Up}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Staged.Unstage}"/>
|
||||
<controls:IconButton
|
||||
Grid.Column="3"
|
||||
Click="UnstageAll"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.DoubleUp}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Staged.UnstageAll}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Staged Changes -->
|
||||
<Border Grid.Row="3" Background="{DynamicResource Brush.Contents}">
|
||||
<widgets:WorkingCopyChanges
|
||||
x:Name="stagedContainer"
|
||||
IsUnstaged="False"
|
||||
Mode="{Binding ElementName=stagedMode, Path=Mode}"
|
||||
DiffTargetChanged="OnDiffTargetChanged"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<GridSplitter Grid.Column="1" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" Background="{DynamicResource Brush.Border0}"/>
|
||||
|
||||
<!-- Right -->
|
||||
<Grid Grid.Column="2" Margin="4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Diff viewer -->
|
||||
<widgets:DiffViewer Grid.Row="0" x:Name="diffViewer"/>
|
||||
|
||||
<!-- Merge Option Panel -->
|
||||
<Grid Grid.Row="0" x:Name="mergePanel" Background="{DynamicResource Brush.Window}" Visibility="Collapsed">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Path
|
||||
Width="64" Height="64"
|
||||
Data="{StaticResource Icon.Conflict}"
|
||||
Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock
|
||||
Margin="0,16,0,28"
|
||||
FontSize="20" FontWeight="DemiBold"
|
||||
Text="{DynamicResource Text.WorkingCopy.Conflicts}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
HorizontalAlignment="Center"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Click="UseTheirs" Content="{DynamicResource Text.WorkingCopy.UseTheirs}" Height="24" Padding="8,0"/>
|
||||
<Button Click="UseMine" Content="{DynamicResource Text.WorkingCopy.UseMine}" Height="24" Margin="8,0" Padding="8,0"/>
|
||||
<Button Click="UseMergeTool" Content="{DynamicResource Text.WorkingCopy.OpenMerger}" Height="24" Padding="8,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Commit Message -->
|
||||
<controls:TextEdit
|
||||
Grid.Row="1"
|
||||
x:Name="txtCommitMessage"
|
||||
Height="64"
|
||||
Margin="0,4" Padding="1"
|
||||
AcceptsReturn="True"
|
||||
AcceptsTab="True"
|
||||
TextWrapping="Wrap"
|
||||
KeyDown="CommitMessageKeyDown"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Placeholder="{DynamicResource Text.WorkingCopy.CommitMessageTip}"
|
||||
PlaceholderBaseline="Top">
|
||||
<TextBox.Text>
|
||||
<Binding ElementName="me" Path="CommitMessage" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validations:CommitMessage/>
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox.Text>
|
||||
</controls:TextEdit>
|
||||
|
||||
<!-- Commit Options -->
|
||||
<Grid Grid.Row="2" Margin="0,0,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:IconButton
|
||||
Grid.Column="0"
|
||||
Width="14" Height="14"
|
||||
Click="OpenCommitMessageRecorder"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.MessageHistories}"
|
||||
Icon="{StaticResource Icon.List}"
|
||||
Opacity=".5"/>
|
||||
|
||||
<CheckBox
|
||||
Grid.Column="1"
|
||||
x:Name="chkAmend"
|
||||
Margin="8,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{DynamicResource Text.WorkingCopy.Amend}"
|
||||
Checked="StartAmend" Unchecked="EndAmend"/>
|
||||
|
||||
<controls:Loading
|
||||
Grid.Column="3"
|
||||
x:Name="iconCommitting"
|
||||
Width="18" Height="18"
|
||||
Margin="0,0,8,0"
|
||||
Visibility="Collapsed"/>
|
||||
|
||||
<Button
|
||||
Grid.Column="4"
|
||||
Height="26"
|
||||
Padding="8,0"
|
||||
Click="Commit"
|
||||
FontWeight="Bold"
|
||||
Background="{DynamicResource Brush.Accent1}"
|
||||
BorderBrush="{DynamicResource Brush.FG1}"
|
||||
Content="{DynamicResource Text.WorkingCopy.Commit}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.CommitTip}"/>
|
||||
|
||||
<Button
|
||||
Grid.Column="5"
|
||||
x:Name="btnCommitAndPush"
|
||||
Height="26"
|
||||
Padding="8,0"
|
||||
Click="CommitAndPush"
|
||||
FontWeight="Bold"
|
||||
Content="{DynamicResource Text.WorkingCopy.CommitAndPush}"
|
||||
Margin="8,0,0,0"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
<UserControl x:Class="SourceGit.Views.Widgets.WorkingCopy"
|
||||
x:Name="me"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
|
||||
xmlns:converter="clr-namespace:SourceGit.Views.Converters"
|
||||
xmlns:models="clr-namespace:SourceGit.Models"
|
||||
xmlns:widgets="clr-namespace:SourceGit.Views.Widgets"
|
||||
xmlns:validations="clr-namespace:SourceGit.Views.Validations"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converter:BoolToCollapsed x:Key="BoolToCollapsed"/>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="300" MinWidth="300"/>
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left -->
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="26"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="26"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Unstaged Toolbar -->
|
||||
<Border Grid.Row="0" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:ChangeDisplaySwitcher
|
||||
Grid.Column="0"
|
||||
x:Name="unstagedMode"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0,0,0"
|
||||
Mode="{Binding Source={x:Static models:Preference.Instance}, Path=Window.ChangeInUnstaged, Mode=TwoWay}"/>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="6,0"
|
||||
Text="{DynamicResource Text.WorkingCopy.Unstaged}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
FontWeight="Bold"/>
|
||||
<controls:Loading
|
||||
Grid.Column="2"
|
||||
Width="12" Height="12"
|
||||
x:Name="iconStaging"
|
||||
IsAnimating="{Binding ElementName=unstagedContainer, Path=IsStaging}"
|
||||
Visibility="{Binding ElementName=unstagedContainer, Path=IsStaging, Converter={StaticResource BoolToCollapsed}}"/>
|
||||
<ToggleButton
|
||||
Grid.Column="4"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Style="{StaticResource Style.ToggleButton.Eye}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.IncludeUntracked}"
|
||||
IsChecked="{Binding Source={x:Static models:Preference.Instance}, Path=Git.IncludeUntrackedInWC, Mode=TwoWay}"
|
||||
Checked="ToggleIncludeUntracked" Unchecked="ToggleIncludeUntracked"/>
|
||||
<controls:IconButton
|
||||
Grid.Column="5"
|
||||
Click="StageSelected"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.Down}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Unstaged.Stage}"/>
|
||||
<controls:IconButton
|
||||
Grid.Column="6"
|
||||
Click="StageAll"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.DoubleDown}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Unstaged.StageAll}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Unstaged Changes -->
|
||||
<Border Grid.Row="1" Background="{DynamicResource Brush.Contents}">
|
||||
<widgets:WorkingCopyChanges
|
||||
x:Name="unstagedContainer"
|
||||
IsUnstaged="True"
|
||||
Mode="{Binding ElementName=unstagedMode, Path=Mode}"
|
||||
DiffTargetChanged="OnDiffTargetChanged"/>
|
||||
</Border>
|
||||
|
||||
<!-- Staged Toolbar -->
|
||||
<Border Grid.Row="2" BorderBrush="{DynamicResource Brush.Border0}" BorderThickness="0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:ChangeDisplaySwitcher
|
||||
Grid.Column="0"
|
||||
x:Name="stagedMode"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0,0,0"
|
||||
Mode="{Binding Source={x:Static models:Preference.Instance}, Path=Window.ChangeInStaged, Mode=TwoWay}"/>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="6,0"
|
||||
Text="{DynamicResource Text.WorkingCopy.Staged}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
FontWeight="Bold"/>
|
||||
|
||||
<controls:IconButton
|
||||
Grid.Column="2"
|
||||
Click="UnstageSelected"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.Up}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Staged.Unstage}"/>
|
||||
<controls:IconButton
|
||||
Grid.Column="3"
|
||||
Click="UnstageAll"
|
||||
Width="14" Height="14"
|
||||
Margin="4,0"
|
||||
Icon="{StaticResource Icon.DoubleUp}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.Staged.UnstageAll}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Staged Changes -->
|
||||
<Border Grid.Row="3" Background="{DynamicResource Brush.Contents}">
|
||||
<widgets:WorkingCopyChanges
|
||||
x:Name="stagedContainer"
|
||||
IsUnstaged="False"
|
||||
Mode="{Binding ElementName=stagedMode, Path=Mode}"
|
||||
DiffTargetChanged="OnDiffTargetChanged"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<GridSplitter Grid.Column="1" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" Background="{DynamicResource Brush.Border0}"/>
|
||||
|
||||
<!-- Right -->
|
||||
<Grid Grid.Column="2" Margin="4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Diff viewer -->
|
||||
<widgets:DiffViewer Grid.Row="0" x:Name="diffViewer"/>
|
||||
|
||||
<!-- Merge Option Panel -->
|
||||
<Grid Grid.Row="0" x:Name="mergePanel" Background="{DynamicResource Brush.Window}" Visibility="Collapsed">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Path
|
||||
Width="64" Height="64"
|
||||
Data="{StaticResource Icon.Conflict}"
|
||||
Fill="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock
|
||||
Margin="0,16,0,28"
|
||||
FontSize="20" FontWeight="DemiBold"
|
||||
Text="{DynamicResource Text.WorkingCopy.Conflicts}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
HorizontalAlignment="Center"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Click="UseTheirs" Content="{DynamicResource Text.WorkingCopy.UseTheirs}" Height="24" Padding="8,0"/>
|
||||
<Button Click="UseMine" Content="{DynamicResource Text.WorkingCopy.UseMine}" Height="24" Margin="8,0" Padding="8,0"/>
|
||||
<Button Click="UseMergeTool" Content="{DynamicResource Text.WorkingCopy.OpenMerger}" Height="24" Padding="8,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Commit Message -->
|
||||
<controls:TextEdit
|
||||
Grid.Row="1"
|
||||
x:Name="txtCommitMessage"
|
||||
Height="64"
|
||||
Margin="0,4" Padding="1"
|
||||
AcceptsReturn="True"
|
||||
AcceptsTab="True"
|
||||
TextWrapping="Wrap"
|
||||
KeyDown="CommitMessageKeyDown"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Placeholder="{DynamicResource Text.WorkingCopy.CommitMessageTip}"
|
||||
PlaceholderBaseline="Top">
|
||||
<TextBox.Text>
|
||||
<Binding ElementName="me" Path="CommitMessage" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validations:CommitMessage/>
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox.Text>
|
||||
</controls:TextEdit>
|
||||
|
||||
<!-- Commit Options -->
|
||||
<Grid Grid.Row="2" Margin="0,0,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:IconButton
|
||||
Grid.Column="0"
|
||||
Width="14" Height="14"
|
||||
Click="OpenCommitMessageRecorder"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.MessageHistories}"
|
||||
Icon="{StaticResource Icon.List}"
|
||||
Opacity=".5"/>
|
||||
|
||||
<CheckBox
|
||||
Grid.Column="1"
|
||||
x:Name="chkAmend"
|
||||
Margin="8,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{DynamicResource Text.WorkingCopy.Amend}"
|
||||
Checked="StartAmend" Unchecked="EndAmend"/>
|
||||
|
||||
<controls:Loading
|
||||
Grid.Column="3"
|
||||
x:Name="iconCommitting"
|
||||
Width="18" Height="18"
|
||||
Margin="0,0,8,0"
|
||||
Visibility="Collapsed"/>
|
||||
|
||||
<Button
|
||||
Grid.Column="4"
|
||||
Height="26"
|
||||
Padding="8,0"
|
||||
Click="Commit"
|
||||
FontWeight="Bold"
|
||||
Background="{DynamicResource Brush.Accent1}"
|
||||
BorderBrush="{DynamicResource Brush.FG1}"
|
||||
Content="{DynamicResource Text.WorkingCopy.Commit}"
|
||||
ToolTip="{DynamicResource Text.WorkingCopy.CommitTip}"/>
|
||||
|
||||
<Button
|
||||
Grid.Column="5"
|
||||
x:Name="btnCommitAndPush"
|
||||
Height="26"
|
||||
Padding="8,0"
|
||||
Click="CommitAndPush"
|
||||
FontWeight="Bold"
|
||||
Content="{DynamicResource Text.WorkingCopy.CommitAndPush}"
|
||||
Margin="8,0,0,0"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,367 +1,372 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace SourceGit.Views.Widgets {
|
||||
/// <summary>
|
||||
/// 工作区
|
||||
/// </summary>
|
||||
public partial class WorkingCopy : UserControl {
|
||||
private Models.Repository repo = null;
|
||||
private bool isLFSEnabled = false;
|
||||
|
||||
public string CommitMessage { get; set; }
|
||||
|
||||
public WorkingCopy(Models.Repository repo) {
|
||||
this.repo = repo;
|
||||
this.isLFSEnabled = new Commands.LFS(repo.Path).IsEnabled();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
unstagedContainer.SetRepository(repo.Path);
|
||||
stagedContainer.SetRepository(repo.Path);
|
||||
}
|
||||
|
||||
public void SetData(List<Models.Change> changes) {
|
||||
List<Models.Change> unstagedChanges = new List<Models.Change>();
|
||||
List<Models.Change> stagedChanges = new List<Models.Change>();
|
||||
|
||||
foreach (var c in changes) {
|
||||
if (c.Index == Models.Change.Status.Modified
|
||||
|| c.Index == Models.Change.Status.Added
|
||||
|| c.Index == Models.Change.Status.Deleted
|
||||
|| c.Index == Models.Change.Status.Renamed) {
|
||||
stagedChanges.Add(c);
|
||||
}
|
||||
|
||||
if (c.WorkTree != Models.Change.Status.None) {
|
||||
unstagedChanges.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
unstagedContainer.SetData(unstagedChanges);
|
||||
stagedContainer.SetData(stagedChanges);
|
||||
|
||||
var current = repo.Branches.Find(x => x.IsCurrent);
|
||||
if (current != null && !string.IsNullOrEmpty(current.Upstream) && chkAmend.IsChecked != true) {
|
||||
btnCommitAndPush.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
var diffTarget = unstagedContainer.DiffTarget;
|
||||
if (diffTarget == null) diffTarget = stagedContainer.DiffTarget;
|
||||
if (diffTarget == null) {
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
diffViewer.Reset();
|
||||
} else if (diffTarget.IsConflit) {
|
||||
mergePanel.Visibility = Visibility.Visible;
|
||||
diffViewer.Reset();
|
||||
} else {
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
diffViewer.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public void TryLoadMergeMessage() {
|
||||
if (string.IsNullOrEmpty(txtCommitMessage.Text)) {
|
||||
var mergeMsgFile = Path.Combine(repo.GitDir, "MERGE_MSG");
|
||||
if (!File.Exists(mergeMsgFile)) return;
|
||||
|
||||
var content = File.ReadAllText(mergeMsgFile);
|
||||
txtCommitMessage.Text = content;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearMessage() {
|
||||
txtCommitMessage.Text = "";
|
||||
Validation.ClearInvalid(txtCommitMessage.GetBindingExpression(TextBox.TextProperty));
|
||||
}
|
||||
|
||||
#region STAGE_UNSTAGE
|
||||
private void StageSelected(object sender, RoutedEventArgs e) {
|
||||
unstagedContainer.StageSelected();
|
||||
}
|
||||
|
||||
private void StageAll(object sender, RoutedEventArgs e) {
|
||||
unstagedContainer.StageAll();
|
||||
}
|
||||
|
||||
private void UnstageSelected(object sender, RoutedEventArgs e) {
|
||||
stagedContainer.UnstageSelected();
|
||||
}
|
||||
|
||||
private void UnstageAll(object sender, RoutedEventArgs e) {
|
||||
stagedContainer.UnstageAll();
|
||||
}
|
||||
|
||||
private void OnDiffTargetChanged(object sender, WorkingCopyChanges.DiffTargetChangedEventArgs e) {
|
||||
var container = sender as WorkingCopyChanges;
|
||||
if (container == null) return;
|
||||
|
||||
if (e.Target == null) {
|
||||
if (e.HasOthers) {
|
||||
if (container.IsUnstaged) {
|
||||
stagedContainer.UnselectAll();
|
||||
} else {
|
||||
unstagedContainer.UnselectAll();
|
||||
}
|
||||
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
diffViewer.Reset();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (container.IsUnstaged) {
|
||||
stagedContainer.UnselectAll();
|
||||
} else {
|
||||
unstagedContainer.UnselectAll();
|
||||
}
|
||||
|
||||
var change = e.Target;
|
||||
if (change.IsConflit) {
|
||||
mergePanel.Visibility = Visibility.Visible;
|
||||
diffViewer.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
if (container.IsUnstaged) {
|
||||
switch (change.WorkTree) {
|
||||
case Models.Change.Status.Added:
|
||||
case Models.Change.Status.Untracked:
|
||||
diffViewer.Diff(repo.Path, new DiffViewer.Option() {
|
||||
ExtraArgs = "--no-index",
|
||||
Path = change.Path,
|
||||
OrgPath = "/dev/null",
|
||||
UseLFS = isLFSEnabled
|
||||
});
|
||||
break;
|
||||
default:
|
||||
diffViewer.Diff(repo.Path, new DiffViewer.Option() {
|
||||
Path = change.Path,
|
||||
OrgPath = change.OriginalPath,
|
||||
UseLFS = isLFSEnabled
|
||||
});
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
diffViewer.Diff(repo.Path, new DiffViewer.Option() {
|
||||
ExtraArgs = "--cached",
|
||||
Path = change.Path,
|
||||
OrgPath = change.OriginalPath,
|
||||
UseLFS = isLFSEnabled
|
||||
});
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MERGE
|
||||
private async void UseTheirs(object sender, RoutedEventArgs e) {
|
||||
var change = unstagedContainer.DiffTarget;
|
||||
if (change == null || !change.IsConflit) return;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(repo.Path).File(change.Path, true));
|
||||
if (succ) {
|
||||
await Task.Run(() => new Commands.Add(repo.Path, new List<string>() { change.Path }).Exec());
|
||||
}
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void UseMine(object sender, RoutedEventArgs e) {
|
||||
var change = unstagedContainer.DiffTarget;
|
||||
if (change == null || !change.IsConflit) return;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(repo.Path).File(change.Path, false));
|
||||
if (succ) {
|
||||
await Task.Run(() => new Commands.Add(repo.Path, new List<string>() { change.Path }).Exec());
|
||||
}
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void UseMergeTool(object sender, RoutedEventArgs e) {
|
||||
var mergeType = Models.Preference.Instance.MergeTool.Type;
|
||||
var mergeExe = Models.Preference.Instance.MergeTool.Path;
|
||||
|
||||
var merger = Models.MergeTool.Supported.Find(x => x.Type == mergeType);
|
||||
if (merger == null || merger.Type == 0 || !File.Exists(mergeExe)) {
|
||||
Models.Exception.Raise("Invalid merge tool in preference setting!");
|
||||
return;
|
||||
}
|
||||
|
||||
var change = unstagedContainer.DiffTarget;
|
||||
if (change == null || !change.IsConflit) return;
|
||||
|
||||
var cmd = new Commands.Command();
|
||||
cmd.Cwd = repo.Path;
|
||||
cmd.DontRaiseError = true;
|
||||
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{mergeExe}\\\" {merger.Cmd}\" ";
|
||||
cmd.Args += "-c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true ";
|
||||
cmd.Args += $"mergetool --tool=sourcegit {change.Path}";
|
||||
|
||||
await Task.Run(() => cmd.Exec());
|
||||
e.Handled = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region COMMIT
|
||||
private void OpenCommitMessageRecorder(object sender, RoutedEventArgs e) {
|
||||
var anchor = sender as Button;
|
||||
|
||||
if (anchor.ContextMenu == null) {
|
||||
anchor.ContextMenu = new ContextMenu();
|
||||
anchor.ContextMenu.PlacementTarget = anchor;
|
||||
anchor.ContextMenu.Placement = PlacementMode.Top;
|
||||
anchor.ContextMenu.VerticalOffset = 0;
|
||||
anchor.ContextMenu.StaysOpen = false;
|
||||
anchor.ContextMenu.Focusable = true;
|
||||
anchor.ContextMenu.MaxWidth = 500;
|
||||
} else {
|
||||
anchor.ContextMenu.Items.Clear();
|
||||
}
|
||||
|
||||
if (repo.CommitMessages.Count == 0) {
|
||||
var tip = new MenuItem();
|
||||
tip.Header = App.Text("WorkingCopy.NoCommitHistories");
|
||||
tip.IsEnabled = false;
|
||||
anchor.ContextMenu.Items.Add(tip);
|
||||
} else {
|
||||
var tip = new MenuItem();
|
||||
tip.Header = App.Text("WorkingCopy.HasCommitHistories");
|
||||
tip.IsEnabled = false;
|
||||
anchor.ContextMenu.Items.Add(tip);
|
||||
anchor.ContextMenu.Items.Add(new Separator());
|
||||
|
||||
foreach (var one in repo.CommitMessages) {
|
||||
var dump = one;
|
||||
|
||||
var item = new MenuItem();
|
||||
item.Header = dump;
|
||||
item.Padding = new Thickness(0);
|
||||
item.Click += (o, ev) => {
|
||||
txtCommitMessage.Text = dump;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
anchor.ContextMenu.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
anchor.ContextMenu.IsOpen = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void StartAmend(object sender, RoutedEventArgs e) {
|
||||
var commits = new Commands.Commits(repo.Path, "-n 1", false).Result();
|
||||
if (commits.Count == 0) {
|
||||
Models.Exception.Raise("No commits to amend!");
|
||||
chkAmend.IsChecked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
txtCommitMessage.Text = commits[0].Subject;
|
||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void EndAmend(object sender, RoutedEventArgs e) {
|
||||
if (!IsLoaded) return;
|
||||
|
||||
var current = repo.Branches.Find(x => x.IsCurrent);
|
||||
if (current != null && !string.IsNullOrEmpty(current.Upstream)) {
|
||||
btnCommitAndPush.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void Commit(object sender, RoutedEventArgs e) {
|
||||
var changes = await Task.Run(() => new Commands.LocalChanges(repo.Path).Result());
|
||||
var conflict = changes.Find(x => x.IsConflit);
|
||||
if (conflict != null) {
|
||||
Models.Exception.Raise("You have unsolved conflicts in your working copy!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (stagedContainer.Changes.Count == 0) {
|
||||
Models.Exception.Raise("No files added to commit!");
|
||||
return;
|
||||
}
|
||||
|
||||
txtCommitMessage.GetBindingExpression(TextBox.TextProperty).UpdateSource();
|
||||
if (Validation.GetHasError(txtCommitMessage)) return;
|
||||
|
||||
repo.PushCommitMessage(CommitMessage);
|
||||
iconCommitting.Visibility = Visibility.Visible;
|
||||
iconCommitting.IsAnimating = true;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var amend = chkAmend.IsChecked == true;
|
||||
var succ = await Task.Run(() => new Commands.Commit(repo.Path, CommitMessage, amend).Exec());
|
||||
if (succ) {
|
||||
ClearMessage();
|
||||
if (amend) chkAmend.IsChecked = false;
|
||||
}
|
||||
|
||||
iconCommitting.IsAnimating = false;
|
||||
iconCommitting.Visibility = Visibility.Collapsed;
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void CommitAndPush(object sender, RoutedEventArgs e) {
|
||||
var changes = await Task.Run(() => new Commands.LocalChanges(repo.Path).Result());
|
||||
var conflict = changes.Find(x => x.IsConflit);
|
||||
if (conflict != null) {
|
||||
Models.Exception.Raise("You have unsolved conflicts in your working copy!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (stagedContainer.Changes.Count == 0) {
|
||||
Models.Exception.Raise("No files added to commit!");
|
||||
return;
|
||||
}
|
||||
|
||||
txtCommitMessage.GetBindingExpression(TextBox.TextProperty).UpdateSource();
|
||||
if (Validation.GetHasError(txtCommitMessage)) return;
|
||||
|
||||
repo.PushCommitMessage(CommitMessage);
|
||||
iconCommitting.Visibility = Visibility.Visible;
|
||||
iconCommitting.IsAnimating = true;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var succ = await Task.Run(() => new Commands.Commit(repo.Path, CommitMessage, false).Exec());
|
||||
if (succ) {
|
||||
new Popups.Push(repo, repo.Branches.Find(x => x.IsCurrent)).ShowAndStart();
|
||||
ClearMessage();
|
||||
}
|
||||
iconCommitting.IsAnimating = false;
|
||||
iconCommitting.Visibility = Visibility.Collapsed;
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CommitMessageKeyDown(object sender, KeyEventArgs e) {
|
||||
if (e.Key == Key.Enter && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) {
|
||||
Commit(sender, e);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace SourceGit.Views.Widgets {
|
||||
/// <summary>
|
||||
/// 工作区
|
||||
/// </summary>
|
||||
public partial class WorkingCopy : UserControl {
|
||||
private Models.Repository repo = null;
|
||||
private bool isLFSEnabled = false;
|
||||
|
||||
public string CommitMessage { get; set; }
|
||||
|
||||
public WorkingCopy(Models.Repository repo) {
|
||||
this.repo = repo;
|
||||
this.isLFSEnabled = new Commands.LFS(repo.Path).IsEnabled();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
unstagedContainer.SetRepository(repo.Path);
|
||||
stagedContainer.SetRepository(repo.Path);
|
||||
}
|
||||
|
||||
public void SetData(List<Models.Change> changes) {
|
||||
List<Models.Change> unstagedChanges = new List<Models.Change>();
|
||||
List<Models.Change> stagedChanges = new List<Models.Change>();
|
||||
|
||||
foreach (var c in changes) {
|
||||
if (c.Index == Models.Change.Status.Modified
|
||||
|| c.Index == Models.Change.Status.Added
|
||||
|| c.Index == Models.Change.Status.Deleted
|
||||
|| c.Index == Models.Change.Status.Renamed) {
|
||||
stagedChanges.Add(c);
|
||||
}
|
||||
|
||||
if (c.WorkTree != Models.Change.Status.None) {
|
||||
unstagedChanges.Add(c);
|
||||
}
|
||||
}
|
||||
|
||||
unstagedContainer.SetData(unstagedChanges);
|
||||
stagedContainer.SetData(stagedChanges);
|
||||
|
||||
var current = repo.Branches.Find(x => x.IsCurrent);
|
||||
if (current != null && !string.IsNullOrEmpty(current.Upstream) && chkAmend.IsChecked != true) {
|
||||
btnCommitAndPush.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
var diffTarget = unstagedContainer.DiffTarget;
|
||||
if (diffTarget == null) diffTarget = stagedContainer.DiffTarget;
|
||||
if (diffTarget == null) {
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
diffViewer.Reset();
|
||||
} else if (diffTarget.IsConflit) {
|
||||
mergePanel.Visibility = Visibility.Visible;
|
||||
diffViewer.Reset();
|
||||
} else {
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
diffViewer.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public void TryLoadMergeMessage() {
|
||||
if (string.IsNullOrEmpty(txtCommitMessage.Text)) {
|
||||
var mergeMsgFile = Path.Combine(repo.GitDir, "MERGE_MSG");
|
||||
if (!File.Exists(mergeMsgFile)) return;
|
||||
|
||||
var content = File.ReadAllText(mergeMsgFile);
|
||||
txtCommitMessage.Text = content;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearMessage() {
|
||||
txtCommitMessage.Text = "";
|
||||
Validation.ClearInvalid(txtCommitMessage.GetBindingExpression(TextBox.TextProperty));
|
||||
}
|
||||
|
||||
public void ToggleIncludeUntracked(object sender, RoutedEventArgs e) {
|
||||
var watcher = Models.Watcher.Get(repo.Path);
|
||||
if (watcher != null) watcher.RefreshWC();
|
||||
}
|
||||
|
||||
#region STAGE_UNSTAGE
|
||||
private void StageSelected(object sender, RoutedEventArgs e) {
|
||||
unstagedContainer.StageSelected();
|
||||
}
|
||||
|
||||
private void StageAll(object sender, RoutedEventArgs e) {
|
||||
unstagedContainer.StageAll();
|
||||
}
|
||||
|
||||
private void UnstageSelected(object sender, RoutedEventArgs e) {
|
||||
stagedContainer.UnstageSelected();
|
||||
}
|
||||
|
||||
private void UnstageAll(object sender, RoutedEventArgs e) {
|
||||
stagedContainer.UnstageAll();
|
||||
}
|
||||
|
||||
private void OnDiffTargetChanged(object sender, WorkingCopyChanges.DiffTargetChangedEventArgs e) {
|
||||
var container = sender as WorkingCopyChanges;
|
||||
if (container == null) return;
|
||||
|
||||
if (e.Target == null) {
|
||||
if (e.HasOthers) {
|
||||
if (container.IsUnstaged) {
|
||||
stagedContainer.UnselectAll();
|
||||
} else {
|
||||
unstagedContainer.UnselectAll();
|
||||
}
|
||||
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
diffViewer.Reset();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (container.IsUnstaged) {
|
||||
stagedContainer.UnselectAll();
|
||||
} else {
|
||||
unstagedContainer.UnselectAll();
|
||||
}
|
||||
|
||||
var change = e.Target;
|
||||
if (change.IsConflit) {
|
||||
mergePanel.Visibility = Visibility.Visible;
|
||||
diffViewer.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
mergePanel.Visibility = Visibility.Collapsed;
|
||||
if (container.IsUnstaged) {
|
||||
switch (change.WorkTree) {
|
||||
case Models.Change.Status.Added:
|
||||
case Models.Change.Status.Untracked:
|
||||
diffViewer.Diff(repo.Path, new DiffViewer.Option() {
|
||||
ExtraArgs = "--no-index",
|
||||
Path = change.Path,
|
||||
OrgPath = "/dev/null",
|
||||
UseLFS = isLFSEnabled
|
||||
});
|
||||
break;
|
||||
default:
|
||||
diffViewer.Diff(repo.Path, new DiffViewer.Option() {
|
||||
Path = change.Path,
|
||||
OrgPath = change.OriginalPath,
|
||||
UseLFS = isLFSEnabled
|
||||
});
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
diffViewer.Diff(repo.Path, new DiffViewer.Option() {
|
||||
ExtraArgs = "--cached",
|
||||
Path = change.Path,
|
||||
OrgPath = change.OriginalPath,
|
||||
UseLFS = isLFSEnabled
|
||||
});
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MERGE
|
||||
private async void UseTheirs(object sender, RoutedEventArgs e) {
|
||||
var change = unstagedContainer.DiffTarget;
|
||||
if (change == null || !change.IsConflit) return;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(repo.Path).File(change.Path, true));
|
||||
if (succ) {
|
||||
await Task.Run(() => new Commands.Add(repo.Path, new List<string>() { change.Path }).Exec());
|
||||
}
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void UseMine(object sender, RoutedEventArgs e) {
|
||||
var change = unstagedContainer.DiffTarget;
|
||||
if (change == null || !change.IsConflit) return;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var succ = await Task.Run(() => new Commands.Checkout(repo.Path).File(change.Path, false));
|
||||
if (succ) {
|
||||
await Task.Run(() => new Commands.Add(repo.Path, new List<string>() { change.Path }).Exec());
|
||||
}
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void UseMergeTool(object sender, RoutedEventArgs e) {
|
||||
var mergeType = Models.Preference.Instance.MergeTool.Type;
|
||||
var mergeExe = Models.Preference.Instance.MergeTool.Path;
|
||||
|
||||
var merger = Models.MergeTool.Supported.Find(x => x.Type == mergeType);
|
||||
if (merger == null || merger.Type == 0 || !File.Exists(mergeExe)) {
|
||||
Models.Exception.Raise("Invalid merge tool in preference setting!");
|
||||
return;
|
||||
}
|
||||
|
||||
var change = unstagedContainer.DiffTarget;
|
||||
if (change == null || !change.IsConflit) return;
|
||||
|
||||
var cmd = new Commands.Command();
|
||||
cmd.Cwd = repo.Path;
|
||||
cmd.DontRaiseError = true;
|
||||
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{mergeExe}\\\" {merger.Cmd}\" ";
|
||||
cmd.Args += "-c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true ";
|
||||
cmd.Args += $"mergetool --tool=sourcegit {change.Path}";
|
||||
|
||||
await Task.Run(() => cmd.Exec());
|
||||
e.Handled = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region COMMIT
|
||||
private void OpenCommitMessageRecorder(object sender, RoutedEventArgs e) {
|
||||
var anchor = sender as Button;
|
||||
|
||||
if (anchor.ContextMenu == null) {
|
||||
anchor.ContextMenu = new ContextMenu();
|
||||
anchor.ContextMenu.PlacementTarget = anchor;
|
||||
anchor.ContextMenu.Placement = PlacementMode.Top;
|
||||
anchor.ContextMenu.VerticalOffset = 0;
|
||||
anchor.ContextMenu.StaysOpen = false;
|
||||
anchor.ContextMenu.Focusable = true;
|
||||
anchor.ContextMenu.MaxWidth = 500;
|
||||
} else {
|
||||
anchor.ContextMenu.Items.Clear();
|
||||
}
|
||||
|
||||
if (repo.CommitMessages.Count == 0) {
|
||||
var tip = new MenuItem();
|
||||
tip.Header = App.Text("WorkingCopy.NoCommitHistories");
|
||||
tip.IsEnabled = false;
|
||||
anchor.ContextMenu.Items.Add(tip);
|
||||
} else {
|
||||
var tip = new MenuItem();
|
||||
tip.Header = App.Text("WorkingCopy.HasCommitHistories");
|
||||
tip.IsEnabled = false;
|
||||
anchor.ContextMenu.Items.Add(tip);
|
||||
anchor.ContextMenu.Items.Add(new Separator());
|
||||
|
||||
foreach (var one in repo.CommitMessages) {
|
||||
var dump = one;
|
||||
|
||||
var item = new MenuItem();
|
||||
item.Header = dump;
|
||||
item.Padding = new Thickness(0);
|
||||
item.Click += (o, ev) => {
|
||||
txtCommitMessage.Text = dump;
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
||||
anchor.ContextMenu.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
anchor.ContextMenu.IsOpen = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void StartAmend(object sender, RoutedEventArgs e) {
|
||||
var commits = new Commands.Commits(repo.Path, "-n 1", false).Result();
|
||||
if (commits.Count == 0) {
|
||||
Models.Exception.Raise("No commits to amend!");
|
||||
chkAmend.IsChecked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
txtCommitMessage.Text = commits[0].Subject;
|
||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void EndAmend(object sender, RoutedEventArgs e) {
|
||||
if (!IsLoaded) return;
|
||||
|
||||
var current = repo.Branches.Find(x => x.IsCurrent);
|
||||
if (current != null && !string.IsNullOrEmpty(current.Upstream)) {
|
||||
btnCommitAndPush.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void Commit(object sender, RoutedEventArgs e) {
|
||||
var changes = await Task.Run(() => new Commands.LocalChanges(repo.Path).Result());
|
||||
var conflict = changes.Find(x => x.IsConflit);
|
||||
if (conflict != null) {
|
||||
Models.Exception.Raise("You have unsolved conflicts in your working copy!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (stagedContainer.Changes.Count == 0) {
|
||||
Models.Exception.Raise("No files added to commit!");
|
||||
return;
|
||||
}
|
||||
|
||||
txtCommitMessage.GetBindingExpression(TextBox.TextProperty).UpdateSource();
|
||||
if (Validation.GetHasError(txtCommitMessage)) return;
|
||||
|
||||
repo.PushCommitMessage(CommitMessage);
|
||||
iconCommitting.Visibility = Visibility.Visible;
|
||||
iconCommitting.IsAnimating = true;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var amend = chkAmend.IsChecked == true;
|
||||
var succ = await Task.Run(() => new Commands.Commit(repo.Path, CommitMessage, amend).Exec());
|
||||
if (succ) {
|
||||
ClearMessage();
|
||||
if (amend) chkAmend.IsChecked = false;
|
||||
}
|
||||
|
||||
iconCommitting.IsAnimating = false;
|
||||
iconCommitting.Visibility = Visibility.Collapsed;
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void CommitAndPush(object sender, RoutedEventArgs e) {
|
||||
var changes = await Task.Run(() => new Commands.LocalChanges(repo.Path).Result());
|
||||
var conflict = changes.Find(x => x.IsConflit);
|
||||
if (conflict != null) {
|
||||
Models.Exception.Raise("You have unsolved conflicts in your working copy!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (stagedContainer.Changes.Count == 0) {
|
||||
Models.Exception.Raise("No files added to commit!");
|
||||
return;
|
||||
}
|
||||
|
||||
txtCommitMessage.GetBindingExpression(TextBox.TextProperty).UpdateSource();
|
||||
if (Validation.GetHasError(txtCommitMessage)) return;
|
||||
|
||||
repo.PushCommitMessage(CommitMessage);
|
||||
iconCommitting.Visibility = Visibility.Visible;
|
||||
iconCommitting.IsAnimating = true;
|
||||
|
||||
Models.Watcher.SetEnabled(repo.Path, false);
|
||||
var succ = await Task.Run(() => new Commands.Commit(repo.Path, CommitMessage, false).Exec());
|
||||
if (succ) {
|
||||
new Popups.Push(repo, repo.Branches.Find(x => x.IsCurrent)).ShowAndStart();
|
||||
ClearMessage();
|
||||
}
|
||||
iconCommitting.IsAnimating = false;
|
||||
iconCommitting.Visibility = Visibility.Collapsed;
|
||||
Models.Watcher.SetEnabled(repo.Path, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CommitMessageKeyDown(object sender, KeyEventArgs e) {
|
||||
if (e.Key == Key.Enter && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) {
|
||||
Commit(sender, e);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue