Skip to content

Commit 8075d0b

Browse files
committed
feature: supports to push to a custom (new) remote branch
Signed-off-by: leo <longshuang@msn.cn>
1 parent 74a9489 commit 8075d0b

File tree

12 files changed

+191
-43
lines changed

12 files changed

+191
-43
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,8 @@
644644
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">Push to all remotes</x:String>
645645
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">Remote:</x:String>
646646
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">Tag:</x:String>
647+
<x:String x:Key="Text.PushToNewBranch" xml:space="preserve">Push to a NEW branch</x:String>
648+
<x:String x:Key="Text.PushToNewBranch.Title" xml:space="preserve">Input name of the new remote branch:</x:String>
647649
<x:String x:Key="Text.Quit" xml:space="preserve">Quit</x:String>
648650
<x:String x:Key="Text.Rebase" xml:space="preserve">Rebase Current Branch</x:String>
649651
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reapply local changes</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@
648648
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">推送到所有远程仓库</x:String>
649649
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">远程仓库 :</x:String>
650650
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">标签 :</x:String>
651+
<x:String x:Key="Text.PushToNewBranch" xml:space="preserve">推送到新的分支</x:String>
652+
<x:String x:Key="Text.PushToNewBranch.Title" xml:space="preserve">输入新的远端分支名</x:String>
651653
<x:String x:Key="Text.Quit" xml:space="preserve">退出</x:String>
652654
<x:String x:Key="Text.Rebase" xml:space="preserve">变基(rebase)操作</x:String>
653655
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自动贮藏并恢复本地变更</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@
648648
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">推送到所有遠端存放庫</x:String>
649649
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">遠端存放庫:</x:String>
650650
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">標籤:</x:String>
651+
<x:String x:Key="Text.PushToNewBranch" xml:space="preserve">推送到新的分支</x:String>
652+
<x:String x:Key="Text.PushToNewBranch.Title" xml:space="preserve">输入新的遠端分支名</x:String>
651653
<x:String x:Key="Text.Quit" xml:space="preserve">結束</x:String>
652654
<x:String x:Key="Text.Rebase" xml:space="preserve">重定基底 (rebase) 操作</x:String>
653655
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">自動擱置變更並復原本機變更</x:String>

src/ViewModels/Push.cs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.ComponentModel.DataAnnotations;
34
using System.Threading.Tasks;
45

@@ -69,9 +70,9 @@ public bool IsSetTrackOptionVisible
6970

7071
public bool Tracking
7172
{
72-
get;
73-
set;
74-
} = true;
73+
get => _tracking;
74+
set => SetProperty(ref _tracking, value);
75+
}
7576

7677
public bool IsCheckSubmodulesVisible
7778
{
@@ -127,8 +128,10 @@ public Push(Repository repo, Models.Branch localBranch)
127128
}
128129

129130
// Find preferred remote if selected local branch has upstream.
130-
if (!string.IsNullOrEmpty(_selectedLocalBranch?.Upstream))
131+
if (!string.IsNullOrEmpty(_selectedLocalBranch?.Upstream) && !_selectedLocalBranch.IsUpstreamGone)
131132
{
133+
_tracking = false;
134+
132135
foreach (var branch in repo.Branches)
133136
{
134137
if (!branch.IsLocal && _selectedLocalBranch.Upstream == branch.FullName)
@@ -138,6 +141,10 @@ public Push(Repository repo, Models.Branch localBranch)
138141
}
139142
}
140143
}
144+
else
145+
{
146+
_tracking = true;
147+
}
141148

142149
// Set default remote to the first if it has not been set.
143150
if (_selectedRemote == null)
@@ -153,6 +160,27 @@ public Push(Repository repo, Models.Branch localBranch)
153160
AutoSelectBranchByRemote();
154161
}
155162

