mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 16:57:49 +03:00
mononoke: remove get_mpath and get_path and use get_name
Summary: As we discussed before, let's add get_name() method that returns MPathElement, and remove get_path() and get_mpath(). Except for renaming, diff also make repoconfig work with tree manifest, and fixes linknodes creation in blobimport - previously basename was used instead of the whole path. Reviewed By: jsgf Differential Revision: D6857097 fbshipit-source-id: c09f3ff40d38643bd44aee8b4488277d658cf4f6
This commit is contained in:
parent
e2d6103e27
commit
1d7668ffba
@ -11,7 +11,7 @@ use futures::future::Future;
|
||||
use futures_ext::{BoxFuture, FutureExt};
|
||||
|
||||
use mercurial::file;
|
||||
use mercurial_types::{Blob, MPath, ManifestId, NodeHash, Parents, RepoPath};
|
||||
use mercurial_types::{Blob, MPath, MPathElement, ManifestId, NodeHash, Parents};
|
||||
use mercurial_types::manifest::{Content, Entry, Manifest, Type};
|
||||
use mercurial_types::nodehash::EntryId;
|
||||
|
||||
@ -25,7 +25,7 @@ use utils::{get_node, RawNodeBlob};
|
||||
|
||||
pub struct BlobEntry {
|
||||
blobstore: Arc<Blobstore>,
|
||||
path: RepoPath,
|
||||
name: Option<MPathElement>,
|
||||
id: EntryId,
|
||||
ty: Type,
|
||||
}
|
||||
@ -53,14 +53,15 @@ pub fn fetch_file_content_from_blobstore(
|
||||
}
|
||||
|
||||
impl BlobEntry {
|
||||
pub fn new(blobstore: Arc<Blobstore>, path: MPath, nodeid: NodeHash, ty: Type) -> Result<Self> {
|
||||
let path = match ty {
|
||||
Type::Tree => RepoPath::dir(path)?,
|
||||
_ => RepoPath::file(path)?,
|
||||
};
|
||||
pub fn new(
|
||||
blobstore: Arc<Blobstore>,
|
||||
name: Option<MPathElement>,
|
||||
nodeid: NodeHash,
|
||||
ty: Type,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
blobstore,
|
||||
path,
|
||||
name,
|
||||
id: EntryId::new(nodeid),
|
||||
ty,
|
||||
})
|
||||
@ -69,7 +70,7 @@ impl BlobEntry {
|
||||
pub fn new_root(blobstore: Arc<Blobstore>, manifestid: ManifestId) -> Self {
|
||||
Self {
|
||||
blobstore,
|
||||
path: RepoPath::RootPath,
|
||||
name: None,
|
||||
id: EntryId::new(manifestid.into_nodehash()),
|
||||
ty: Type::Tree,
|
||||
}
|
||||
@ -158,7 +159,7 @@ impl Entry for BlobEntry {
|
||||
&self.id
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &RepoPath {
|
||||
&self.path
|
||||
fn get_name(&self) -> &Option<MPathElement> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
@ -62,11 +62,14 @@ impl BlobManifest {
|
||||
|
||||
impl Manifest for BlobManifest {
|
||||
fn lookup(&self, path: &MPath) -> BoxFuture<Option<Box<Entry + Sync>>, Error> {
|
||||
// Path is a single MPathElement. In t25575327 we'll change the type.
|
||||
let name = path.clone().into_iter().next_back();
|
||||
|
||||
let res = self.files.get(path).map({
|
||||
move |d| {
|
||||
BlobEntry::new(
|
||||
self.blobstore.clone(),
|
||||
path.clone(),
|
||||
name,
|
||||
d.entryid().into_nodehash(),
|
||||
d.flag(),
|
||||
)
|
||||
@ -86,9 +89,10 @@ impl Manifest for BlobManifest {
|
||||
.map({
|
||||
let blobstore = self.blobstore.clone();
|
||||
move |(path, d)| {
|
||||
let name = path.clone().into_iter().next_back();
|
||||
BlobEntry::new(
|
||||
blobstore.clone(),
|
||||
path,
|
||||
name,
|
||||
d.entryid().into_nodehash(),
|
||||
d.flag(),
|
||||
)
|
||||
|
@ -19,7 +19,7 @@ use heads::Heads;
|
||||
use linknodes::Linknodes;
|
||||
use mercurial::{self, RevlogManifest, RevlogRepo};
|
||||
use mercurial::revlog::RevIdx;
|
||||
use mercurial_types::{Changeset, Manifest, NodeHash, RepoPath};
|
||||
use mercurial_types::{Changeset, MPath, Manifest, NodeHash, RepoPath};
|
||||
use mercurial_types::nodehash::{ChangesetId, EntryId};
|
||||
use stats::Timeseries;
|
||||
|
||||
@ -209,14 +209,15 @@ where
|
||||
entry,
|
||||
revlog_repo.clone(),
|
||||
linkrev.clone(),
|
||||
MPath::empty(),
|
||||
)
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.for_each(move |entry| {
|
||||
.for_each(move |(entry, repopath)| {
|
||||
// All entries share the same linknode to the changelog.
|
||||
let linknode_future = linknodes_store.add(
|
||||
entry.get_path().clone(),
|
||||
repopath,
|
||||
&entry.get_hash().into_nodehash(),
|
||||
&linknode,
|
||||
);
|
||||
|
@ -15,7 +15,7 @@ use blobrepo::RawNodeBlob;
|
||||
use futures_ext::StreamExt;
|
||||
use mercurial::RevlogRepo;
|
||||
use mercurial::revlog::RevIdx;
|
||||
use mercurial_types::{self, Blob, BlobHash, Entry, NodeHash, Parents, Type};
|
||||
use mercurial_types::{self, Blob, BlobHash, Entry, MPath, NodeHash, Parents, RepoPath, Type};
|
||||
|
||||
use BlobstoreEntry;
|
||||
|
||||
@ -73,8 +73,15 @@ pub(crate) fn get_entry_stream(
|
||||
entry: Box<Entry>,
|
||||
revlog_repo: RevlogRepo,
|
||||
cs_rev: RevIdx,
|
||||
) -> Box<Stream<Item = Box<Entry>, Error = Error> + Send> {
|
||||
let revlog = revlog_repo.get_path_revlog(entry.get_path());
|
||||
basepath: MPath,
|
||||
) -> Box<Stream<Item = (Box<Entry>, RepoPath), Error = Error> + Send> {
|
||||
let path = basepath.join_element(&entry.get_name());
|
||||
let repopath = if entry.get_type() == Type::Tree {
|
||||
RepoPath::DirectoryPath(path.clone())
|
||||
} else {
|
||||
RepoPath::FilePath(path.clone())
|
||||
};
|
||||
let revlog = revlog_repo.get_path_revlog(&repopath);
|
||||
|
||||
let linkrev = revlog
|
||||
.and_then(|file_revlog| file_revlog.get_entry_by_id(&entry.get_hash()))
|
||||
@ -96,7 +103,9 @@ pub(crate) fn get_entry_stream(
|
||||
}
|
||||
|
||||
match entry.get_type() {
|
||||
Type::File | Type::Executable | Type::Symlink => futures::stream::once(Ok(entry)).boxify(),
|
||||
Type::File | Type::Executable | Type::Symlink => {
|
||||
futures::stream::once(Ok((entry, repopath))).boxify()
|
||||
}
|
||||
Type::Tree => entry
|
||||
.get_content()
|
||||
.and_then(|content| match content {
|
||||
@ -105,11 +114,11 @@ pub(crate) fn get_entry_stream(
|
||||
})
|
||||
.flatten_stream()
|
||||
.map(move |entry| {
|
||||
get_entry_stream(entry, revlog_repo.clone(), cs_rev.clone())
|
||||
get_entry_stream(entry, revlog_repo.clone(), cs_rev.clone(), path.clone())
|
||||
})
|
||||
.map_err(Error::from)
|
||||
.flatten()
|
||||
.chain(futures::stream::once(Ok(entry)))
|
||||
.chain(futures::stream::once(Ok((entry, repopath))))
|
||||
.boxify(),
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ use futures_ext::{BoxFuture, FutureExt};
|
||||
use futures_stats::{Stats, Timed};
|
||||
use hyper::StatusCode;
|
||||
use hyper::server::{Http, Request, Response, Service};
|
||||
use mercurial_types::NodeHash;
|
||||
use mercurial_types::{MPathElement, NodeHash};
|
||||
use native_tls::TlsAcceptor;
|
||||
use native_tls::backend::openssl::TlsAcceptorBuilderExt;
|
||||
use openssl::ssl::{SSL_VERIFY_FAIL_IF_NO_PEER_CERT, SSL_VERIFY_PEER};
|
||||
@ -166,15 +166,21 @@ lazy_static! {
|
||||
struct TreeMetadata {
|
||||
hash: NodeHash,
|
||||
path: PathBuf,
|
||||
#[serde(rename = "type")] ty: mercurial_types::Type,
|
||||
#[serde(rename = "type")]
|
||||
ty: mercurial_types::Type,
|
||||
size: Option<usize>,
|
||||
}
|
||||
|
||||
impl TreeMetadata {
|
||||
fn new(size: Option<usize>, entry: Box<mercurial_types::Entry>) -> TreeMetadata {
|
||||
let name = entry
|
||||
.get_name()
|
||||
.clone()
|
||||
.unwrap_or(MPathElement::new(vec![]));
|
||||
|
||||
TreeMetadata {
|
||||
hash: entry.get_hash().into_nodehash().clone(),
|
||||
path: PathBuf::from(OsString::from_vec(entry.get_mpath().to_vec())),
|
||||
path: PathBuf::from(OsString::from_vec(Vec::from(name.as_bytes()))),
|
||||
ty: entry.get_type(),
|
||||
size,
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ where
|
||||
.map(move |parents| (entry, parents, content, linknode, basepath))
|
||||
})
|
||||
.and_then(|(entry, parents, content, linknode, basepath)| {
|
||||
let path = basepath.clone().join(&entry.get_mpath());
|
||||
let path = basepath.join_element(entry.get_name());
|
||||
let path = if path.is_empty() {
|
||||
Ok(RepoPath::RootPath)
|
||||
} else {
|
||||
|
@ -10,7 +10,7 @@ use failure::Error;
|
||||
use futures::{stream, IntoFuture};
|
||||
use futures_ext::{BoxFuture, BoxStream, FutureExt, StreamExt};
|
||||
|
||||
use mercurial_types::{Blob, Entry, MPath, Manifest, RepoPath, Type};
|
||||
use mercurial_types::{Blob, Entry, MPath, MPathElement, Manifest, RepoPath, Type};
|
||||
use mercurial_types::blobnode::Parents;
|
||||
use mercurial_types::manifest::Content;
|
||||
use mercurial_types::nodehash::EntryId;
|
||||
@ -22,6 +22,7 @@ pub fn make_file<C: AsRef<str>>(content: C) -> ContentFactory {
|
||||
Arc::new(move || Content::File(Blob::Dirty(content.clone())))
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MockManifest {
|
||||
entries: Vec<MockEntry>,
|
||||
}
|
||||
@ -47,10 +48,14 @@ impl MockManifest {
|
||||
MockManifest { entries }
|
||||
}
|
||||
|
||||
pub fn with_content(content: Vec<(&'static str, ContentFactory)>) -> Self {
|
||||
pub fn with_content(content: Vec<(&'static str, ContentFactory, Type)>) -> Self {
|
||||
let entries = content
|
||||
.into_iter()
|
||||
.map(|(p, c)| MockEntry::new(Self::p(p), c))
|
||||
.map(|(p, c, ty)| {
|
||||
let mut mock_entry = MockEntry::new(Self::p(p), c);
|
||||
mock_entry.set_type(ty);
|
||||
mock_entry
|
||||
})
|
||||
.collect();
|
||||
MockManifest { entries }
|
||||
}
|
||||
@ -67,6 +72,7 @@ impl Manifest for MockManifest {
|
||||
|
||||
pub struct MockEntry {
|
||||
path: RepoPath,
|
||||
name: Option<MPathElement>,
|
||||
content_factory: ContentFactory,
|
||||
ty: Option<Type>,
|
||||
hash: Option<EntryId>,
|
||||
@ -76,6 +82,7 @@ impl Clone for MockEntry {
|
||||
fn clone(&self) -> Self {
|
||||
MockEntry {
|
||||
path: self.path.clone(),
|
||||
name: self.name.clone(),
|
||||
content_factory: self.content_factory.clone(),
|
||||
ty: self.ty.clone(),
|
||||
hash: self.hash.clone(),
|
||||
@ -85,8 +92,15 @@ impl Clone for MockEntry {
|
||||
|
||||
impl MockEntry {
|
||||
pub fn new(path: RepoPath, content_factory: ContentFactory) -> Self {
|
||||
let name = match path.clone() {
|
||||
RepoPath::RootPath => None,
|
||||
RepoPath::FilePath(path) | RepoPath::DirectoryPath(path) => {
|
||||
path.clone().into_iter().next_back()
|
||||
}
|
||||
};
|
||||
MockEntry {
|
||||
path,
|
||||
name,
|
||||
content_factory,
|
||||
ty: None,
|
||||
hash: None,
|
||||
@ -124,7 +138,7 @@ impl Entry for MockEntry {
|
||||
None => panic!("hash is not set!"),
|
||||
}
|
||||
}
|
||||
fn get_path(&self) -> &RepoPath {
|
||||
&self.path
|
||||
fn get_name(&self) -> &Option<MPathElement> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use blob::Blob;
|
||||
use blobnode::Parents;
|
||||
use futures_ext::{BoxFuture, BoxStream, FutureExt, StreamExt};
|
||||
use nodehash::EntryId;
|
||||
use path::{MPath, RepoPath};
|
||||
use path::{MPath, MPathElement};
|
||||
|
||||
/// Interface for a manifest
|
||||
///
|
||||
@ -155,15 +155,8 @@ pub trait Entry: Send + 'static {
|
||||
/// Get the identity of the object this entry refers to.
|
||||
fn get_hash(&self) -> &EntryId;
|
||||
|
||||
/// Get the full path of this entry (meaningless - see T25575327)
|
||||
fn get_path(&self) -> &RepoPath;
|
||||
|
||||
fn get_mpath(&self) -> MPath {
|
||||
match self.get_path() {
|
||||
&RepoPath::RootPath => MPath::empty(),
|
||||
&RepoPath::DirectoryPath(ref path) | &RepoPath::FilePath(ref path) => path.clone(),
|
||||
}
|
||||
}
|
||||
/// Get the name of the entry. None means that this is a root entry
|
||||
fn get_name(&self) -> &Option<MPathElement>;
|
||||
|
||||
/// Return an Entry as a type-erased trait object.
|
||||
/// (Do we still need this as a trait method? T25577105)
|
||||
@ -222,12 +215,8 @@ where
|
||||
self.entry.get_hash()
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &RepoPath {
|
||||
self.entry.get_path()
|
||||
}
|
||||
|
||||
fn get_mpath(&self) -> MPath {
|
||||
self.entry.get_mpath()
|
||||
fn get_name(&self) -> &Option<MPathElement> {
|
||||
self.entry.get_name()
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,11 +245,7 @@ impl Entry for Box<Entry + Sync> {
|
||||
(**self).get_hash()
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &RepoPath {
|
||||
(**self).get_path()
|
||||
}
|
||||
|
||||
fn get_mpath(&self) -> MPath {
|
||||
(**self).get_mpath()
|
||||
fn get_name(&self) -> &Option<MPathElement> {
|
||||
(**self).get_name()
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use futures::stream::{empty, iter_ok, once, Stream};
|
||||
use futures_ext::{BoxStream, StreamExt};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use super::{Entry, MPath, Manifest};
|
||||
use super::{Entry, MPath, MPathElement, Manifest};
|
||||
use super::manifest::{Content, Type};
|
||||
|
||||
use errors::*;
|
||||
@ -84,15 +84,18 @@ fn recursive_changed_entry_stream(changed_entry: ChangedEntry) -> BoxStream<Chan
|
||||
let substream = if left.get_type() == Type::Tree {
|
||||
let contents = left.get_content().join(right.get_content());
|
||||
let path = changed_entry.path.clone();
|
||||
let entry_path = left.get_mpath().clone();
|
||||
let entry_path = left.get_name().clone();
|
||||
|
||||
let substream = contents
|
||||
.map(move |(left_content, right_content)| {
|
||||
let left_manifest = get_tree_content(left_content);
|
||||
let right_manifest = get_tree_content(right_content);
|
||||
|
||||
diff_manifests(path.join(&entry_path), left_manifest, right_manifest)
|
||||
.map(recursive_changed_entry_stream)
|
||||
diff_manifests(
|
||||
path.join_element(&entry_path),
|
||||
left_manifest,
|
||||
right_manifest,
|
||||
).map(recursive_changed_entry_stream)
|
||||
})
|
||||
.flatten_stream()
|
||||
.flatten();
|
||||
@ -115,15 +118,15 @@ fn recursive_changed_entry_stream(changed_entry: ChangedEntry) -> BoxStream<Chan
|
||||
/// Given an entry and path from the root of the repo to this entry, returns all subentries with
|
||||
/// their path from the root of the repo.
|
||||
/// For a non-tree entry returns a stream with a single (entry, path) pair.
|
||||
fn recursive_entry_stream(
|
||||
pub fn recursive_entry_stream(
|
||||
rootpath: MPath,
|
||||
entry: Box<Entry + Sync>,
|
||||
) -> BoxStream<(MPath, Box<Entry + Sync>), Error> {
|
||||
let subentries = match entry.get_type() {
|
||||
Type::File | Type::Symlink | Type::Executable => empty().boxify(),
|
||||
Type::Tree => {
|
||||
let entry_basename = entry.get_mpath().clone();
|
||||
let path = rootpath.join(&entry_basename);
|
||||
let entry_basename = entry.get_name();
|
||||
let path = rootpath.join(entry_basename);
|
||||
|
||||
entry
|
||||
.get_content()
|
||||
@ -175,8 +178,14 @@ pub fn diff_sorted_vecs(
|
||||
loop {
|
||||
match (left.pop_front(), right.pop_front()) {
|
||||
(Some(left_entry), Some(right_entry)) => {
|
||||
let left_path = left_entry.get_mpath().to_vec();
|
||||
let right_path = right_entry.get_mpath().to_vec();
|
||||
let left_path = left_entry
|
||||
.get_name()
|
||||
.clone()
|
||||
.unwrap_or(MPathElement::new(vec![]));
|
||||
let right_path = right_entry
|
||||
.get_name()
|
||||
.clone()
|
||||
.unwrap_or(MPathElement::new(vec![]));
|
||||
|
||||
if left_path < right_path {
|
||||
res.push(ChangedEntry::new_added(path.clone(), left_entry));
|
||||
|
@ -4,7 +4,6 @@
|
||||
// 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::cmp;
|
||||
use std::convert::{From, TryFrom, TryInto};
|
||||
use std::ffi::OsStr;
|
||||
@ -204,6 +203,13 @@ impl MPath {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join_element(&self, element: &Option<MPathElement>) -> MPath {
|
||||
match element {
|
||||
&Some(ref element) => self.join(element),
|
||||
&None => self.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate<W: Write>(&self, out: &mut W) -> io::Result<()> {
|
||||
out.write_all(&self.to_vec())
|
||||
}
|
||||
|
@ -197,18 +197,14 @@ fn check_changed_paths(
|
||||
for changed_entry in actual {
|
||||
match changed_entry.status {
|
||||
EntryStatus::Added(entry) => {
|
||||
paths_added.push(changed_entry.path.join(&entry.get_mpath()));
|
||||
paths_added.push(changed_entry.path.join_element(&entry.get_name()));
|
||||
}
|
||||
EntryStatus::Deleted(entry) => {
|
||||
paths_deleted.push(changed_entry.path.join(&entry.get_mpath()));
|
||||
paths_deleted.push(changed_entry.path.join_element(&entry.get_name()));
|
||||
}
|
||||
EntryStatus::Modified(left_entry, right_entry) => {
|
||||
assert_eq!(left_entry.get_type(), right_entry.get_type());
|
||||
assert_eq!(
|
||||
left_entry.get_mpath().to_vec(),
|
||||
right_entry.get_mpath().to_vec()
|
||||
);
|
||||
paths_modified.push(changed_entry.path.join(&left_entry.get_mpath()));
|
||||
paths_modified.push(changed_entry.path.join_element(&left_entry.get_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use futures_ext::{BoxFuture, BoxStream, FutureExt, StreamExt};
|
||||
use errors::*;
|
||||
use failure;
|
||||
use file;
|
||||
use mercurial_types::{Blob, BlobNode, MPath, NodeHash, Parents, RepoPath};
|
||||
use mercurial_types::{Blob, BlobNode, MPath, MPathElement, NodeHash, Parents, RepoPath};
|
||||
use mercurial_types::manifest::{Content, Entry, Manifest, Type};
|
||||
use mercurial_types::nodehash::EntryId;
|
||||
|
||||
@ -200,6 +200,7 @@ where
|
||||
pub struct RevlogEntry {
|
||||
repo: RevlogRepo,
|
||||
path: RepoPath,
|
||||
name: Option<MPathElement>,
|
||||
details: Details,
|
||||
}
|
||||
|
||||
@ -247,18 +248,27 @@ impl Manifest for RevlogManifest {
|
||||
|
||||
impl RevlogEntry {
|
||||
fn new(repo: RevlogRepo, path: MPath, details: Details) -> Result<Self> {
|
||||
let name = (&path).into_iter().next_back().map(|path| path.clone());
|
||||
let path = match details.flag() {
|
||||
Type::Tree => RepoPath::dir(path)
|
||||
.with_context(|_| ErrorKind::Path("error while creating RepoPath".into()))?,
|
||||
_ => RepoPath::file(path)
|
||||
.with_context(|_| ErrorKind::Path("error while creating RepoPath".into()))?,
|
||||
};
|
||||
|
||||
// For revlog we still need to store full path, because full path is used to find revlog
|
||||
// file
|
||||
Ok(RevlogEntry {
|
||||
repo,
|
||||
path,
|
||||
name,
|
||||
details,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &RepoPath {
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
||||
impl Entry for RevlogEntry {
|
||||
@ -351,8 +361,8 @@ impl Entry for RevlogEntry {
|
||||
&self.details.entryid
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &RepoPath {
|
||||
&self.path
|
||||
fn get_name(&self) -> &Option<MPathElement> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,8 +434,9 @@ mod test {
|
||||
(
|
||||
MPath::new(b"hello123").unwrap(),
|
||||
Details {
|
||||
entryid : EntryId::new(
|
||||
"da39a3ee5e6b4b0d3255bfef95601890afd80709".parse().unwrap()),
|
||||
entryid: EntryId::new(
|
||||
"da39a3ee5e6b4b0d3255bfef95601890afd80709".parse().unwrap(),
|
||||
),
|
||||
flag: Type::Symlink,
|
||||
},
|
||||
),
|
||||
|
@ -225,6 +225,7 @@ mod test {
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use mercurial_types::Type;
|
||||
use mercurial_types_mocks::manifest::{make_file, MockManifest};
|
||||
|
||||
#[test]
|
||||
@ -239,10 +240,26 @@ mod test {
|
||||
repotype="revlog"
|
||||
"#;
|
||||
|
||||
let my_path_manifest = MockManifest::with_content(vec![
|
||||
("my_files", Arc::new(|| unimplemented!()), Type::File),
|
||||
]);
|
||||
|
||||
let repos_manifest = MockManifest::with_content(vec![
|
||||
("fbsource", make_file(fbsource_content), Type::File),
|
||||
("www", make_file(www_content), Type::File),
|
||||
]);
|
||||
|
||||
let repoconfig = RepoConfigs::read_manifest(&MockManifest::with_content(vec![
|
||||
("my_path/my_files", Arc::new(|| unimplemented!())),
|
||||
("repos/fbsource", make_file(fbsource_content)),
|
||||
("repos/www", make_file(www_content)),
|
||||
(
|
||||
"my_path",
|
||||
Arc::new(move || Content::Tree(Box::new(my_path_manifest.clone()))),
|
||||
Type::File,
|
||||
),
|
||||
(
|
||||
"repos",
|
||||
Arc::new(move || Content::Tree(Box::new(repos_manifest.clone()))),
|
||||
Type::Tree,
|
||||
),
|
||||
])).wait()
|
||||
.expect("failed to read config from manifest");
|
||||
|
||||
|
@ -26,7 +26,7 @@ use mercurial;
|
||||
use mercurial_bundles::{parts, Bundle2EncodeBuilder};
|
||||
use mercurial_bundles::bundle2::{self, Bundle2Stream, StreamEvent};
|
||||
use mercurial_types::{percent_encode, BlobNode, Changeset, Entry, MPath, ManifestId, NodeHash,
|
||||
Parents, Type, NULL_HASH};
|
||||
Parents, RepoPath, Type, NULL_HASH};
|
||||
use mercurial_types::manifest_utils::{changed_entry_stream, EntryStatus};
|
||||
use metaconfig::repoconfig::RepoType;
|
||||
|
||||
@ -510,14 +510,14 @@ impl HgCommands for RepoClient {
|
||||
.filter_map(move |entry_status| match entry_status.status {
|
||||
EntryStatus::Added(entry) => {
|
||||
if entry.get_type() == Type::Tree {
|
||||
Some(entry)
|
||||
Some((entry, entry_status.path))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
EntryStatus::Modified(entry, _) => {
|
||||
if entry.get_type() == Type::Tree {
|
||||
Some(entry)
|
||||
Some((entry, entry_status.path))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -526,9 +526,9 @@ impl HgCommands for RepoClient {
|
||||
})
|
||||
.and_then({
|
||||
let hgrepo = self.repo.hgrepo.clone();
|
||||
move |val| fetch_linknode(hgrepo.clone(), val)
|
||||
move |(entry, path)| fetch_linknode(hgrepo.clone(), entry, path)
|
||||
})
|
||||
.map(|(entry, linknode)| (entry, linknode, MPath::empty()));
|
||||
.map(|(entry, linknode, basepath)| (entry, linknode, basepath));
|
||||
|
||||
// Append root manifest
|
||||
let root_entry_stream = Ok(self.repo
|
||||
@ -537,9 +537,9 @@ impl HgCommands for RepoClient {
|
||||
.into_future()
|
||||
.and_then({
|
||||
let hgrepo = self.repo.hgrepo.clone();
|
||||
move |val| fetch_linknode(hgrepo.clone(), val)
|
||||
move |entry| fetch_linknode(hgrepo.clone(), entry, MPath::empty())
|
||||
})
|
||||
.map(|(entry, linknode)| stream::once(Ok((entry, linknode, MPath::empty()))))
|
||||
.map(|(entry, linknode, basepath)| stream::once(Ok((entry, linknode, basepath))))
|
||||
.flatten_stream();
|
||||
|
||||
parts::treepack_part(changed_entries.chain(root_entry_stream))
|
||||
@ -557,8 +557,22 @@ impl HgCommands for RepoClient {
|
||||
fn fetch_linknode(
|
||||
repo: Arc<BlobRepo>,
|
||||
entry: Box<Entry + Sync>,
|
||||
) -> BoxFuture<(Box<Entry + Sync>, NodeHash), Error> {
|
||||
let linknode_fut =
|
||||
repo.get_linknode(entry.get_path().clone(), &entry.get_hash().into_nodehash());
|
||||
linknode_fut.map(|linknode| (entry, linknode)).boxify()
|
||||
basepath: MPath,
|
||||
) -> BoxFuture<(Box<Entry + Sync>, NodeHash, MPath), Error> {
|
||||
let path = match entry.get_name() {
|
||||
&Some(ref name) => {
|
||||
let path = basepath.clone().join(name.clone().into_iter());
|
||||
if entry.get_type() == Type::Tree {
|
||||
RepoPath::DirectoryPath(path)
|
||||
} else {
|
||||
RepoPath::FilePath(path)
|
||||
}
|
||||
}
|
||||
&None => RepoPath::RootPath,
|
||||
};
|
||||
|
||||
let linknode_fut = repo.get_linknode(path, &entry.get_hash().into_nodehash());
|
||||
linknode_fut
|
||||
.map(|linknode| (entry, linknode, basepath))
|
||||
.boxify()
|
||||
}
|
||||
|
@ -16,6 +16,31 @@ function wait_for_mononoke {
|
||||
done
|
||||
}
|
||||
|
||||
function setup_config_repo {
|
||||
hg init mononoke-config
|
||||
cd mononoke-config || exit
|
||||
cat >> .hg/hgrc <<EOF
|
||||
[extensions]
|
||||
treemanifest=
|
||||
remotefilelog=
|
||||
[treemanifest]
|
||||
server=True
|
||||
[remotefilelog]
|
||||
server=True
|
||||
shallowtrees=True
|
||||
EOF
|
||||
|
||||
mkdir repos
|
||||
cat > repos/repo <<CONFIG
|
||||
path="$TESTTMP/repo"
|
||||
repotype="blob:files"
|
||||
CONFIG
|
||||
hg add -q repos
|
||||
hg ci -ma
|
||||
hg bookmark test-config
|
||||
hg backfilltree
|
||||
cd ..
|
||||
}
|
||||
function blobimport {
|
||||
$MONONOKE_BLOBIMPORT "$@"
|
||||
}
|
||||
|
@ -1,27 +1,7 @@
|
||||
$ . $TESTDIR/library.sh
|
||||
|
||||
setup configuration
|
||||
|
||||
$ hg init mononoke-config
|
||||
$ cd mononoke-config
|
||||
$ mkdir repos
|
||||
$ cat > repos/repo <<CONFIG
|
||||
> path="$TESTTMP/repo"
|
||||
> repotype="blob:files"
|
||||
> CONFIG
|
||||
$ hg add repos
|
||||
adding repos/repo
|
||||
$ hg ci -ma
|
||||
$ hg bookmark test-config
|
||||
$ hg log
|
||||
changeset: 0:* (glob)
|
||||
bookmark: test-config
|
||||
tag: tip
|
||||
user: test
|
||||
date: Thu Jan 01 00:00:00 1970 +0000
|
||||
summary: a
|
||||
|
||||
|
||||
$ setup_config_repo
|
||||
$ cd $TESTTMP
|
||||
|
||||
setup common configuration
|
||||
|
@ -2,25 +2,7 @@
|
||||
|
||||
setup configuration
|
||||
|
||||
$ hg init mononoke-config
|
||||
$ cd mononoke-config
|
||||
$ mkdir repos
|
||||
$ cat > repos/repo <<CONFIG
|
||||
> path="$TESTTMP/repo"
|
||||
> repotype="blob:files"
|
||||
> CONFIG
|
||||
$ hg add repos
|
||||
adding repos/repo
|
||||
$ hg ci -ma
|
||||
$ hg bookmark test-config
|
||||
$ hg log
|
||||
changeset: 0:* (glob)
|
||||
bookmark: test-config
|
||||
tag: tip
|
||||
user: test
|
||||
date: Thu Jan 01 00:00:00 1970 +0000
|
||||
summary: a
|
||||
|
||||
$ setup_config_repo
|
||||
|
||||
$ cd $TESTTMP
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#[macro_use]
|
||||
extern crate failure_ext as failure;
|
||||
extern crate futures;
|
||||
extern crate futures_ext;
|
||||
extern crate itertools;
|
||||
extern crate mercurial_types;
|
||||
|
||||
|
@ -9,9 +9,10 @@ use std::sync::Arc;
|
||||
|
||||
use futures::{Future, Stream};
|
||||
|
||||
use mercurial_types::{Entry, Manifest};
|
||||
use mercurial_types::{Entry, Manifest, Type};
|
||||
use mercurial_types::manifest::Content;
|
||||
use mercurial_types::path::{MPathElement, DOT, DOTDOT};
|
||||
use mercurial_types::manifest_utils::recursive_entry_stream;
|
||||
use mercurial_types::path::{MPath, MPathElement, DOT, DOTDOT};
|
||||
|
||||
use node::{VfsDir, VfsFile, VfsNode};
|
||||
use tree::{TNodeId, Tree, TreeValue, ROOT_ID};
|
||||
@ -33,18 +34,23 @@ where
|
||||
manifest
|
||||
.list()
|
||||
.map_err(|err| {
|
||||
err.context("failed while listing the manifest").into()
|
||||
let error: Error = err.context("failed while listing the manifest").into();
|
||||
error
|
||||
})
|
||||
.map(|entry| recursive_entry_stream(MPath::empty(), entry))
|
||||
.flatten()
|
||||
.filter(|pathentry| pathentry.1.get_type() != Type::Tree)
|
||||
.collect()
|
||||
.and_then(|entries| {
|
||||
.and_then(|pathentries| {
|
||||
let mut path_tree = Tree::new();
|
||||
for (entry_idx, entry) in entries.iter().enumerate() {
|
||||
let mut path = entry.get_mpath().clone().into_iter();
|
||||
let leaf_key = path.next_back().ok_or_else(|| {
|
||||
ErrorKind::ManifestInvalidPath("the path shouldn't be empty".into())
|
||||
let mut entries = vec![];
|
||||
for (entry_idx, (path, entry)) in pathentries.into_iter().enumerate() {
|
||||
let name = entry.get_name().clone();
|
||||
let name = name.ok_or_else(|| {
|
||||
ErrorKind::ManifestInvalidPath("name shouldn't be empty".into())
|
||||
})?;
|
||||
|
||||
path_tree.insert(path, leaf_key, TEntryId(entry_idx))?;
|
||||
path_tree.insert(path, name, TEntryId(entry_idx))?;
|
||||
entries.push(entry);
|
||||
}
|
||||
Ok(ManifestVfsDir {
|
||||
root: Arc::new(ManifestVfsRoot { entries, path_tree }),
|
||||
@ -180,6 +186,7 @@ mod test {
|
||||
use test::*;
|
||||
|
||||
use mercurial_types::MPath;
|
||||
use mercurial_types_mocks::manifest::MockManifest;
|
||||
use node::VfsWalker;
|
||||
|
||||
fn unwrap_dir<TDir: VfsDir>(node: VfsNode<TDir, TDir::TFile>) -> TDir {
|
||||
@ -208,7 +215,49 @@ mod test {
|
||||
}
|
||||
|
||||
fn example_vfs() -> ManifestVfsDir {
|
||||
get_vfs(vec!["a/b", "a/ab", "c/d/e", "c/d/da", "c/ca/afsd", "f"])
|
||||
let a_manifest = MockManifest::with_content(vec![
|
||||
("b", Arc::new(|| unimplemented!()), Type::File),
|
||||
("ab", Arc::new(|| unimplemented!()), Type::File),
|
||||
]);
|
||||
|
||||
let d_manifest = MockManifest::with_content(vec![
|
||||
("e", Arc::new(|| unimplemented!()), Type::File),
|
||||
("da", Arc::new(|| unimplemented!()), Type::File),
|
||||
]);
|
||||
|
||||
let ca_manifest =
|
||||
MockManifest::with_content(vec![("afsd", Arc::new(|| unimplemented!()), Type::File)]);
|
||||
|
||||
let c_manifest = MockManifest::with_content(vec![
|
||||
(
|
||||
"d",
|
||||
Arc::new(move || Content::Tree(Box::new(d_manifest.clone()))),
|
||||
Type::Tree,
|
||||
),
|
||||
(
|
||||
"ca",
|
||||
Arc::new(move || Content::Tree(Box::new(ca_manifest.clone()))),
|
||||
Type::Tree,
|
||||
),
|
||||
]);
|
||||
|
||||
let root_manifest = MockManifest::with_content(vec![
|
||||
(
|
||||
"a",
|
||||
Arc::new(move || Content::Tree(Box::new(a_manifest.clone()))),
|
||||
Type::Tree,
|
||||
),
|
||||
(
|
||||
"c",
|
||||
Arc::new(move || Content::Tree(Box::new(c_manifest.clone()))),
|
||||
Type::Tree,
|
||||
),
|
||||
("f", Arc::new(|| unimplemented!()), Type::File),
|
||||
]);
|
||||
|
||||
vfs_from_manifest(&root_manifest)
|
||||
.wait()
|
||||
.expect("failed to get vfs")
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user