mononoke: add PathKey to walker, use in parse_node

Summary: add PathKey newtype to Node so can implement FromStr and use it in parsing for HgManifest

Reviewed By: mitrandir77

Differential Revision: D24711371

fbshipit-source-id: a9879f6d2e16eb54b2ca7af4e812a4f031c9e584
This commit is contained in:
Alex Hornby 2020-11-13 05:21:34 -08:00 committed by Facebook GitHub Bot
parent 8cbe06923d
commit 557d6b58ab
4 changed files with 41 additions and 24 deletions

View File

@ -126,7 +126,7 @@ macro_rules! root_edge_type {
macro_rules! create_graph {
($nodetypeenum:ident, $nodekeyenum:ident, $edgetypeenum:ident,
$(($source:ident, $sourcekey:tt, [$($target:ident$(($targettype:ident))?),*])),* $(,)?) => {
$(($source:ident, $sourcekey:ty, [$($target:ident$(($targettype:ident))?),*])),* $(,)?) => {
create_graph_impl! {
$nodetypeenum, $nodekeyenum, $edgetypeenum,
{}
@ -155,6 +155,17 @@ macro_rules! create_graph {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct UnitKey();
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathKey<T: fmt::Debug + Clone + PartialEq + Eq + Hash> {
pub id: T,
pub path: WrappedPath,
}
impl<T: fmt::Debug + Clone + PartialEq + Eq + Hash> PathKey<T> {
pub fn new(id: T, path: WrappedPath) -> Self {
Self { id, path }
}
}
create_graph!(
NodeType,
Node,
@ -211,7 +222,7 @@ create_graph!(
),
(
HgManifest,
(WrappedPath, HgManifestId),
PathKey<HgManifestId>,
[HgFileEnvelope, HgFileNode, ChildHgManifest(HgManifest)]
),
(HgFileEnvelope, HgFileNodeId, [FileContent]),
@ -438,7 +449,7 @@ impl Node {
// Hg
Node::HgBonsaiMapping(k) => k.blobstore_key(),
Node::HgChangeset(k) => k.blobstore_key(),
Node::HgManifest((_, k)) => k.blobstore_key(),
Node::HgManifest(PathKey { id, path: _ }) => id.blobstore_key(),
Node::HgFileEnvelope(k) => k.blobstore_key(),
Node::HgFileNode((_, k)) => k.blobstore_key(),
// Content
@ -464,7 +475,7 @@ impl Node {
// Hg
Node::HgBonsaiMapping(_) => None,
Node::HgChangeset(_) => None,
Node::HgManifest((p, _)) => Some(&p),
Node::HgManifest(PathKey { id: _, path }) => Some(&path),
Node::HgFileEnvelope(_) => None,
Node::HgFileNode((p, _)) => Some(&p),
// Content
@ -491,7 +502,7 @@ impl Node {
// Hg
Node::HgBonsaiMapping(k) => Some(k.sampling_fingerprint()),
Node::HgChangeset(k) => Some(k.sampling_fingerprint()),
Node::HgManifest((_, k)) => Some(k.sampling_fingerprint()),
Node::HgManifest(PathKey { id, path: _ }) => Some(id.sampling_fingerprint()),
Node::HgFileEnvelope(k) => Some(k.sampling_fingerprint()),
Node::HgFileNode((_, k)) => Some(k.sampling_fingerprint()),
// Content

View File

@ -5,7 +5,7 @@
* GNU General Public License version 2.
*/
use crate::graph::{AliasType, Node, NodeType, UnitKey, WrappedPath};
use crate::graph::{AliasType, Node, NodeType, PathKey, UnitKey, WrappedPath};
use anyhow::{format_err, Error};
use bookmarks::BookmarkName;
@ -21,7 +21,7 @@ use strum::IntoEnumIterator;
const NODE_SEP: &str = ":";
fn check_and_build_mpath(node_type: NodeType, parts: &[&str]) -> Result<Option<MPath>, Error> {
fn check_and_build_path(node_type: NodeType, parts: &[&str]) -> Result<WrappedPath, Error> {
if parts.len() < 2 {
return Err(format_err!(
"parse_node requires a path and key for {}",
@ -32,7 +32,7 @@ fn check_and_build_mpath(node_type: NodeType, parts: &[&str]) -> Result<Option<M
"/" => None,
p => Some(MPath::new(p)?),
};
Ok(mpath)
Ok(WrappedPath::from(mpath))
}
impl FromStr for UnitKey {
@ -46,6 +46,16 @@ impl FromStr for UnitKey {
}
}
impl FromStr for PathKey<HgManifestId> {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<_> = s.split(NODE_SEP).collect();
let path = check_and_build_path(NodeType::HgManifest, &parts)?;
let id = HgManifestId::from_str(parts[0])?;
Ok(Self { id, path })
}
}
pub fn parse_node(s: &str) -> Result<Node, Error> {
let parts: Vec<_> = s.split(NODE_SEP).collect();
if parts.len() < 1 {
@ -91,18 +101,14 @@ pub fn parse_node(s: &str) -> Result<Node, Error> {
Node::HgBonsaiMapping(HgChangesetId::from_str(&parts.join(NODE_SEP))?)
}
NodeType::HgChangeset => Node::HgChangeset(HgChangesetId::from_str(&parts.join(NODE_SEP))?),
NodeType::HgManifest => {
let mpath = check_and_build_mpath(node_type, parts)?;
let id = HgManifestId::from_str(parts[0])?;
Node::HgManifest((WrappedPath::from(mpath), id))
}
NodeType::HgManifest => Node::HgManifest(PathKey::from_str(&parts.join(NODE_SEP))?),
NodeType::HgFileEnvelope => {
Node::HgFileEnvelope(HgFileNodeId::from_str(&parts.join(NODE_SEP))?)
}
NodeType::HgFileNode => {
let mpath = check_and_build_mpath(node_type, parts)?;
let path = check_and_build_path(node_type, parts)?;
let id = HgFileNodeId::from_str(parts[0])?;
Node::HgFileNode((WrappedPath::from(mpath), id))
Node::HgFileNode((path, id))
}
// Content
NodeType::FileContent => Node::FileContent(ContentId::from_str(&parts.join(NODE_SEP))?),
@ -134,9 +140,9 @@ pub fn parse_node(s: &str) -> Result<Node, Error> {
Node::ChangesetInfo(ChangesetId::from_str(&parts.join(NODE_SEP))?)
}
NodeType::Fsnode => {
let mpath = check_and_build_mpath(node_type, parts)?;
let path = check_and_build_path(node_type, parts)?;
let id = FsnodeId::from_str(parts[0])?;
Node::Fsnode((WrappedPath::from(mpath), id))
Node::Fsnode((path, id))
}
};
Ok(node)

View File

@ -287,9 +287,9 @@ impl VisitOne for WalkState {
Node::HgChangeset(hg_cs_id) => {
self.record(&self.visited_hg_cs, &self.hg_cs_ids.interned(hg_cs_id))
}
Node::HgManifest((p, id)) => self.record_with_path(
Node::HgManifest(k) => self.record_with_path(
&self.visited_hg_manifest,
(p, &self.hg_manifest_ids.interned(id)),
(&k.path, &self.hg_manifest_ids.interned(&k.id)),
),
Node::HgFileNode((p, id)) => self.record_with_path(
&self.visited_hg_filenode,

View File

@ -5,7 +5,7 @@
* GNU General Public License version 2.
*/
use crate::graph::{EdgeType, FileContentData, Node, NodeData, NodeType, WrappedPath};
use crate::graph::{EdgeType, FileContentData, Node, NodeData, NodeType, PathKey, WrappedPath};
use crate::validate::{add_node_to_scuba, CHECK_FAIL, CHECK_TYPE, EDGE_TYPE};
use anyhow::{format_err, Context, Error};
@ -505,7 +505,7 @@ fn hg_changeset_step<'a, V: VisitOne>(
let mut edges = vec![];
// 1:1 but will then expand a lot, usually
checker.add_edge(&mut edges, EdgeType::HgChangesetToHgManifest, || {
Node::HgManifest((WrappedPath::Root, hgchangeset.manifestid()))
Node::HgManifest(PathKey::new(hgchangeset.manifestid(), WrappedPath::Root))
});
// Mostly 1:1, can be 1:2, with further expansion
for p in hgchangeset.parents().into_iter() {
@ -640,7 +640,7 @@ fn hg_manifest_step<'a, V: VisitOne>(
// Manifests expand as a tree so 1:N
for (full_path, hg_child_manifest_id) in manifests {
checker.add_edge(&mut edges, EdgeType::HgManifestToChildHgManifest, || {
Node::HgManifest((full_path, hg_child_manifest_id))
Node::HgManifest(PathKey::new(hg_child_manifest_id, full_path))
})
}
@ -1072,8 +1072,8 @@ where
Node::HgFileNode((path, hg_file_node_id)) => {
hg_file_node_step(ctx.clone(), &repo, &checker, path, hg_file_node_id).await
}
Node::HgManifest((path, hg_manifest_id)) => {
hg_manifest_step(ctx.clone(), &repo, &checker, path, hg_manifest_id).await
Node::HgManifest(PathKey { id, path }) => {
hg_manifest_step(ctx.clone(), &repo, &checker, path, id).await
}
// Content
Node::FileContent(content_id) => {