diff --git a/eden/scm/lib/edenapi/types/Cargo.toml b/eden/scm/lib/edenapi/types/Cargo.toml index 4c1c014c61..22bdaeac51 100644 --- a/eden/scm/lib/edenapi/types/Cargo.toml +++ b/eden/scm/lib/edenapi/types/Cargo.toml @@ -10,6 +10,7 @@ default = ["for-tests"] for-tests = [] [dependencies] +dag = { path = "../../dag", features = ["for-tests"] } revisionstore_types = { path = "../../revisionstore/types" } types = { path = "../../types" } anyhow = "1.0" diff --git a/eden/scm/lib/edenapi/types/src/lib.rs b/eden/scm/lib/edenapi/types/src/lib.rs index fd426c6170..08076ed1d7 100644 --- a/eden/scm/lib/edenapi/types/src/lib.rs +++ b/eden/scm/lib/edenapi/types/src/lib.rs @@ -50,6 +50,9 @@ pub use crate::metadata::{ pub use crate::tree::{TreeChildEntry, TreeEntry, TreeError, TreeRequest}; pub use crate::wire::{ToApi, ToWire, WireToApiConversionError}; +// re-export CloneData +pub use dag::{CloneData, FlatSegment, PreparedFlatSegments}; + #[cfg(any(test, feature = "for-tests"))] use quickcheck::Arbitrary; use thiserror::Error; diff --git a/eden/scm/lib/edenapi/types/src/wire/clone.rs b/eden/scm/lib/edenapi/types/src/wire/clone.rs new file mode 100644 index 0000000000..894ec0cc6d --- /dev/null +++ b/eden/scm/lib/edenapi/types/src/wire/clone.rs @@ -0,0 +1,144 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This software may be used and distributed according to the terms of the + * GNU General Public License version 2. + */ + +use std::collections::HashMap; + +#[cfg(any(test, feature = "for-tests"))] +use quickcheck::Arbitrary; +use serde_derive::{Deserialize, Serialize}; + +use types::HgId; + +use crate::wire::{ToApi, ToWire, WireDagId, WireHgId, WireToApiConversionError}; +use crate::{CloneData, FlatSegment, PreparedFlatSegments}; + +// Only when an id has more than one parent it is sent over the wire. +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct WireCloneData { + #[serde(rename = "1")] + pub head_id: WireDagId, + #[serde(rename = "2")] + pub flat_segments: Vec, + #[serde(rename = "3")] + pub idmap: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct WireFlatSegment { + #[serde(rename = "1")] + pub low: WireDagId, + #[serde(rename = "2")] + pub high: WireDagId, + #[serde(rename = "3")] + pub parents: Vec, +} + +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct WireIdMapEntry { + #[serde(rename = "1")] + pub dag_id: WireDagId, + #[serde(rename = "2")] + pub hg_id: WireHgId, +} + +impl ToWire for CloneData { + type Wire = WireCloneData; + + fn to_wire(self) -> Self::Wire { + let idmap = self + .idmap + .into_iter() + .map(|(k, v)| WireIdMapEntry { + dag_id: k.to_wire(), + hg_id: v.to_wire(), + }) + .collect(); + WireCloneData { + head_id: self.head_id.to_wire(), + flat_segments: self.flat_segments.segments.to_wire(), + idmap, + } + } +} + +impl ToApi for WireCloneData { + type Api = CloneData; + type Error = WireToApiConversionError; + + fn to_api(self) -> Result { + let mut idmap = HashMap::new(); + for wie in self.idmap { + idmap.insert(wie.dag_id.to_api()?, wie.hg_id.to_api()?); + } + let flat_segments = PreparedFlatSegments { + segments: self.flat_segments.to_api()?, + }; + Ok(CloneData { + head_id: self.head_id.to_api()?, + flat_segments, + idmap, + }) + } +} + +impl ToWire for FlatSegment { + type Wire = WireFlatSegment; + + fn to_wire(self) -> Self::Wire { + WireFlatSegment { + low: self.low.to_wire(), + high: self.high.to_wire(), + parents: self.parents.to_wire(), + } + } +} + +impl ToApi for WireFlatSegment { + type Api = FlatSegment; + type Error = WireToApiConversionError; + + fn to_api(self) -> Result { + Ok(FlatSegment { + low: self.low.to_api()?, + high: self.high.to_api()?, + parents: self.parents.to_api()?, + }) + } +} + +#[cfg(any(test, feature = "for-tests"))] +impl Arbitrary for WireFlatSegment { + fn arbitrary(g: &mut G) -> Self { + FlatSegment::arbitrary(g).to_wire() + } +} + +#[cfg(any(test, feature = "for-tests"))] +impl Arbitrary for WireCloneData { + fn arbitrary(g: &mut G) -> Self { + CloneData::arbitrary(g).to_wire() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::wire::tests::{check_serialize_roundtrip, check_wire_roundtrip}; + + use quickcheck::quickcheck; + + quickcheck! { + fn test_request_roundtrip_serialize(v: WireCloneData) -> bool { + check_serialize_roundtrip(v) + } + + fn test_request_roundtrip_wire(v: CloneData) -> bool { + check_wire_roundtrip(v) + } + } +} diff --git a/eden/scm/lib/edenapi/types/src/wire/mod.rs b/eden/scm/lib/edenapi/types/src/wire/mod.rs index d02c34e344..53b5df644e 100644 --- a/eden/scm/lib/edenapi/types/src/wire/mod.rs +++ b/eden/scm/lib/edenapi/types/src/wire/mod.rs @@ -45,6 +45,7 @@ //! 7. If the type has a corresponding API type, add a quickcheck wire-API round //! trip test. +pub mod clone; pub mod complete_tree; pub mod file; pub mod history; @@ -52,6 +53,7 @@ pub mod metadata; pub mod tree; pub use crate::wire::{ + clone::{WireCloneData, WireIdMapEntry}, complete_tree::WireCompleteTreeRequest, file::{WireFileEntry, WireFileRequest}, history::{WireHistoryRequest, WireHistoryResponseChunk, WireWireHistoryEntry}, @@ -427,6 +429,26 @@ impl ToApi for u32 { } } +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WireDagId(u64); + +impl ToWire for dag::Id { + type Wire = WireDagId; + + fn to_wire(self) -> Self::Wire { + WireDagId(self.0) + } +} + +impl ToApi for WireDagId { + type Api = dag::Id; + type Error = Infallible; + + fn to_api(self) -> Result { + Ok(dag::Id(self.0)) + } +} + fn is_default(v: &T) -> bool { v == &T::default() } @@ -482,6 +504,13 @@ impl Arbitrary for WireRevisionstoreMetadata { } } +#[cfg(any(test, feature = "for-tests"))] +impl Arbitrary for WireDagId { + fn arbitrary(g: &mut G) -> Self { + dag::Id::arbitrary(g).to_wire() + } +} + #[cfg(test)] pub mod tests { use super::*; @@ -530,6 +559,10 @@ pub mod tests { check_serialize_roundtrip(v) } + fn test_dagid_roundtrip_serialize(v: WireDagId) -> bool { + check_serialize_roundtrip(v) + } + // API-Wire roundtrips fn test_hgid_roundtrip_wire(v: HgId) -> bool { check_wire_roundtrip(v) @@ -550,5 +583,9 @@ pub mod tests { fn test_meta_roundtrip_wire(v: RevisionstoreMetadata) -> bool { check_wire_roundtrip(v) } + + fn test_dagid_roundtrip_wire(v: dag::Id) -> bool { + check_wire_roundtrip(v) + } } } diff --git a/eden/scm/lib/hgcommits/Cargo.toml b/eden/scm/lib/hgcommits/Cargo.toml index d76ff94e03..d412319a23 100644 --- a/eden/scm/lib/hgcommits/Cargo.toml +++ b/eden/scm/lib/hgcommits/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" include = ["src/**/*.rs"] [dependencies] -dag = { path = "../dag" } +dag = { path = "../dag", features = ["for-tests"] } edenapi = { path = "../edenapi" } gitdag = { path = "../dag/gitdag" } metalog = { path = "../metalog" }