forked from mirrors/jj
cli: make jj git push
push all branches by default
It's annoying to have to add `--branch main` every time I push to GitHub. Maybe we should make it push only the current branch by default, but we don't even have a concept of a current branch yet...
This commit is contained in:
parent
0bc42c0066
commit
cea3c1537a
2 changed files with 105 additions and 75 deletions
|
@ -108,12 +108,15 @@ fn find_pair_to_remove(
|
|||
None
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct BranchPushUpdate {
|
||||
pub old_target: Option<CommitId>,
|
||||
pub new_target: Option<CommitId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum BranchPushAction {
|
||||
Update {
|
||||
old_target: Option<CommitId>,
|
||||
new_target: Option<CommitId>,
|
||||
},
|
||||
Update(BranchPushUpdate),
|
||||
AlreadyMatches,
|
||||
LocalConflicted,
|
||||
RemoteConflicted,
|
||||
|
@ -134,19 +137,19 @@ pub fn classify_branch_push_action(
|
|||
(_, Some(RefTarget::Conflict { .. })) => BranchPushAction::LocalConflicted,
|
||||
(Some(RefTarget::Conflict { .. }), _) => BranchPushAction::RemoteConflicted,
|
||||
(Some(RefTarget::Normal(old_target)), Some(RefTarget::Normal(new_target))) => {
|
||||
BranchPushAction::Update {
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: Some(old_target.clone()),
|
||||
new_target: Some(new_target.clone()),
|
||||
})
|
||||
}
|
||||
}
|
||||
(Some(RefTarget::Normal(old_target)), None) => BranchPushAction::Update {
|
||||
(Some(RefTarget::Normal(old_target)), None) => BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: Some(old_target.clone()),
|
||||
new_target: None,
|
||||
},
|
||||
(None, Some(RefTarget::Normal(new_target))) => BranchPushAction::Update {
|
||||
}),
|
||||
(None, Some(RefTarget::Normal(new_target))) => BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: None,
|
||||
new_target: Some(new_target.clone()),
|
||||
},
|
||||
}),
|
||||
(None, None) => {
|
||||
panic!("Unexpected branch doesn't exist anywhere")
|
||||
}
|
||||
|
@ -183,10 +186,10 @@ mod tests {
|
|||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(&branch, "origin"),
|
||||
BranchPushAction::Update {
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: None,
|
||||
new_target: Some(commit_id1),
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -201,10 +204,10 @@ mod tests {
|
|||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(&branch, "origin"),
|
||||
BranchPushAction::Update {
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: Some(commit_id1),
|
||||
new_target: None,
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -220,10 +223,10 @@ mod tests {
|
|||
};
|
||||
assert_eq!(
|
||||
classify_branch_push_action(&branch, "origin"),
|
||||
BranchPushAction::Update {
|
||||
BranchPushAction::Update(BranchPushUpdate {
|
||||
old_target: Some(commit_id1),
|
||||
new_target: Some(commit_id2),
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1260,13 +1260,17 @@ https://github.com/martinvonz/jj/blob/main/docs/git-comparison.md.\
|
|||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("push")
|
||||
.about("Push a branch to a Git remote")
|
||||
.about("Push to a Git remote")
|
||||
.long_about(
|
||||
"Push to a Git remote
|
||||
|
||||
By default, all branches are pushed. Use `--branch` if you want to push only one branch.",
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("branch")
|
||||
.long("branch")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.help("The name of the branch to push"),
|
||||
.help("Push only this branch"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("remote")
|
||||
|
@ -3296,9 +3300,10 @@ fn cmd_git_push(
|
|||
) -> Result<(), CommandError> {
|
||||
let repo_command = command.repo_helper(ui)?;
|
||||
let repo = repo_command.repo();
|
||||
let branch_name = cmd_matches.value_of("branch").unwrap();
|
||||
let remote_name = cmd_matches.value_of("remote").unwrap();
|
||||
|
||||
let mut branch_updates = HashMap::new();
|
||||
if let Some(branch_name) = cmd_matches.value_of("branch") {
|
||||
let maybe_branch_target = repo.view().get_branch(branch_name);
|
||||
if maybe_branch_target.is_none() {
|
||||
return Err(CommandError::UserError(format!(
|
||||
|
@ -3309,7 +3314,6 @@ fn cmd_git_push(
|
|||
let branch_target = maybe_branch_target.unwrap();
|
||||
let push_action = classify_branch_push_action(branch_target, remote_name);
|
||||
|
||||
let mut ref_updates = vec![];
|
||||
match push_action {
|
||||
BranchPushAction::AlreadyMatches => {
|
||||
writeln!(
|
||||
|
@ -3331,19 +3335,43 @@ fn cmd_git_push(
|
|||
branch_name, remote_name
|
||||
)));
|
||||
}
|
||||
BranchPushAction::Update {
|
||||
old_target,
|
||||
new_target,
|
||||
} => {
|
||||
let qualified_name = format!("refs/heads/{}", branch_name);
|
||||
if let Some(new_target) = new_target {
|
||||
let new_target_commit = repo.store().get_commit(&new_target)?;
|
||||
BranchPushAction::Update(update) => {
|
||||
if let Some(new_target) = &update.new_target {
|
||||
let new_target_commit = repo.store().get_commit(new_target)?;
|
||||
if new_target_commit.is_open() {
|
||||
return Err(CommandError::UserError(
|
||||
"Won't push open commit".to_string(),
|
||||
));
|
||||
}
|
||||
let force = match old_target {
|
||||
}
|
||||
branch_updates.insert(branch_name, update);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: Is it useful to warn about conflicted branches?
|
||||
for (branch_name, branch_target) in repo.view().branches() {
|
||||
let push_action = classify_branch_push_action(branch_target, remote_name);
|
||||
match push_action {
|
||||
BranchPushAction::AlreadyMatches => {}
|
||||
BranchPushAction::LocalConflicted => {}
|
||||
BranchPushAction::RemoteConflicted => {}
|
||||
BranchPushAction::Update(update) => {
|
||||
branch_updates.insert(branch_name, update);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if branch_updates.is_empty() {
|
||||
writeln!(ui, "Nothing changed.")?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut ref_updates = vec![];
|
||||
for (branch_name, update) in branch_updates {
|
||||
let qualified_name = format!("refs/heads/{}", branch_name);
|
||||
if let Some(new_target) = update.new_target {
|
||||
let force = match update.old_target {
|
||||
None => false,
|
||||
Some(old_target) => !repo.index().is_ancestor(&old_target, &new_target),
|
||||
};
|
||||
|
@ -3360,7 +3388,6 @@ fn cmd_git_push(
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let git_repo = get_git_repo(repo.store())?;
|
||||
git::push_updates(&git_repo, remote_name, &ref_updates)
|
||||
|
|
Loading…
Reference in a new issue