mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-27 11:36:48 +03:00
Assure we can use different merge bases when showing branch details.
Alternatively, correct the assumption that there is a difference.
This commit is contained in:
parent
07dc9efe02
commit
7362bab7aa
@ -314,11 +314,12 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to update the target branch
|
/// try to update the target branch
|
||||||
// this means that we need to:
|
/// this means that we need to:
|
||||||
// determine if what the target branch is now pointing to is mergeable with our current working directory
|
/// - determine if what the target branch is now pointing to is mergeable with our current working directory,
|
||||||
// merge the target branch into our current working directory
|
/// - merge the target branch into our current working directory
|
||||||
// update the target sha
|
/// - update the target sha
|
||||||
|
/// - return all conflicting references that were unapplied to avoid the conflict
|
||||||
pub(crate) fn update_base_branch(
|
pub(crate) fn update_base_branch(
|
||||||
ctx: &CommandContext,
|
ctx: &CommandContext,
|
||||||
perm: &mut WorktreeWritePermission,
|
perm: &mut WorktreeWritePermission,
|
||||||
|
@ -428,7 +428,7 @@ pub fn get_branch_listing_details(
|
|||||||
let repo = ctx.repository();
|
let repo = ctx.repository();
|
||||||
let branches = list_branches(ctx, None, Some(branch_names))?;
|
let branches = list_branches(ctx, None, Some(branch_names))?;
|
||||||
|
|
||||||
let (default_target_upstream_commit_id, default_target_merge_base) = {
|
let (default_target_current_upstream_commit_id, default_target_seen_at_last_update) = {
|
||||||
let target = ctx
|
let target = ctx
|
||||||
.project()
|
.project()
|
||||||
.virtual_branches()
|
.virtual_branches()
|
||||||
@ -446,12 +446,12 @@ pub fn get_branch_listing_details(
|
|||||||
for branch in branches {
|
for branch in branches {
|
||||||
let other_branch_commit_id = if let Some(virtual_branch) = branch.virtual_branch {
|
let other_branch_commit_id = if let Some(virtual_branch) = branch.virtual_branch {
|
||||||
if virtual_branch.in_workspace {
|
if virtual_branch.in_workspace {
|
||||||
default_target_merge_base
|
default_target_seen_at_last_update
|
||||||
} else {
|
} else {
|
||||||
default_target_upstream_commit_id
|
default_target_current_upstream_commit_id
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
default_target_upstream_commit_id
|
default_target_current_upstream_commit_id
|
||||||
};
|
};
|
||||||
let Ok(base) = repo.merge_base(other_branch_commit_id, branch.head) else {
|
let Ok(base) = repo.merge_base(other_branch_commit_id, branch.head) else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -49,4 +49,7 @@ git clone remote complex-repo
|
|||||||
echo non-virtual-feature >> file
|
echo non-virtual-feature >> file
|
||||||
git commit -am "non-virtual-feat-$round"
|
git commit -am "non-virtual-feat-$round"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# pretend the remote is at the same state as our local `main`
|
||||||
|
git update-ref refs/remotes/origin/main main
|
||||||
)
|
)
|
||||||
|
@ -52,12 +52,13 @@ fn many_commits_in_all_branch_types() -> anyhow::Result<()> {
|
|||||||
list[0],
|
list[0],
|
||||||
BranchListingDetails {
|
BranchListingDetails {
|
||||||
name: "feature".into(),
|
name: "feature".into(),
|
||||||
lines_added: 100 + 5,
|
lines_added: 100,
|
||||||
lines_removed: 0,
|
lines_removed: 0,
|
||||||
number_of_files: 1,
|
number_of_files: 1,
|
||||||
number_of_commits: 100 + 5, /* local tracking branch is merge base */
|
number_of_commits: 100,
|
||||||
authors: vec![default_author()],
|
authors: vec![default_author()],
|
||||||
}
|
},
|
||||||
|
"local branches use the *current* local tracking branch…"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
list[1],
|
list[1],
|
||||||
@ -66,21 +67,24 @@ fn many_commits_in_all_branch_types() -> anyhow::Result<()> {
|
|||||||
lines_added: 15,
|
lines_added: 15,
|
||||||
lines_removed: 0,
|
lines_removed: 0,
|
||||||
number_of_files: 1,
|
number_of_files: 1,
|
||||||
// TODO(ST): why is it also going against the local tracking branch instead of the local `main`?
|
|
||||||
number_of_commits: 10 + 5,
|
number_of_commits: 10 + 5,
|
||||||
authors: vec![default_author()],
|
authors: vec![default_author()],
|
||||||
}
|
},
|
||||||
|
"…while virtual branches use the 'target' stored when the workspace was last updated.\
|
||||||
|
That way the 'update' of the workspace performs the calculation to put it back on top of \
|
||||||
|
the local tracking branch."
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
list[2],
|
list[2],
|
||||||
BranchListingDetails {
|
BranchListingDetails {
|
||||||
name: "non-virtual-feature".into(),
|
name: "non-virtual-feature".into(),
|
||||||
lines_added: 55,
|
lines_added: 50,
|
||||||
lines_removed: 0,
|
lines_removed: 0,
|
||||||
number_of_files: 1,
|
number_of_files: 1,
|
||||||
number_of_commits: 50 + 5,
|
number_of_commits: 50,
|
||||||
authors: vec![default_author()],
|
authors: vec![default_author()],
|
||||||
}
|
},
|
||||||
|
"This is a non-virtual brnach, so it sees the local tracking branch as well"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,19 @@ use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializ
|
|||||||
pub struct Target {
|
pub struct Target {
|
||||||
/// The combination of remote name and branch name, i.e. `origin` and `main`.
|
/// The combination of remote name and branch name, i.e. `origin` and `main`.
|
||||||
/// The remote name is the one used to fetch from.
|
/// The remote name is the one used to fetch from.
|
||||||
|
/// It's equivalent to e.g. `refs/remotes/origin/main` , and the type `RemoteRefName`
|
||||||
|
/// stores it as `<remote>` and `<suffix>` so that finding references named `<remote>/<suffix>`
|
||||||
|
/// will typically find the local tracking branch unambiguously.
|
||||||
pub branch: RemoteRefname,
|
pub branch: RemoteRefname,
|
||||||
/// The URL of the remote behind the symbolic name.
|
/// The URL of the remote behind the symbolic name.
|
||||||
pub remote_url: String,
|
pub remote_url: String,
|
||||||
/// The merge-base between `branch` and the current worktree `HEAD`.
|
/// The merge-base between `branch` and the current worktree `HEAD` upon first creation,
|
||||||
// TODO(ST): is it safe/correct to rename this to `merge_base_commit_id`?
|
/// but then it's the set to the new destination of e.g. `refs/remotes/origin/main` after
|
||||||
// It seems like it, but why was it named just `sha` in the first place?
|
/// the remote was fetched. This value is used to determine if there was a change,
|
||||||
|
/// and if the *workspace* needs to be recalculated/rebased against the new commit.
|
||||||
|
// TODO(ST): is it safe/correct to rename this to `branch_target_id`? Should be!
|
||||||
|
// It's just a bit strange it starts life as merge-base, but maybe it ends
|
||||||
|
// up the same anyway? Definitely could use a test then.
|
||||||
pub sha: git2::Oid,
|
pub sha: git2::Oid,
|
||||||
/// The name of the remote to push to.
|
/// The name of the remote to push to.
|
||||||
pub push_remote_name: Option<String>,
|
pub push_remote_name: Option<String>,
|
||||||
|
@ -71,6 +71,8 @@ pub mod vbranch {
|
|||||||
},
|
},
|
||||||
/// List all branches that can be relevant.
|
/// List all branches that can be relevant.
|
||||||
ListAll,
|
ListAll,
|
||||||
|
/// After fetching the target (i.e. local tracking branch), recompute our workspace against it.
|
||||||
|
UpdateTarget,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,11 @@ use gitbutler_project::Project;
|
|||||||
|
|
||||||
use crate::command::debug_print;
|
use crate::command::debug_print;
|
||||||
|
|
||||||
|
pub fn update_target(project: Project) -> Result<()> {
|
||||||
|
let unapplied = VirtualBranchActions.update_base_branch(&project)?;
|
||||||
|
debug_print(unapplied)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn list_all(project: Project) -> Result<()> {
|
pub fn list_all(project: Project) -> Result<()> {
|
||||||
let ctx = CommandContext::open(&project)?;
|
let ctx = CommandContext::open(&project)?;
|
||||||
debug_print(list_branches(&ctx, None, None)?)
|
debug_print(list_branches(&ctx, None, None)?)
|
||||||
|
@ -36,6 +36,9 @@ fn main() -> Result<()> {
|
|||||||
command::vbranch::details(project, names)
|
command::vbranch::details(project, names)
|
||||||
}
|
}
|
||||||
Some(vbranch::SubCommands::ListAll) => command::vbranch::list_all(project),
|
Some(vbranch::SubCommands::ListAll) => command::vbranch::list_all(project),
|
||||||
|
Some(vbranch::SubCommands::UpdateTarget) => {
|
||||||
|
command::vbranch::update_target(project)
|
||||||
|
}
|
||||||
None => command::vbranch::list(project),
|
None => command::vbranch::list(project),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user