Skip to content

Commit 80bcd0b

Browse files
author
K
committed
Improvements
1 parent 6ba9e96 commit 80bcd0b

File tree

3 files changed

+106
-99
lines changed

3 files changed

+106
-99
lines changed

src/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,20 @@ pub enum FileMode {
10521052
}
10531053

10541054
impl FileMode {
1055+
#[cfg(target_os = "windows")]
1056+
fn from(mode: i32) -> Self {
1057+
match mode {
1058+
raw::GIT_FILEMODE_UNREADABLE => FileMode::Unreadable,
1059+
raw::GIT_FILEMODE_TREE => FileMode::Tree,
1060+
raw::GIT_FILEMODE_BLOB => FileMode::Blob,
1061+
raw::GIT_FILEMODE_BLOB_EXECUTABLE => FileMode::BlobExecutable,
1062+
raw::GIT_FILEMODE_LINK => FileMode::Link,
1063+
raw::GIT_FILEMODE_COMMIT => FileMode::Commit,
1064+
mode => panic!("unknown file mode: {}", mode),
1065+
}
1066+
}
1067+
1068+
#[cfg(not(target_os = "windows"))]
10551069
fn from(mode: u32) -> Self {
10561070
match mode {
10571071
raw::GIT_FILEMODE_UNREADABLE => FileMode::Unreadable,

src/merge.rs

+29-54
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::str;
55

66
use crate::call::Convert;
77
use crate::util::Binding;
8-
use crate::{raw, Commit, FileFavor, FileMode, IndexEntry, IntoCString, Oid, Repository};
8+
use crate::{raw, Commit, FileFavor, FileMode, IntoCString, Oid};
99
use core::{ptr, slice};
1010
use std::ffi::{CStr, CString};
1111

@@ -293,7 +293,7 @@ impl MergeFileOptions {
293293
}
294294

295295
/// For git_merge_file_input
296-
pub struct MergeFileInput {
296+
pub struct MergeFileInput<'a> {
297297
raw: raw::git_merge_file_input,
298298

299299
/// File name of the conflicted file, or `NULL` to not merge the path.
@@ -304,26 +304,22 @@ pub struct MergeFileInput {
304304
/// internal `util` module in this crate’s source code.
305305
path: Option<CString>,
306306

307-
/// File mode of the conflicted file, or `0` to not merge the mode.
308-
pub mode: Option<FileMode>,
309-
310307
/// File content
311-
pub content: Option<Vec<u8>>,
308+
content: Option<&'a [u8]>,
312309
}
313310

314-
impl Default for MergeFileInput {
311+
impl Default for MergeFileInput<'_> {
315312
fn default() -> Self {
316313
Self::new()
317314
}
318315
}
319316

320-
impl MergeFileInput {
317+
impl<'a> MergeFileInput<'a> {
321318
/// Creates a new set of empty diff options.
322-
pub fn new() -> MergeFileInput {
319+
pub fn new() -> MergeFileInput<'a> {
323320
let mut input = MergeFileInput {
324321
raw: unsafe { mem::zeroed() },
325322
path: None,
326-
mode: None,
327323
content: None,
328324
};
329325
assert_eq!(
@@ -334,7 +330,7 @@ impl MergeFileInput {
334330
}
335331

336332
/// File name of the conflicted file, or `None` to not merge the path.
337-
pub fn path<T: IntoCString>(&mut self, t: T) -> &mut MergeFileInput {
333+
pub fn path<T: IntoCString>(&mut self, t: T) -> &mut MergeFileInput<'a> {
338334
self.path = Some(t.into_c_string().unwrap());
339335

340336
self.raw.path = self
@@ -347,18 +343,16 @@ impl MergeFileInput {
347343
}
348344

349345
/// File mode of the conflicted file, or `0` to not merge the mode.
350-
pub fn mode(&mut self, mode: Option<FileMode>) -> &mut MergeFileInput {
351-
self.mode = mode;
352-
353-
if let Some(mode) = self.mode {
346+
pub fn mode(&mut self, mode: Option<FileMode>) -> &mut MergeFileInput<'a> {
347+
if let Some(mode) = mode {
354348
self.raw.mode = mode as u32;
355349
}
356350

357351
self
358352
}
359353

360354
/// File content, text or binary
361-
pub fn content(&mut self, content: Option<Vec<u8>>) -> &mut MergeFileInput {
355+
pub fn content(&mut self, content: Option<&'a [u8]>) -> &mut MergeFileInput<'a> {
362356
self.content = content;
363357

364358
self.raw.size = self.content.as_ref().map(|c| c.len()).unwrap_or(0);
@@ -377,47 +371,29 @@ impl MergeFileInput {
377371
}
378372
}
379373

380-
impl MergeFileInput {
381-
/// Create from Repository and IndexEntry
382-
pub fn from(repo: &Repository, index_entry: &IndexEntry) -> MergeFileInput {
383-
let blob = repo
384-
.find_blob(index_entry.id.clone())
385-
.expect("failed to find blob of index entry to make MergeFileInput");
386-
let content = blob.content().to_vec();
387-
388-
let mut input = MergeFileInput::new();
389-
input.content(Some(content));
390-
input.path(index_entry.path.clone());
391-
input.mode(Some(FileMode::from(index_entry.mode)));
392-
393-
input
394-
}
395-
}
396-
397-
impl std::fmt::Debug for MergeFileInput {
374+
impl std::fmt::Debug for MergeFileInput<'_> {
398375
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
399376
let mut ds = f.debug_struct("MergeFileInput");
400377
if let Some(path) = &self.path {
401378
ds.field("path", path);
402379
}
403-
ds.field("mode", &self.mode);
380+
ds.field("mode", &FileMode::from(self.raw.mode));
404381

405-
if let Some(mode) = self.mode {
406-
match mode {
407-
FileMode::Unreadable => {}
408-
FileMode::Tree => {}
409-
FileMode::Blob => {
410-
let content = self
411-
.content
412-
.as_ref()
413-
.map(|s| String::from_utf8_lossy(&s).to_string())
414-
.unwrap_or("unknown content".to_string());
415-
ds.field("content", &content);
416-
}
417-
FileMode::BlobExecutable => {}
418-
FileMode::Link => {}
419-
FileMode::Commit => {}
382+
match FileMode::from(self.raw.mode) {
383+
FileMode::Unreadable => {}
384+
FileMode::Tree => {}
385+
FileMode::Blob => {
386+
let content = self
387+
.content
388+
.as_ref()
389+
.map(|s| String::from_utf8_lossy(&s).to_string())
390+
.unwrap_or("unknown content".to_string());
391+
392+
ds.field("content", &content);
420393
}
394+
FileMode::BlobExecutable => {}
395+
FileMode::Link => {}
396+
FileMode::Commit => {}
421397
}
422398
ds.finish()
423399
}
@@ -442,13 +418,12 @@ pub struct MergeFileResult {
442418

443419
impl MergeFileResult {
444420
/// Create MergeFileResult from C
445-
pub fn from_raw(raw: raw::git_merge_file_result) -> MergeFileResult {
446-
let c_str: &CStr = unsafe { CStr::from_ptr(raw.path) };
421+
pub unsafe fn from_raw(raw: raw::git_merge_file_result) -> MergeFileResult {
422+
let c_str: &CStr = CStr::from_ptr(raw.path);
447423
let str_slice: &str = c_str.to_str().unwrap();
448424
let path: String = str_slice.to_owned();
449425

450-
let content =
451-
unsafe { slice::from_raw_parts(raw.ptr as *const u8, raw.len as usize).to_vec() };
426+
let content = slice::from_raw_parts(raw.ptr as *const u8, raw.len as usize).to_vec();
452427

453428
MergeFileResult {
454429
automergeable: raw.automergeable > 0,

src/repo.rs

+63-45
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::string_array::StringArray;
1818
use crate::tagforeach::{tag_foreach_cb, TagForeachCB, TagForeachData};
1919
use crate::util::{self, path_to_repo_path, Binding};
2020
use crate::worktree::{Worktree, WorktreeAddOptions};
21+
use crate::CherrypickOptions;
2122
use crate::RevertOptions;
2223
use crate::{
2324
raw, AttrCheckFlags, Buf, Error, Object, Remote, RepositoryOpenFlags, RepositoryState, Revspec,
@@ -29,7 +30,6 @@ use crate::{
2930
use crate::{ApplyLocation, ApplyOptions, Rebase, RebaseOptions};
3031
use crate::{Blame, BlameOptions, Reference, References, ResetType, Signature, Submodule};
3132
use crate::{Blob, BlobWriter, Branch, BranchType, Branches, Commit, Config, Index, Oid, Tree};
32-
use crate::{CherrypickOptions, IndexEntry};
3333
use crate::{Describe, IntoCString, Reflog, RepositoryInitMode, RevparseMode};
3434
use crate::{DescribeOptions, Diff, DiffOptions, Odb, PackBuilder, TreeBuilder};
3535
use crate::{Note, Notes, ObjectType, Revwalk, Status, StatusOptions, Statuses, Tag};
@@ -1848,47 +1848,13 @@ impl Repository {
18481848
///
18491849
/// Note that this function does not reference a repository and any
18501850
/// configuration must be passed as `git_merge_file_options`.
1851-
///
1852-
/// @param out The git_merge_file_result to be filled in
1853-
/// @param ancestor The contents of the ancestor file
1854-
/// @param ours The contents of the file in "our" side
1855-
/// @param theirs The contents of the file in "their" side
1856-
/// @param opts The merge file options or `NULL` for defaults
1857-
/// @return 0 on success or error code
18581851
pub fn merge_file(
18591852
&self,
1860-
ancestor: Option<&IndexEntry>,
1861-
ours: Option<&IndexEntry>,
1862-
theirs: Option<&IndexEntry>,
1853+
ancestor: Option<&MergeFileInput<'_>>,
1854+
ours: Option<&MergeFileInput<'_>>,
1855+
theirs: Option<&MergeFileInput<'_>>,
18631856
options: Option<&MergeFileOptions>,
18641857
) -> Result<MergeFileResult, Error> {
1865-
let ancestor_input;
1866-
let ours_input;
1867-
let theirs_input;
1868-
1869-
let ancestor_raw;
1870-
let ours_raw;
1871-
let theirs_raw;
1872-
1873-
if let Some(ancestor) = ancestor {
1874-
ancestor_input = MergeFileInput::from(&self, ancestor);
1875-
ancestor_raw = ancestor_input.raw();
1876-
} else {
1877-
ancestor_raw = ptr::null();
1878-
}
1879-
if let Some(ours) = ours {
1880-
ours_input = MergeFileInput::from(&self, ours);
1881-
ours_raw = ours_input.raw();
1882-
} else {
1883-
ours_raw = ptr::null();
1884-
}
1885-
if let Some(theirs) = theirs {
1886-
theirs_input = MergeFileInput::from(&self, theirs);
1887-
theirs_raw = theirs_input.raw();
1888-
} else {
1889-
theirs_raw = ptr::null();
1890-
}
1891-
18921858
let mut ret = raw::git_merge_file_result {
18931859
automergeable: 0,
18941860
path: ptr::null(),
@@ -1900,9 +1866,9 @@ impl Repository {
19001866
unsafe {
19011867
try_call!(raw::git_merge_file(
19021868
&mut ret,
1903-
ancestor_raw,
1904-
ours_raw,
1905-
theirs_raw,
1869+
ancestor.map(|a| a.raw()).unwrap_or(ptr::null()),
1870+
ours.map(|a| a.raw()).unwrap_or(ptr::null()),
1871+
theirs.map(|a| a.raw()).unwrap_or(ptr::null()),
19061872
options.map(|o| o.raw())
19071873
));
19081874

@@ -3104,7 +3070,7 @@ impl RepositoryInitOptions {
31043070
#[cfg(test)]
31053071
mod tests {
31063072
use crate::build::CheckoutBuilder;
3107-
use crate::{CherrypickOptions, FileMode};
3073+
use crate::{CherrypickOptions, FileMode, MergeFileInput};
31083074
use crate::{ObjectType, Oid, Repository, ResetType};
31093075
use std::ffi::OsStr;
31103076
use std::fs;
@@ -3457,11 +3423,63 @@ mod tests {
34573423
for conflict in index_conflicts {
34583424
let conflict = conflict.unwrap();
34593425

3426+
let ancestor_input;
3427+
let ours_input;
3428+
let theirs_input;
3429+
3430+
let ancestor_blob;
3431+
let ours_blob;
3432+
let theirs_blob;
3433+
3434+
let ancestor_content;
3435+
let ours_content;
3436+
let theirs_content;
3437+
3438+
if let Some(ancestor) = conflict.ancestor {
3439+
ancestor_blob = repo
3440+
.find_blob(ancestor.id.clone())
3441+
.expect("failed to find blob of index entry to make MergeFileInput");
3442+
ancestor_content = ancestor_blob.content();
3443+
let mut input = MergeFileInput::new();
3444+
input.path(String::from_utf8(ancestor.path).unwrap());
3445+
input.mode(Some(FileMode::from(ancestor.mode)));
3446+
input.content(Some(&ancestor_content));
3447+
ancestor_input = Some(input);
3448+
} else {
3449+
ancestor_input = None;
3450+
}
3451+
if let Some(ours) = conflict.our {
3452+
ours_blob = repo
3453+
.find_blob(ours.id.clone())
3454+
.expect("failed to find blob of index entry to make MergeFileInput");
3455+
ours_content = ours_blob.content();
3456+
let mut input = MergeFileInput::new();
3457+
input.path(String::from_utf8(ours.path).unwrap());
3458+
input.mode(Some(FileMode::from(ours.mode)));
3459+
input.content(Some(&ours_content));
3460+
ours_input = Some(input);
3461+
} else {
3462+
ours_input = None;
3463+
}
3464+
if let Some(theirs) = conflict.their {
3465+
theirs_blob = repo
3466+
.find_blob(theirs.id.clone())
3467+
.expect("failed to find blob of index entry to make MergeFileInput");
3468+
theirs_content = theirs_blob.content();
3469+
let mut input = MergeFileInput::new();
3470+
input.path(String::from_utf8(theirs.path).unwrap());
3471+
input.mode(Some(FileMode::from(theirs.mode)));
3472+
input.content(Some(&theirs_content));
3473+
theirs_input = Some(input);
3474+
} else {
3475+
theirs_input = None;
3476+
}
3477+
34603478
let merge_file_result = repo
34613479
.merge_file(
3462-
conflict.ancestor.as_ref(),
3463-
conflict.our.as_ref(),
3464-
conflict.their.as_ref(),
3480+
ancestor_input.as_ref(),
3481+
ours_input.as_ref(),
3482+
theirs_input.as_ref(),
34653483
None,
34663484
)
34673485
.unwrap();

0 commit comments

Comments
 (0)