Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 259c734

Browse files
committedMar 18, 2025··
push: respect branch.*.merge when push default is upstream
1 parent 5f09a46 commit 259c734

File tree

6 files changed

+80
-7
lines changed

6 files changed

+80
-7
lines changed
 

‎CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
* After commit: jump back to unstaged area [[@tommady](https://github.com/tommady)] ([#2476](https://github.com/extrawurst/gitui/issues/2476))
1818
* The default key to close the commit error message popup is now the Escape key [[@wessamfathi](https://github.com/wessamfathi)] ([#2552](https://github.com/extrawurst/gitui/issues/2552))
1919
* use OSC52 copying in case other methods fail [[@naseschwarz](https://github.com/naseschwarz)] ([#2366](https://github.com/gitui-org/gitui/issues/2366))
20+
* push: respect `branch.*.merge` when push default is upstream [[@vlad-anger](https://github.com/vlad-anger)] ([#2542](https://github.com/gitui-org/gitui/pull/2542))
2021

2122
## [0.27.0] - 2024-01-14
2223

‎asyncgit/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ pub enum Error {
5353
#[error("git error:{0}")]
5454
Git(#[from] git2::Error),
5555

56+
///
57+
#[error("git config error: {0}")]
58+
GitConfig(String),
59+
5660
///
5761
#[error("strip prefix error: {0}")]
5862
StripPrefix(#[from] StripPrefixError),

‎asyncgit/src/sync/branch/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ pub fn get_branch_remote(
245245

246246
/// Retrieve the upstream merge of a local `branch`,
247247
/// configured in "branch.*.merge"
248-
///
248+
///
249249
/// For details check git2 `branch_upstream_merge`
250250
pub fn get_branch_upstream_merge(
251251
repo_path: &RepoPath,

‎asyncgit/src/sync/config.rs

+46
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,52 @@ pub fn untracked_files_config_repo(
6262
Ok(ShowUntrackedFilesConfig::All)
6363
}
6464

65+
// see https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault
66+
/// represents `push.default` git config
67+
#[derive(PartialEq, Eq)]
68+
pub enum PushDefaultStrategyConfig {
69+
Nothing,
70+
Current,
71+
Upstream,
72+
Simple,
73+
Matching,
74+
}
75+
76+
impl Default for PushDefaultStrategyConfig {
77+
fn default() -> Self {
78+
Self::Simple
79+
}
80+
}
81+
82+
impl<'a> TryFrom<&'a str> for PushDefaultStrategyConfig {
83+
type Error = crate::Error;
84+
fn try_from(
85+
value: &'a str,
86+
) -> std::result::Result<Self, Self::Error> {
87+
match value {
88+
"nothing" => Ok(Self::Nothing),
89+
"current" => Ok(Self::Current),
90+
"upstream" | "tracking" => Ok(Self::Upstream),
91+
"simple" => Ok(Self::Simple),
92+
"matching" => Ok(Self::Matching),
93+
_ => Err(crate::Error::GitConfig(format!(
94+
"malformed value for push.default: {value}, must be one of nothing, matching, simple, upstream or current"
95+
))),
96+
}
97+
}
98+
}
99+
100+
pub fn push_default_strategy_config_repo(
101+
repo: &Repository,
102+
) -> Result<PushDefaultStrategyConfig> {
103+
(get_config_string_repo(repo, "push.default")?).map_or_else(
104+
|| Ok(PushDefaultStrategyConfig::default()),
105+
|entry_str| {
106+
PushDefaultStrategyConfig::try_from(entry_str.as_str())
107+
},
108+
)
109+
}
110+
65111
///
66112
pub fn untracked_files_config(
67113
repo_path: &RepoPath,

‎asyncgit/src/sync/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub use blame::{blame_file, BlameHunk, FileBlame};
3939
pub use branch::{
4040
branch_compare_upstream, checkout_branch, checkout_commit,
4141
config_is_pull_rebase, create_branch, delete_branch,
42-
get_branch_remote, get_branches_info, get_branch_upstream_merge,
42+
get_branch_remote, get_branch_upstream_merge, get_branches_info,
4343
merge_commit::merge_upstream_commit,
4444
merge_ff::branch_merge_upstream_fastforward,
4545
merge_rebase::merge_upstream_rebase, rename::rename_branch,

‎asyncgit/src/sync/remotes/push.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ use crate::{
33
progress::ProgressPercent,
44
sync::{
55
branch::branch_set_upstream_after_push,
6+
config::{
7+
push_default_strategy_config_repo,
8+
PushDefaultStrategyConfig,
9+
},
610
cred::BasicAuthCredential,
11+
get_branch_upstream_merge,
712
remotes::{proxy_auto, Callbacks},
813
repository::repo,
914
CommitId, RepoPath,
@@ -92,7 +97,7 @@ impl AsyncProgress for ProgressNotification {
9297
}
9398

9499
///
95-
#[derive(Copy, Clone, Debug)]
100+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
96101
pub enum PushType {
97102
///
98103
Branch,
@@ -145,6 +150,9 @@ pub fn push_raw(
145150
let repo = repo(repo_path)?;
146151
let mut remote = repo.find_remote(remote)?;
147152

153+
let push_default_strategy =
154+
push_default_strategy_config_repo(&repo)?;
155+
148156
let mut options = PushOptions::new();
149157
options.proxy_options(proxy_auto());
150158

@@ -158,14 +166,28 @@ pub fn push_raw(
158166
(true, false) => "+",
159167
(false, false) => "",
160168
};
161-
let ref_type = match ref_type {
169+
let git_ref_type = match ref_type {
162170
PushType::Branch => "heads",
163171
PushType::Tag => "tags",
164172
};
165173

166-
let branch_name =
167-
format!("{branch_modifier}refs/{ref_type}/{branch}");
168-
remote.push(&[branch_name.as_str()], Some(&mut options))?;
174+
let mut push_ref =
175+
format!("{branch_modifier}refs/{git_ref_type}/{branch}");
176+
177+
if !delete
178+
&& ref_type == PushType::Branch
179+
&& push_default_strategy
180+
== PushDefaultStrategyConfig::Upstream
181+
{
182+
if let Ok(Some(branch_upstream_merge)) =
183+
get_branch_upstream_merge(repo_path, branch)
184+
{
185+
push_ref.push_str(&format!(":{branch_upstream_merge}"));
186+
}
187+
}
188+
189+
log::debug!("push to: {push_ref}");
190+
remote.push(&[push_ref], Some(&mut options))?;
169191

170192
if let Some((reference, msg)) =
171193
callbacks.get_stats()?.push_rejected_msg

0 commit comments

Comments
 (0)
Please sign in to comment.