mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
skeleton_manifest: add first_case_conflict method
Summary: Add a method to `SkeletonManifest` which finds the paths to the first case conflict, if there is one. First means lexicographically first within directories, and with the shortest path. Reviewed By: ahornby, StanislavGlebik Differential Revision: D24990175 fbshipit-source-id: ec10f66582b81c40740823e32362ca489a6ebb4d
This commit is contained in:
parent
aea605a82d
commit
eddc285862
@ -406,6 +406,12 @@ mod test {
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
b_skeleton
|
||||
.first_case_conflict(&ctx, repo.blobstore())
|
||||
.await?,
|
||||
None,
|
||||
);
|
||||
|
||||
// Changeset C introduces some case conflicts
|
||||
let c_bcs = changesets["C"].load(ctx.clone(), repo.blobstore()).await?;
|
||||
@ -426,6 +432,15 @@ mod test {
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
c_skeleton
|
||||
.first_case_conflict(&ctx, repo.blobstore())
|
||||
.await?,
|
||||
Some((
|
||||
MPath::new(b"dir1/subdir1/SUBSUBDIR2")?,
|
||||
MPath::new(b"dir1/subdir1/subsubdir2")?
|
||||
))
|
||||
);
|
||||
|
||||
let c_sk_dir1 = skeleton_dir(&c_skeleton, b"dir1")?
|
||||
.id()
|
||||
@ -465,6 +480,15 @@ mod test {
|
||||
let d_skeleton = d_skeleton_id.load(ctx.clone(), repo.blobstore()).await?;
|
||||
assert_eq!(d_skeleton.summary().child_case_conflicts, false);
|
||||
assert_eq!(d_skeleton.summary().descendant_case_conflicts, true);
|
||||
assert_eq!(
|
||||
d_skeleton
|
||||
.first_case_conflict(&ctx, repo.blobstore())
|
||||
.await?,
|
||||
Some((
|
||||
MPath::new(b"dir1/subdir1/subsubdir1/FILE1")?,
|
||||
MPath::new(b"dir1/subdir1/subsubdir1/file1")?
|
||||
))
|
||||
);
|
||||
|
||||
let d_sk_dir1 = skeleton_dir(&d_skeleton, b"dir1")?
|
||||
.id()
|
||||
|
@ -9,13 +9,16 @@ use anyhow::{Context, Result};
|
||||
|
||||
use crate::blob::{Blob, BlobstoreValue, SkeletonManifestBlob};
|
||||
use crate::errors::ErrorKind;
|
||||
use crate::path::MPathElement;
|
||||
use crate::path::{MPath, MPathElement};
|
||||
use crate::thrift;
|
||||
use crate::typed_hash::{SkeletonManifestId, SkeletonManifestIdContext};
|
||||
|
||||
use blobstore::{Blobstore, StoreLoadable};
|
||||
use context::CoreContext;
|
||||
use fbthrift::compact_protocol;
|
||||
use sorted_vector_map::SortedVectorMap;
|
||||
use std::collections::BTreeMap;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
/// A skeleton manifest is a manifest node containing summary information about the
|
||||
/// the structure of files (their names, but not their contents) that is useful
|
||||
@ -83,6 +86,44 @@ impl SkeletonManifest {
|
||||
&self.summary
|
||||
}
|
||||
|
||||
pub async fn first_case_conflict(
|
||||
&self,
|
||||
ctx: &CoreContext,
|
||||
blobstore: &(impl Blobstore + Clone),
|
||||
) -> Result<Option<(MPath, MPath)>> {
|
||||
let mut sk_mf = Cow::Borrowed(self);
|
||||
let mut path: Option<MPath> = None;
|
||||
'outer: loop {
|
||||
if sk_mf.summary.child_case_conflicts {
|
||||
let mut lower_map = HashMap::new();
|
||||
for name in sk_mf.subentries.keys() {
|
||||
if let Some(lower_name) = name.to_lowercase_utf8() {
|
||||
if let Some(other_name) = lower_map.insert(lower_name, name.clone()) {
|
||||
return Ok(Some((
|
||||
MPath::join_opt_element(path.as_ref(), &other_name),
|
||||
MPath::join_opt_element(path.as_ref(), name),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if sk_mf.summary.descendant_case_conflicts {
|
||||
for (name, entry) in sk_mf.subentries.iter() {
|
||||
if let SkeletonManifestEntry::Directory(subdir) = entry {
|
||||
if subdir.summary.child_case_conflicts
|
||||
|| subdir.summary.descendant_case_conflicts
|
||||
{
|
||||
path = Some(MPath::join_opt_element(path.as_ref(), name));
|
||||
sk_mf = Cow::Owned(subdir.id.load(ctx.clone(), blobstore).await?);
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_thrift(t: thrift::SkeletonManifest) -> Result<SkeletonManifest> {
|
||||
let subentries = t
|
||||
.subentries
|
||||
|
Loading…
Reference in New Issue
Block a user