2021-04-05 08:56:10 +03:00
|
|
|
// Copyright 2021 Google LLC
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
use jujutsu_lib::backend::{CommitId, MillisSinceEpoch, Signature, Timestamp};
|
2021-05-15 19:16:31 +03:00
|
|
|
use jujutsu_lib::commit_builder::CommitBuilder;
|
2021-07-11 20:58:01 +03:00
|
|
|
use jujutsu_lib::op_store::RefTarget;
|
2021-05-15 19:16:31 +03:00
|
|
|
use jujutsu_lib::repo::RepoRef;
|
2021-05-28 18:37:06 +03:00
|
|
|
use jujutsu_lib::revset::{parse, resolve_symbol, RevsetError};
|
2021-05-15 19:16:31 +03:00
|
|
|
use jujutsu_lib::testutils::CommitGraphBuilder;
|
2021-05-30 09:52:50 +03:00
|
|
|
use jujutsu_lib::{git, testutils};
|
2021-04-05 08:56:10 +03:00
|
|
|
use test_case::test_case;
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-05 08:56:10 +03:00
|
|
|
fn test_resolve_symbol_root(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(repo.as_repo_ref(), "root"),
|
|
|
|
Ok(vec![repo.store().root_commit_id().clone()])
|
2021-04-05 08:56:10 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_resolve_symbol_commit_id() {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
// Test only with git so we can get predictable commit ids
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, true);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
let signature = Signature {
|
|
|
|
name: "test".to_string(),
|
|
|
|
email: "test".to_string(),
|
|
|
|
timestamp: Timestamp {
|
|
|
|
timestamp: MillisSinceEpoch(0),
|
|
|
|
tz_offset: 0,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut commits = vec![];
|
|
|
|
for i in &[1, 167, 895] {
|
|
|
|
let commit = CommitBuilder::for_new_commit(
|
|
|
|
&settings,
|
|
|
|
repo.store(),
|
|
|
|
repo.store().empty_tree_id().clone(),
|
|
|
|
)
|
|
|
|
.set_description(format!("test {}", i))
|
|
|
|
.set_author(signature.clone())
|
|
|
|
.set_committer(signature.clone())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
commits.push(commit);
|
|
|
|
}
|
2021-07-31 00:35:08 +03:00
|
|
|
let repo = tx.commit();
|
2021-04-05 08:56:10 +03:00
|
|
|
|
|
|
|
// Test the test setup
|
|
|
|
assert_eq!(
|
|
|
|
commits[0].id().hex(),
|
|
|
|
"0454de3cae04c46cda37ba2e8873b4c17ff51dcb"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
commits[1].id().hex(),
|
|
|
|
"045f56cd1b17e8abde86771e2705395dcde6a957"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
commits[2].id().hex(),
|
|
|
|
"0468f7da8de2ce442f512aacf83411d26cd2e0cf"
|
|
|
|
);
|
|
|
|
|
|
|
|
// Test lookup by full commit id
|
2021-07-31 00:35:08 +03:00
|
|
|
let repo_ref = repo.as_repo_ref();
|
2021-04-05 08:56:10 +03:00
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(repo_ref, "0454de3cae04c46cda37ba2e8873b4c17ff51dcb"),
|
|
|
|
Ok(vec![commits[0].id().clone()])
|
2021-04-05 08:56:10 +03:00
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(repo_ref, "045f56cd1b17e8abde86771e2705395dcde6a957"),
|
|
|
|
Ok(vec![commits[1].id().clone()])
|
2021-04-05 08:56:10 +03:00
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(repo_ref, "0468f7da8de2ce442f512aacf83411d26cd2e0cf"),
|
|
|
|
Ok(vec![commits[2].id().clone()])
|
2021-04-05 08:56:10 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Test commit id prefix
|
2021-05-30 20:26:23 +03:00
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "046"),
|
|
|
|
Ok(vec![commits[2].id().clone()])
|
|
|
|
);
|
2021-04-05 08:56:10 +03:00
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04"),
|
|
|
|
Err(RevsetError::AmbiguousCommitIdPrefix("04".to_string()))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, ""),
|
|
|
|
Err(RevsetError::AmbiguousCommitIdPrefix("".to_string()))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "040"),
|
|
|
|
Err(RevsetError::NoSuchRevision("040".to_string()))
|
|
|
|
);
|
|
|
|
|
2021-04-10 09:51:37 +03:00
|
|
|
// Test non-hex string
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "foo"),
|
|
|
|
Err(RevsetError::NoSuchRevision("foo".to_string()))
|
|
|
|
);
|
2021-04-05 08:56:10 +03:00
|
|
|
}
|
|
|
|
|
2021-05-30 09:52:50 +03:00
|
|
|
#[test]
|
|
|
|
fn test_resolve_symbol_change_id() {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
// Test only with git so we can get predictable change ids
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, true);
|
|
|
|
|
|
|
|
let git_repo = repo.store().git_repo().unwrap();
|
|
|
|
// Add some commits that will end up having change ids with common prefixes
|
|
|
|
let empty_tree_id = git_repo.treebuilder(None).unwrap().write().unwrap();
|
|
|
|
let git_author = git2::Signature::new(
|
|
|
|
"git author",
|
|
|
|
"git.author@example.com",
|
|
|
|
&git2::Time::new(1000, 60),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
let git_committer = git2::Signature::new(
|
|
|
|
"git committer",
|
|
|
|
"git.committer@example.com",
|
|
|
|
&git2::Time::new(2000, -480),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
let git_tree = git_repo.find_tree(empty_tree_id).unwrap();
|
|
|
|
let mut git_commit_ids = vec![];
|
|
|
|
for i in &[133, 664, 840] {
|
|
|
|
let git_commit_id = git_repo
|
|
|
|
.commit(
|
|
|
|
Some(&format!("refs/heads/branch{}", i)),
|
|
|
|
&git_author,
|
|
|
|
&git_committer,
|
|
|
|
&format!("test {}", i),
|
|
|
|
&git_tree,
|
|
|
|
&[],
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
git_commit_ids.push(git_commit_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
git::import_refs(tx.mut_repo(), &git_repo).unwrap();
|
|
|
|
let repo = tx.commit();
|
|
|
|
|
|
|
|
// Test the test setup
|
|
|
|
assert_eq!(
|
|
|
|
hex::encode(git_commit_ids[0].as_bytes()),
|
|
|
|
// "04e12a5467bba790efb88a9870894ec208b16bf1" reversed
|
|
|
|
"8fd68d104372910e19511df709e5dde62a548720"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
hex::encode(git_commit_ids[1].as_bytes()),
|
|
|
|
// "040b3ba3a51d8edbc4c5855cbd09de71d4c29cca" reversed
|
|
|
|
"5339432b8e7b90bd3aa1a323db71b8a5c5dcd020"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
hex::encode(git_commit_ids[2].as_bytes()),
|
|
|
|
// "04e1c7082e4e34f3f371d8a1a46770b861b9b547" reversed
|
|
|
|
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
|
|
|
);
|
|
|
|
|
|
|
|
// Test lookup by full change id
|
|
|
|
let repo_ref = repo.as_repo_ref();
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04e12a5467bba790efb88a9870894ec2"),
|
|
|
|
Ok(vec![CommitId::from_hex(
|
|
|
|
"8fd68d104372910e19511df709e5dde62a548720"
|
|
|
|
)])
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "040b3ba3a51d8edbc4c5855cbd09de71"),
|
|
|
|
Ok(vec![CommitId::from_hex(
|
|
|
|
"5339432b8e7b90bd3aa1a323db71b8a5c5dcd020"
|
|
|
|
)])
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04e1c7082e4e34f3f371d8a1a46770b8"),
|
|
|
|
Ok(vec![CommitId::from_hex(
|
|
|
|
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
|
|
|
)])
|
|
|
|
);
|
|
|
|
|
|
|
|
// Test change id prefix
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04e12"),
|
|
|
|
Ok(vec![CommitId::from_hex(
|
|
|
|
"8fd68d104372910e19511df709e5dde62a548720"
|
|
|
|
)])
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04e1c"),
|
|
|
|
Ok(vec![CommitId::from_hex(
|
|
|
|
"e2ad9d861d0ee625851b8ecfcf2c727410e38720"
|
|
|
|
)])
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04e1"),
|
|
|
|
Err(RevsetError::AmbiguousChangeIdPrefix("04e1".to_string()))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, ""),
|
|
|
|
// Commit id is checked first, so this is considered an ambiguous commit id
|
|
|
|
Err(RevsetError::AmbiguousCommitIdPrefix("".to_string()))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "04e13"),
|
|
|
|
Err(RevsetError::NoSuchRevision("04e13".to_string()))
|
|
|
|
);
|
|
|
|
|
|
|
|
// Test non-hex string
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(repo_ref, "foo"),
|
|
|
|
Err(RevsetError::NoSuchRevision("foo".to_string()))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-05 08:56:10 +03:00
|
|
|
fn test_resolve_symbol_checkout(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
|
|
|
|
mut_repo.set_checkout(commit1.id().clone());
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "@"),
|
|
|
|
Ok(vec![commit1.id().clone()])
|
2021-04-05 08:56:10 +03:00
|
|
|
);
|
|
|
|
mut_repo.set_checkout(commit2.id().clone());
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "@"),
|
|
|
|
Ok(vec![commit2.id().clone()])
|
2021-04-05 08:56:10 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
2021-04-10 09:40:52 +03:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_resolve_symbol_git_refs() {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, true);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
// Create some commits and refs to work with and so the repo is not empty
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit3 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit4 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit5 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch1".to_string(),
|
|
|
|
RefTarget::Normal(commit1.id().clone()),
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch2".to_string(),
|
|
|
|
RefTarget::Normal(commit2.id().clone()),
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/conflicted".to_string(),
|
|
|
|
RefTarget::Conflict {
|
|
|
|
removes: vec![commit2.id().clone()],
|
|
|
|
adds: vec![commit1.id().clone(), commit3.id().clone()],
|
|
|
|
},
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/tag1".to_string(),
|
|
|
|
RefTarget::Normal(commit2.id().clone()),
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-04-10 09:40:52 +03:00
|
|
|
"refs/tags/remotes/origin/branch1".to_string(),
|
2021-07-11 20:58:01 +03:00
|
|
|
RefTarget::Normal(commit3.id().clone()),
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Non-existent ref
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "non-existent"),
|
|
|
|
Err(RevsetError::NoSuchRevision("non-existent".to_string()))
|
|
|
|
);
|
|
|
|
|
|
|
|
// Full ref
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch".to_string(),
|
|
|
|
RefTarget::Normal(commit4.id().clone()),
|
|
|
|
);
|
2021-04-10 09:40:52 +03:00
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "refs/heads/branch"),
|
|
|
|
Ok(vec![commit4.id().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Qualified with only heads/
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch".to_string(),
|
|
|
|
RefTarget::Normal(commit5.id().clone()),
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/branch".to_string(),
|
|
|
|
RefTarget::Normal(commit4.id().clone()),
|
|
|
|
);
|
2021-04-10 09:40:52 +03:00
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "heads/branch"),
|
|
|
|
Ok(vec![commit5.id().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Unqualified branch name
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch".to_string(),
|
|
|
|
RefTarget::Normal(commit3.id().clone()),
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/branch".to_string(),
|
|
|
|
RefTarget::Normal(commit4.id().clone()),
|
|
|
|
);
|
2021-04-10 09:40:52 +03:00
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "branch"),
|
|
|
|
Ok(vec![commit3.id().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Unqualified tag name
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/tag".to_string(),
|
|
|
|
RefTarget::Normal(commit4.id().clone()),
|
|
|
|
);
|
2021-04-10 09:40:52 +03:00
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "tag"),
|
|
|
|
Ok(vec![commit4.id().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Unqualified remote-tracking branch name
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-04-10 09:40:52 +03:00
|
|
|
"refs/remotes/origin/remote-branch".to_string(),
|
2021-07-11 20:58:01 +03:00
|
|
|
RefTarget::Normal(commit2.id().clone()),
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "origin/remote-branch"),
|
|
|
|
Ok(vec![commit2.id().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
// Cannot shadow checkout ("@") or root symbols
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref("@".to_string(), RefTarget::Normal(commit2.id().clone()));
|
|
|
|
mut_repo.set_git_ref("root".to_string(), RefTarget::Normal(commit3.id().clone()));
|
2021-04-10 09:40:52 +03:00
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "@"),
|
|
|
|
Ok(vec![mut_repo.view().checkout().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-05-30 20:26:23 +03:00
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "root"),
|
|
|
|
Ok(vec![mut_repo.store().root_commit().id().clone()])
|
2021-04-10 09:40:52 +03:00
|
|
|
);
|
|
|
|
|
2021-07-11 20:58:01 +03:00
|
|
|
// Conflicted ref resolves to its "adds"
|
|
|
|
assert_eq!(
|
|
|
|
resolve_symbol(mut_repo.as_repo_ref(), "refs/heads/conflicted"),
|
|
|
|
Ok(vec![commit1.id().clone(), commit3.id().clone()])
|
|
|
|
);
|
|
|
|
|
2021-04-10 09:40:52 +03:00
|
|
|
tx.discard();
|
|
|
|
}
|
2021-04-10 20:18:30 +03:00
|
|
|
|
|
|
|
fn resolve_commit_ids(repo: RepoRef, revset_str: &str) -> Vec<CommitId> {
|
2021-04-15 02:54:27 +03:00
|
|
|
let expression = parse(revset_str).unwrap();
|
2021-05-28 18:37:06 +03:00
|
|
|
expression
|
|
|
|
.evaluate(repo)
|
2021-04-10 20:18:30 +03:00
|
|
|
.unwrap()
|
|
|
|
.iter()
|
|
|
|
.map(|entry| entry.commit_id())
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-10 20:18:30 +03:00
|
|
|
fn test_evaluate_expression_root_and_checkout(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let root_commit = repo.store().root_commit();
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
|
|
|
|
// Can find the root commit
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "root"),
|
|
|
|
vec![root_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Can find the current checkout
|
|
|
|
mut_repo.set_checkout(commit1.id().clone());
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "@"),
|
|
|
|
vec![commit1.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-10 20:18:30 +03:00
|
|
|
fn test_evaluate_expression_parents(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-10 20:18:30 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.initial_commit();
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit2, &commit3]);
|
|
|
|
let commit5 = graph_builder.commit_with_parents(&[&commit2]);
|
2021-04-10 20:18:30 +03:00
|
|
|
|
|
|
|
// The root commit has no parents
|
|
|
|
assert_eq!(resolve_commit_ids(mut_repo.as_repo_ref(), ":root"), vec![]);
|
|
|
|
|
|
|
|
// Can find parents of the current checkout
|
|
|
|
mut_repo.set_checkout(commit2.id().clone());
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), ":@"),
|
|
|
|
vec![commit1.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Can find parents of a merge commit
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), &format!(":{}", commit4.id().hex())),
|
2021-04-19 01:09:29 +03:00
|
|
|
vec![commit3.id().clone(), commit2.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Parents of all commits in input are returned
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!(":({} | {})", commit2.id().hex(), commit3.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit1.id().clone(), root_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Parents already in input set are returned
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
2021-04-23 08:45:58 +03:00
|
|
|
&format!(":({} | {})", commit1.id().hex(), commit2.id().hex())
|
2021-04-19 01:09:29 +03:00
|
|
|
),
|
|
|
|
vec![commit1.id().clone(), root_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Parents shared among commits in input are not repeated
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!(":({} | {})", commit4.id().hex(), commit5.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit3.id().clone(), commit2.id().clone()]
|
2021-04-10 20:18:30 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-22 00:51:23 +03:00
|
|
|
fn test_evaluate_expression_children(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let wc_commit = repo.working_copy_locked().current_commit();
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit3 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.set_predecessors(vec![commit2.id().clone()])
|
|
|
|
.set_change_id(commit2.change_id().clone())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit4 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit3.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit5 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit6 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit4.id().clone(), commit5.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
|
|
|
|
// Can find children of the root commit
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "root:"),
|
|
|
|
vec![commit1.id().clone(), wc_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Children do not include hidden commits (commit2)
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), &format!("{}:", commit1.id().hex())),
|
|
|
|
vec![commit5.id().clone(), commit3.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Children of all commits in input are returned, including those already in the
|
|
|
|
// input set
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("({} | {}):", commit1.id().hex(), commit3.id().hex())
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone()
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Children shared among commits in input are not repeated
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("({} | {}):", commit4.id().hex(), commit5.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit6.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-10 20:18:30 +03:00
|
|
|
fn test_evaluate_expression_ancestors(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-10 20:18:30 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit1, &commit3]);
|
2021-04-10 20:18:30 +03:00
|
|
|
|
|
|
|
// The ancestors of the root commit is just the root commit itself
|
|
|
|
assert_eq!(
|
2021-04-22 09:34:20 +03:00
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), ",,root"),
|
2021-04-10 20:18:30 +03:00
|
|
|
vec![root_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Can find ancestors of a specific commit. Commits reachable via multiple paths
|
|
|
|
// are not repeated.
|
|
|
|
assert_eq!(
|
2021-04-22 09:34:20 +03:00
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), &format!(",,{}", commit4.id().hex())),
|
2021-04-10 20:18:30 +03:00
|
|
|
vec![
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
root_commit.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
2021-04-16 08:19:08 +03:00
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-23 21:11:39 +03:00
|
|
|
fn test_evaluate_expression_range(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit1, &commit3]);
|
2021-04-23 21:11:39 +03:00
|
|
|
|
|
|
|
// The range from the root to the root is empty (because the left side of the
|
|
|
|
// range is exclusive)
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "root,,,root"),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Linear range
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,,{}", commit1.id().hex(), commit3.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit3.id().clone(), commit2.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Empty range (descendant first)
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,,{}", commit3.id().hex(), commit1.id().hex())
|
|
|
|
),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Range including a merge
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,,{}", commit1.id().hex(), commit4.id().hex())
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone()
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Sibling commits
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,,{}", commit2.id().hex(), commit3.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit3.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-23 08:45:58 +03:00
|
|
|
fn test_evaluate_expression_dag_range(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-23 08:45:58 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit5 = graph_builder.commit_with_parents(&[&commit3, &commit4]);
|
2021-04-23 08:45:58 +03:00
|
|
|
|
|
|
|
// Can get DAG range of just the root commit
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "root,,root"),
|
|
|
|
vec![root_commit.id().clone(),]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Linear range
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,{}", root_commit.id().hex(), commit2.id().hex())
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
root_commit.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Empty range
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,{}", commit2.id().hex(), commit4.id().hex())
|
|
|
|
),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Including a merge
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,{}", commit1.id().hex(), commit5.id().hex())
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Including a merge, but only ancestors only from one side
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{},,{}", commit2.id().hex(), commit5.id().hex())
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-22 00:51:23 +03:00
|
|
|
fn test_evaluate_expression_descendants(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let root_commit = repo.store().root_commit();
|
|
|
|
let wc_commit = repo.working_copy_locked().current_commit();
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit3 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.set_predecessors(vec![commit2.id().clone()])
|
|
|
|
.set_change_id(commit2.change_id().clone())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit4 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit3.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit5 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit6 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit4.id().clone(), commit5.id().clone()])
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
|
|
|
|
// The descendants of the root commit is all the non-hidden commits in the repo
|
|
|
|
// (commit2 is excluded)
|
|
|
|
assert_eq!(
|
2021-04-22 09:34:20 +03:00
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "root,,"),
|
2021-04-22 00:51:23 +03:00
|
|
|
vec![
|
|
|
|
commit6.id().clone(),
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
wc_commit.id().clone(),
|
|
|
|
root_commit.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
2021-08-29 08:03:49 +03:00
|
|
|
// Can find descendants of a specific commit
|
2021-04-22 00:51:23 +03:00
|
|
|
assert_eq!(
|
2021-08-29 08:03:49 +03:00
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), &format!("{},,", commit3.id().hex())),
|
2021-04-22 00:51:23 +03:00
|
|
|
vec![
|
|
|
|
commit6.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-16 08:19:08 +03:00
|
|
|
fn test_evaluate_expression_all_heads(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
let wc_commit = repo.working_copy_locked().current_commit();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
2021-04-16 08:19:08 +03:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "all_heads()"),
|
|
|
|
vec![commit2.id().clone(), wc_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
2021-04-16 08:52:33 +03:00
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-19 03:30:21 +03:00
|
|
|
fn test_evaluate_expression_public_heads(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-19 03:30:21 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.initial_commit();
|
2021-04-19 03:30:21 +03:00
|
|
|
|
|
|
|
// Can get public heads with root commit as only public head
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "public_heads()"),
|
2021-04-19 08:52:31 +03:00
|
|
|
vec![root_commit.id().clone()]
|
2021-04-19 03:30:21 +03:00
|
|
|
);
|
|
|
|
// Can get public heads with a single public head
|
|
|
|
mut_repo.add_public_head(&commit1);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "public_heads()"),
|
|
|
|
vec![commit1.id().clone()]
|
|
|
|
);
|
|
|
|
// Can get public heads with multiple public head
|
|
|
|
mut_repo.add_public_head(&commit2);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "public_heads()"),
|
|
|
|
vec![commit2.id().clone(), commit1.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-26 09:38:23 +03:00
|
|
|
fn test_evaluate_expression_git_refs(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
2021-07-11 20:58:01 +03:00
|
|
|
let commit3 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit4 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
2021-04-26 09:38:23 +03:00
|
|
|
|
|
|
|
// Can get git refs when there are none
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "git_refs()"),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
// Can get a mix of git refs
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch1".to_string(),
|
|
|
|
RefTarget::Normal(commit1.id().clone()),
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/tag1".to_string(),
|
|
|
|
RefTarget::Normal(commit2.id().clone()),
|
|
|
|
);
|
2021-04-26 09:38:23 +03:00
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "git_refs()"),
|
|
|
|
vec![commit2.id().clone(), commit1.id().clone()]
|
|
|
|
);
|
|
|
|
// Two refs pointing to the same commit does not result in a duplicate in the
|
|
|
|
// revset
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/tag2".to_string(),
|
|
|
|
RefTarget::Normal(commit2.id().clone()),
|
|
|
|
);
|
2021-04-26 09:38:23 +03:00
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "git_refs()"),
|
|
|
|
vec![commit2.id().clone(), commit1.id().clone()]
|
|
|
|
);
|
2021-07-11 20:58:01 +03:00
|
|
|
// Can get git refs when there are conflicted refs
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/heads/branch1".to_string(),
|
|
|
|
RefTarget::Conflict {
|
|
|
|
removes: vec![commit1.id().clone()],
|
|
|
|
adds: vec![commit2.id().clone(), commit3.id().clone()],
|
|
|
|
},
|
|
|
|
);
|
2021-08-04 18:42:16 +03:00
|
|
|
mut_repo.set_git_ref(
|
2021-07-11 20:58:01 +03:00
|
|
|
"refs/tags/tag1".to_string(),
|
|
|
|
RefTarget::Conflict {
|
|
|
|
removes: vec![commit2.id().clone()],
|
|
|
|
adds: vec![commit3.id().clone(), commit4.id().clone()],
|
|
|
|
},
|
|
|
|
);
|
|
|
|
mut_repo.remove_git_ref("refs/tags/tag2");
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "git_refs()"),
|
|
|
|
vec![
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone()
|
|
|
|
]
|
|
|
|
);
|
2021-04-26 09:38:23 +03:00
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-16 08:52:33 +03:00
|
|
|
fn test_evaluate_expression_obsolete(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let root_commit = repo.store().root_commit();
|
|
|
|
let wc_commit = repo.working_copy_locked().current_commit();
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_predecessors(vec![commit1.id().clone()])
|
|
|
|
.set_change_id(commit1.change_id().clone())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit3 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_predecessors(vec![commit2.id().clone()])
|
|
|
|
.set_change_id(commit2.change_id().clone())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit4 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit3.id().clone()])
|
|
|
|
.set_pruned(true)
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "non_obsolete_heads()"),
|
|
|
|
vec![commit3.id().clone(), wc_commit.id().clone()]
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("non_obsolete_heads({})", commit4.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit3.id().clone()]
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("non_obsolete_heads({})", commit1.id().hex())
|
|
|
|
),
|
|
|
|
vec![root_commit.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
2021-04-16 20:24:22 +03:00
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-05-02 00:29:43 +03:00
|
|
|
fn test_evaluate_expression_merges(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.initial_commit();
|
|
|
|
let commit3 = graph_builder.initial_commit();
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit1, &commit2]);
|
|
|
|
let commit5 = graph_builder.commit_with_parents(&[&commit1, &commit2, &commit3]);
|
|
|
|
|
|
|
|
// Finds all merges by default
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "merges()"),
|
|
|
|
vec![commit5.id().clone(), commit4.id().clone(),]
|
|
|
|
);
|
|
|
|
// Searches only among candidates if specified
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("merges(,,{})", commit5.id().hex())
|
|
|
|
),
|
|
|
|
vec![commit5.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-16 20:24:22 +03:00
|
|
|
fn test_evaluate_expression_description(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
|
|
|
|
let commit1 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_description("commit 1".to_string())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit2 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit1.id().clone()])
|
|
|
|
.set_description("commit 2".to_string())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
let commit3 = testutils::create_random_commit(&settings, &repo)
|
|
|
|
.set_parents(vec![commit2.id().clone()])
|
|
|
|
.set_description("commit 3".to_string())
|
|
|
|
.write_to_repo(mut_repo);
|
|
|
|
|
|
|
|
// Can find multiple matches
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "description(commit)"),
|
|
|
|
vec![
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone()
|
|
|
|
]
|
|
|
|
);
|
|
|
|
// Can find a unique match
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(mut_repo.as_repo_ref(), "description(\"commit 2\")"),
|
|
|
|
vec![commit2.id().clone()]
|
|
|
|
);
|
2021-05-02 00:29:43 +03:00
|
|
|
// Searches only among candidates if specified
|
2021-04-16 20:24:22 +03:00
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
"description(\"commit 2\",all_heads())"
|
|
|
|
),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
2021-04-18 01:25:52 +03:00
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-19 01:09:29 +03:00
|
|
|
fn test_evaluate_expression_union(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-19 01:09:29 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit3]);
|
|
|
|
let commit5 = graph_builder.commit_with_parents(&[&commit2]);
|
2021-04-19 01:09:29 +03:00
|
|
|
|
|
|
|
// Union between ancestors
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
2021-04-22 09:34:20 +03:00
|
|
|
&format!(",,{} | ,,{}", commit4.id().hex(), commit5.id().hex())
|
2021-04-19 01:09:29 +03:00
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
root_commit.id().clone()
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Unioning can add back commits removed by difference
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!(
|
2021-04-22 09:34:20 +03:00
|
|
|
"(,,{} - ,,{}) | ,,{}",
|
2021-04-19 01:09:29 +03:00
|
|
|
commit4.id().hex(),
|
|
|
|
commit2.id().hex(),
|
|
|
|
commit5.id().hex()
|
|
|
|
)
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone(),
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
root_commit.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Unioning of disjoint sets
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!(
|
2021-04-22 09:34:20 +03:00
|
|
|
"(,,{} - ,,{}) | {}",
|
2021-04-19 01:09:29 +03:00
|
|
|
commit4.id().hex(),
|
|
|
|
commit2.id().hex(),
|
|
|
|
commit5.id().hex(),
|
|
|
|
)
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit5.id().clone(),
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit3.id().clone()
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-19 03:10:17 +03:00
|
|
|
fn test_evaluate_expression_intersection(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-19 03:10:17 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit3]);
|
|
|
|
let commit5 = graph_builder.commit_with_parents(&[&commit2]);
|
2021-04-19 03:10:17 +03:00
|
|
|
|
|
|
|
// Intersection between ancestors
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
2021-04-22 09:34:20 +03:00
|
|
|
&format!(",,{} & ,,{}", commit4.id().hex(), commit5.id().hex())
|
2021-04-19 03:10:17 +03:00
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit2.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
root_commit.id().clone()
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Intersection of disjoint sets
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!("{} & {}", commit4.id().hex(), commit2.id().hex())
|
|
|
|
),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-04-18 01:25:52 +03:00
|
|
|
fn test_evaluate_expression_difference(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2021-05-01 07:41:27 +03:00
|
|
|
let root_commit = repo.store().root_commit();
|
2021-04-18 01:25:52 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let mut_repo = tx.mut_repo();
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
|
|
|
let commit1 = graph_builder.initial_commit();
|
|
|
|
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
|
|
|
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
|
|
|
let commit4 = graph_builder.commit_with_parents(&[&commit3]);
|
|
|
|
let commit5 = graph_builder.commit_with_parents(&[&commit2]);
|
2021-04-18 01:25:52 +03:00
|
|
|
|
|
|
|
// Difference between ancestors
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
2021-04-22 09:34:20 +03:00
|
|
|
&format!(",,{} - ,,{}", commit4.id().hex(), commit5.id().hex())
|
2021-04-18 01:25:52 +03:00
|
|
|
),
|
|
|
|
vec![commit4.id().clone(), commit3.id().clone()]
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
2021-04-22 09:34:20 +03:00
|
|
|
&format!(",,{} - ,,{}", commit5.id().hex(), commit4.id().hex())
|
2021-04-18 01:25:52 +03:00
|
|
|
),
|
|
|
|
vec![commit5.id().clone()]
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
2021-04-22 09:34:20 +03:00
|
|
|
&format!(",,{} - ,,{}", commit4.id().hex(), commit2.id().hex())
|
2021-04-18 01:25:52 +03:00
|
|
|
),
|
|
|
|
vec![commit4.id().clone(), commit3.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Associativity
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!(
|
2021-04-22 09:34:20 +03:00
|
|
|
",,{} - {} - {}",
|
2021-04-18 01:25:52 +03:00
|
|
|
commit4.id().hex(),
|
|
|
|
commit2.id().hex(),
|
|
|
|
commit3.id().hex()
|
|
|
|
)
|
|
|
|
),
|
|
|
|
vec![
|
|
|
|
commit4.id().clone(),
|
|
|
|
commit1.id().clone(),
|
|
|
|
root_commit.id().clone(),
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
// Subtracting a difference does not add back any commits
|
|
|
|
assert_eq!(
|
|
|
|
resolve_commit_ids(
|
|
|
|
mut_repo.as_repo_ref(),
|
|
|
|
&format!(
|
2021-04-22 09:34:20 +03:00
|
|
|
"(,,{} - ,,{}) - (,,{} - ,,{})",
|
2021-04-18 01:25:52 +03:00
|
|
|
commit4.id().hex(),
|
|
|
|
commit1.id().hex(),
|
|
|
|
commit3.id().hex(),
|
|
|
|
commit1.id().hex(),
|
|
|
|
)
|
|
|
|
),
|
|
|
|
vec![commit4.id().clone()]
|
|
|
|
);
|
|
|
|
|
|
|
|
tx.discard();
|
|
|
|
}
|