Skip to content

Commit ce42465

Browse files
committed
Add V3 support for discarding files
For now, no hunks or hunk-ranges.
1 parent be56afd commit ce42465

File tree

15 files changed

+773
-23
lines changed

15 files changed

+773
-23
lines changed

Cargo.lock

Lines changed: 40 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/but-testsupport/src/lib.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ pub fn visualize_commit_graph(
9090
Ok(log.stdout.to_str().expect("no illformed UTF-8").to_string())
9191
}
9292

93+
/// Run a condensed status on `repo`.
94+
pub fn git_status(repo: &gix::Repository) -> std::io::Result<String> {
95+
let out = git(repo).args(["status", "--porcelain"]).output()?;
96+
assert!(out.status.success());
97+
Ok(out.stdout.to_str().expect("no illformed UTF-8").to_string())
98+
}
99+
93100
/// Display a Git tree in the style of the `tree` CLI program, but include blob contents and usful Git metadata.
94101
pub fn visualize_tree(tree_id: gix::Id<'_>) -> termtree::Tree<String> {
95102
fn visualize_tree(
@@ -141,3 +148,51 @@ pub fn visualize_tree(tree_id: gix::Id<'_>) -> termtree::Tree<String> {
141148
}
142149
visualize_tree(tree_id.object().unwrap().peel_to_tree().unwrap().id(), None).unwrap()
143150
}
151+
152+
/// Visualize a tree on disk with mode information.
153+
/// For convenience, skip `.git` and don't display the root.
154+
///
155+
/// # IMPORTANT: Portability
156+
///
157+
/// As it's intended for tests, this can't be called on Windows were modes don't exist.
158+
/// Further, be sure to set the `umask` of the process to something explicit, or else it may differ
159+
/// between runs and cause failures.
160+
#[cfg(unix)]
161+
pub fn visualize_disk_tree_skip_dot_git(root: &Path) -> anyhow::Result<termtree::Tree<String>> {
162+
use std::os::unix::fs::MetadataExt;
163+
fn label(p: &Path, md: &std::fs::Metadata) -> String {
164+
format!(
165+
"{name}:{mode:o}",
166+
name = p.file_name().unwrap().to_str().unwrap(),
167+
mode = md.mode(),
168+
)
169+
}
170+
171+
fn tree(p: &Path, show_label: bool) -> std::io::Result<termtree::Tree<String>> {
172+
let mut cur = termtree::Tree::new(if show_label {
173+
label(p, &p.symlink_metadata()?)
174+
} else {
175+
".".into()
176+
});
177+
178+
let mut entries: Vec<_> = std::fs::read_dir(p)?.filter_map(|e| e.ok()).collect();
179+
entries.sort_by_key(|e| e.file_name());
180+
for entry in entries {
181+
let md = entry.metadata()?;
182+
if md.is_dir() && entry.file_name() != ".git" {
183+
cur.push(tree(&entry.path(), true)?);
184+
} else {
185+
cur.push(termtree::Tree::new(label(&entry.path(), &md)));
186+
}
187+
}
188+
Ok(cur)
189+
}
190+
191+
Ok(tree(root, false)?)
192+
}
193+
194+
/// Windows dummy
195+
#[cfg(not(unix))]
196+
pub fn visualize_disk_tree(root: &Path) -> anyhow::Result<termtree::Tree<String>> {
197+
anyhow::bail!("BUG: must not run on Windows - results won't be desirable");
198+
}

crates/but-workspace/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ toml.workspace = true
3434
tracing.workspace = true
3535

3636
[dev-dependencies]
37+
rustix = { version = "1.0.2", features = ["process", "fs"] }
3738
but-testsupport.workspace = true
3839
insta = "1.42.1"
3940
but-core = { workspace = true, features = ["testing"] }

crates/but-workspace/src/commit_engine/index.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub fn apply_lhs_to_rhs(
5252
&md,
5353
id.into_owned(),
5454
entry_mode,
55+
gix::index::entry::Flags::empty(),
5556
&mut num_sorted_entries,
5657
)?;
5758
}
@@ -72,12 +73,13 @@ pub fn apply_lhs_to_rhs(
7273
// TODO(gix): this could be a platform in Gix which supports these kinds of edits while assuring
7374
// consistency. It could use some tricks to not have worst-case performance like this has.
7475
// It really is index-add that we need.
75-
fn upsert_index_entry(
76+
pub fn upsert_index_entry(
7677
index: &mut gix::index::State,
7778
rela_path: &BStr,
7879
md: &gix::index::fs::Metadata,
7980
id: gix::ObjectId,
8081
mode: gix::index::entry::Mode,
82+
add_flags: gix::index::entry::Flags,
8183
num_sorted_entries: &mut usize,
8284
) -> anyhow::Result<bool> {
8385
use gix::index::entry::Stage;
@@ -100,14 +102,15 @@ fn upsert_index_entry(
100102
// This basically forces it to look closely, bad for performance, but at
101103
// least correct. Usually it fixes itself as well.
102104
entry.stat = Default::default();
105+
entry.flags |= add_flags;
103106
entry.id = id;
104107
entry.mode = mode;
105108
false
106109
} else {
107110
index.dangerously_push_entry(
108111
gix::index::entry::Stat::from_fs(md)?,
109112
id,
110-
gix::index::entry::Flags::empty(),
113+
add_flags,
111114
mode,
112115
rela_path,
113116
);

crates/but-workspace/src/commit_engine/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mod tree;
1616
use crate::commit_engine::reference_frame::InferenceMode;
1717
use tree::{CreateTreeOutcome, create_tree};
1818

19-
mod index;
19+
pub(crate) mod index;
2020
/// Utility types
2121
pub mod reference_frame;
2222
mod refs;

crates/but-workspace/src/commit_engine/tree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ fn apply_worktree_changes<'repo>(
263263
entry.object()?.detach().data
264264
} else if entry.mode().is_blob() {
265265
let mut obj_in_git = entry.object()?;
266+
266267
match pipeline.convert_to_worktree(
267268
&obj_in_git.data,
268269
base_rela_path,

0 commit comments

Comments
 (0)