mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-28 03:55:02 +03:00
Merge pull request #769 from gitbutlerapp/can-commit-binary-files
Binary diff support
This commit is contained in:
commit
ede0c571f5
@ -661,7 +661,6 @@ impl Repository {
|
||||
}
|
||||
|
||||
let no_commiter_mark = config.get_string("gitbutler.utmostDiscretion");
|
||||
dbg!(&no_commiter_mark);
|
||||
if no_commiter_mark.is_ok() && no_commiter_mark? == "1" {
|
||||
committer = author.clone();
|
||||
}
|
||||
|
@ -4,12 +4,14 @@ use anyhow::{Context, Result};
|
||||
|
||||
use super::Repository;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Hunk {
|
||||
pub old_start: usize,
|
||||
pub old_lines: usize,
|
||||
pub new_start: usize,
|
||||
pub new_lines: usize,
|
||||
pub diff: String,
|
||||
pub binary: bool,
|
||||
}
|
||||
|
||||
pub struct Options {
|
||||
@ -37,15 +39,15 @@ pub fn workdir(
|
||||
diff_opts
|
||||
.recurse_untracked_dirs(true)
|
||||
.include_untracked(true)
|
||||
.show_binary(true)
|
||||
.show_untracked_content(true);
|
||||
|
||||
diff_opts.context_lines(opts.context_lines);
|
||||
|
||||
let diff = repository
|
||||
.git_repository
|
||||
.diff_tree_to_workdir(Some(&tree), Some(&mut diff_opts))?;
|
||||
let repo = &repository.git_repository;
|
||||
let diff = repo.diff_tree_to_workdir(Some(&tree), Some(&mut diff_opts))?;
|
||||
|
||||
hunks_by_filepath(&diff)
|
||||
hunks_by_filepath(repo, &diff)
|
||||
}
|
||||
|
||||
pub fn trees(
|
||||
@ -56,17 +58,19 @@ pub fn trees(
|
||||
let mut opts = git2::DiffOptions::new();
|
||||
opts.recurse_untracked_dirs(true)
|
||||
.include_untracked(true)
|
||||
.show_binary(true)
|
||||
.show_untracked_content(true);
|
||||
|
||||
let diff =
|
||||
repository
|
||||
.git_repository
|
||||
.diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None)?;
|
||||
let repo = &repository.git_repository;
|
||||
let diff = repo.diff_tree_to_tree(Some(&old_tree), Some(&new_tree), None)?;
|
||||
|
||||
hunks_by_filepath(&diff)
|
||||
hunks_by_filepath(repo, &diff)
|
||||
}
|
||||
|
||||
fn hunks_by_filepath(diff: &git2::Diff) -> Result<HashMap<path::PathBuf, Vec<Hunk>>> {
|
||||
fn hunks_by_filepath(
|
||||
repo: &git2::Repository,
|
||||
diff: &git2::Diff,
|
||||
) -> Result<HashMap<path::PathBuf, Vec<Hunk>>> {
|
||||
// find all the hunks
|
||||
let mut hunks_by_filepath: HashMap<path::PathBuf, Vec<Hunk>> = HashMap::new();
|
||||
let mut current_diff = String::new();
|
||||
@ -77,6 +81,7 @@ fn hunks_by_filepath(diff: &git2::Diff) -> Result<HashMap<path::PathBuf, Vec<Hun
|
||||
let mut current_new_lines: Option<usize> = None;
|
||||
let mut current_old_start: Option<usize> = None;
|
||||
let mut current_old_lines: Option<usize> = None;
|
||||
let mut current_binary = false;
|
||||
|
||||
diff.print(git2::DiffFormat::Patch, |delta, hunk, line| {
|
||||
let file_path = delta.new_file().path().unwrap_or_else(|| {
|
||||
@ -101,7 +106,12 @@ fn hunks_by_filepath(diff: &git2::Diff) -> Result<HashMap<path::PathBuf, Vec<Hun
|
||||
hunk.old_lines(),
|
||||
)
|
||||
} else {
|
||||
return true;
|
||||
if line.origin() == 'B' {
|
||||
let hunk_id = format!("{:?}:{}", file_path.as_os_str(), delta.new_file().id());
|
||||
(hunk_id.clone(), 0, 0, 0, 0)
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
let is_path_changed = if current_file_path.is_none() {
|
||||
@ -124,6 +134,7 @@ fn hunks_by_filepath(diff: &git2::Diff) -> Result<HashMap<path::PathBuf, Vec<Hun
|
||||
new_start: current_new_start.unwrap(),
|
||||
new_lines: current_new_lines.unwrap(),
|
||||
diff: current_diff.clone(),
|
||||
binary: current_binary,
|
||||
});
|
||||
current_diff = String::new();
|
||||
}
|
||||
@ -133,7 +144,27 @@ fn hunks_by_filepath(diff: &git2::Diff) -> Result<HashMap<path::PathBuf, Vec<Hun
|
||||
_ => {}
|
||||
}
|
||||
|
||||
current_diff.push_str(std::str::from_utf8(line.content()).unwrap());
|
||||
// is this a binary patch or a hunk?
|
||||
match line.origin() {
|
||||
'B' => {
|
||||
// save the file_path to the odb
|
||||
if !delta.new_file().id().is_zero() {
|
||||
// the binary file wasnt deleted
|
||||
let full_path = repo.workdir().unwrap().join(file_path);
|
||||
let blob_oid = repo.blob_path(full_path.as_path()).unwrap();
|
||||
if blob_oid != delta.new_file().id() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
current_diff.push_str(&format!("{}", delta.new_file().id()));
|
||||
current_binary = true;
|
||||
}
|
||||
_ => {
|
||||
current_diff.push_str(std::str::from_utf8(line.content()).unwrap());
|
||||
current_binary = false;
|
||||
}
|
||||
}
|
||||
|
||||
current_file_path = Some(file_path.to_path_buf());
|
||||
current_hunk_id = Some(hunk_id);
|
||||
current_new_start = Some(new_start as usize);
|
||||
@ -153,6 +184,7 @@ fn hunks_by_filepath(diff: &git2::Diff) -> Result<HashMap<path::PathBuf, Vec<Hun
|
||||
new_start: current_new_start.unwrap(),
|
||||
new_lines: current_new_lines.unwrap(),
|
||||
diff: current_diff,
|
||||
binary: current_binary,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ pub struct VirtualBranchFile {
|
||||
pub hunks: Vec<VirtualBranchHunk>,
|
||||
pub modified_at: u128,
|
||||
pub conflicted: bool,
|
||||
pub binary: bool,
|
||||
}
|
||||
|
||||
// this struct is a mapping to the view `Hunk` type in Typescript
|
||||
@ -104,6 +105,7 @@ pub struct VirtualBranchHunk {
|
||||
pub hash: String,
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
pub binary: bool,
|
||||
}
|
||||
|
||||
// this struct is a mapping to the view `RemoteBranch` type in Typescript
|
||||
@ -766,6 +768,7 @@ pub fn list_virtual_branches(
|
||||
id: file_path.display().to_string(),
|
||||
path: file_path.clone(),
|
||||
hunks: hunks.clone(),
|
||||
binary: hunks.iter().any(|h| h.binary),
|
||||
modified_at: hunks.iter().map(|h| h.modified_at).max().unwrap_or(0),
|
||||
conflicted: conflicts::is_conflicting(
|
||||
project_repository,
|
||||
@ -1233,6 +1236,7 @@ fn hunks_by_filepath(
|
||||
diff: hunk.diff.clone(),
|
||||
start: hunk.new_start,
|
||||
end: hunk.new_start + hunk.new_lines,
|
||||
binary: hunk.binary,
|
||||
hash: diff_hash(&hunk.diff),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@ -1446,6 +1450,7 @@ pub fn get_status_by_branch(
|
||||
id: file_path.display().to_string(),
|
||||
path: file_path.clone(),
|
||||
hunks: hunks.clone(),
|
||||
binary: hunks.iter().any(|h| h.binary),
|
||||
modified_at: hunks.iter().map(|h| h.modified_at).max().unwrap_or(0),
|
||||
conflicted: conflicts::is_conflicting(
|
||||
project_repository,
|
||||
@ -1925,33 +1930,40 @@ fn write_tree(
|
||||
let blob_oid = git_repository.blob(bytes)?;
|
||||
builder.upsert(rel_path, blob_oid, filemode);
|
||||
} else if let Ok(tree_entry) = base_tree.get_path(rel_path) {
|
||||
// blob from tree_entry
|
||||
let blob = tree_entry
|
||||
.to_object(git_repository)
|
||||
.unwrap()
|
||||
.peel_to_blob()
|
||||
.context("failed to get blob")?;
|
||||
if file.binary {
|
||||
let new_blob_oid = &file.hunks[0].diff;
|
||||
// convert string to Oid
|
||||
let new_blob_oid = git2::Oid::from_str(&new_blob_oid)?;
|
||||
builder.upsert(rel_path, new_blob_oid, filemode);
|
||||
} else {
|
||||
// blob from tree_entry
|
||||
let blob = tree_entry
|
||||
.to_object(git_repository)
|
||||
.unwrap()
|
||||
.peel_to_blob()
|
||||
.context("failed to get blob")?;
|
||||
|
||||
// get the contents
|
||||
let blob_contents = blob.content();
|
||||
// get the contents
|
||||
let blob_contents = blob.content();
|
||||
|
||||
let mut patch = "--- original\n+++ modified\n".to_string();
|
||||
let mut patch = "--- original\n+++ modified\n".to_string();
|
||||
|
||||
let mut hunks = file.hunks.to_vec();
|
||||
hunks.sort_by_key(|hunk| hunk.start);
|
||||
for hunk in hunks {
|
||||
patch.push_str(&hunk.diff);
|
||||
let mut hunks = file.hunks.to_vec();
|
||||
hunks.sort_by_key(|hunk| hunk.start);
|
||||
for hunk in hunks {
|
||||
patch.push_str(&hunk.diff);
|
||||
}
|
||||
|
||||
// apply patch to blob_contents
|
||||
let patch_bytes = patch.as_bytes();
|
||||
let patch = Patch::from_bytes(patch_bytes)?;
|
||||
let new_content = apply_bytes(blob_contents, &patch)?;
|
||||
|
||||
// create a blob
|
||||
let new_blob_oid = git_repository.blob(&new_content)?;
|
||||
// upsert into the builder
|
||||
builder.upsert(rel_path, new_blob_oid, filemode);
|
||||
}
|
||||
|
||||
// apply patch to blob_contents
|
||||
let patch_bytes = patch.as_bytes();
|
||||
let patch = Patch::from_bytes(patch_bytes)?;
|
||||
let new_content = apply_bytes(blob_contents, &patch)?;
|
||||
|
||||
// create a blob
|
||||
let new_blob_oid = git_repository.blob(&new_content)?;
|
||||
// upsert into the builder
|
||||
builder.upsert(rel_path, new_blob_oid, filemode);
|
||||
} else {
|
||||
// create a git blob from a file on disk
|
||||
let blob_oid = git_repository.blob_path(&full_path)?;
|
||||
@ -1976,9 +1988,11 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> {
|
||||
let object = entry.to_object(repo).context("failed to get object")?;
|
||||
let blob = object.as_blob().context("failed to get blob")?;
|
||||
// convert content to string
|
||||
let content =
|
||||
std::str::from_utf8(blob.content()).context("failed to convert content to string")?;
|
||||
println!(" blob: {:?}", content);
|
||||
if let Ok(content) = std::str::from_utf8(blob.content()) {
|
||||
println!(" blob: {:?}", content);
|
||||
} else {
|
||||
println!(" blob: BINARY");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ fn commit_all(repository: &git2::Repository) -> Result<git2::Oid> {
|
||||
|
||||
fn test_repository() -> Result<git2::Repository> {
|
||||
let path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
//dbg!(&path);
|
||||
let repository = git2::Repository::init(path)?;
|
||||
repository.remote_add_fetch("origin/master", "master")?;
|
||||
let mut index = repository.index()?;
|
||||
@ -119,6 +120,124 @@ fn test_commit_on_branch_then_change_file_then_get_status() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_track_binary_files() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = projects::Project::try_from(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let storage = storage::Storage::from_path(tempdir()?.path());
|
||||
let user_store = users::Storage::new(storage.clone());
|
||||
let project_store = projects::Storage::new(storage);
|
||||
project_store.add_project(&project)?;
|
||||
let gb_repo = gb_repository::Repository::open(
|
||||
gb_repo_path,
|
||||
project.id.clone(),
|
||||
project_store,
|
||||
user_store,
|
||||
)?;
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
let file_path = std::path::Path::new("test.txt");
|
||||
std::fs::write(
|
||||
std::path::Path::new(&project.path).join(file_path),
|
||||
"line1\nline2\nline3\nline4\n",
|
||||
)?;
|
||||
let file_path2 = std::path::Path::new("test2.txt");
|
||||
std::fs::write(
|
||||
std::path::Path::new(&project.path).join(file_path2),
|
||||
"line5\nline6\nline7\nline8\n",
|
||||
)?;
|
||||
// add a binary file
|
||||
let image_data: [u8; 12] = [
|
||||
255, 0, 0, // Red pixel
|
||||
0, 0, 255, // Blue pixel
|
||||
255, 255, 0, // Yellow pixel
|
||||
0, 255, 0, // Green pixel
|
||||
];
|
||||
let mut file = fs::File::create(std::path::Path::new(&project.path).join("image.bin"))?;
|
||||
file.write_all(&image_data)?;
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
remote_name: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
update_gitbutler_integration(&gb_repo, &project_repository)?;
|
||||
|
||||
let branch1_id = create_virtual_branch(&gb_repo, &BranchCreateRequest::default())
|
||||
.expect("failed to create virtual branch")
|
||||
.id;
|
||||
|
||||
// test file change
|
||||
std::fs::write(
|
||||
std::path::Path::new(&project.path).join(file_path2),
|
||||
"line5\nline6\nline7\nline8\nline9\n",
|
||||
)?;
|
||||
|
||||
// add a binary file
|
||||
let image_data: [u8; 12] = [
|
||||
255, 0, 0, // Red pixel
|
||||
0, 255, 0, // Green pixel
|
||||
0, 0, 255, // Blue pixel
|
||||
255, 255, 0, // Yellow pixel
|
||||
];
|
||||
let mut file = fs::File::create(std::path::Path::new(&project.path).join("image.bin"))?;
|
||||
file.write_all(&image_data)?;
|
||||
|
||||
let branches = list_virtual_branches(&gb_repo, &project_repository, true)?;
|
||||
let branch = &branches[0];
|
||||
assert_eq!(branch.files.len(), 2);
|
||||
let img_file = &branch
|
||||
.files
|
||||
.iter()
|
||||
.find(|b| b.path.as_os_str() == "image.bin")
|
||||
.unwrap();
|
||||
assert_eq!(img_file.binary, true);
|
||||
assert_eq!(
|
||||
img_file.hunks[0].diff,
|
||||
"944996dd82015a616247c72b251e41661e528ae1"
|
||||
);
|
||||
|
||||
// commit
|
||||
commit(&gb_repo, &project_repository, &branch1_id, "test commit")?;
|
||||
|
||||
// status (no files)
|
||||
let branches = list_virtual_branches(&gb_repo, &project_repository, true)?;
|
||||
let commit_id = &branches[0].commits[0].id;
|
||||
let commit_obj = repository.find_commit(git2::Oid::from_str(commit_id).unwrap())?;
|
||||
let tree = commit_obj.tree()?;
|
||||
let files = tree_to_entry_list(&repository, &tree)?;
|
||||
assert_eq!(files[0].0, "image.bin");
|
||||
assert_eq!(files[0].3, "944996dd82015a616247c72b251e41661e528ae1");
|
||||
|
||||
let image_data: [u8; 12] = [
|
||||
0, 255, 0, // Green pixel
|
||||
255, 0, 0, // Red pixel
|
||||
255, 255, 0, // Yellow pixel
|
||||
0, 0, 255, // Blue pixel
|
||||
];
|
||||
let mut file = fs::File::create(std::path::Path::new(&project.path).join("image.bin"))?;
|
||||
file.write_all(&image_data)?;
|
||||
|
||||
// commit
|
||||
commit(&gb_repo, &project_repository, &branch1_id, "test commit")?;
|
||||
|
||||
let branches = list_virtual_branches(&gb_repo, &project_repository, true)?;
|
||||
let commit_id = &branches[0].commits[0].id;
|
||||
// get tree from commit_id
|
||||
let commit_obj = repository.find_commit(git2::Oid::from_str(commit_id).unwrap())?;
|
||||
let tree = commit_obj.tree()?;
|
||||
let files = tree_to_entry_list(&repository, &tree)?;
|
||||
|
||||
assert_eq!(files[0].0, "image.bin");
|
||||
assert_eq!(files[0].3, "ea6901a04d1eed6ebf6822f4360bda9f008fa317");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_branch_with_ownership() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
@ -2533,7 +2652,7 @@ fn tree_to_file_list(repository: &git2::Repository, tree: &git2::Tree) -> Result
|
||||
fn tree_to_entry_list(
|
||||
repository: &git2::Repository,
|
||||
tree: &git2::Tree,
|
||||
) -> Result<Vec<(String, String, String)>> {
|
||||
) -> Result<Vec<(String, String, String, String)>> {
|
||||
let mut file_list = Vec::new();
|
||||
for entry in tree.iter() {
|
||||
let path = entry.name().unwrap();
|
||||
@ -2545,10 +2664,24 @@ fn tree_to_entry_list(
|
||||
.context(format!("failed to get object for tree entry {}", path))?;
|
||||
let blob = object.as_blob().context("failed to get blob")?;
|
||||
// convert content to string
|
||||
let content =
|
||||
std::str::from_utf8(blob.content()).context("failed to convert content to string")?;
|
||||
let octal_mode = format!("{:o}", entry.filemode());
|
||||
file_list.push((path.to_string(), octal_mode, content.to_string()));
|
||||
if let Ok(content) =
|
||||
std::str::from_utf8(blob.content()).context("failed to convert content to string")
|
||||
{
|
||||
file_list.push((
|
||||
path.to_string(),
|
||||
octal_mode,
|
||||
content.to_string(),
|
||||
blob.id().to_string(),
|
||||
));
|
||||
} else {
|
||||
file_list.push((
|
||||
path.to_string(),
|
||||
octal_mode,
|
||||
"BINARY".to_string(),
|
||||
blob.id().to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(file_list)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ export class File {
|
||||
modifiedAt!: Date;
|
||||
conflicted!: boolean;
|
||||
content!: string;
|
||||
binary!: boolean;
|
||||
}
|
||||
|
||||
export class Branch {
|
||||
|
@ -84,7 +84,7 @@
|
||||
class="flex w-full flex-col justify-center gap-2 border-b border-t border-light-400 bg-light-50 py-1 text-light-900 dark:border-dark-400 dark:bg-dark-800 dark:text-light-300"
|
||||
>
|
||||
<div
|
||||
class="flex pl-2 cursor-default"
|
||||
class="flex cursor-default pl-2"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
on:dblclick={() => {
|
||||
@ -116,10 +116,12 @@
|
||||
tabindex="0"
|
||||
class="cursor-pointer px-3 py-2 text-light-600 dark:text-dark-200"
|
||||
>
|
||||
{#if expanded}
|
||||
<IconTriangleUp />
|
||||
{:else}
|
||||
<IconTriangleDown />
|
||||
{#if !file.binary}
|
||||
{#if expanded}
|
||||
<IconTriangleUp />
|
||||
{:else}
|
||||
<IconTriangleDown />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<div
|
||||
id="new-branch-dz"
|
||||
role="group"
|
||||
class="h-full pt-6 flex w-[22.5rem] shrink-0 justify-center text-center text-light-800 dark:text-dark-100"
|
||||
class="flex h-full w-[22.5rem] shrink-0 justify-center pt-6 text-center text-light-800 dark:text-dark-100"
|
||||
use:dzHighlight={{ type: 'text/hunk', hover: 'drop-zone-hover', active: 'drop-zone-active' }}
|
||||
on:drop|stopPropagation={(e) => {
|
||||
if (!e.dataTransfer) {
|
||||
@ -33,7 +33,7 @@
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drop-zone-marker h-36 hidden border border-green-450 p-8">
|
||||
<div class="drop-zone-marker hidden h-36 border border-green-450 p-8">
|
||||
<div class="flex h-full flex-col items-center self-center p-2">
|
||||
<p>Drop here to create new virtual branch</p>
|
||||
</div>
|
||||
|
@ -43,7 +43,7 @@
|
||||
{line.afterLineNumber || ''}
|
||||
</div>
|
||||
<div
|
||||
class="flex-grow overflow-hidden pl-1 whitespace-pre"
|
||||
class="flex-grow overflow-hidden whitespace-pre pl-1"
|
||||
class:diff-line-deletion={sectionType === SectionType.RemovedLines}
|
||||
class:diff-line-addition={sectionType === SectionType.AddedLines}
|
||||
>
|
||||
|
@ -405,7 +405,8 @@ test('parses file with one hunk and balanced add-remove', () => {
|
||||
expanded: true,
|
||||
modifiedAt: new Date(2021, 1, 1),
|
||||
conflicted: false,
|
||||
content: fileContent
|
||||
content: fileContent,
|
||||
binary: false
|
||||
};
|
||||
const sections = parseFileSections(file);
|
||||
expect(sections.length).toBe(3);
|
||||
@ -462,7 +463,8 @@ test('parses file with one hunk with more added than removed', () => {
|
||||
expanded: true,
|
||||
modifiedAt: new Date(2021, 1, 1),
|
||||
conflicted: false,
|
||||
content: fileContent
|
||||
content: fileContent,
|
||||
binary: false
|
||||
};
|
||||
const sections = parseFileSections(file);
|
||||
expect(sections.length).toBe(3);
|
||||
@ -521,7 +523,8 @@ test('parses file with two hunks ordered by position in file', () => {
|
||||
expanded: true,
|
||||
modifiedAt: new Date(2021, 1, 1),
|
||||
conflicted: false,
|
||||
content: fileContent
|
||||
content: fileContent,
|
||||
binary: false
|
||||
};
|
||||
const sections = parseFileSections(file);
|
||||
expect(sections.length).toBe(3);
|
||||
@ -592,7 +595,8 @@ test('parses whole file deleted', () => {
|
||||
expanded: true,
|
||||
modifiedAt: new Date(2021, 1, 1),
|
||||
conflicted: false,
|
||||
content: fileContent
|
||||
content: fileContent,
|
||||
binary: false
|
||||
};
|
||||
const sections = parseFileSections(file);
|
||||
expect(sections.length).toBe(1);
|
||||
@ -617,7 +621,8 @@ test('parses new file created', () => {
|
||||
expanded: true,
|
||||
modifiedAt: new Date(2021, 1, 1),
|
||||
conflicted: false,
|
||||
content: fileContent
|
||||
content: fileContent,
|
||||
binary: false
|
||||
};
|
||||
const sections = parseFileSections(file);
|
||||
expect(sections.length).toBe(1);
|
||||
|
Loading…
Reference in New Issue
Block a user