@@ -51,6 +51,65 @@ pub fn get_default_remote(repo_path: &RepoPath) -> Result<String> {
51
51
get_default_remote_in_repo ( & repo)
52
52
}
53
53
54
+ /// Gets the current branch the user is on.
55
+ /// Returns none if they are not on a branch
56
+ /// and Err if there was a problem finding the branch
57
+ fn get_current_branch (
58
+ repo : & Repository ,
59
+ ) -> Result < Option < git2:: Branch > > {
60
+ for b in repo. branches ( None ) ? {
61
+ let branch = b?. 0 ;
62
+ if branch. is_head ( ) {
63
+ return Ok ( Some ( branch) ) ;
64
+ }
65
+ }
66
+ Ok ( None )
67
+ }
68
+
69
+ /// Tries to find the default repo to push to based on configuration.
70
+ ///
71
+ /// > remote.pushDefault
72
+ /// >
73
+ /// > The remote to push to by default. Overrides branch.<name>.remote for all branches, and is
74
+ /// > overridden by branch.<name>.pushRemote for specific branches.
75
+ ///
76
+ /// [git-config-remote-push-default]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-remotepushDefault
77
+ ///
78
+ /// Falls back to `get_default_remote_in_repo`.
79
+ pub fn get_default_remote_for_push (
80
+ repo_path : & RepoPath ,
81
+ ) -> Result < String > {
82
+ let repo = repo ( repo_path) ?;
83
+ get_default_remote_for_push_in_repo ( & repo)
84
+ }
85
+
86
+ pub ( crate ) fn get_default_remote_for_push_in_repo (
87
+ repo : & Repository ,
88
+ ) -> Result < String > {
89
+ scope_time ! ( "get_default_remote_for_push_in_repo" ) ;
90
+
91
+ let config = repo. config ( ) ?;
92
+
93
+ let branch = get_current_branch ( repo) ?;
94
+
95
+ if let Some ( branch) = branch {
96
+ let remote_name = bytes2string ( branch. name_bytes ( ) ?) ?;
97
+
98
+ let entry_name =
99
+ format ! ( "branch.{}.pushRemote" , & remote_name) ;
100
+
101
+ if let Ok ( entry) = config. get_entry ( & entry_name) {
102
+ return bytes2string ( entry. value_bytes ( ) ) ;
103
+ }
104
+
105
+ if let Ok ( entry) = config. get_entry ( "remote.pushDefault" ) {
106
+ return bytes2string ( entry. value_bytes ( ) ) ;
107
+ }
108
+ }
109
+
110
+ get_default_remote_in_repo ( repo)
111
+ }
112
+
54
113
/// see `get_default_remote`
55
114
pub ( crate ) fn get_default_remote_in_repo (
56
115
repo : & Repository ,
@@ -272,7 +331,7 @@ mod tests {
272
331
fn test_default_remote_inconclusive ( ) {
273
332
let ( remote_dir, _remote) = repo_init ( ) . unwrap ( ) ;
274
333
let remote_path = remote_dir. path ( ) . to_str ( ) . unwrap ( ) ;
275
- let ( repo_dir, _repo ) = repo_clone ( remote_path) . unwrap ( ) ;
334
+ let ( repo_dir, repo ) = repo_clone ( remote_path) . unwrap ( ) ;
276
335
let repo_path: & RepoPath = & repo_dir
277
336
. into_path ( )
278
337
. as_os_str ( )
@@ -299,9 +358,39 @@ mod tests {
299
358
]
300
359
) ;
301
360
302
- let res =
303
- get_default_remote_in_repo ( & repo ( repo_path) . unwrap ( ) ) ;
304
- assert_eq ! ( res. is_err( ) , true ) ;
305
- assert ! ( matches!( res, Err ( Error :: NoDefaultRemoteFound ) ) ) ;
361
+ let default_push_remote =
362
+ get_default_remote_for_push_in_repo ( & repo) ;
363
+
364
+ assert ! ( matches!(
365
+ default_push_remote,
366
+ Err ( Error :: NoDefaultRemoteFound )
367
+ ) ) ;
368
+
369
+ let mut config = repo. config ( ) . unwrap ( ) ;
370
+
371
+ config
372
+ . set_str ( "remote.pushDefault" , "defaultreporemote" )
373
+ . unwrap ( ) ;
374
+
375
+ let default_push_remote =
376
+ get_default_remote_for_push_in_repo ( & repo) ;
377
+
378
+ assert ! (
379
+ matches!( default_push_remote, Ok ( remote_name) if remote_name == "defaultreporemote" )
380
+ ) ;
381
+
382
+ config
383
+ . set_str (
384
+ "branch.master.pushRemote" ,
385
+ "defaultbranchremote" ,
386
+ )
387
+ . unwrap ( ) ;
388
+
389
+ let default_push_remote =
390
+ get_default_remote_for_push_in_repo ( & repo) ;
391
+
392
+ assert ! (
393
+ matches!( default_push_remote, Ok ( remote_name) if remote_name == "defaultbranchremote" )
394
+ ) ;
306
395
}
307
396
}
0 commit comments