mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-02 07:53:55 +03:00
fix: handle symlinks correctly when adding and flushing files in the repository
This commit is contained in:
parent
2f4e26475e
commit
0edbfc1a54
@ -802,16 +802,24 @@ fn add_wd_path(
|
||||
) -> Result<()> {
|
||||
let file_path = dir.join(rel_file_path);
|
||||
|
||||
let metadata = file_path
|
||||
.metadata()
|
||||
.with_context(|| "failed to get metadata for".to_string())?;
|
||||
let metadata = std::fs::symlink_metadata(&file_path).context("failed to get metadata for")?;
|
||||
let modify_time = FileTime::from_last_modification_time(&metadata);
|
||||
let create_time = FileTime::from_creation_time(&metadata).unwrap_or(modify_time);
|
||||
|
||||
// look for files that are bigger than 4GB, which are not supported by git
|
||||
// insert a pointer as the blob content instead
|
||||
// TODO: size limit should be configurable
|
||||
let blob = if metadata.len() > 100_000_000 {
|
||||
let blob = if metadata.is_symlink() {
|
||||
// it's a symlink, make the content the path of the link
|
||||
let link_target = std::fs::read_link(&file_path)?;
|
||||
// if the link target is inside the project repository, make it relative
|
||||
let link_target = link_target.strip_prefix(dir).unwrap_or(&link_target);
|
||||
// bytes dance
|
||||
let path_str = link_target.to_str().unwrap();
|
||||
let bytes: &[u8] = path_str.as_bytes();
|
||||
|
||||
gb_repository.git_repository.blob(bytes)?
|
||||
} else if metadata.len() > 100_000_000 {
|
||||
tracing::warn!(
|
||||
project_id = %gb_repository.project.id,
|
||||
path = %file_path.display(),
|
||||
@ -837,10 +845,7 @@ fn add_wd_path(
|
||||
let lfs_path = lfs_objects_dir.join(sha);
|
||||
std::fs::copy(file_path, lfs_path)?;
|
||||
|
||||
gb_repository
|
||||
.git_repository
|
||||
.blob(lfs_pointer.as_bytes())
|
||||
.unwrap()
|
||||
gb_repository.git_repository.blob(lfs_pointer.as_bytes())?
|
||||
} else {
|
||||
// read the file into a blob, get the object id
|
||||
gb_repository.git_repository.blob_path(&file_path)?
|
||||
|
97
packages/tauri/tests/gb_repository/mod.rs
Normal file
97
packages/tauri/tests/gb_repository/mod.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use gblib::{gb_repository, project_repository, projects};
|
||||
|
||||
use crate::{common::TestProject, paths};
|
||||
|
||||
mod init {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn handle_file_symlink() {
|
||||
let test_project = TestProject::default();
|
||||
|
||||
let data_dir = paths::data_dir();
|
||||
let projects = projects::Controller::from(&data_dir);
|
||||
|
||||
let project = projects
|
||||
.add(test_project.path())
|
||||
.expect("failed to add project");
|
||||
|
||||
std::fs::write(project.path.join("file"), "content").unwrap();
|
||||
std::fs::hard_link(project.path.join("file"), project.path.join("link")).unwrap();
|
||||
|
||||
let project_repository = project_repository::Repository::try_from(project).unwrap();
|
||||
|
||||
gb_repository::Repository::open(&data_dir, &project_repository, None).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_dir_symlink() {
|
||||
let test_project = TestProject::default();
|
||||
|
||||
let data_dir = paths::data_dir();
|
||||
let projects = projects::Controller::from(&data_dir);
|
||||
|
||||
let project = projects
|
||||
.add(test_project.path())
|
||||
.expect("failed to add project");
|
||||
|
||||
std::fs::create_dir(project.path.join("dir")).unwrap();
|
||||
std::fs::write(project.path.join("dir/file"), "content").unwrap();
|
||||
std::os::unix::fs::symlink(project.path.join("dir"), project.path.join("dir_link"))
|
||||
.unwrap();
|
||||
|
||||
let project_repository = project_repository::Repository::try_from(project).unwrap();
|
||||
|
||||
gb_repository::Repository::open(&data_dir, &project_repository, None).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
mod flush {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn handle_file_symlink() {
|
||||
let test_project = TestProject::default();
|
||||
|
||||
let data_dir = paths::data_dir();
|
||||
let projects = projects::Controller::from(&data_dir);
|
||||
|
||||
let project = projects
|
||||
.add(test_project.path())
|
||||
.expect("failed to add project");
|
||||
|
||||
let project_repository = project_repository::Repository::try_from(&project).unwrap();
|
||||
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(&data_dir, &project_repository, None).unwrap();
|
||||
|
||||
std::fs::write(project.path.join("file"), "content").unwrap();
|
||||
std::fs::hard_link(project.path.join("file"), project.path.join("link")).unwrap();
|
||||
|
||||
gb_repo.flush(&project_repository, None).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_dir_symlink() {
|
||||
let test_project = TestProject::default();
|
||||
|
||||
let data_dir = paths::data_dir();
|
||||
let projects = projects::Controller::from(&data_dir);
|
||||
|
||||
let project = projects
|
||||
.add(test_project.path())
|
||||
.expect("failed to add project");
|
||||
|
||||
let project_repository = project_repository::Repository::try_from(&project).unwrap();
|
||||
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(&data_dir, &project_repository, None).unwrap();
|
||||
|
||||
std::fs::create_dir(project.path.join("dir")).unwrap();
|
||||
std::fs::write(project.path.join("dir/file"), "content").unwrap();
|
||||
std::os::unix::fs::symlink(project.path.join("dir"), project.path.join("dir_link"))
|
||||
.unwrap();
|
||||
|
||||
gb_repo.flush(&project_repository, None).unwrap();
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#![allow(clippy::dbg_macro)]
|
||||
|
||||
mod common;
|
||||
mod gb_repository;
|
||||
mod paths;
|
||||
mod projects;
|
||||
mod virtual_branches;
|
||||
|
Loading…
Reference in New Issue
Block a user