mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-28 20:15:20 +03:00
Edit trees directly when running create_wd_tree()
to bypass the index.
This commit is contained in:
parent
099ac50f5d
commit
31626b726b
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -2716,6 +2716,7 @@ dependencies = [
|
||||
"gix-revision",
|
||||
"gix-revwalk 0.15.0",
|
||||
"gix-sec 0.10.8 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
"gix-status",
|
||||
"gix-submodule",
|
||||
"gix-tempfile 14.0.2 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
"gix-trace 0.1.10 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
@ -3573,6 +3574,28 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-status"
|
||||
version = "0.13.0"
|
||||
source = "git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a#72daa46bad9d397ef2cc48a3cffda23f414ccd8a"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"filetime",
|
||||
"gix-diff",
|
||||
"gix-dir",
|
||||
"gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
"gix-filter",
|
||||
"gix-fs 0.11.3 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
"gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
"gix-index 0.35.0",
|
||||
"gix-object 0.44.0",
|
||||
"gix-path 0.10.11 (git+https://github.com/Byron/gitoxide?rev=72daa46bad9d397ef2cc48a3cffda23f414ccd8a)",
|
||||
"gix-pathspec",
|
||||
"gix-worktree 0.36.0",
|
||||
"portable-atomic",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gix-submodule"
|
||||
version = "0.14.0"
|
||||
@ -5827,6 +5850,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
|
@ -7,7 +7,7 @@ publish = false
|
||||
|
||||
[dependencies]
|
||||
git2.workspace = true
|
||||
gix.workspace = true
|
||||
gix = { workspace = true, features = ["status", "tree-editor"] }
|
||||
anyhow = "1.0.86"
|
||||
bstr.workspace = true
|
||||
tokio = { workspace = true, features = [
|
||||
|
@ -5,13 +5,14 @@ use std::os::windows::process::CommandExt;
|
||||
use std::{io::Write, path::Path, process::Stdio, str};
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use bstr::BString;
|
||||
use bstr::{BString, ByteSlice};
|
||||
use git2::{BlameOptions, Tree};
|
||||
use gitbutler_branch::{gix_to_git2_signature, SignaturePurpose};
|
||||
use gitbutler_commit::{commit_buffer::CommitBuffer, commit_headers::CommitHeadersV2};
|
||||
use gitbutler_config::git::{GbConfig, GitConfig};
|
||||
use gitbutler_error::error::Code;
|
||||
use gitbutler_reference::{Refname, RemoteRefname};
|
||||
use gix::status::plumbing::index_as_worktree::{Change, EntryStatus};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::{Config, LogUntil};
|
||||
@ -147,14 +148,76 @@ impl RepositoryExt for git2::Repository {
|
||||
}
|
||||
}
|
||||
|
||||
/// Note that this will add all untracked files in the worktree to the index,
|
||||
/// and write a tree from it.
|
||||
/// The index won't be stored though.
|
||||
/// Note that this will add all untracked and modified files in the worktree to
|
||||
/// the object database, and create a tree from it.
|
||||
///
|
||||
/// Note that right now, it doesn't skip big files.
|
||||
#[instrument(level = tracing::Level::DEBUG, skip(self), err(Debug))]
|
||||
fn create_wd_tree(&self) -> Result<Tree> {
|
||||
let mut index = self.index()?;
|
||||
index.add_all(["*"], git2::IndexAddOption::DEFAULT, None)?;
|
||||
let oid = index.write_tree()?;
|
||||
let repo = gix::open(self.path())?;
|
||||
let workdir = repo.work_dir().context("Need non-bare repository")?;
|
||||
let mut head_tree_editor = repo.edit_tree(repo.head_tree_id()?)?;
|
||||
let status_changes = repo
|
||||
.status(gix::progress::Discard)?
|
||||
.index_worktree_rewrites(None)
|
||||
.index_worktree_submodules(None)
|
||||
.into_index_worktree_iter(None::<BString>)?;
|
||||
for change in status_changes {
|
||||
let change = change?;
|
||||
match change {
|
||||
// modified or tracked files are unconditionally added as blob.
|
||||
gix::status::index_worktree::iter::Item::Modification {
|
||||
rela_path,
|
||||
status: EntryStatus::Change(Change::Type | Change::Modification { .. }),
|
||||
..
|
||||
}
|
||||
| gix::status::index_worktree::iter::Item::DirectoryContents {
|
||||
entry:
|
||||
gix::dir::Entry {
|
||||
rela_path,
|
||||
status: gix::dir::entry::Status::Untracked,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
let path = workdir.join(gix::path::from_bstr(&rela_path));
|
||||
let Ok(md) = std::fs::symlink_metadata(&path) else {
|
||||
continue;
|
||||
};
|
||||
let (id, kind) = if md.is_symlink() {
|
||||
let target = std::fs::read_link(&path).with_context(|| {
|
||||
format!(
|
||||
"Failed to read link at '{}' for adding to the object database",
|
||||
path.display()
|
||||
)
|
||||
})?;
|
||||
let id = repo.write_blob(gix::path::into_bstr(target).as_bytes())?;
|
||||
(id, gix::object::tree::EntryKind::Link)
|
||||
} else {
|
||||
let mut file = std::fs::File::open(&path).with_context(|| {
|
||||
format!(
|
||||
"Could not open file at '{}' for adding it to the object database",
|
||||
path.display()
|
||||
)
|
||||
})?;
|
||||
let kind = if gix::fs::is_executable(&md) {
|
||||
gix::object::tree::EntryKind::BlobExecutable
|
||||
} else {
|
||||
gix::object::tree::EntryKind::Blob
|
||||
};
|
||||
(repo.write_blob_stream(&mut file)?, kind)
|
||||
};
|
||||
|
||||
head_tree_editor.upsert(rela_path, kind, id)?;
|
||||
}
|
||||
gix::status::index_worktree::iter::Item::Rewrite { .. } => {
|
||||
unreachable!("disabled")
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let oid = git2::Oid::from_bytes(head_tree_editor.write()?.as_bytes())?;
|
||||
self.find_tree(oid).map(Into::into).map_err(Into::into)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user