status: use WorkingCopy status instead of static status

Summary:
Now that we share a working copy between Rust and Python, we can just
call status on it, instead of building a working copy in the static status
invocation.

Also moved last_write to become a parameter to status. Since we no longer create
a WorkingCopy explicitly for the status, we don't have the opportunity to set it
at that time. It probably didn't make sense to set it at working copy creation time
anyway.

Reviewed By: jordanwebster

Differential Revision: D39753347

fbshipit-source-id: c03777c084d3eea5b9d6f0b0cb59126c19f06588
This commit is contained in:
Durham Goode 2022-09-28 09:28:48 -07:00 committed by Facebook GitHub Bot
parent 6b0448a753
commit a2842e2d85
10 changed files with 39 additions and 137 deletions

View File

@ -953,29 +953,10 @@ class dirstate(object):
def _ruststatus(
self, match: "Callable[[str], bool]", ignored: bool, clean: bool, unknown: bool
) -> "scmutil.status":
if util.safehasattr(self._fs, "_fsmonitorstate"):
filesystem = "watchman"
elif "eden" in self._repo.requirements:
filesystem = "eden"
else:
filesystem = "normal"
if ignored or clean:
raise self.FallbackToPythonStatus
tree = self._repo._rsrepo.workingcopy().treestate()
return bindings.workingcopy.status.status(
self._root,
self._repo[self.p1()].manifest(),
self._repo.fileslog.filescmstore,
tree,
self._lastnormaltime,
match,
unknown,
filesystem,
self._ui._uiconfig._rcfg,
)
return self._repo._rsrepo.workingcopy().status(match, self._lastnormaltime)
@perftrace.tracefunc("Status")
def status(

View File

@ -18,28 +18,22 @@ use anyhow::anyhow;
use anyhow::Error;
use anyhow::Result;
use cpython::*;
use cpython_ext::convert::ImplInto;
use cpython_ext::error::ResultPyErrExt;
use cpython_ext::PyPathBuf;
use parking_lot::RwLock;
use pathmatcher::Matcher;
use pyconfigparser::config as PyConfig;
use pymanifest::treemanifest;
use pypathmatcher::extract_matcher;
use pypathmatcher::extract_option_matcher;
use pytreestate::treestate;
use rsworkingcopy::walker::WalkError;
use rsworkingcopy::walker::Walker;
use rsworkingcopy::workingcopy::WorkingCopy;
use storemodel::ReadFileContents;
type ArcReadFileContents = Arc<dyn ReadFileContents<Error = anyhow::Error> + Send + Sync>;
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
let name = [package, "workingcopy"].join(".");
let m = PyModule::new(py, &name)?;
m.add_class::<walker>(py)?;
m.add_class::<status>(py)?;
m.add_class::<workingcopy>(py)?;
Ok(m)
}
@ -88,63 +82,27 @@ py_class!(class walker |py| {
});
py_class!(class status |py| {
@staticmethod
def status(
pyroot: PyPathBuf,
pymanifest: treemanifest,
pystore: ImplInto<ArcReadFileContents>,
pytreestate: treestate,
last_write: u32,
pymatcher: Option<PyObject>,
listunknown: bool,
filesystem: &str,
config: PyConfig,
) -> PyResult<PyObject> {
let root = pyroot.to_path_buf();
let manifest = pymanifest.get_underlying(py);
let store = pystore.into();
let last_write = SystemTime::UNIX_EPOCH.checked_add(
Duration::from_secs(last_write.into())).ok_or_else(|| anyhow!("Failed to convert {} to SystemTime", last_write)
).map_pyerr(py)?;
let matcher = extract_option_matcher(py, pymatcher)?;
let filesystem = match filesystem {
"normal" => {
rsworkingcopy::filesystem::FileSystemType::Normal
},
"watchman" => {
rsworkingcopy::filesystem::FileSystemType::Watchman
},
"eden" => {
rsworkingcopy::filesystem::FileSystemType::Eden
},
_ => return Err(anyhow!("Unsupported filesystem type: {}", filesystem)).map_pyerr(py),
};
let treestate = pytreestate.get_state(py);
let config = config.get_cfg(py);
let status = py.allow_threads(|| rsworkingcopy::status::status(
root,
filesystem,
manifest,
store,
treestate,
last_write,
matcher,
listunknown,
&config,
));
let status = status.map_pyerr(py)?;
pystatus::to_python_status(py, &status)
}
});
py_class!(pub class workingcopy |py| {
data inner_wc: Arc<RwLock<WorkingCopy>>;
data inner: Arc<RwLock<WorkingCopy>>;
def treestate(&self) -> PyResult<treestate> {
treestate::create_instance(py, self.inner_wc(py).read().treestate())
treestate::create_instance(py, self.inner(py).read().treestate())
}
def status(
&self,
pymatcher: Option<PyObject>,
lastwrite: u32,
) -> PyResult<PyObject> {
let wc = self.inner(py).write();
let matcher = extract_option_matcher(py, pymatcher)?;
let last_write = SystemTime::UNIX_EPOCH.checked_add(
Duration::from_secs(lastwrite.into())).ok_or_else(|| anyhow!("Failed to convert {} to SystemTime", lastwrite)
).map_pyerr(py)?;
pystatus::to_python_status(py,
&py.allow_threads(|| {
wc.status(matcher, last_write)
}).map_pyerr(py)?
)
}
});

