ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: search @- for branches to push when @ has none

This commit is contained in:
Benjamin Saunders 2022-10-20 14:18:34 -07:00
parent b009019d8d
commit 305cb3a7ee
3 changed files with 59 additions and 15 deletions

View file

@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* The new `jj git remote rename` command allows git remotes to be renamed
in-place.
* `jj git push` will search `@-` for branches to push if `@` has none.
## [0.5.1] - 2022-10-17
No changes (just trying to get automated GitHub release to work).

View file

@ -33,7 +33,7 @@ use jujutsu_lib::files::DiffLine;
use jujutsu_lib::git::{GitFetchError, GitRefUpdate};
use jujutsu_lib::index::IndexEntry;
use jujutsu_lib::matchers::{EverythingMatcher, Matcher};
use jujutsu_lib::op_store::{RefTarget, WorkspaceId};
use jujutsu_lib::op_store::{BranchTarget, RefTarget, WorkspaceId};
use jujutsu_lib::operation::Operation;
use jujutsu_lib::refs::{classify_branch_push_action, BranchPushAction, BranchPushUpdate};
use jujutsu_lib::repo::{ReadonlyRepo, RepoRef};
@ -899,9 +899,10 @@ struct GitCloneArgs {
/// Push to a Git remote
///
/// By default, pushes any branches pointing to `@`. Use `--branch` to push a
/// specific branch. Use `--all` to push all branches. Use `--change` to
/// generate a branch name based on a specific commit's change ID.
/// By default, pushes any branches pointing to `@`, or `@-` if no branches
/// point to `@`. Use `--branch` to push a specific branch. Use `--all` to push
/// all branches. Use `--change` to generate a branch name based on a specific
/// commit's change ID.
#[derive(clap::Args, Clone, Debug)]
#[command(group(ArgGroup::new("what").args(&["branch", "all", "change"])))]
struct GitPushArgs {
@ -4239,17 +4240,41 @@ fn cmd_git_push(
));
}
Some(checkout) => {
let desired_target = Some(RefTarget::Normal(checkout.clone()));
for (branch_name, branch_target) in workspace_command.repo().view().branches() {
if branch_target.local_target == desired_target {
let push_action = classify_branch_push_action(branch_target, &args.remote);
match push_action {
BranchPushAction::AlreadyMatches => {}
BranchPushAction::LocalConflicted => {}
BranchPushAction::RemoteConflicted => {}
BranchPushAction::Update(update) => {
branch_updates.push((branch_name.clone(), update));
}
fn find_branches_targeting<'a>(
view: &'a View,
target: &RefTarget,
) -> Vec<(&'a String, &'a BranchTarget)> {
view.branches()
.iter()
.filter(|(_, branch_target)| {
branch_target.local_target.as_ref() == Some(target)
})
.collect()
}
// Search for branches targeting @
let mut branches = find_branches_targeting(
workspace_command.repo().view(),
&RefTarget::Normal(checkout.clone()),
);
if branches.is_empty() {
// Try @- instead if it has exactly one parent, such as after `jj squash`
let commit = workspace_command.repo().store().get_commit(checkout)?;
if let [parent] = commit.parent_ids() {
branches = find_branches_targeting(
workspace_command.repo().view(),
&RefTarget::Normal(parent.clone()),
);
}
}
for (branch_name, branch_target) in branches {
let push_action = classify_branch_push_action(branch_target, &args.remote);
match push_action {
BranchPushAction::AlreadyMatches => {}
BranchPushAction::LocalConflicted => {}
BranchPushAction::RemoteConflicted => {}
BranchPushAction::Update(update) => {
branch_updates.push((branch_name.clone(), update));
}
}
}

View file

@ -115,6 +115,23 @@ fn test_git_push_current_branch() {
"###);
}
#[test]
fn test_git_push_parent_branch() {
let (test_env, workspace_root) = set_up();
test_env.jj_cmd_success(&workspace_root, &["edit", "branch1"]);
test_env.jj_cmd_success(
&workspace_root,
&["describe", "-m", "modified branch1 commit"],
);
test_env.jj_cmd_success(&workspace_root, &["new"]);
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--dry-run"]);
insta::assert_snapshot!(stdout, @r###"
Branch changes to push to origin:
Force branch branch1 from a3ccc578ea7b to ad7201b22c46
Dry-run requested, not pushing.
"###);
}
#[test]
fn test_git_push_no_current_branch() {
let (test_env, workspace_root) = set_up();