mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 16:57:49 +03:00
commit_rewriting: allow non-prefix free maps in metaconfig
Summary: This is in line with other changes we're making to map logic now. Note that apart from checking in-repo prefix-free-ness of the map, this also checked the same across many small repos. It probably does not make sense to do that either now that we allow non-prefix free maps within a repo. Reviewed By: StanislavGlebik Differential Revision: D24348161 fbshipit-source-id: caaa22953c8a15a08607157b99c9f0fd0edf633f
This commit is contained in:
parent
7af104b330
commit
a4f69ed7da
@ -597,204 +597,6 @@ mod test {
|
||||
assert!(msg.contains("present multiple times in the same CommitSyncConfig"));
|
||||
}
|
||||
|
||||
#[fbinit::test]
|
||||
fn test_commit_sync_config_conflicting_path_prefixes_small_to_large(fb: FacebookInit) {
|
||||
let commit_sync_config = r#"
|
||||
[mega]
|
||||
large_repo_id = 1
|
||||
common_pushrebase_bookmarks = ["master"]
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 2
|
||||
bookmark_prefix = "repo2"
|
||||
default_action = "preserve"
|
||||
direction = "small_to_large"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p1" = ".r2-legacy/p1"
|
||||
"p5" = "subdir"
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 3
|
||||
bookmark_prefix = "repo3"
|
||||
default_action = "prepend_prefix"
|
||||
default_prefix = "subdir"
|
||||
direction = "small_to_large"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p1" = "p1"
|
||||
"p4" = "p5/p4"
|
||||
"#;
|
||||
|
||||
let paths = btreemap! {
|
||||
"common/commitsyncmap.toml" => commit_sync_config
|
||||
};
|
||||
let tmp_dir = write_files(&paths);
|
||||
let res = load_repo_configs(fb, tmp_dir.path());
|
||||
let msg = format!("{:#?}", res);
|
||||
println!("res = {}", msg);
|
||||
assert!(res.is_err());
|
||||
assert!(msg.contains("is a prefix of MPath"));
|
||||
}
|
||||
|
||||
#[fbinit::test]
|
||||
fn test_commit_sync_config_conflicting_path_prefixes_large_to_small(fb: FacebookInit) {
|
||||
// Purely identical prefixes, allowed in large-to-small
|
||||
let commit_sync_config = r#"
|
||||
[mega]
|
||||
large_repo_id = 1
|
||||
common_pushrebase_bookmarks = ["master"]
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 2
|
||||
bookmark_prefix = "repo2"
|
||||
default_action = "preserve"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p5" = "subdir"
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 3
|
||||
bookmark_prefix = "repo3"
|
||||
default_action = "prepend_prefix"
|
||||
default_prefix = "subdir"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p1" = "p1"
|
||||
"#;
|
||||
|
||||
let paths = btreemap! {
|
||||
"common/commitsyncmap.toml" => commit_sync_config
|
||||
};
|
||||
let tmp_dir = write_files(&paths);
|
||||
let commit_sync_config = load_repo_configs(fb, tmp_dir.path());
|
||||
assert!(commit_sync_config.is_ok());
|
||||
|
||||
// Overlapping, but not identical prefixes
|
||||
let commit_sync_config = r#"
|
||||
[mega]
|
||||
large_repo_id = 1
|
||||
common_pushrebase_bookmarks = ["master"]
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 2
|
||||
bookmark_prefix = "repo2"
|
||||
default_action = "preserve"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p5" = "subdir/bla"
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 3
|
||||
bookmark_prefix = "repo3"
|
||||
default_action = "prepend_prefix"
|
||||
default_prefix = "subdir"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p1" = "p1"
|
||||
"#;
|
||||
|
||||
let paths = btreemap! {
|
||||
"common/commitsyncmap.toml" => commit_sync_config
|
||||
};
|
||||
let tmp_dir = write_files(&paths);
|
||||
let res = load_repo_configs(fb, tmp_dir.path());
|
||||
let msg = format!("{:#?}", res);
|
||||
println!("res = {}", msg);
|
||||
assert!(res.is_err());
|
||||
assert!(msg.contains("is a prefix of MPath"));
|
||||
}
|
||||
|
||||
#[fbinit::test]
|
||||
fn test_commit_sync_config_conflicting_path_prefixes_mixed(fb: FacebookInit) {
|
||||
// Conflicting paths, should fail
|
||||
let commit_sync_config = r#"
|
||||
[mega]
|
||||
large_repo_id = 1
|
||||
common_pushrebase_bookmarks = ["master"]
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 2
|
||||
bookmark_prefix = "repo2"
|
||||
default_action = "preserve"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p5" = "subdir"
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 3
|
||||
bookmark_prefix = "repo3"
|
||||
default_action = "prepend_prefix"
|
||||
default_prefix = "subdir"
|
||||
direction = "small_to_large"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p1" = "p1"
|
||||
"#;
|
||||
|
||||
let paths = btreemap! {
|
||||
"common/commitsyncmap.toml" => commit_sync_config
|
||||
};
|
||||
let tmp_dir = write_files(&paths);
|
||||
let res = load_repo_configs(fb, tmp_dir.path());
|
||||
let msg = format!("{:#?}", res);
|
||||
println!("res = {}", msg);
|
||||
assert!(res.is_err());
|
||||
assert!(msg.contains("is a prefix of MPath"));
|
||||
|
||||
// Paths, identical between large-to-smalls, but
|
||||
// overlapping with small-to-large, should fail
|
||||
let commit_sync_config = r#"
|
||||
[mega]
|
||||
large_repo_id = 1
|
||||
common_pushrebase_bookmarks = ["master"]
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 2
|
||||
bookmark_prefix = "repo2"
|
||||
default_action = "preserve"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p5" = "subdir"
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 3
|
||||
bookmark_prefix = "repo3"
|
||||
default_action = "prepend_prefix"
|
||||
default_prefix = "r3"
|
||||
direction = "small_to_large"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p1" = "subdir/bla"
|
||||
|
||||
[[mega.small_repos]]
|
||||
repoid = 4
|
||||
bookmark_prefix = "repo4"
|
||||
default_action = "prepend_prefix"
|
||||
default_prefix = "r4"
|
||||
direction = "large_to_small"
|
||||
|
||||
[mega.small_repos.mapping]
|
||||
"p4" = "subdir"
|
||||
"#;
|
||||
|
||||
let paths = btreemap! {
|
||||
"common/commitsyncmap.toml" => commit_sync_config
|
||||
};
|
||||
let tmp_dir = write_files(&paths);
|
||||
let res = load_repo_configs(fb, tmp_dir.path());
|
||||
let msg = format!("{:#?}", res);
|
||||
println!("res = {}", msg);
|
||||
assert!(res.is_err());
|
||||
assert!(msg.contains("is a prefix of MPath"));
|
||||
}
|
||||
|
||||
#[fbinit::test]
|
||||
fn test_commit_sync_config_conflicting_bookmark_prefixes(fb: FacebookInit) {
|
||||
let commit_sync_config = r#"
|
||||
|
@ -48,15 +48,6 @@ fn check_no_duplicate_small_repos(small_repos: &[RawCommitSyncSmallRepoConfig])
|
||||
|
||||
/// Validate the commit sync config
|
||||
///
|
||||
/// - Check that all the prefixes in the large repo (target prefixes in a map and prefixes
|
||||
/// from `DefaultSmallToLargeCommitSyncPathAction::PrependPrefix`) are independent, e.g. aren't prefixes
|
||||
/// of each other, if the sync direction is small-to-large. This is not allowed, because
|
||||
/// otherwise there is no way to prevent path conflicts. For example, if one repo maps
|
||||
/// `p1 => foo/bar` and the other maps `p2 => foo`, both repos can accept commits that
|
||||
/// change `foo` and these commits can contain path conflicts. Given that the repos have
|
||||
/// already replied successfully to their clients, it's too late to reject these commits.
|
||||
/// To avoid this problem, we remove the possiblity of path conflicts altogether.
|
||||
///
|
||||
/// - Check that no two small repos use the same bookmark prefix. If they did, this would
|
||||
/// mean potentail bookmark name collisions.
|
||||
///
|
||||
@ -72,51 +63,12 @@ fn validate_commit_sync_config(commit_sync_config: &CommitSyncConfig) -> Result<
|
||||
));
|
||||
}
|
||||
|
||||
let all_prefixes_with_direction: Vec<(&MPath, CommitSyncDirection)> = commit_sync_config
|
||||
.small_repos
|
||||
.values()
|
||||
.flat_map(|small_repo_sync_config| {
|
||||
let SmallRepoCommitSyncConfig {
|
||||
default_action,
|
||||
map,
|
||||
direction,
|
||||
..
|
||||
} = small_repo_sync_config;
|
||||
let all_prefixes = map.values();
|
||||
match default_action {
|
||||
DefaultSmallToLargeCommitSyncPathAction::PrependPrefix(prefix) => {
|
||||
all_prefixes.chain(vec![prefix].into_iter())
|
||||
}
|
||||
DefaultSmallToLargeCommitSyncPathAction::Preserve => {
|
||||
all_prefixes.chain(vec![].into_iter())
|
||||
}
|
||||
}
|
||||
.map(move |prefix| (prefix, direction.clone()))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let bookmark_prefixes: Vec<&AsciiString> = commit_sync_config
|
||||
.small_repos
|
||||
.iter()
|
||||
.map(|(_, sr)| &sr.bookmark_prefix)
|
||||
.collect();
|
||||
|
||||
for ((first_prefix, first_direction), (second_prefix, second_direction)) in
|
||||
all_prefixes_with_direction
|
||||
.iter()
|
||||
.tuple_combinations::<(_, _)>()
|
||||
{
|
||||
if first_prefix == second_prefix
|
||||
&& *first_direction == CommitSyncDirection::LargeToSmall
|
||||
&& *second_direction == CommitSyncDirection::LargeToSmall
|
||||
{
|
||||
// when syncing large-to-small, it is allowed to have identical prefixes,
|
||||
// but not prefixes that are proper prefixes of other prefixes
|
||||
continue;
|
||||
}
|
||||
validate_mpath_prefixes(first_prefix, second_prefix)?;
|
||||
}
|
||||
|
||||
// No two small repos can have the same bookmark prefix
|
||||
for (first_prefix, second_prefix) in bookmark_prefixes.iter().tuple_combinations::<(_, _)>() {
|
||||
let fp = first_prefix.as_str();
|
||||
@ -133,25 +85,6 @@ fn validate_commit_sync_config(commit_sync_config: &CommitSyncConfig) -> Result<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify that two mpaths are not a prefix of each other
|
||||
fn validate_mpath_prefixes(first_prefix: &MPath, second_prefix: &MPath) -> Result<()> {
|
||||
if first_prefix.is_prefix_of(second_prefix) {
|
||||
return Err(anyhow!(
|
||||
"{:?} is a prefix of {:?}, which is disallowed",
|
||||
first_prefix,
|
||||
second_prefix
|
||||
));
|
||||
}
|
||||
if second_prefix.is_prefix_of(first_prefix) {
|
||||
return Err(anyhow!(
|
||||
"{:?} is a prefix of {:?}, which is disallowed",
|
||||
second_prefix,
|
||||
first_prefix
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Convert for RawCommitSyncConfig {
|
||||
type Output = CommitSyncConfig;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user