View File

@ -8,6 +8,7 @@
mod print;
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::Result;
use clidispatch::errors;
@ -163,7 +164,7 @@ pub fn run(ctx: ReqCtx<StatusOpts>, repo: &mut Repo, wc: &mut WorkingCopy) -> Re
let (status, copymap) = match repo.config().get_or_default("status", "use-rust")? {
true => {
let matcher = Arc::new(AlwaysMatcher::new());
let status = wc.status(matcher)?;
let status = wc.status(matcher, SystemTime::UNIX_EPOCH)?;
let copymap = wc.copymap()?.into_iter().collect();
(status, copymap)
}

View File

@ -10,7 +10,6 @@ use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::anyhow;
use anyhow::Result;
@ -418,7 +417,6 @@ impl Repo {
treestate,
tree_resolver,
file_store,
SystemTime::UNIX_EPOCH,
&self.config,
)?)
}

View File

@ -7,6 +7,7 @@
use std::path::PathBuf;
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::anyhow;
use anyhow::Result;
@ -32,6 +33,7 @@ impl PendingChanges for EdenFileSystem {
fn pending_changes(
&self,
_matcher: Arc<dyn Matcher + Send + Sync + 'static>,
_last_write: SystemTime,
) -> Result<Box<dyn Iterator<Item = Result<PendingChangeResult>>>> {
let result = edenfs_client::status::get_status(&self.root)?;
Ok(Box::new(result.status.entries.into_iter().filter_map(

View File

@ -6,6 +6,7 @@
*/
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::Result;
use pathmatcher::Matcher;
@ -37,5 +38,6 @@ pub trait PendingChanges {
fn pending_changes(
&self,
matcher: Arc<dyn Matcher + Send + Sync + 'static>,
last_write: SystemTime,
) -> Result<Box<dyn Iterator<Item = Result<PendingChangeResult>>>>;
}

View File

@ -8,6 +8,7 @@
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::Result;
use manifest_tree::ReadTreeManifest;
@ -23,7 +24,6 @@ use vfs::VFS;
use crate::filechangedetector::FileChangeDetector;
use crate::filechangedetector::FileChangeDetectorTrait;
use crate::filechangedetector::FileChangeResult;
use crate::filechangedetector::HgModifiedTime;
use crate::filechangedetector::ResolvedFileChangeResult;
use crate::filesystem::PendingChangeResult;
use crate::filesystem::PendingChanges as PendingChangesTrait;
@ -41,7 +41,6 @@ pub struct PhysicalFileSystem {
store: ArcReadFileContents,
treestate: Arc<Mutex<TreeState>>,
include_directories: bool,
last_write: HgModifiedTime,
num_threads: u8,
}
@ -52,7 +51,6 @@ impl PhysicalFileSystem {
store: ArcReadFileContents,
treestate: Arc<Mutex<TreeState>>,
include_directories: bool,
last_write: HgModifiedTime,
num_threads: u8,
) -> Result<Self> {
Ok(PhysicalFileSystem {
@ -61,7 +59,6 @@ impl PhysicalFileSystem {
store,
treestate,
include_directories,
last_write,
num_threads,
})
}
@ -71,6 +68,7 @@ impl PendingChangesTrait for PhysicalFileSystem {
fn pending_changes(
&self,
matcher: Arc<dyn Matcher + Send + Sync + 'static>,
last_write: SystemTime,
) -> Result<Box<dyn Iterator<Item = Result<PendingChangeResult>>>> {
let root = self.vfs.root().to_path_buf();
let ident = identity::must_sniff_dir(&root)?;
@ -86,7 +84,7 @@ impl PendingChangesTrait for PhysicalFileSystem {
let file_change_detector = FileChangeDetector::new(
self.treestate.clone(),
self.vfs.clone(),
self.last_write.clone(),
last_write.try_into()?,
manifests[0].clone(),
self.store.clone(),
);

View File

@ -7,12 +7,9 @@
use std::collections::HashMap;
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::Result;
use configparser::config::ConfigSet;
use manifest::Manifest;
use manifest_tree::ReadTreeManifest;
use manifest_tree::TreeManifest;
@ -22,17 +19,12 @@ use pathmatcher::ExactMatcher;
use pathmatcher::Matcher;
use status::Status;
use status::StatusBuilder;
use storemodel::ReadFileContents;
use treestate::filestate::StateFlags;
use treestate::treestate::TreeState;
use types::HgId;
use types::RepoPathBuf;
use crate::filesystem::ChangeType;
use crate::filesystem::FileSystemType;
use crate::workingcopy::WorkingCopy;
type ArcReadFileContents = Arc<dyn ReadFileContents<Error = anyhow::Error> + Send + Sync>;
struct FakeTreeResolver {
pub manifest: Arc<RwLock<TreeManifest>>,
@ -44,31 +36,6 @@ impl ReadTreeManifest for FakeTreeResolver {
}
}
pub fn status(
root: PathBuf,
file_system_type: FileSystemType,
manifest: Arc<RwLock<TreeManifest>>,
store: ArcReadFileContents,
treestate: Arc<Mutex<TreeState>>,
last_write: SystemTime,
matcher: Arc<dyn Matcher + Send + Sync + 'static>,
_list_unknown: bool,
config: &ConfigSet,
) -> Result<Status> {
let manifest_resolver = Arc::new(FakeTreeResolver { manifest });
let working_copy = WorkingCopy::new(
root,
file_system_type,
treestate,
manifest_resolver,
store,
last_write,
config,
)?;
working_copy.status(matcher)
}
/// Compute the status of the working copy relative to the current commit.
#[allow(unused_variables)]
pub fn compute_status(

View File

@ -7,6 +7,7 @@
use std::path::PathBuf;
use std::sync::Arc;
use std::time::SystemTime;
use anyhow::Result;
use manifest_tree::ReadTreeManifest;
@ -21,7 +22,6 @@ use super::state::WatchmanState;
use super::treestate::WatchmanTreeState;
use crate::filechangedetector::ArcReadFileContents;
use crate::filechangedetector::FileChangeDetector;
use crate::filechangedetector::HgModifiedTime;
use crate::filesystem::PendingChangeResult;
use crate::filesystem::PendingChanges;
use crate::workingcopy::WorkingCopy;
@ -33,7 +33,6 @@ pub struct WatchmanFileSystem {
treestate: Arc<Mutex<TreeState>>,
tree_resolver: ArcReadTreeManifest,
store: ArcReadFileContents,
last_write: HgModifiedTime,
}
impl WatchmanFileSystem {
@ -42,14 +41,12 @@ impl WatchmanFileSystem {
treestate: Arc<Mutex<TreeState>>,
tree_resolver: ArcReadTreeManifest,
store: ArcReadFileContents,
last_write: HgModifiedTime,
) -> Result<Self> {
Ok(WatchmanFileSystem {
vfs: VFS::new(root)?,
treestate,
tree_resolver,
store,
last_write,
})
}
@ -84,6 +81,7 @@ impl PendingChanges for WatchmanFileSystem {
fn pending_changes(
&self,
_matcher: Arc<dyn Matcher + Send + Sync + 'static>,
last_write: SystemTime,
) -> Result<Box<dyn Iterator<Item = Result<PendingChangeResult>>>> {
let state = WatchmanState::new(WatchmanTreeState {
treestate: self.treestate.clone(),
@ -97,7 +95,7 @@ impl PendingChanges for WatchmanFileSystem {
let file_change_detector = FileChangeDetector::new(
self.treestate.clone(),
self.vfs.clone(),
self.last_write.clone(),
last_write.try_into()?,
manifests[0].clone(),
self.store.clone(),
);

View File

@ -35,7 +35,6 @@ use types::RepoPathBuf;
#[cfg(feature = "eden")]
use crate::edenfs::EdenFileSystem;
use crate::filechangedetector::HgModifiedTime;
use crate::filesystem::FileSystemType;
use crate::filesystem::PendingChangeResult;
use crate::filesystem::PendingChanges;
@ -74,7 +73,6 @@ impl WorkingCopy {
treestate: Arc<Mutex<TreeState>>,
tree_resolver: ArcReadTreeManifest,
filestore: ArcReadFileContents,
last_write: SystemTime,
config: &ConfigSet,
) -> Result<Self> {
tracing::debug!(target: "dirstate_size", dirstate_size=treestate.lock().len());
@ -93,7 +91,6 @@ impl WorkingCopy {
treestate.clone(),
tree_resolver.clone(),
filestore,
last_write,
)?);
Ok(WorkingCopy {
@ -144,9 +141,7 @@ impl WorkingCopy {
treestate: Arc<Mutex<TreeState>>,
tree_resolver: ArcReadTreeManifest,
store: ArcReadFileContents,
last_write: SystemTime,
) -> Result<FileSystem> {
let last_write: HgModifiedTime = last_write.try_into()?;
let inner: Box<dyn PendingChanges + Send> = match file_system_type {
FileSystemType::Normal => Box::new(PhysicalFileSystem::new(
root.clone(),
@ -154,7 +149,6 @@ impl WorkingCopy {
store.clone(),
treestate.clone(),
false,
last_write,
8,
)?),
FileSystemType::Watchman => Box::new(WatchmanFileSystem::new(
@ -162,7 +156,6 @@ impl WorkingCopy {
treestate.clone(),
tree_resolver,
store.clone(),
last_write,
)?),
FileSystemType::Eden => {
#[cfg(not(feature = "eden"))]
@ -238,7 +231,11 @@ impl WorkingCopy {
Ok(Arc::new(UnionMatcher::new(sparse_matchers)))
}
pub fn status(&self, matcher: Arc<dyn Matcher + Send + Sync + 'static>) -> Result<Status> {
pub fn status(
&self,
matcher: Arc<dyn Matcher + Send + Sync + 'static>,
last_write: SystemTime,
) -> Result<Status> {
let added_files = self.added_files()?;
let manifests =
@ -269,7 +266,7 @@ impl WorkingCopy {
.filesystem
.lock()
.inner
.pending_changes(matcher.clone())?
.pending_changes(matcher.clone(), last_write)?
.filter_map(|result| match result {
Ok(PendingChangeResult::File(change_type)) => {
match matcher.matches_file(change_type.get_path()) {