mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-18 14:31:30 +03:00
Merge pull request #5071 from gitbutlerapp/Add-extra-info-on-patch-series-remote_commit_id
Add an extra field `remote_commit_id` on the API type `VirtualBranchCommit`
This commit is contained in:
commit
f2d2a7ae14
@ -188,6 +188,19 @@ export class DetailedCommit {
|
||||
// author, commit and message.
|
||||
copiedFromRemoteId?: string;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents the remote commit id of this patch.
|
||||
* This field is set if:
|
||||
* - The commit has been pushed
|
||||
* - The commit has been copied from a remote commit (when applying a remote branch)
|
||||
*
|
||||
* The `remoteCommitId` may be the same as the `id` or it may be different if the commit has been rebased or updated.
|
||||
*
|
||||
* Note: This makes both the `isRemote` and `copiedFromRemoteId` fields redundant, but they are kept for compatibility.
|
||||
*/
|
||||
remoteCommitId?: string;
|
||||
|
||||
prev?: DetailedCommit;
|
||||
next?: DetailedCommit;
|
||||
|
||||
|
@ -25,6 +25,7 @@ pub struct VirtualBranchCommit {
|
||||
pub description: BStringForFrontend,
|
||||
pub created_at: u128,
|
||||
pub author: Author,
|
||||
/// Dont use, favor `remote_commit_id` instead
|
||||
pub is_remote: bool,
|
||||
pub files: Vec<VirtualBranchFile>,
|
||||
pub is_integrated: bool,
|
||||
@ -39,6 +40,16 @@ pub struct VirtualBranchCommit {
|
||||
/// This is used by the frontend similar to the `change_id` to group matching commits.
|
||||
#[serde(with = "gitbutler_serde::oid_opt")]
|
||||
pub copied_from_remote_id: Option<git2::Oid>,
|
||||
/// Represents the remote commit id of this patch.
|
||||
/// This field is set if:
|
||||
/// - The commit has been pushed
|
||||
/// - The commit has been copied from a remote commit (when applying a remote branch)
|
||||
///
|
||||
/// The `remote_commit_id` may be the same as the `id` or it may be different if the commit has been rebased or updated.
|
||||
///
|
||||
/// Note: This makes both the `is_remote` and `copied_from_remote_id` fields redundant, but they are kept for compatibility.
|
||||
#[serde(with = "gitbutler_serde::oid_opt")]
|
||||
pub remote_commit_id: Option<git2::Oid>,
|
||||
}
|
||||
|
||||
pub(crate) fn commit_to_vbranch_commit(
|
||||
@ -48,6 +59,7 @@ pub(crate) fn commit_to_vbranch_commit(
|
||||
is_integrated: bool,
|
||||
is_remote: bool,
|
||||
copied_from_remote_id: Option<git2::Oid>,
|
||||
remote_commit_id: Option<git2::Oid>,
|
||||
) -> Result<VirtualBranchCommit> {
|
||||
let timestamp = u128::try_from(commit.time().seconds())?;
|
||||
let message = commit.message_bstr().to_owned();
|
||||
@ -76,6 +88,7 @@ pub(crate) fn commit_to_vbranch_commit(
|
||||
is_signed: commit.is_signed(),
|
||||
conflicted: commit.is_conflicted(),
|
||||
copied_from_remote_id,
|
||||
remote_commit_id: remote_commit_id.or(copied_from_remote_id),
|
||||
};
|
||||
|
||||
Ok(commit)
|
||||
|
@ -380,6 +380,7 @@ pub fn list_virtual_branches_cached(
|
||||
is_integrated,
|
||||
is_remote,
|
||||
copied_from_remote_id,
|
||||
None, // remote_commit_id is only used inside PatchSeries
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
@ -420,7 +421,13 @@ pub fn list_virtual_branches_cached(
|
||||
let refname = branch.refname()?.into();
|
||||
|
||||
// TODO: Error out here once this API is stable
|
||||
let series = match stack_series(ctx, &branch, &default_target, &check_commit) {
|
||||
let series = match stack_series(
|
||||
ctx,
|
||||
&branch,
|
||||
&default_target,
|
||||
&check_commit,
|
||||
remote_commit_data,
|
||||
) {
|
||||
Ok(series) => series,
|
||||
Err(e) => {
|
||||
tracing::warn!("failed to compute stack series: {:?}", e);
|
||||
@ -472,6 +479,7 @@ fn stack_series(
|
||||
branch: &Stack,
|
||||
default_target: &Target,
|
||||
check_commit: &IsCommitIntegrated,
|
||||
remote_commit_data: HashMap<CommitData, git2::Oid>,
|
||||
) -> Result<Vec<PatchSeries>> {
|
||||
let mut api_series: Vec<PatchSeries> = vec![];
|
||||
let stack_series = branch.list_series(ctx)?;
|
||||
@ -487,13 +495,23 @@ fn stack_series(
|
||||
for patch in series.clone().local_commits {
|
||||
let commit = commit_by_oid_or_change_id(&patch, ctx, branch.head(), default_target)?;
|
||||
let is_integrated = check_commit.is_integrated(&commit)?;
|
||||
let copied_from_remote_id = CommitData::try_from(&commit)
|
||||
.ok()
|
||||
.and_then(|data| remote_commit_data.get(&data).copied());
|
||||
let remote_commit_id = commit.change_id().and_then(|change_id| {
|
||||
series
|
||||
.remote_commit_ids_by_change_id
|
||||
.get(&change_id)
|
||||
.cloned()
|
||||
});
|
||||
let vcommit = commit_to_vbranch_commit(
|
||||
ctx,
|
||||
branch,
|
||||
&commit,
|
||||
is_integrated,
|
||||
series.remote(&patch),
|
||||
None,
|
||||
copied_from_remote_id,
|
||||
remote_commit_id,
|
||||
)?;
|
||||
patches.push(vcommit);
|
||||
}
|
||||
@ -508,7 +526,8 @@ fn stack_series(
|
||||
&commit,
|
||||
is_integrated,
|
||||
true, // per definition
|
||||
None,
|
||||
None, // per definition
|
||||
Some(commit.id()),
|
||||
)?;
|
||||
upstream_patches.push(vcommit);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
use gitbutler_patch_reference::{CommitOrChangeId, PatchReference};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Series or (patch) Series is a set of patches (commits) that are dependent on each other.
|
||||
/// This is effectively a sub-branch within a (series) stack.
|
||||
/// The difference from a branch is that only the patches (commits) unique to the series are included.
|
||||
///
|
||||
/// The `pushed` status, as well as the `remote_reference` can be obtained from the methods on `head` (PatchReference).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Series {
|
||||
/// The GitButler-managed head reference for this series. It points to a commit ID or a change ID in the stack.
|
||||
/// This head may or may not be part of the commits that are in the series
|
||||
@ -19,6 +20,9 @@ pub struct Series {
|
||||
/// If the branch/series have never been pushed, this list will be empty.
|
||||
/// Topologically ordered, the first entry is the newest in the series.
|
||||
pub remote_commits: Vec<CommitOrChangeId>,
|
||||
/// The commit IDs of the remote commits that are part of this series, grouped by change id.
|
||||
/// Since we dont have a change_id to commit_id index, this is used to determine
|
||||
pub remote_commit_ids_by_change_id: HashMap<String, git2::Oid>,
|
||||
}
|
||||
|
||||
impl Series {
|
||||
|
@ -24,6 +24,7 @@ use crate::heads::add_head;
|
||||
use crate::heads::get_head;
|
||||
use crate::heads::remove_head;
|
||||
use crate::series::Series;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// A (series) Stack represents multiple "branches" that are dependent on each other in series.
|
||||
///
|
||||
@ -457,6 +458,7 @@ impl StackExt for Stack {
|
||||
.collect_vec();
|
||||
|
||||
let mut remote_patches: Vec<CommitOrChangeId> = vec![];
|
||||
let mut remote_commit_ids_by_change_id: HashMap<String, git2::Oid> = HashMap::new();
|
||||
if let Some(remote_name) = default_target.push_remote_name.as_ref() {
|
||||
if head.pushed(remote_name, ctx).unwrap_or_default() {
|
||||
let head_commit = repo
|
||||
@ -466,17 +468,24 @@ impl StackExt for Stack {
|
||||
repo.log(head_commit.id(), LogUntil::Commit(merge_base))?
|
||||
.iter()
|
||||
.rev()
|
||||
.map(|c| match c.change_id() {
|
||||
Some(change_id) => CommitOrChangeId::ChangeId(change_id.to_string()),
|
||||
.for_each(|c| {
|
||||
let commit_or_change_id = match c.change_id() {
|
||||
Some(change_id) => {
|
||||
remote_commit_ids_by_change_id
|
||||
.insert(change_id.to_string(), c.id());
|
||||
CommitOrChangeId::ChangeId(change_id.to_string())
|
||||
}
|
||||
None => CommitOrChangeId::CommitId(c.id().to_string()),
|
||||
})
|
||||
.for_each(|c| remote_patches.push(c));
|
||||
};
|
||||
remote_patches.push(commit_or_change_id);
|
||||
});
|
||||
}
|
||||
};
|
||||
all_series.push(Series {
|
||||
head: head.clone(),
|
||||
local_commits: local_patches,
|
||||
remote_commits: remote_patches,
|
||||
remote_commit_ids_by_change_id,
|
||||
});
|
||||
previous_head = head_commit;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user