mercurial: define a HgNodeKey key for node keys

Summary:
This is used in a bunch of places throughout bundle2-resolver, and is
the default key that should be used throughout Mercurial.

Reviewed By: farnz

Differential Revision: D7578081

fbshipit-source-id: 8f44b54189b22b0aba8f08853bbd2bbbaa3efc5c
This commit is contained in:
Siddharth Agarwal 2018-04-11 13:33:18 -07:00 committed by Facebook Github Bot
parent 8e7a1acc0f
commit 361ae35558
6 changed files with 86 additions and 64 deletions

View File

@ -33,8 +33,7 @@ pub struct FilelogDeltaed {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Filelog {
pub path: RepoPath,
pub node: mercurial::NodeHash,
pub node_key: mercurial::HgNodeKey,
pub p1: Option<mercurial::NodeHash>,
pub p2: Option<mercurial::NodeHash>,
pub linknode: mercurial::NodeHash,
@ -44,9 +43,8 @@ pub struct Filelog {
impl UploadableBlob for Filelog {
type Value = Shared<BoxFuture<(BlobEntry, RepoPath), Compat<Error>>>;
fn upload(self, repo: &BlobRepo) -> Result<((mercurial::NodeHash, RepoPath), Self::Value)> {
let path = self.path;
let node = self.node;
fn upload(self, repo: &BlobRepo) -> Result<(mercurial::HgNodeKey, Self::Value)> {
let node_key = self.node_key;
let p1 = self.p1.map(|p1| NodeHash::new(p1.sha1().clone()));
let p2 = self.p2.map(|p1| NodeHash::new(p1.sha1().clone()));
@ -55,8 +53,8 @@ impl UploadableBlob for Filelog {
manifest::Type::File(FileType::Regular),
p1,
p2,
path.clone(),
).map(move |(_node, fut)| ((node, path), fut.map_err(Error::compat).boxify().shared()))
node_key.path.clone(),
).map(move |(_node, fut)| (node_key, fut.map_err(Error::compat).boxify().shared()))
}
}
@ -80,8 +78,10 @@ where
.decode(node.clone(), base.into_option(), delta)
.and_then(move |blob| {
Ok(Filelog {
path: RepoPath::file(path)?,
node,
node_key: mercurial::HgNodeKey {
path: RepoPath::FilePath(path),
hash: node,
},
p1: p1.into_option(),
p2: p2.into_option(),
linknode,
@ -167,9 +167,10 @@ impl DeltaCache {
impl Arbitrary for Filelog {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Filelog {
path: RepoPath::file(MPath::arbitrary(g))
.unwrap_or(RepoPath::file(MPath::new(b"test").unwrap()).unwrap()),
node: mercurial::NodeHash::arbitrary(g),
node_key: mercurial::HgNodeKey {
path: RepoPath::FilePath(MPath::arbitrary(g)),
hash: mercurial::NodeHash::arbitrary(g),
},
p1: mercurial::NodeHash::arbitrary(g).into_option(),
p2: mercurial::NodeHash::arbitrary(g).into_option(),
linknode: mercurial::NodeHash::arbitrary(g),
@ -185,15 +186,9 @@ impl Arbitrary for Filelog {
let mut result = Vec::new();
if self.path.mpath() != Some(&MPath::new(b"test").unwrap()) {
if self.node_key.hash != mercurial::NULL_HASH {
let mut f = self.clone();
f.path = RepoPath::file(MPath::new(b"test").unwrap()).unwrap();
append(&mut result, f);
}
if self.node != mercurial::NULL_HASH {
let mut f = self.clone();
f.node = mercurial::NULL_HASH;
f.node_key.hash = mercurial::NULL_HASH;
append(&mut result, f);
}
@ -281,9 +276,9 @@ mod tests {
fn filelog_to_deltaed(f: &Filelog) -> FilelogDeltaed {
FilelogDeltaed {
path: f.path.mpath().unwrap().clone(),
path: f.node_key.path.mpath().unwrap().clone(),
chunk: CgDeltaChunk {
node: f.node.clone(),
node: f.node_key.hash.clone(),
p1: f.p1.clone().unwrap_or(NULL_HASH),
p2: f.p2.clone().unwrap_or(NULL_HASH),
base: NULL_HASH,
@ -343,8 +338,10 @@ mod tests {
#[test]
fn two_fulltext_files() {
let f1 = Filelog {
path: RepoPath::file(MPath::new(b"test").unwrap()).unwrap(),
node: ONES_HASH,
node_key: mercurial::HgNodeKey {
path: RepoPath::FilePath(MPath::new(b"test").unwrap()),
hash: ONES_HASH,
},
p1: Some(TWOS_HASH),
p2: Some(THREES_HASH),
linknode: FOURS_HASH,
@ -352,8 +349,10 @@ mod tests {
};
let f2 = Filelog {
path: RepoPath::file(MPath::new(b"test2").unwrap()).unwrap(),
node: FIVES_HASH,
node_key: mercurial::HgNodeKey {
path: RepoPath::FilePath(MPath::new(b"test2").unwrap()),
hash: FIVES_HASH,
},
p1: Some(SIXES_HASH),
p2: Some(SEVENS_HASH),
linknode: EIGHTS_HASH,
@ -368,8 +367,10 @@ mod tests {
fn files_check_order(correct_order: bool) {
let f1 = Filelog {
path: RepoPath::file(MPath::new(b"test").unwrap()).unwrap(),
node: ONES_HASH,
node_key: mercurial::HgNodeKey {
path: RepoPath::FilePath(MPath::new(b"test").unwrap()),
hash: ONES_HASH,
},
p1: Some(TWOS_HASH),
p2: Some(THREES_HASH),
linknode: FOURS_HASH,
@ -377,8 +378,10 @@ mod tests {
};
let f2 = Filelog {
path: RepoPath::file(MPath::new(b"test2").unwrap()).unwrap(),
node: FIVES_HASH,
node_key: mercurial::HgNodeKey {
path: RepoPath::FilePath(MPath::new(b"test2").unwrap()),
hash: FIVES_HASH,
},
p1: Some(SIXES_HASH),
p2: Some(SEVENS_HASH),
linknode: EIGHTS_HASH,
@ -388,7 +391,7 @@ mod tests {
let f1_deltaed = filelog_to_deltaed(&f1);
let mut f2_deltaed = filelog_to_deltaed(&f2);
f2_deltaed.chunk.base = f1.node.clone();
f2_deltaed.chunk.base = f1.node_key.hash.clone();
f2_deltaed.chunk.delta =
compute_delta(f1.blob.as_slice().unwrap(), f2.blob.as_slice().unwrap());
@ -445,17 +448,17 @@ mod tests {
let mut hash_gen = NodeHashGen::new();
let mut f = f.clone();
f.node = hash_gen.next();
f.node_key.hash = hash_gen.next();
let mut fs = fs.clone();
for el in fs.iter_mut() {
el.node = hash_gen.next();
el.node_key.hash = hash_gen.next();
}
let mut deltas = vec![filelog_to_deltaed(&f)];
for filelog in &fs {
let mut delta = filelog_to_deltaed(filelog);
delta.chunk.base = f.node.clone();
delta.chunk.base = f.node_key.hash.clone();
delta.chunk.delta =
compute_delta(f.blob.as_slice().unwrap(), filelog.blob.as_slice().unwrap());
deltas.push(delta);
@ -471,7 +474,7 @@ mod tests {
let mut fs = fs.clone();
for el in fs.iter_mut() {
el.node = hash_gen.next();
el.node_key.hash = hash_gen.next();
}
let deltas = {
@ -483,7 +486,7 @@ mod tests {
for (prev, next) in fs.iter().zip(it) {
let mut delta = filelog_to_deltaed(next);
delta.chunk.base = prev.node.clone();
delta.chunk.base = prev.node_key.hash.clone();
delta.chunk.delta =
compute_delta(prev.blob.as_slice().unwrap(), next.blob.as_slice().unwrap());
deltas.push(delta);

View File

@ -31,9 +31,8 @@ use wirepackparser::{TreemanifestBundle2Parser, TreemanifestEntry};
type PartId = u32;
type Changesets = Vec<(mercurial::NodeHash, RevlogChangeset)>;
type Filelogs = HashMap<(mercurial::NodeHash, RepoPath), <Filelog as UploadableBlob>::Value>;
type Manifests =
HashMap<(mercurial::NodeHash, RepoPath), <TreemanifestEntry as UploadableBlob>::Value>;
type Filelogs = HashMap<mercurial::HgNodeKey, <Filelog as UploadableBlob>::Value>;
type Manifests = HashMap<mercurial::HgNodeKey, <TreemanifestEntry as UploadableBlob>::Value>;
type UploadedChangesets = HashMap<mercurial::NodeHash, ChangesetHandle>;
/// The resolve function takes a bundle2, interprets it's content as Changesets, Filelogs and
@ -507,7 +506,10 @@ fn walk_manifests(
};
if details.is_tree() {
let key = (nodehash, RepoPath::DirectoryPath(next_path));
let key = mercurial::HgNodeKey {
path: RepoPath::DirectoryPath(next_path),
hash: nodehash,
};
if let Some(&(ref manifest_content, ref blobfuture)) = manifests.get(&key) {
entries.push(
@ -518,14 +520,18 @@ fn walk_manifests(
.boxify(),
);
entries.append(&mut walk_helper(
&key.1,
&key.path,
manifest_content,
manifests,
filelogs,
)?);
}
} else {
if let Some(blobfuture) = filelogs.get(&(nodehash, RepoPath::FilePath(next_path))) {
let key = mercurial::HgNodeKey {
path: RepoPath::FilePath(next_path),
hash: nodehash,
};
if let Some(blobfuture) = filelogs.get(&key) {
entries.push(
blobfuture
.clone()
@ -540,8 +546,13 @@ fn walk_manifests(
Ok(entries)
}
let root_key = mercurial::HgNodeKey {
path: RepoPath::root(),
hash: manifest_root_id.clone().into_nodehash(),
};
let &(ref manifest_content, ref manifest_root) = manifests
.get(&(manifest_root_id.clone().into_nodehash(), RepoPath::root()))
.get(&root_key)
.ok_or_else(|| format_err!("Missing root tree manifest"))?;
Ok((

View File

@ -12,14 +12,13 @@ use futures_ext::{BoxFuture, FutureExt};
use blobrepo::BlobRepo;
use mercurial;
use mercurial_types::RepoPath;
use errors::*;
pub trait UploadableBlob {
type Value: Send + 'static;
fn upload(self, repo: &BlobRepo) -> Result<((mercurial::NodeHash, RepoPath), Self::Value)>;
fn upload(self, repo: &BlobRepo) -> Result<(mercurial::HgNodeKey, Self::Value)>;
}
#[derive(PartialEq, Eq)]
@ -33,7 +32,7 @@ pub fn upload_blobs<S, B>(
repo: Arc<BlobRepo>,
blobs: S,
ubtype: UploadBlobsType,
) -> BoxFuture<HashMap<(mercurial::NodeHash, RepoPath), B::Value>, Error>
) -> BoxFuture<HashMap<mercurial::HgNodeKey, B::Value>, Error>
where
S: Stream<Item = B, Error = Error> + Send + 'static,
B: UploadableBlob,

View File

@ -58,30 +58,27 @@ where
#[derive(Debug, Eq, PartialEq)]
pub struct TreemanifestEntry {
pub node: mercurial::NodeHash,
pub node_key: mercurial::HgNodeKey,
pub data: Bytes,
pub p1: Option<mercurial::NodeHash>,
pub p2: Option<mercurial::NodeHash>,
pub path: RepoPath,
pub manifest_content: ManifestContent,
}
impl TreemanifestEntry {
fn new(
node: mercurial::NodeHash,
node_key: mercurial::HgNodeKey,
data: Bytes,
p1: mercurial::NodeHash,
p2: mercurial::NodeHash,
path: RepoPath,
) -> Result<Self> {
let manifest_content = ManifestContent::parse(data.as_ref())?;
Ok(Self {
node,
node_key,
data,
p1: p1.into_option(),
p2: p2.into_option(),
path,
manifest_content,
})
}
@ -93,9 +90,8 @@ impl UploadableBlob for TreemanifestEntry {
Shared<BoxFuture<(BlobEntry, RepoPath), Compat<Error>>>,
);
fn upload(self, repo: &BlobRepo) -> Result<((mercurial::NodeHash, RepoPath), Self::Value)> {
let path = self.path;
let node = self.node;
fn upload(self, repo: &BlobRepo) -> Result<(mercurial::HgNodeKey, Self::Value)> {
let node_key = self.node_key;
let manifest_content = self.manifest_content;
let p1 = self.p1.map(|p1| NodeHash::new(p1.sha1().clone()));
let p2 = self.p2.map(|p1| NodeHash::new(p1.sha1().clone()));
@ -104,10 +100,10 @@ impl UploadableBlob for TreemanifestEntry {
manifest::Type::Tree,
p1,
p2,
path.clone(),
node_key.path.clone(),
).map(move |(_node, value)| {
(
(node, path),
node_key,
(
manifest_content,
value.map_err(Error::compat).boxify().shared(),
@ -172,13 +168,15 @@ impl WirePackPartProcessor for TreemanifestPartProcessor {
return Err(ErrorKind::MalformedTreemanifestPart(msg).into());
}
let node = unwrap_field(&mut self.node, "node")?;
let node_key = mercurial::HgNodeKey {
path: unwrap_field(&mut self.path, "path")?,
hash: unwrap_field(&mut self.node, "node")?,
};
let bytes = Bytes::from(delta::apply("".as_bytes(), &data_entry.delta));
let p1 = unwrap_field(&mut self.p1, "p1")?;
let p2 = unwrap_field(&mut self.p2, "p2")?;
let path = unwrap_field(&mut self.path, "path")?;
Ok(Some(TreemanifestEntry::new(node, bytes, p1, p2, path)?))
Ok(Some(TreemanifestEntry::new(node_key, bytes, p1, p2)?))
}
fn end(&mut self) -> Result<Option<Self::Data>> {
@ -337,7 +335,10 @@ mod test {
}
fn get_expected_entry() -> TreemanifestEntry {
let node = nodehash_mocks::ONES_HASH;
let node_key = mercurial::HgNodeKey {
path: RepoPath::root(),
hash: nodehash_mocks::ONES_HASH,
};
let p1 = nodehash_mocks::TWOS_HASH;
let p2 = nodehash_mocks::THREES_HASH;
@ -347,8 +348,7 @@ mod test {
data
};
let entry =
TreemanifestEntry::new(node, Bytes::from(data), p1, p2, RepoPath::root()).unwrap();
let entry = TreemanifestEntry::new(node_key, Bytes::from(data), p1, p2).unwrap();
assert_eq!(
entry.manifest_content,

View File

@ -72,5 +72,5 @@ pub use errors::*;
pub use blobnode::{BlobNode, Parents};
pub use changeset::RevlogChangeset;
pub use manifest::{EntryContent, RevlogEntry};
pub use nodehash::{EntryId, HgChangesetId, HgManifestId, NodeHash, NULL_HASH};
pub use nodehash::{EntryId, HgChangesetId, HgManifestId, HgNodeKey, NodeHash, NULL_HASH};
pub use revlogrepo::{RevlogManifest, RevlogRepo, RevlogRepoOptions};

View File

@ -14,6 +14,7 @@ use ascii::{AsciiStr, AsciiString};
use quickcheck::{single_shrinker, Arbitrary, Gen};
use errors::*;
use mercurial_types::RepoPath;
use mercurial_types::hash::{self, Sha1};
use serde;
use sql_types::{HgChangesetIdSql, HgManifestIdSql};
@ -266,3 +267,11 @@ impl Display for EntryId {
self.0.fmt(fmt)
}
}
/// A (path, hash) combination. This is the key used throughout Mercurial for manifest and file
/// nodes.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct HgNodeKey {
pub path: RepoPath,
pub hash: NodeHash,
}