163+
public void PushToNewBranch(string name)
164+
{
165+
var exist = _remoteBranches.Find(x => x.Name.Equals(name, StringComparison.Ordinal));
166+
if (exist != null)
167+
{
168+
SelectedRemoteBranch = exist;
169+
return;
170+
}
171+
172+
var fake = new Models.Branch()
173+
{
174+
Name = name,
175+
Remote = _selectedRemote.Name,
176+
};
177+
var collection = new List<Models.Branch>();
178+
collection.AddRange(_remoteBranches);
179+
collection.Add(fake);
180+
RemoteBranches = collection;
181+
SelectedRemoteBranch = fake;
182+
}
183+
156184
public override bool CanStartDirectly()
157185
{
158186
return !string.IsNullOrEmpty(_selectedRemoteBranch?.Head);
@@ -175,7 +203,7 @@ public override async Task<bool> Sure()
175203
remoteBranchName,
176204
PushAllTags,
177205
_repo.Submodules.Count > 0 && CheckSubmodules,
178-
_isSetTrackOptionVisible && Tracking,
206+
_isSetTrackOptionVisible && _tracking,
179207
ForcePush).Use(log).RunAsync();
180208

181209
log.Complete();
@@ -234,5 +262,6 @@ private void AutoSelectBranchByRemote()
234262
private List<Models.Branch> _remoteBranches = [];
235263
private Models.Branch _selectedRemoteBranch = null;
236264
private bool _isSetTrackOptionVisible = false;
265+
private bool _tracking = true;
237266
}
238267
}

src/Views/Pull.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@
4646
Margin="0,0,8,0"
4747
Text="{DynamicResource Text.Pull.Branch}"/>
4848
<ComboBox Grid.Row="1" Grid.Column="1"
49-
x:Name="RemoteBranchesComboBox"
5049
Height="28" Padding="8,0"
5150
VerticalAlignment="Center" HorizontalAlignment="Stretch"
5251
ItemsSource="{Binding RemoteBranches}"
5352
SelectedItem="{Binding SelectedBranch, Mode=TwoWay}"
5453
IsTextSearchEnabled="True"
54+
TextSearch.TextBinding="{Binding Name, DataType=m:Branch}"
5555
IsEnabled="{Binding !HasSpecifiedRemoteBranch}">
5656
<ComboBox.ItemTemplate>
5757
<DataTemplate x:DataType="{x:Type m:Branch}">

src/Views/Pull.axaml.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using Avalonia.Controls;
2-
using Avalonia.Controls.Primitives;
3-
using Avalonia.Data;
42

53
namespace SourceGit.Views
64
{
@@ -9,7 +7,6 @@ public partial class Pull : UserControl
97
public Pull()
108
{
119
InitializeComponent();
12-
TextSearch.SetTextBinding(RemoteBranchesComboBox, new Binding("Name"));
1310
}
1411
}
1512
}

