mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-30 01:17:37 +03:00
get_applied_status returns VirtualBranchFiles instead of a tuple of path and hunks
This commit is contained in:
parent
c25e48877b
commit
ea4f47da1b
@ -1,6 +1,9 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{
|
||||
conflicts::{self},
|
||||
ensure_selected_for_changes, get_applied_status,
|
||||
hunk::VirtualBranchHunk,
|
||||
integration::get_integration_commiter,
|
||||
NameConflictResolution, VirtualBranchesExt,
|
||||
};
|
||||
@ -87,10 +90,15 @@ impl BranchManager<'_> {
|
||||
|final_tree, status| {
|
||||
let final_tree = final_tree?;
|
||||
let branch = status.0;
|
||||
let files = status
|
||||
.1
|
||||
.into_iter()
|
||||
.map(|file| (file.path, file.hunks))
|
||||
.collect::<Vec<(PathBuf, Vec<VirtualBranchHunk>)>>();
|
||||
let tree_oid = gitbutler_diff::write::hunks_onto_oid(
|
||||
self.project_repository,
|
||||
&branch.head,
|
||||
status.1,
|
||||
files,
|
||||
)?;
|
||||
let branch_tree = repo.find_tree(tree_oid)?;
|
||||
let mut result =
|
||||
|
@ -74,6 +74,15 @@ pub struct VirtualBranchFile {
|
||||
pub large: bool,
|
||||
}
|
||||
|
||||
pub trait Get<T> {
|
||||
fn get(&self, path: &Path) -> Option<T>;
|
||||
}
|
||||
impl Get<VirtualBranchFile> for Vec<VirtualBranchFile> {
|
||||
fn get(&self, path: &Path) -> Option<VirtualBranchFile> {
|
||||
self.iter().find(|f| f.path == path).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn list_virtual_commit_files(
|
||||
project_repository: &ProjectRepository,
|
||||
commit: &git2::Commit,
|
||||
|
@ -15,6 +15,7 @@ mod integration;
|
||||
pub use integration::{update_gitbutler_integration, verify_branch};
|
||||
|
||||
mod file;
|
||||
pub use file::Get;
|
||||
pub use file::RemoteBranchFile;
|
||||
|
||||
mod remote;
|
||||
|
@ -8,6 +8,7 @@ use gitbutler_project::access::WorktreeWritePermission;
|
||||
use gitbutler_repo::RepositoryExt;
|
||||
use std::{collections::HashMap, path::PathBuf, vec};
|
||||
|
||||
use crate::file::{virtual_hunks_into_virtual_files, VirtualBranchFile};
|
||||
use crate::hunk::file_hunks_from_diffs;
|
||||
use crate::{
|
||||
conflicts::RepoConflictsExt,
|
||||
@ -19,7 +20,7 @@ use crate::{
|
||||
/// Represents the uncommitted status of the applied virtual branches in the workspace.
|
||||
pub struct VirtualBranchesStatus {
|
||||
/// A collection of branches and their associated uncommitted file changes.
|
||||
pub branches: Vec<(Branch, HashMap<PathBuf, Vec<VirtualBranchHunk>>)>,
|
||||
pub branches: Vec<(Branch, Vec<VirtualBranchFile>)>,
|
||||
/// A collection of files that were skipped during the diffing process (due to being very large and unprocessable).
|
||||
pub skipped_files: Vec<gitbutler_diff::FileDiff>,
|
||||
}
|
||||
@ -208,8 +209,16 @@ pub fn get_applied_status(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let files_by_branch: Vec<(Branch, Vec<VirtualBranchFile>)> = hunks_by_branch
|
||||
.iter()
|
||||
.map(|(branch, hunks)| {
|
||||
let files = virtual_hunks_into_virtual_files(project_repository, hunks.clone());
|
||||
(branch.clone(), files)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(VirtualBranchesStatus {
|
||||
branches: hunks_by_branch,
|
||||
branches: files_by_branch,
|
||||
skipped_files,
|
||||
})
|
||||
}
|
||||
|
@ -25,11 +25,12 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::branch_manager::BranchManagerExt;
|
||||
use crate::commit::{commit_to_vbranch_commit, VirtualBranchCommit};
|
||||
use crate::conflicts::{self, RepoConflictsExt};
|
||||
use crate::file::{virtual_hunks_into_virtual_files, VirtualBranchFile};
|
||||
use crate::file::VirtualBranchFile;
|
||||
use crate::hunk::VirtualBranchHunk;
|
||||
use crate::integration::get_workspace_head;
|
||||
use crate::remote::{branch_to_remote_branch, RemoteBranch};
|
||||
use crate::status::get_applied_status;
|
||||
use crate::Get;
|
||||
use crate::VirtualBranchesExt;
|
||||
use gitbutler_error::error::Code;
|
||||
use gitbutler_error::error::Marker;
|
||||
@ -110,17 +111,17 @@ pub fn unapply_ownership(
|
||||
.map(
|
||||
|(_branch, branch_files)| -> Result<Vec<(PathBuf, gitbutler_diff::GitHunk)>> {
|
||||
let mut hunks_to_unapply: Vec<(PathBuf, GitHunk)> = Vec::new();
|
||||
for (path, hunks) in branch_files {
|
||||
for file in branch_files {
|
||||
let ownership_hunks: Vec<&Hunk> = ownership
|
||||
.claims
|
||||
.iter()
|
||||
.filter(|o| o.file_path == *path)
|
||||
.filter(|o| o.file_path == file.path)
|
||||
.flat_map(|f| &f.hunks)
|
||||
.collect();
|
||||
for hunk in hunks {
|
||||
for hunk in &file.hunks {
|
||||
let hunk: GitHunk = hunk.clone().into();
|
||||
if ownership_hunks.contains(&&Hunk::from(&hunk)) {
|
||||
hunks_to_unapply.push((path.clone(), hunk));
|
||||
hunks_to_unapply.push((file.path.clone(), hunk));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,10 +156,15 @@ pub fn unapply_ownership(
|
||||
target_commit.tree().context("failed to get target tree"),
|
||||
|final_tree, status| {
|
||||
let final_tree = final_tree?;
|
||||
let files = status
|
||||
.1
|
||||
.into_iter()
|
||||
.map(|file| (file.path, file.hunks))
|
||||
.collect::<Vec<(PathBuf, Vec<VirtualBranchHunk>)>>();
|
||||
let tree_oid = gitbutler_diff::write::hunks_onto_oid(
|
||||
project_repository,
|
||||
&integration_commit_id,
|
||||
status.1,
|
||||
files,
|
||||
)?;
|
||||
let branch_tree = repo.find_tree(tree_oid)?;
|
||||
let mut result = repo.merge_trees(&base_tree, &final_tree, &branch_tree, None)?;
|
||||
@ -276,7 +282,6 @@ pub fn list_virtual_branches(
|
||||
.get_default_target()
|
||||
.context("failed to get default target")?;
|
||||
|
||||
// let (statuses, skipped_files, locks) = get_applied_status(ctx, Some(perm))?;
|
||||
let status = get_applied_status(ctx, Some(perm))?;
|
||||
let max_selected_for_changes = status
|
||||
.branches
|
||||
@ -285,9 +290,9 @@ pub fn list_virtual_branches(
|
||||
.max()
|
||||
.unwrap_or(-1);
|
||||
|
||||
for (branch, files) in status.branches {
|
||||
for (branch, mut files) in status.branches {
|
||||
let repo = ctx.repo();
|
||||
update_conflict_markers(ctx, &files)?;
|
||||
update_conflict_markers(ctx, files.clone())?;
|
||||
|
||||
let upstream_branch = match branch.clone().upstream {
|
||||
Some(upstream) => repo.find_branch_by_refname(&Refname::from(upstream))?,
|
||||
@ -350,8 +355,6 @@ pub fn list_virtual_branches(
|
||||
let upstream = upstream_branch
|
||||
.and_then(|upstream_branch| branch_to_remote_branch(ctx, &upstream_branch));
|
||||
|
||||
let mut files = virtual_hunks_into_virtual_files(ctx, files);
|
||||
|
||||
let path_claim_positions: HashMap<&PathBuf, usize> = branch
|
||||
.ownership
|
||||
.claims
|
||||
@ -932,7 +935,7 @@ pub fn commit(
|
||||
.find(|(branch, _)| branch.id == branch_id)
|
||||
.with_context(|| format!("branch {branch_id} not found"))?;
|
||||
|
||||
update_conflict_markers(project_repository, &files)
|
||||
update_conflict_markers(project_repository, files.clone())
|
||||
.context(Code::CommitMergeConflictFailure)?;
|
||||
|
||||
project_repository
|
||||
@ -940,15 +943,16 @@ pub fn commit(
|
||||
.context(Code::CommitMergeConflictFailure)?;
|
||||
|
||||
let tree_oid = if let Some(ownership) = ownership {
|
||||
let files = files.into_iter().filter_map(|(filepath, hunks)| {
|
||||
let hunks = hunks
|
||||
let files = files.into_iter().filter_map(|file| {
|
||||
let hunks = file
|
||||
.hunks
|
||||
.into_iter()
|
||||
.filter(|hunk| {
|
||||
let hunk: GitHunk = hunk.clone().into();
|
||||
ownership
|
||||
.claims
|
||||
.iter()
|
||||
.find(|f| f.file_path.eq(&filepath))
|
||||
.find(|f| f.file_path.eq(&file.path))
|
||||
.map_or(false, |f| {
|
||||
f.hunks.iter().any(|h| {
|
||||
h.start == hunk.new_start
|
||||
@ -960,11 +964,15 @@ pub fn commit(
|
||||
if hunks.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((filepath, hunks))
|
||||
Some((file.path, hunks))
|
||||
}
|
||||
});
|
||||
gitbutler_diff::write::hunks_onto_commit(project_repository, branch.head, files)?
|
||||
} else {
|
||||
let files = files
|
||||
.into_iter()
|
||||
.map(|file| (file.path, file.hunks))
|
||||
.collect::<Vec<(PathBuf, Vec<VirtualBranchHunk>)>>();
|
||||
gitbutler_diff::write::hunks_onto_commit(project_repository, branch.head, files)?
|
||||
};
|
||||
|
||||
@ -1504,8 +1512,8 @@ pub(crate) fn amend(
|
||||
.filter_map(|file_ownership| {
|
||||
let hunks = target_status
|
||||
.get(&file_ownership.file_path)
|
||||
.map(|hunks| {
|
||||
hunks
|
||||
.map(|file| {
|
||||
file.hunks
|
||||
.iter()
|
||||
.filter(|hunk| {
|
||||
let hunk: GitHunk = (*hunk).clone().into();
|
||||
@ -1985,11 +1993,11 @@ pub(crate) fn move_commit(
|
||||
|
||||
let branch_head_diff: HashMap<_, _> =
|
||||
gitbutler_diff::diff_files_into_hunks(branch_head_diff).collect();
|
||||
let is_source_locked = source_branch_non_comitted_files
|
||||
.iter()
|
||||
.any(|(path, hunks)| {
|
||||
branch_head_diff.get(path).map_or(false, |head_diff_hunks| {
|
||||
hunks.iter().any(|hunk| {
|
||||
let is_source_locked = source_branch_non_comitted_files.iter().any(|file| {
|
||||
branch_head_diff
|
||||
.get(&file.path)
|
||||
.map_or(false, |head_diff_hunks| {
|
||||
file.hunks.iter().any(|hunk| {
|
||||
let hunk: GitHunk = hunk.clone().into();
|
||||
head_diff_hunks.iter().any(|head_hunk| {
|
||||
joined(
|
||||
@ -2073,14 +2081,14 @@ pub(crate) fn move_commit(
|
||||
// conflicts file.
|
||||
fn update_conflict_markers(
|
||||
project_repository: &ProjectRepository,
|
||||
files: &HashMap<PathBuf, Vec<impl Into<GitHunk> + Clone>>,
|
||||
files: Vec<VirtualBranchFile>,
|
||||
) -> Result<()> {
|
||||
let conflicting_files = conflicts::conflicting_files(project_repository)?;
|
||||
for (file_path, non_commited_hunks) in files {
|
||||
for file in files {
|
||||
let mut conflicted = false;
|
||||
if conflicting_files.contains(file_path) {
|
||||
if conflicting_files.contains(&file.path) {
|
||||
// check file for conflict markers, resolve the file if there are none in any hunk
|
||||
for hunk in non_commited_hunks {
|
||||
for hunk in file.hunks {
|
||||
let hunk: GitHunk = hunk.clone().into();
|
||||
if hunk.diff_lines.contains_str(b"<<<<<<< ours") {
|
||||
conflicted = true;
|
||||
@ -2090,7 +2098,7 @@ fn update_conflict_markers(
|
||||
}
|
||||
}
|
||||
if !conflicted {
|
||||
conflicts::resolve(project_repository, file_path).unwrap();
|
||||
conflicts::resolve(project_repository, file.path).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ use gitbutler_branch::{
|
||||
BranchOwnershipClaims, Target, {BranchCreateRequest, BranchUpdateRequest},
|
||||
};
|
||||
use gitbutler_branch_actions::BranchManagerExt;
|
||||
use gitbutler_branch_actions::Get;
|
||||
use gitbutler_branch_actions::{
|
||||
commit, get_applied_status, integrate_upstream_commits, is_remote_branch_mergeable,
|
||||
list_virtual_branches, unapply_ownership, update_branch, update_gitbutler_integration,
|
||||
@ -549,15 +550,27 @@ fn move_hunks_multiple_sources() -> Result<()> {
|
||||
assert_eq!(files_by_branch_id[&branch2_id].len(), 0);
|
||||
assert_eq!(files_by_branch_id[&branch3_id].len(), 1);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch3_id][Path::new("test.txt")].len(),
|
||||
files_by_branch_id[&branch3_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch3_id][Path::new("test.txt")][0].diff,
|
||||
files_by_branch_id[&branch3_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks[0]
|
||||
.diff,
|
||||
"@@ -1,3 +1,4 @@\n+line0\n line1\n line2\n line3\n"
|
||||
);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch3_id][Path::new("test.txt")][1].diff,
|
||||
files_by_branch_id[&branch3_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks[1]
|
||||
.diff,
|
||||
"@@ -10,3 +11,4 @@ line9\n line10\n line11\n line12\n+line13\n"
|
||||
);
|
||||
Ok(())
|
||||
@ -628,21 +641,37 @@ fn move_hunks_partial_explicitly() -> Result<()> {
|
||||
assert_eq!(files_by_branch_id.len(), 2);
|
||||
assert_eq!(files_by_branch_id[&branch1_id].len(), 1);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch1_id][Path::new("test.txt")].len(),
|
||||
files_by_branch_id[&branch1_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch1_id][Path::new("test.txt")][0].diff,
|
||||
files_by_branch_id[&branch1_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks[0]
|
||||
.diff,
|
||||
"@@ -11,3 +12,4 @@ line10\n line11\n line12\n line13\n+line14\n"
|
||||
);
|
||||
|
||||
assert_eq!(files_by_branch_id[&branch2_id].len(), 1);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch2_id][Path::new("test.txt")].len(),
|
||||
files_by_branch_id[&branch2_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
files_by_branch_id[&branch2_id][Path::new("test.txt")][0].diff,
|
||||
files_by_branch_id[&branch2_id]
|
||||
.get(Path::new("test.txt"))
|
||||
.unwrap()
|
||||
.hunks[0]
|
||||
.diff,
|
||||
"@@ -1,3 +1,4 @@\n+line0\n line1\n line2\n line3\n"
|
||||
);
|
||||
|
||||
@ -678,7 +707,7 @@ fn add_new_hunk_to_the_end() -> Result<()> {
|
||||
.expect("failed to get status")
|
||||
.branches;
|
||||
assert_eq!(
|
||||
statuses[0].1[Path::new("test.txt")][0].diff,
|
||||
statuses[0].1.get(Path::new("test.txt")).unwrap().hunks[0].diff,
|
||||
"@@ -11,5 +11,5 @@ line10\n line11\n line12\n line13\n-line13\n line14\n+line15\n"
|
||||
);
|
||||
|
||||
@ -692,11 +721,11 @@ fn add_new_hunk_to_the_end() -> Result<()> {
|
||||
.branches;
|
||||
|
||||
assert_eq!(
|
||||
statuses[0].1[Path::new("test.txt")][0].diff,
|
||||
statuses[0].1.get(Path::new("test.txt")).unwrap().hunks[0].diff,
|
||||
"@@ -11,5 +12,5 @@ line10\n line11\n line12\n line13\n-line13\n line14\n+line15\n"
|
||||
);
|
||||
assert_eq!(
|
||||
statuses[0].1[Path::new("test.txt")][1].diff,
|
||||
statuses[0].1.get(Path::new("test.txt")).unwrap().hunks[1].diff,
|
||||
"@@ -1,3 +1,4 @@\n+line0\n line1\n line2\n line3\n"
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user