Skip to content

Commit 3f4f0ac

Browse files
committed
feature: pushing branch will respect git's branch.<name>.pushRemote configuration (#2281)
Signed-off-by: leo <longshuang@msn.cn>
1 parent 17f96bf commit 3f4f0ac

2 files changed

Lines changed: 107 additions & 45 deletions

File tree

src/ViewModels/Push.cs

Lines changed: 105 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,26 @@ public bool HasSpecifiedLocalBranch
1414
private set;
1515
}
1616

17+
public List<Models.Branch> LocalBranches
18+
{
19+
get;
20+
}
21+
1722
[Required(ErrorMessage = "Local branch is required!!!")]
1823
public Models.Branch SelectedLocalBranch
1924
{
2025
get => _selectedLocalBranch;
2126
set
2227
{
2328
if (SetProperty(ref _selectedLocalBranch, value, true))
24-
AutoSelectBranchByRemote();
29+
PostLocalBranchChanged();
2530
}
2631
}
2732

28-
public List<Models.Branch> LocalBranches
29-
{
30-
get;
31-
}
32-
3333
public List<Models.Remote> Remotes
3434
{
35-
get => _repo.Remotes;
35+
get => _remotes;
36+
private set => SetProperty(ref _remotes, value);
3637
}
3738

3839
[Required(ErrorMessage = "Remote is required!!!")]
@@ -42,7 +43,7 @@ public Models.Remote SelectedRemote
4243
set
4344
{
4445
if (SetProperty(ref _selectedRemote, value, true))
45-
AutoSelectBranchByRemote();
46+
PostSelectedRemoteChanged();
4647
}
4748
}
4849

@@ -59,7 +60,12 @@ public Models.Branch SelectedRemoteBranch
5960
set
6061
{
6162
if (SetProperty(ref _selectedRemoteBranch, value, true))
62-
IsSetTrackOptionVisible = value != null && (value.Head == null || _selectedLocalBranch.Upstream != value.FullName);
63+
{
64+
IsSetTrackOptionVisible = !string.IsNullOrEmpty(_selectedRemote.URL)
65+
&& value != null
66+
&& (value.Head == null || _selectedLocalBranch.Upstream != value.FullName);
67+
Tracking = true;
68+
}
6369
}
6470
}
6571

@@ -126,46 +132,14 @@ public Push(Repository repo, Models.Branch localBranch)
126132
if (LocalBranches.Count == 0)
127133
LocalBranches.Add(localBranch);
128134

129-
_selectedLocalBranch = localBranch;
130135
HasSpecifiedLocalBranch = true;
136+
SelectedLocalBranch = localBranch;
131137
}
132138
else
133139
{
134-
_selectedLocalBranch = current;
135140
HasSpecifiedLocalBranch = false;
141+
SelectedLocalBranch = current;
136142
}
137-
138-
// Find preferred remote if selected local branch has upstream.
139-
if (_selectedLocalBranch != null)
140-
{
141-
var upstream = _selectedLocalBranch.Upstream;
142-
if (!string.IsNullOrEmpty(upstream) && !_selectedLocalBranch.IsUpstreamGone)
143-
{
144-
_tracking = false;
145-
146-
foreach (var branch in repo.Branches)
147-
{
148-
if (!branch.IsLocal && upstream.Equals(branch.FullName, StringComparison.Ordinal))
149-
{
150-
_selectedRemote = repo.Remotes.Find(x => x.Name == branch.Remote);
151-
break;
152-
}
153-
}
154-
}
155-
}
156-
157-
// Set default remote to the first if it has not been set.
158-
if (_selectedRemote == null)
159-
{
160-
Models.Remote remote = null;
161-
if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote))
162-
remote = repo.Remotes.Find(x => x.Name == _repo.Settings.DefaultRemote);
163-
164-
_selectedRemote = remote ?? repo.Remotes[0];
165-
}
166-
167-
// Auto select preferred remote branch.
168-
AutoSelectBranchByRemote();
169143
}
170144

171145
public void PushToNewBranch(string name)
@@ -230,7 +204,74 @@ public override void Terminate()
230204
var _ = _cancellation?.CancelAsync();
231205
}
232206

