mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 16:57:49 +03:00
mononoke/types: clean up ContentMetadata out of FileContents
Summary: There's a lot of stuff in file_contents.rs that's not actually about file contents per-se. This fixes that. Reviewed By: ahornby Differential Revision: D16598905 fbshipit-source-id: 9832b96261264c54809e0c32980cf449f8537517
This commit is contained in:
parent
68569e5d0c
commit
bea4a85117
150
mononoke_types/src/content_metadata.rs
Normal file
150
mononoke_types/src/content_metadata.rs
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2018-present, Facebook, Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// This software may be used and distributed according to the terms of the
|
||||
// GNU General Public License version 2 or any later version.
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use bytes::Bytes;
|
||||
use failure_ext::{bail_err, chain::*};
|
||||
use quickcheck::{Arbitrary, Gen};
|
||||
use rust_thrift::compact_protocol;
|
||||
|
||||
use crate::{
|
||||
blob::{Blob, BlobstoreBytes, BlobstoreValue, ContentMetadataBlob},
|
||||
errors::*,
|
||||
hash, thrift, thrift_field,
|
||||
typed_hash::{ContentId, ContentMetadataId},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ContentAlias(ContentId);
|
||||
|
||||
impl ContentAlias {
|
||||
pub fn from_content_id(id: ContentId) -> Self {
|
||||
ContentAlias(id)
|
||||
}
|
||||
|
||||
pub fn from_bytes(blob: Bytes) -> Result<Self> {
|
||||
let thrift_tc = compact_protocol::deserialize(blob.as_ref())
|
||||
.chain_err(ErrorKind::BlobDeserializeError("ContentAlias".into()))?;
|
||||
Self::from_thrift(thrift_tc)
|
||||
}
|
||||
|
||||
pub fn from_thrift(ca: thrift::ContentAlias) -> Result<Self> {
|
||||
match ca {
|
||||
thrift::ContentAlias::ContentId(id) => {
|
||||
Ok(Self::from_content_id(ContentId::from_thrift(id)?))
|
||||
}
|
||||
thrift::ContentAlias::UnknownField(x) => bail_err!(ErrorKind::InvalidThrift(
|
||||
"ContentAlias".into(),
|
||||
format!("unknown content alias field: {}", x)
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_blob(self) -> BlobstoreBytes {
|
||||
let alias = thrift::ContentAlias::ContentId(self.0.into_thrift());
|
||||
BlobstoreBytes::from_bytes(compact_protocol::serialize(&alias))
|
||||
}
|
||||
|
||||
pub fn content_id(&self) -> ContentId {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ContentMetadata {
|
||||
pub total_size: u64,
|
||||
pub content_id: ContentId,
|
||||
pub sha1: hash::Sha1,
|
||||
pub sha256: hash::Sha256,
|
||||
pub git_sha1: hash::GitSha1,
|
||||
}
|
||||
|
||||
impl ContentMetadata {
|
||||
pub fn from_thrift(cab: thrift::ContentMetadata) -> Result<Self> {
|
||||
let total_size = thrift_field!(ContentMetadata, cab, total_size)?;
|
||||
let total_size: u64 = total_size.try_into()?;
|
||||
|
||||
let res = ContentMetadata {
|
||||
total_size,
|
||||
content_id: ContentId::from_thrift(thrift_field!(ContentMetadata, cab, content_id)?)?,
|
||||
sha1: hash::Sha1::from_bytes(&thrift_field!(ContentMetadata, cab, sha1)?.0)?,
|
||||
sha256: hash::Sha256::from_bytes(&thrift_field!(ContentMetadata, cab, sha256)?.0)?,
|
||||
git_sha1: hash::GitSha1::from_bytes(
|
||||
&thrift_field!(ContentMetadata, cab, git_sha1)?.0,
|
||||
"blob",
|
||||
total_size,
|
||||
)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn into_thrift(self) -> thrift::ContentMetadata {
|
||||
thrift::ContentMetadata {
|
||||
total_size: Some(self.total_size as i64),
|
||||
content_id: Some(self.content_id.into_thrift()),
|
||||
sha1: Some(self.sha1.into_thrift()),
|
||||
git_sha1: Some(self.git_sha1.into_thrift()),
|
||||
sha256: Some(self.sha256.into_thrift()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for ContentMetadata {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||
let total_size = u64::arbitrary(g);
|
||||
|
||||
Self {
|
||||
total_size,
|
||||
content_id: ContentId::arbitrary(g),
|
||||
sha1: hash::Sha1::arbitrary(g),
|
||||
sha256: hash::Sha256::arbitrary(g),
|
||||
git_sha1: hash::GitSha1::from_sha1(hash::Sha1::arbitrary(g), "blob", total_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlobstoreValue for ContentMetadata {
|
||||
type Key = ContentMetadataId;
|
||||
|
||||
fn into_blob(self) -> ContentMetadataBlob {
|
||||
let id = From::from(self.content_id.clone());
|
||||
let thrift = self.into_thrift();
|
||||
let data = compact_protocol::serialize(&thrift);
|
||||
Blob::new(id, data)
|
||||
}
|
||||
|
||||
fn from_blob(blob: ContentMetadataBlob) -> Result<Self> {
|
||||
let thrift_tc = compact_protocol::deserialize(blob.data().as_ref())
|
||||
.chain_err(ErrorKind::BlobDeserializeError("ContentMetadata".into()))?;
|
||||
Self::from_thrift(thrift_tc)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use quickcheck::quickcheck;
|
||||
|
||||
quickcheck! {
|
||||
fn content_metadata_thrift_roundtrip(cab: ContentMetadata) -> bool {
|
||||
let thrift_cab = cab.clone().into_thrift();
|
||||
let cab2 = ContentMetadata::from_thrift(thrift_cab)
|
||||
.expect("thrift roundtrips should always be valid");
|
||||
println!("cab: {:?}", cab);
|
||||
println!("cab2: {:?}", cab2);
|
||||
cab == cab2
|
||||
}
|
||||
|
||||
fn content_metadata_blob_roundtrip(cab: ContentMetadata) -> bool {
|
||||
let blob = cab.clone().into_blob();
|
||||
let cab2 = ContentMetadata::from_blob(blob)
|
||||
.expect("blob roundtrips should always be valid");
|
||||
cab == cab2
|
||||
}
|
||||
}
|
||||
}
|
@ -13,10 +13,10 @@ use quickcheck::{empty_shrinker, single_shrinker, Arbitrary, Gen};
|
||||
use rust_thrift::compact_protocol;
|
||||
|
||||
use crate::{
|
||||
blob::{Blob, BlobstoreBytes, BlobstoreValue, ContentBlob, ContentMetadataBlob},
|
||||
blob::{Blob, BlobstoreValue, ContentBlob},
|
||||
errors::*,
|
||||
hash, thrift, thrift_field,
|
||||
typed_hash::{ContentChunkId, ContentId, ContentIdContext, ContentMetadataId},
|
||||
thrift,
|
||||
typed_hash::{ContentChunkId, ContentId, ContentIdContext},
|
||||
};
|
||||
|
||||
/// An enum representing contents for a file.
|
||||
@ -251,113 +251,6 @@ impl Arbitrary for ContentChunkPointer {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ContentAlias(ContentId);
|
||||
|
||||
impl ContentAlias {
|
||||
pub fn from_content_id(id: ContentId) -> Self {
|
||||
ContentAlias(id)
|
||||
}
|
||||
|
||||
pub fn from_bytes(blob: Bytes) -> Result<Self> {
|
||||
let thrift_tc = compact_protocol::deserialize(blob.as_ref())
|
||||
.chain_err(ErrorKind::BlobDeserializeError("ContentAlias".into()))?;
|
||||
Self::from_thrift(thrift_tc)
|
||||
}
|
||||
|
||||
pub fn from_thrift(ca: thrift::ContentAlias) -> Result<Self> {
|
||||
match ca {
|
||||
thrift::ContentAlias::ContentId(id) => {
|
||||
Ok(Self::from_content_id(ContentId::from_thrift(id)?))
|
||||
}
|
||||
thrift::ContentAlias::UnknownField(x) => bail_err!(ErrorKind::InvalidThrift(
|
||||
"ContentAlias".into(),
|
||||
format!("unknown content alias field: {}", x)
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_blob(self) -> BlobstoreBytes {
|
||||
let alias = thrift::ContentAlias::ContentId(self.0.into_thrift());
|
||||
BlobstoreBytes::from_bytes(compact_protocol::serialize(&alias))
|
||||
}
|
||||
|
||||
pub fn content_id(&self) -> ContentId {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ContentMetadata {
|
||||
pub total_size: u64,
|
||||
pub content_id: ContentId,
|
||||
pub sha1: hash::Sha1,
|
||||
pub sha256: hash::Sha256,
|
||||
pub git_sha1: hash::GitSha1,
|
||||
}
|
||||
|
||||
impl ContentMetadata {
|
||||
pub fn from_thrift(cab: thrift::ContentMetadata) -> Result<Self> {
|
||||
let total_size = thrift_field!(ContentMetadata, cab, total_size)?;
|
||||
let total_size: u64 = total_size.try_into()?;
|
||||
|
||||
let res = ContentMetadata {
|
||||
total_size,
|
||||
content_id: ContentId::from_thrift(thrift_field!(ContentMetadata, cab, content_id)?)?,
|
||||
sha1: hash::Sha1::from_bytes(&thrift_field!(ContentMetadata, cab, sha1)?.0)?,
|
||||
sha256: hash::Sha256::from_bytes(&thrift_field!(ContentMetadata, cab, sha256)?.0)?,
|
||||
git_sha1: hash::GitSha1::from_bytes(
|
||||
&thrift_field!(ContentMetadata, cab, git_sha1)?.0,
|
||||
"blob",
|
||||
total_size,
|
||||
)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn into_thrift(self) -> thrift::ContentMetadata {
|
||||
thrift::ContentMetadata {
|
||||
total_size: Some(self.total_size as i64),
|
||||
content_id: Some(self.content_id.into_thrift()),
|
||||
sha1: Some(self.sha1.into_thrift()),
|
||||
git_sha1: Some(self.git_sha1.into_thrift()),
|
||||
sha256: Some(self.sha256.into_thrift()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for ContentMetadata {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||
let total_size = u64::arbitrary(g);
|
||||
|
||||
Self {
|
||||
total_size,
|
||||
content_id: ContentId::arbitrary(g),
|
||||
sha1: hash::Sha1::arbitrary(g),
|
||||
sha256: hash::Sha256::arbitrary(g),
|
||||
git_sha1: hash::GitSha1::from_sha1(hash::Sha1::arbitrary(g), "blob", total_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlobstoreValue for ContentMetadata {
|
||||
type Key = ContentMetadataId;
|
||||
|
||||
fn into_blob(self) -> ContentMetadataBlob {
|
||||
let id = From::from(self.content_id.clone());
|
||||
let thrift = self.into_thrift();
|
||||
let data = compact_protocol::serialize(&thrift);
|
||||
Blob::new(id, data)
|
||||
}
|
||||
|
||||
fn from_blob(blob: ContentMetadataBlob) -> Result<Self> {
|
||||
let thrift_tc = compact_protocol::deserialize(blob.data().as_ref())
|
||||
.chain_err(ErrorKind::BlobDeserializeError("ContentMetadata".into()))?;
|
||||
Self::from_thrift(thrift_tc)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@ -377,22 +270,6 @@ mod test {
|
||||
.expect("blob roundtrips should always be valid");
|
||||
fc == fc2
|
||||
}
|
||||
|
||||
fn content_alias_metadata_thrift_roundtrip(cab: ContentMetadata) -> bool {
|
||||
let thrift_cab = cab.clone().into_thrift();
|
||||
let cab2 = ContentMetadata::from_thrift(thrift_cab)
|
||||
.expect("thrift roundtrips should always be valid");
|
||||
println!("cab: {:?}", cab);
|
||||
println!("cab2: {:?}", cab2);
|
||||
cab == cab2
|
||||
}
|
||||
|
||||
fn content_alias_metadata_blob_roundtrip(cab: ContentMetadata) -> bool {
|
||||
let blob = cab.clone().into_blob();
|
||||
let cab2 = ContentMetadata::from_blob(blob)
|
||||
.expect("blob roundtrips should always be valid");
|
||||
cab == cab2
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -12,6 +12,7 @@
|
||||
pub mod blob;
|
||||
pub mod bonsai_changeset;
|
||||
pub mod content_chunk;
|
||||
pub mod content_metadata;
|
||||
pub mod datetime;
|
||||
pub mod errors;
|
||||
pub mod file_change;
|
||||
@ -28,11 +29,10 @@ pub mod unode;
|
||||
pub use blob::{Blob, BlobstoreBytes, BlobstoreValue, ChangesetBlob, ContentBlob, RawBundle2Blob};
|
||||
pub use bonsai_changeset::{BonsaiChangeset, BonsaiChangesetMut};
|
||||
pub use content_chunk::ContentChunk;
|
||||
pub use content_metadata::{ContentAlias, ContentMetadata};
|
||||
pub use datetime::{DateTime, Timestamp};
|
||||
pub use file_change::{FileChange, FileType};
|
||||
pub use file_contents::{
|
||||
ChunkedFileContents, ContentAlias, ContentChunkPointer, ContentMetadata, FileContents,
|
||||
};
|
||||
pub use file_contents::{ChunkedFileContents, ContentChunkPointer, FileContents};
|
||||
pub use generation::Generation;
|
||||
pub use path::{check_case_conflicts, MPath, MPathElement, MPathHash, RepoPath, RepoPathCached};
|
||||
pub use rawbundle2::RawBundle2;
|
||||
|
@ -19,8 +19,9 @@ use crate::{
|
||||
blob::BlobstoreValue,
|
||||
bonsai_changeset::BonsaiChangeset,
|
||||
content_chunk::ContentChunk,
|
||||
content_metadata::ContentMetadata,
|
||||
errors::*,
|
||||
file_contents::{ContentMetadata, FileContents},
|
||||
file_contents::FileContents,
|
||||
hash::{Blake2, Context},
|
||||
rawbundle2::RawBundle2,
|
||||
thrift,
|
||||
|
Loading…
Reference in New Issue
Block a user