#[cfg(feature = "dirty-tracker")]
use crate::dirty_tracker::{DirtyTreeTracker, State as DirtyTrackerState};
use crate::error::Error;
use crate::tree::PyTree;
use crate::workingtree::PyWorkingTree;
use pyo3::prelude::*;
#[cfg(feature = "dirty-tracker")]
pub fn reset_tree_with_dirty_tracker(
local_tree: &dyn PyWorkingTree,
basis_tree: Option<&dyn PyTree>,
subpath: Option<&std::path::Path>,
dirty_tracker: Option<&mut DirtyTreeTracker>,
) -> Result<(), Error> {
if let Some(dirty_tracker) = dirty_tracker {
if dirty_tracker.state() == DirtyTrackerState::Clean {
return Ok(());
}
}
reset_tree(local_tree, basis_tree, subpath)
}
pub fn reset_tree(
local_tree: &dyn PyWorkingTree,
basis_tree: Option<&dyn PyTree>,
subpath: Option<&std::path::Path>,
) -> Result<(), Error> {
let lock = local_tree.lock_write()?;
let result = Python::attach(|py| {
let workspace_m = py.import("breezy.workspace")?;
let reset_tree = workspace_m.getattr("reset_tree")?;
let local_tree: Py<PyAny> = local_tree.to_object(py);
let basis_tree: Option<Py<PyAny>> = basis_tree.map(|o| o.to_object(py));
let subpath_str = subpath.map(|p| p.to_string_lossy().replace('\\', "/"));
reset_tree.call1((local_tree, basis_tree, subpath_str))?;
Ok(())
});
drop(lock);
result
}
pub fn check_clean_tree(
local_tree: &dyn PyWorkingTree,
basis_tree: &dyn PyTree,
subpath: &std::path::Path,
) -> Result<(), Error> {
let lock = local_tree.lock_read()?;
let result = Python::attach(|py| {
let workspace_m = py.import("breezy.workspace")?;
let check_clean_tree = workspace_m.getattr("check_clean_tree")?;
let local_tree: Py<PyAny> = local_tree.to_object(py).clone_ref(py);
let basis_tree: Py<PyAny> = basis_tree.to_object(py).clone_ref(py);
let subpath_str = subpath.to_string_lossy().replace('\\', "/");
check_clean_tree.call1((local_tree, basis_tree, subpath_str))?;
Ok(())
});
drop(lock);
result
}
#[cfg(test)]
mod tests {
use super::*;
use crate::controldir::create_standalone_workingtree;
use crate::tree::MutableTree;
use crate::workingtree::WorkingTree;
use std::path::Path;
#[test]
fn test_reset_tree() {
let tmp_dir = tempfile::tempdir().unwrap();
let wt = create_standalone_workingtree(tmp_dir.path(), "2a").unwrap();
let basis_tree = wt.basis_tree().unwrap();
let result = reset_tree(&wt, Some(&basis_tree), None);
assert!(result.is_ok());
}
#[test]
fn test_reset_tree_no_basis() {
let tmp_dir = tempfile::tempdir().unwrap();
let wt = create_standalone_workingtree(tmp_dir.path(), "2a").unwrap();
let result = reset_tree(&wt, None, None);
assert!(result.is_ok());
}
#[test]
#[serial_test::serial]
#[cfg_attr(
windows,
ignore = "Breezy raises OSError errno 13 (ERROR_INVALID_DATA) on Windows when calling reset_tree with subpath - likely a Breezy bug"
)]
fn test_reset_tree_with_subpath() {
let env = crate::testing::TestEnv::new();
let wt = create_standalone_workingtree(&env.working_dir, "2a").unwrap();
std::fs::create_dir("subdir").unwrap();
std::fs::write("subdir/file.txt", "content").unwrap();
wt.add(&[Path::new("subdir")]).unwrap();
wt.add(&[Path::new("subdir/file.txt")]).unwrap();
wt.build_commit().message("Add subdir").commit().unwrap();
let basis_tree = wt.basis_tree().unwrap();
let subpath = Path::new("subdir");
let result = reset_tree(&wt, Some(&basis_tree), Some(subpath));
if let Err(e) = &result {
eprintln!("reset_tree failed with error: {:?}", e);
}
assert!(result.is_ok());
std::mem::drop(env); }
#[test]
#[serial_test::serial]
fn test_check_clean_tree() {
let env = crate::testing::TestEnv::new();
let wt = create_standalone_workingtree(&env.working_dir, "2a").unwrap();
std::fs::write(env.working_dir.join("file.txt"), "content").unwrap();
wt.add(&[Path::new("file.txt")]).unwrap();
wt.build_commit()
.message("Initial commit")
.commit()
.unwrap();
let basis_tree = wt.basis_tree().unwrap();
let subpath = Path::new("");
let result = check_clean_tree(&wt, &basis_tree, subpath);
assert!(result.is_ok());
std::mem::drop(env);
}
#[cfg(feature = "dirty-tracker")]
#[test]
fn test_reset_tree_with_dirty_tracker() {
use crate::dirty_tracker::DirtyTreeTracker;
let tmp_dir = tempfile::tempdir().unwrap();
let wt = create_standalone_workingtree(tmp_dir.path(), "2a").unwrap();
let basis_tree = wt.basis_tree().unwrap();
let mut dirty_tracker = DirtyTreeTracker::new(Clone::clone(&wt));
let result =
reset_tree_with_dirty_tracker(&wt, Some(&basis_tree), None, Some(&mut dirty_tracker));
assert!(result.is_ok());
}
}