233-
private void AutoSelectBranchByRemote()
207+
private void PostLocalBranchChanged()
208+
{
209+
if (_selectedLocalBranch == null)
210+
return;
211+
212+
var remotes = new List<Models.Remote>();
213+
remotes.AddRange(_repo.Remotes);
214+
215+
// Respect the `branch.<name>.pushRemote` settings.
216+
var pushRemote = new Commands.Config(_repo.FullPath).Get($"branch.\"{_selectedLocalBranch.Name}\".pushRemote");
217+
if (!string.IsNullOrEmpty(pushRemote))
218+
{
219+
var remote = remotes.Find(x => x.URL.Equals(pushRemote, StringComparison.Ordinal));
220+
if (remote == null)
221+
{
222+
var extra = new Models.Remote() { Name = pushRemote };
223+
remotes.Add(extra);
224+
225+
Remotes = remotes;
226+
ForceUpdateSelectedRemote(extra);
227+
}
228+
else
229+
{
230+
// Force to trigger `PostRemoteChanged` even if the remote is the same as before.
231+
Remotes = remotes;
232+
ForceUpdateSelectedRemote(remote);
233+
}
234+
235+
return;
236+
}
237+
238+
// Update remotes list.
239+
Remotes = remotes;
240+
241+
// Try to select remote by upstream branch.
242+
var upstream = _selectedLocalBranch.Upstream;
243+
if (!string.IsNullOrEmpty(upstream) && !_selectedLocalBranch.IsUpstreamGone)
244+
{
245+
foreach (var branch in _repo.Branches)
246+
{
247+
if (!branch.IsLocal && upstream.Equals(branch.FullName, StringComparison.Ordinal))
248+
{
249+
ForceUpdateSelectedRemote(Remotes.Find(x => x.Name == branch.Remote));
250+
return;
251+
}
252+
}
253+
}
254+
255+
// Fallback to select the first remote.
256+
if (Remotes.Count > 0)
257+
{
258+
Models.Remote fallback = null;
259+
if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote))
260+
fallback = Remotes.Find(x => x.Name.Equals(_repo.Settings.DefaultRemote, StringComparison.Ordinal));
261+
262+
ForceUpdateSelectedRemote(fallback ?? Remotes[0]);
263+
}
264+
}
265+
266+
private void ForceUpdateSelectedRemote(Models.Remote remote)
267+
{
268+
var old = _selectedRemote;
269+
SelectedRemote = remote;
270+
if (remote == old)
271+
PostSelectedRemoteChanged();
272+
}
273+
274+
private void PostSelectedRemoteChanged()
234275
{
235276
if (_selectedRemote == null || _selectedLocalBranch == null)
236277
return;
@@ -243,6 +284,25 @@ private void AutoSelectBranchByRemote()
243284
branches.Add(branch);
244285
}
245286

287+
// Check `branch.<name>.merge` configuration if selected remote comes from an extra `branch.<name>.pushRemote`
288+
if (string.IsNullOrEmpty(_selectedRemote.URL))
289+
{
290+
var mergeTarget = new Commands.Config(_repo.FullPath).Get($"branch.\"{_selectedLocalBranch.Name}\".merge");
291+
if (!string.IsNullOrEmpty(mergeTarget))
292+
{
293+
var target = new Models.Branch()
294+
{
295+
Name = mergeTarget.StartsWith("refs/heads/") ? mergeTarget.Substring(11) : mergeTarget,
296+
Remote = _selectedRemote.Name,
297+
Head = "Unknown (but used in View)",
298+
};
299+
branches.Add(target);
300+
RemoteBranches = branches;
301+
SelectedRemoteBranch = target;
302+
return;
303+
}
304+
}
305+
246306
// If selected local branch has upstream. Try to find it in current remote branches.
247307
if (!string.IsNullOrEmpty(_selectedLocalBranch.Upstream))
248308
{
@@ -280,6 +340,7 @@ private void AutoSelectBranchByRemote()
280340
}
281341

282342
private readonly Repository _repo = null;
343+
private List<Models.Remote> _remotes = null;
283344
private Models.Branch _selectedLocalBranch = null;
284345
private Models.Remote _selectedRemote = null;
285346
private List<Models.Branch> _remoteBranches = [];

src/Views/Push.axaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
Text="{DynamicResource Text.Push.Title}"/>
2020
</StackPanel>
2121

22-
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,Auto,32,32,32" ColumnDefinitions="130,*">
22+
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,Auto,Auto,32,32" ColumnDefinitions="130,*">
2323
<TextBlock Grid.Row="0" Grid.Column="0"
2424
HorizontalAlignment="Right" VerticalAlignment="Center"
2525
Margin="0,0,8,0"
@@ -88,6 +88,7 @@
8888
<CheckBox Grid.Row="5" Grid.Column="1"
8989
Content="{DynamicResource Text.Push.WithAllTags}"
9090
IsChecked="{Binding PushAllTags, Mode=TwoWay}"
91+
IsVisible="{Binding !HasSpecifiedLocalBranch}"
9192
ToolTip.Tip="--tags"/>
9293

9394
<CheckBox Grid.Row="6" Grid.Column="1"

0 commit comments

Comments
 (0)