@@ -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 = [ ] ;
0 commit comments