src/Views/Push.axaml

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
Margin="0,0,8,0"
1919
Text="{DynamicResource Text.Push.Local}"/>
2020
<ComboBox Grid.Row="0" Grid.Column="1"
21-
x:Name="LocalBranchesComboBox"
2221
Height="28" Padding="8,0"
2322
VerticalAlignment="Center" HorizontalAlignment="Stretch"
2423
ItemsSource="{Binding LocalBranches}"
2524
SelectedItem="{Binding SelectedLocalBranch, Mode=TwoWay}"
2625
IsTextSearchEnabled="True"
26+
TextSearch.TextBinding="{Binding Name, DataType=m:Branch}"
2727
IsEnabled="{Binding !HasSpecifiedLocalBranch}">
2828
<ComboBox.ItemTemplate>
2929
<DataTemplate x:DataType="{x:Type m:Branch}">
@@ -58,30 +58,40 @@
5858
HorizontalAlignment="Right" VerticalAlignment="Center"
5959
Margin="0,0,8,0"
6060
Text="{DynamicResource Text.Push.To}"/>
61-
<ComboBox Grid.Row="2" Grid.Column="1"
62-
x:Name="RemoteBranchesComboBox"
63-
Height="28" Padding="8,0"
64-
VerticalAlignment="Center" HorizontalAlignment="Stretch"
65-
ItemsSource="{Binding RemoteBranches}"
66-
IsTextSearchEnabled="True"
67-
SelectedItem="{Binding SelectedRemoteBranch, Mode=TwoWay}">
68-
<ComboBox.ItemTemplate>
69-
<DataTemplate x:DataType="{x:Type m:Branch}">
70-
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
71-
<Path Margin="0,0,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Branch}"/>
72-
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
73-
<Border Height="14"
74-
CornerRadius="7"
75-
Margin="4,0,0,0" Padding="6,0"
76-
VerticalAlignment="Center"
77-
Background="Green"
78-
IsVisible="{Binding Head, Converter={x:Static StringConverters.IsNullOrEmpty}}">
79-
<TextBlock Text="{DynamicResource Text.Push.New}" FontSize="9" FontFamily="{DynamicResource Fonts.Monospace}" Foreground="White" VerticalAlignment="Center"/>
80-
</Border>
81-
</StackPanel>
82-
</DataTemplate>
83-
</ComboBox.ItemTemplate>
84-
</ComboBox>
61+
<Grid Grid.Row="2" Grid.Column="1" ColumnDefinitions="*,Auto">
62+
<ComboBox Grid.Column="0"
63+
Height="28" Padding="8,0"
64+
VerticalAlignment="Center" HorizontalAlignment="Stretch"
65+
ItemsSource="{Binding RemoteBranches}"
66+
IsTextSearchEnabled="True"
67+
TextSearch.TextBinding="{Binding Name, DataType=m:Branch}"
68+
SelectedItem="{Binding SelectedRemoteBranch, Mode=TwoWay}">
69+
<ComboBox.ItemTemplate>
70+
<DataTemplate x:DataType="{x:Type m:Branch}">
71+
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
72+
<Path Margin="0,0,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Branch}"/>
73+
<TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
74+
<Border Height="14"
75+
CornerRadius="7"
76+
Margin="4,0,0,0" Padding="6,0"
77+
VerticalAlignment="Center"
78+
Background="Green"
79+
IsVisible="{Binding Head, Converter={x:Static StringConverters.IsNullOrEmpty}}">
80+
<TextBlock Text="{DynamicResource Text.Push.New}" FontSize="9" FontFamily="{DynamicResource Fonts.Monospace}" Foreground="White" VerticalAlignment="Center"/>
81+
</Border>
82+
</StackPanel>
83+
</DataTemplate>
84+
</ComboBox.ItemTemplate>
85+
</ComboBox>
86+
87+
<Button Grid.Column="1"
88+
Classes="icon_button"
89+
Width="26" Height="32"
90+
Click="OnPushToNewBranch"
91+
ToolTip.Tip="{DynamicResource Text.PushToNewBranch}">
92+
<Path Width="14" Height="14" Data="{StaticResource Icons.Branch.Add}"/>
93+
</Button>
94+
</Grid>
8595

8696
<CheckBox Grid.Row="3" Grid.Column="1"
8797
Height="32"

src/Views/Push.axaml.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Avalonia.Controls;
2-
using Avalonia.Controls.Primitives;
3-
using Avalonia.Data;
2+
using Avalonia.Interactivity;
3+
using Avalonia.VisualTree;
44

55
namespace SourceGit.Views
66
{
@@ -9,8 +9,23 @@ public partial class Push : UserControl
99
public Push()
1010
{
1111
InitializeComponent();
12-
TextSearch.SetTextBinding(LocalBranchesComboBox, new Binding("Name"));
13-
TextSearch.SetTextBinding(RemoteBranchesComboBox, new Binding("Name"));
12+
}
13+
14+
private async void OnPushToNewBranch(object sender, RoutedEventArgs e)
15+
{
16+
if (DataContext is not ViewModels.Push push)
17+
return;
18+
19+
var launcher = this.FindAncestorOfType<Launcher>();
20+
if (launcher == null)
21+
return;
22+
23+
var dialog = new PushToNewBranch();
24+
dialog.SetRemote(push.SelectedRemote.Name);
25+
26+
var name = await dialog.ShowDialog<string>(launcher);
27+
if (!string.IsNullOrEmpty(name))
28+
push.PushToNewBranch(name);
1429
}
1530
}
1631
}

