manifest: rename FsNode to FsNodeMetadata

Summary:
Consistency in naming. The general idea is to have Metadata types that don't
contain paths. Then we will have File, Directory and eventually FsNode that
will contain paths.

Reviewed By: quark-zju

Differential Revision: D18870141

fbshipit-source-id: a1f09add7f1c3dd4fa0348693cd3ce2fd5767fa7
This commit is contained in:
Stefan Filip 2019-12-10 10:15:53 -08:00 committed by Facebook Github Bot
parent 05aa630a18
commit 67b0e3a600
6 changed files with 72 additions and 58 deletions

View File

@ -16,7 +16,7 @@ use cpython::*;
use cpython_ext::{pyset_add, pyset_new};
use cpython_failure::ResultPyErrExt;
use encoding::{local_bytes_to_repo_path, repo_path_to_local_bytes};
use manifest::{DiffType, File, FileMetadata, FileType, FsNode, Manifest};
use manifest::{DiffType, File, FileMetadata, FileType, FsNodeMetadata, Manifest};
use manifest_tree::TreeManifest;
use pathmatcher::{AlwaysMatcher, Matcher, TreeMatcher};
use pypathmatcher::PythonMatcher;
@ -162,7 +162,7 @@ py_class!(class treemanifest |py| {
let repo_path = pybytes_to_path(py, path);
let tree = self.underlying(py).borrow();
let result = match tree.get(&repo_path).map_pyerr::<exc::RuntimeError>(py)? {
Some(FsNode::Directory(_)) => true,
Some(FsNodeMetadata::Directory(_)) => true,
_ => false
};
Ok(result)

View File

@ -11,7 +11,7 @@
use crate::raw::CBytes;
use anyhow::{format_err, Result};
use manifest::{FileType, FsNode};
use manifest::{FileType, FsNodeMetadata};
use manifest_tree::List;
use std::convert::TryFrom;
use types::PathComponentBuf;
@ -45,10 +45,12 @@ pub struct TreeEntry {
}
impl TreeEntry {
fn try_from_path_node(path: PathComponentBuf, node: FsNode) -> Result<Self> {
fn try_from_path_node(path: PathComponentBuf, node: FsNodeMetadata) -> Result<Self> {
let (ttype, hash) = match node {
FsNode::Directory(Some(hgid)) => (TreeEntryType::Tree, hgid.as_ref().to_vec()),
FsNode::File(metadata) => (metadata.file_type.into(), metadata.hgid.as_ref().to_vec()),
FsNodeMetadata::Directory(Some(hgid)) => (TreeEntryType::Tree, hgid.as_ref().to_vec()),
FsNodeMetadata::File(metadata) => {
(metadata.file_type.into(), metadata.hgid.as_ref().to_vec())
}
_ => return Err(format_err!("received an ephemeral directory")),
};

View File

@ -9,7 +9,7 @@ use std::collections::{btree_map, VecDeque};
use anyhow::{Error, Result};
use manifest::FsNode;
use manifest::FsNodeMetadata;
use pathmatcher::Matcher;
use types::{Key, PathComponentBuf, RepoPath, RepoPathBuf};
@ -52,13 +52,15 @@ impl<'a> BfsIter<'a> {
}
impl<'a> Iterator for BfsIter<'a> {
type Item = Result<(RepoPathBuf, FsNode)>;
type Item = Result<(RepoPathBuf, FsNodeMetadata)>;
fn next(&mut self) -> Option<Self::Item> {
let (path, children, hgid) = match self.queue.pop_front() {
None => return None,
Some((path, link)) => match link {
Link::Leaf(file_metadata) => return Some(Ok((path, FsNode::File(*file_metadata)))),
Link::Leaf(file_metadata) => {
return Some(Ok((path, FsNodeMetadata::File(*file_metadata))))
}
Link::Ephemeral(children) => (path, children, None),
Link::Durable(entry) => loop {
match entry.get_links() {
@ -81,7 +83,7 @@ impl<'a> Iterator for BfsIter<'a> {
self.queue.push_back((child_path, &link));
}
}
Some(Ok((path, FsNode::Directory(hgid))))
Some(Ok((path, FsNodeMetadata::Directory(hgid))))
}
}

View File

@ -24,7 +24,7 @@ use crypto::{digest::Digest, sha1::Sha1};
use once_cell::sync::OnceCell;
use thiserror::Error;
use manifest::{DiffEntry, Directory, File, FileMetadata, FsNode, Manifest};
use manifest::{DiffEntry, Directory, File, FileMetadata, FsNodeMetadata, Manifest};
use pathmatcher::Matcher;
use types::{HgId, Key, PathComponent, PathComponentBuf, RepoPath, RepoPathBuf};
@ -94,7 +94,7 @@ impl TreeManifest {
}
impl Manifest for TreeManifest {
fn get(&self, path: &RepoPath) -> Result<Option<FsNode>> {
fn get(&self, path: &RepoPath) -> Result<Option<FsNodeMetadata>> {
let result = self.get_link(path)?.map(|link| link.to_fs_node());
Ok(result)
}
@ -264,7 +264,7 @@ impl Manifest for TreeManifest {
matcher: &'a M,
) -> Box<dyn Iterator<Item = Result<File>> + 'a> {
let files = BfsIter::new(&self, matcher).filter_map(|result| match result {
Ok((path, FsNode::File(metadata))) => Some(Ok(File::new(path, metadata))),
Ok((path, FsNodeMetadata::File(metadata))) => Some(Ok(File::new(path, metadata))),
Ok(_) => None,
Err(e) => Some(Err(e)),
});
@ -281,7 +281,9 @@ impl Manifest for TreeManifest {
matcher: &'a M,
) -> Box<dyn Iterator<Item = Result<Directory>> + 'a> {
let dirs = BfsIter::new(&self, matcher).filter_map(|result| match result {
Ok((path, FsNode::Directory(metadata))) => Some(Ok(Directory::new(path, metadata))),
Ok((path, FsNodeMetadata::Directory(metadata))) => {
Some(Ok(Directory::new(path, metadata)))
}
Ok(_) => None,
Err(e) => Some(Err(e)),
});
@ -539,7 +541,7 @@ impl TreeManifest {
pub enum List {
NotFound,
File,
Directory(Vec<(PathComponentBuf, FsNode)>),
Directory(Vec<(PathComponentBuf, FsNodeMetadata)>),
}
/// The purpose of this function is to provide compatible behavior with the C++ implementation
@ -823,11 +825,11 @@ mod tests {
.unwrap();
assert_eq!(
tree.get(repo_path("foo/bar")).unwrap(),
Some(FsNode::Directory(None))
Some(FsNodeMetadata::Directory(None))
);
assert_eq!(
tree.get(repo_path("foo")).unwrap(),
Some(FsNode::Directory(None))
Some(FsNodeMetadata::Directory(None))
);
}
@ -865,7 +867,7 @@ mod tests {
assert_eq!(tree.get(repo_path("a1/b1/c1")).unwrap(), None);
assert_eq!(
tree.get(repo_path("a1/b2")).unwrap(),
Some(FsNode::File(make_meta("20")))
Some(FsNodeMetadata::File(make_meta("20")))
);
assert_eq!(
tree.remove(repo_path("a1/b2")).unwrap(),
@ -875,7 +877,7 @@ mod tests {
assert_eq!(
tree.get(repo_path("a2/b2/c2")).unwrap(),
Some(FsNode::File(make_meta("30")))
Some(FsNodeMetadata::File(make_meta("30")))
);
assert_eq!(
tree.remove(repo_path("a2/b2/c2")).unwrap(),
@ -885,7 +887,7 @@ mod tests {
assert_eq!(
tree.get(RepoPath::empty()).unwrap(),
Some(FsNode::Directory(None))
Some(FsNodeMetadata::Directory(None))
);
}
@ -913,7 +915,7 @@ mod tests {
assert_eq!(
tree.get(RepoPath::empty()).unwrap(),
Some(FsNode::Directory(Some(tree_hgid)))
Some(FsNodeMetadata::Directory(Some(tree_hgid)))
);
assert_eq!(tree.remove(repo_path("a1")).unwrap(), None);
assert_eq!(
@ -923,7 +925,7 @@ mod tests {
assert_eq!(tree.get(repo_path("a1/b1")).unwrap(), None);
assert_eq!(
tree.get(repo_path("a1/b2")).unwrap(),
Some(FsNode::File(make_meta("12")))
Some(FsNodeMetadata::File(make_meta("12")))
);
assert_eq!(
tree.remove(repo_path("a1/b2")).unwrap(),
@ -935,13 +937,13 @@ mod tests {
assert_eq!(
tree.get(repo_path("a2")).unwrap(),
Some(FsNode::File(make_meta("20")))
Some(FsNodeMetadata::File(make_meta("20")))
);
assert_eq!(tree.remove(repo_path("a2")).unwrap(), Some(make_meta("20")));
assert_eq!(tree.get(repo_path("a2")).unwrap(), None);
assert_eq!(
tree.get(RepoPath::empty()).unwrap(),
Some(FsNode::Directory(None))
Some(FsNodeMetadata::Directory(None))
);
}
@ -1450,7 +1452,10 @@ mod tests {
assert_eq!(tree.list(repo_path("a1/b1/c1")).unwrap(), List::File);
assert_eq!(
tree.list(repo_path("a1/b1")).unwrap(),
List::Directory(vec![(path_component_buf("c1"), FsNode::File(c1_meta))]),
List::Directory(vec![(
path_component_buf("c1"),
FsNodeMetadata::File(c1_meta)
)]),
);
assert_eq!(
tree.list(repo_path("a1")).unwrap(),
@ -1459,19 +1464,22 @@ mod tests {
path_component_buf("b1"),
tree.get(repo_path("a1/b1")).unwrap().unwrap()
),
(path_component_buf("b2"), FsNode::File(b2_meta)),
(path_component_buf("b2"), FsNodeMetadata::File(b2_meta)),
]),
);
assert_eq!(tree.list(repo_path("a2/b3/c2")).unwrap(), List::File);
assert_eq!(
tree.list(repo_path("a2/b3")).unwrap(),
List::Directory(vec![(path_component_buf("c2"), FsNode::File(c2_meta))]),
List::Directory(vec![(
path_component_buf("c2"),
FsNodeMetadata::File(c2_meta)
)]),
);
assert_eq!(
tree.list(repo_path("a2")).unwrap(),
List::Directory(vec![
(path_component_buf("b3"), FsNode::Directory(None)),
(path_component_buf("b4"), FsNode::File(b4_meta)),
(path_component_buf("b3"), FsNodeMetadata::Directory(None)),
(path_component_buf("b4"), FsNodeMetadata::File(b4_meta)),
]),
);
assert_eq!(
@ -1481,7 +1489,7 @@ mod tests {
path_component_buf("a1"),
tree.get(repo_path("a1")).unwrap().unwrap()
),
(path_component_buf("a2"), FsNode::Directory(None)),
(path_component_buf("a2"), FsNodeMetadata::Directory(None)),
]),
);
}

View File

@ -10,7 +10,7 @@ use std::{cmp::Ordering, collections::BTreeMap, sync::Arc};
use anyhow::{bail, format_err, Context, Result};
use once_cell::sync::OnceCell;
use manifest::{File, FileMetadata, FsNode};
use manifest::{File, FileMetadata, FsNodeMetadata};
use pathmatcher::{DirectoryMatch, Matcher};
use types::{HgId, Key, PathComponentBuf, RepoPath, RepoPathBuf};
@ -77,11 +77,11 @@ impl Link {
}
}
pub fn to_fs_node(&self) -> FsNode {
pub fn to_fs_node(&self) -> FsNodeMetadata {
match self {
&Link::Leaf(metadata) => FsNode::File(metadata),
Link::Ephemeral(_) => FsNode::Directory(None),
Link::Durable(durable) => FsNode::Directory(Some(durable.hgid)),
&Link::Leaf(metadata) => FsNodeMetadata::File(metadata),
Link::Ephemeral(_) => FsNodeMetadata::Directory(None),
Link::Durable(durable) => FsNodeMetadata::Directory(Some(durable.hgid)),
}
}

View File

@ -29,10 +29,11 @@ use types::{HgId, RepoPath, RepoPathBuf};
/// determined previously to be directories will result in Errors.
pub trait Manifest {
/// Inspects the manifest for the given path.
/// If the path is pointing to an file then Some(FsNode::File) is returned with then
/// If the path is pointing to an file then Some(FsNodeMetadata::File) is returned with then
/// file_metadata associated with the file. If the path is poitning to a directory then
/// Some(FsNode::Directory) is returned. If the path is not found then None is returned.
fn get(&self, path: &RepoPath) -> Result<Option<FsNode>>;
/// Some(FsNodeMetadata::Directory) is returned. If the path is not found then None is
/// returned.
fn get(&self, path: &RepoPath) -> Result<Option<FsNodeMetadata>>;
/// Associates a file path with specific file metadata.
/// A call with a file path that already exists results in an override or the old metadata.
@ -50,8 +51,8 @@ pub trait Manifest {
/// Paths that were not set will return None.
fn get_file(&self, file_path: &RepoPath) -> Result<Option<FileMetadata>> {
let result = self.get(file_path)?.and_then(|fs_hgid| match fs_hgid {
FsNode::File(file_metadata) => Some(file_metadata),
FsNode::Directory(_) => None,
FsNodeMetadata::File(file_metadata) => Some(file_metadata),
FsNodeMetadata::Directory(_) => None,
});
Ok(result)
}
@ -80,17 +81,34 @@ pub trait Manifest {
) -> Box<dyn Iterator<Item = Result<DiffEntry>> + 'a>;
}
/// FsNode short for file system node.
/// FsNodeMetadata short for file system node.
/// The manifest tracks a list of files. However file systems are hierarchical structures
/// composed of directories and files at the end. For different operations it is useful to have
/// a representation for file or directory. A good example is listing a directory. This structure
/// helps us represent that notion.
#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum FsNode {
pub enum FsNodeMetadata {
Directory(Option<HgId>),
File(FileMetadata),
}
/// A directory entry in a manifest.
///
/// Consists of the full path to the directory. Directories may or may not be assigned
/// identifiers. When an identifier is available it is also returned.
// TODO: Move hgid to a new DirectoryMetadata struct.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Directory {
pub path: RepoPathBuf,
pub hgid: Option<HgId>,
}
impl Directory {
pub fn new(path: RepoPathBuf, hgid: Option<HgId>) -> Self {
Self { path, hgid }
}
}
/// A file entry in a manifest.
///
/// Consists of the full path to the file along with the associated file metadata.
@ -106,22 +124,6 @@ impl File {
}
}
/// A directory entry in a manifest.
///
/// Consists of the full path to the directory. Directories may or may not be assigned
/// identifiers. When an identifier is available it is also returned.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Directory {
pub path: RepoPathBuf,
pub hgid: Option<HgId>,
}
impl Directory {
pub fn new(path: RepoPathBuf, hgid: Option<HgId>) -> Self {
Self { path, hgid }
}
}
/// The contents of the Manifest for a file.
/// * hgid: used to determine the revision of the file in the repository.
/// * file_type: determines the type of the file.