//! Copyright (c) 2022-2026 GitDataAi All rights reserved. use crate::bare::GitBare; use crate::error::{GitError, GitResult}; use crate::paginate; use crate::pb::{ListMergeConflictsRequest, ListMergeConflictsResponse, MergeConflict}; impl GitBare { pub fn list_merge_conflicts( &self, request: ListMergeConflictsRequest, ) -> GitResult { let target = match request.target.and_then(|s| s.selector) { Some(crate::pb::object_selector::Selector::Oid(oid)) => { crate::sanitize::validate_oid_hex(&oid.hex)?; oid.hex } Some(crate::pb::object_selector::Selector::Revision(name)) => { crate::sanitize::validate_revision(&name.revision)?; name.revision } None => return Err(GitError::InvalidArgument("target is required".into())), }; let source = match request.source.and_then(|s| s.selector) { Some(crate::pb::object_selector::Selector::Oid(oid)) => { crate::sanitize::validate_oid_hex(&oid.hex)?; oid.hex } Some(crate::pb::object_selector::Selector::Revision(name)) => { crate::sanitize::validate_revision(&name.revision)?; name.revision } None => return Err(GitError::InvalidArgument("source is required".into())), }; let result = duct::cmd( "git", [ "--git-dir", self.bare_dir.to_string_lossy().as_ref(), "merge-tree", "--write-tree", "--name-only", "-z", target.as_str(), source.as_str(), ], ) .stdout_capture() .stderr_capture() .unchecked() .run()?; let stdout = String::from_utf8_lossy(&result.stdout); if result.status.success() { return Ok(ListMergeConflictsResponse { conflicts: vec![], page_info: Some(crate::pb::PageInfo { next_page_token: String::new(), has_next_page: false, total_count: 0, }), }); } let mut conflicts: Vec = stdout .split('\0') .filter(|s| !s.is_empty()) .map(|path| MergeConflict { path: path.to_string(), ..Default::default() }) .collect(); paginate::apply_sort(&mut conflicts, 0); let (conflicts, page_info) = paginate::paginate(&conflicts, request.pagination.as_ref()); Ok(ListMergeConflictsResponse { conflicts, page_info: Some(page_info), }) } }