src/Views/PushToNewBranch.axaml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:v="using:SourceGit.Views"
6+
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
7+
x:Class="SourceGit.Views.PushToNewBranch"
8+
x:Name="ThisControl"
9+
Icon="/App.ico"
10+
Title="{DynamicResource Text.PushToNewBranch}"
11+
SizeToContent="WidthAndHeight"
12+
CanResize="False"
13+
WindowStartupLocation="CenterOwner">
14+
<Grid RowDefinitions="Auto,*">
15+
<!-- TitleBar -->
16+
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
17+
<Border Background="{DynamicResource Brush.TitleBar}"
18+
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
19+
PointerPressed="BeginMoveWindow"/>
20+
21+
<Path Width="14" Height="14"
22+
Margin="10,0,0,0"
23+
HorizontalAlignment="Left"
24+
Data="{StaticResource Icons.Edit}"
25+
IsVisible="{OnPlatform True, macOS=False}"/>
26+
27+
<TextBlock Classes="bold"
28+
Text="{DynamicResource Text.PushToNewBranch}"
29+
HorizontalAlignment="Center" VerticalAlignment="Center"
30+
IsHitTestVisible="False"/>
31+
32+
<v:CaptionButtons HorizontalAlignment="Right"
33+
IsCloseButtonOnly="True"
34+
IsVisible="{OnPlatform True, macOS=False}"/>
35+
</Grid>
36+
37+
<StackPanel Grid.Row="1" Margin="0,16" Orientation="Vertical">
38+
<Border Margin="16,0">
39+
<TextBlock Text="{DynamicResource Text.PushToNewBranch.Title}"/>
40+
</Border>
41+
42+
<Grid ColumnDefinitions="Auto,*" Margin="16,8,16,0">
43+
<TextBlock Grid.Column="0" x:Name="TxtPrefix" Text="REMOTE/" Margin="0,0,6,0"/>
44+
<TextBox Grid.Column="1"
45+
x:Name="TxtName"
46+
MinWidth="300" Height="32"
47+
CornerRadius="3"
48+
Focusable="True"
49+
v:AutoFocusBehaviour.IsEnabled="True"/>
50+
</Grid>
51+
52+
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
53+
<Button Classes="flat primary"
54+
Width="80"
55+
Content="{DynamicResource Text.Sure}"
56+
Click="OnSure"
57+
HotKey="Enter"/>
58+
<Button Classes="flat"
59+
Width="80"
60+
Margin="16,0,0,0"
61+
Content="{DynamicResource Text.Cancel}"
62+
Click="OnCancel"/>
63+
</StackPanel>
64+
</StackPanel>
65+
</Grid>
66+
</v:ChromelessWindow>

src/Views/PushToNewBranch.axaml.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Avalonia.Interactivity;
2+
3+
namespace SourceGit.Views
4+
{
5+
public partial class PushToNewBranch : ChromelessWindow
6+
{
7+
public PushToNewBranch()
8+
{
9+
CloseOnESC = true;
10+
InitializeComponent();
11+
}
12+
13+
public void SetRemote(string remote)
14+
{
15+
TxtPrefix.Text = remote + "/";
16+
}
17+
18+
private void OnSure(object _1, RoutedEventArgs _2)
19+
{
20+
Close(TxtName.Text);
21+
}
22+
23+
private void OnCancel(object _1, RoutedEventArgs _2)
24+
{
25+
Close(string.Empty);
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)