2020-12-12 11:00:42 +03:00
|
|
|
// Copyright 2020 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-03-14 20:37:28 +03:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
use jujutsu_lib::backend::CommitId;
|
2021-05-15 19:16:31 +03:00
|
|
|
use jujutsu_lib::commit::Commit;
|
|
|
|
use jujutsu_lib::commit_builder::CommitBuilder;
|
|
|
|
use jujutsu_lib::index::IndexRef;
|
|
|
|
use jujutsu_lib::repo::ReadonlyRepo;
|
|
|
|
use jujutsu_lib::settings::UserSettings;
|
|
|
|
use jujutsu_lib::testutils;
|
|
|
|
use jujutsu_lib::testutils::{create_random_commit, CommitGraphBuilder};
|
2020-12-12 11:00:42 +03:00
|
|
|
use test_case::test_case;
|
|
|
|
|
|
|
|
#[must_use]
|
|
|
|
fn child_commit(settings: &UserSettings, repo: &ReadonlyRepo, commit: &Commit) -> CommitBuilder {
|
2021-06-14 10:18:38 +03:00
|
|
|
testutils::create_random_commit(settings, repo).set_parents(vec![commit.id().clone()])
|
2020-12-12 11:00:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helper just to reduce line wrapping
|
2021-02-06 11:40:34 +03:00
|
|
|
fn generation_number<'a>(index: impl Into<IndexRef<'a>>, commit_id: &CommitId) -> u32 {
|
|
|
|
index
|
|
|
|
.into()
|
|
|
|
.entry_by_id(commit_id)
|
|
|
|
.unwrap()
|
|
|
|
.generation_number()
|
2020-12-12 11:00:42 +03:00
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2020-12-12 11:00:42 +03:00
|
|
|
fn test_index_commits_empty_repo(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit
|
|
|
|
assert_eq!(index.num_commits(), 2);
|
|
|
|
|
|
|
|
// Check the generation numbers of the root and the working copy
|
|
|
|
assert_eq!(
|
2021-04-13 08:47:21 +03:00
|
|
|
generation_number(index.as_ref(), repo.store().root_commit_id()),
|
2021-02-06 11:40:34 +03:00
|
|
|
0
|
|
|
|
);
|
2021-11-17 23:29:08 +03:00
|
|
|
assert_eq!(generation_number(index.as_ref(), repo.view().checkout()), 1);
|
2020-12-12 11:00:42 +03:00
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2020-12-12 11:00:42 +03:00
|
|
|
fn test_index_commits_standard_cases(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
2021-05-19 23:39:03 +03:00
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
2020-12-12 11:00:42 +03:00
|
|
|
|
|
|
|
// o H
|
|
|
|
// o | G
|
|
|
|
// o | F
|
|
|
|
// |\|
|
|
|
|
// | o E
|
|
|
|
// | o D
|
|
|
|
// | o C
|
|
|
|
// o | B
|
|
|
|
// |/
|
|
|
|
// o A
|
|
|
|
// | o working copy
|
|
|
|
// |/
|
|
|
|
// o root
|
|
|
|
|
2021-11-17 23:29:08 +03:00
|
|
|
let root_commit_id = repo.store().root_commit_id();
|
|
|
|
let checkout_id = repo.view().checkout().clone();
|
2020-12-12 11:00:42 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, tx.mut_repo());
|
|
|
|
let commit_a = graph_builder.initial_commit();
|
|
|
|
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
|
|
|
let commit_c = graph_builder.commit_with_parents(&[&commit_a]);
|
|
|
|
let commit_d = graph_builder.commit_with_parents(&[&commit_c]);
|
|
|
|
let commit_e = graph_builder.commit_with_parents(&[&commit_d]);
|
|
|
|
let commit_f = graph_builder.commit_with_parents(&[&commit_b, &commit_e]);
|
|
|
|
let commit_g = graph_builder.commit_with_parents(&[&commit_f]);
|
|
|
|
let commit_h = graph_builder.commit_with_parents(&[&commit_e]);
|
2021-05-19 23:39:03 +03:00
|
|
|
let repo = tx.commit();
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit, plus
|
|
|
|
// 8 more
|
|
|
|
assert_eq!(index.num_commits(), 2 + 8);
|
|
|
|
|
|
|
|
let stats = index.stats();
|
|
|
|
assert_eq!(stats.num_commits, 2 + 8);
|
|
|
|
assert_eq!(stats.num_merges, 1);
|
|
|
|
assert_eq!(stats.max_generation_number, 6);
|
|
|
|
|
2021-11-17 23:29:08 +03:00
|
|
|
assert_eq!(generation_number(index.as_ref(), root_commit_id), 0);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), &checkout_id), 1);
|
2021-04-13 08:47:21 +03:00
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_a.id()), 1);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_b.id()), 2);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_c.id()), 2);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_d.id()), 3);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_e.id()), 4);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_f.id()), 5);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_g.id()), 6);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_h.id()), 5);
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2021-11-17 23:29:08 +03:00
|
|
|
assert!(index.is_ancestor(root_commit_id, commit_a.id()));
|
|
|
|
assert!(!index.is_ancestor(commit_a.id(), root_commit_id));
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2021-11-17 23:29:08 +03:00
|
|
|
assert!(index.is_ancestor(root_commit_id, commit_b.id()));
|
|
|
|
assert!(!index.is_ancestor(commit_b.id(), root_commit_id));
|
2020-12-12 11:00:42 +03:00
|
|
|
|
|
|
|
assert!(!index.is_ancestor(commit_b.id(), commit_c.id()));
|
|
|
|
|
|
|
|
assert!(index.is_ancestor(commit_a.id(), commit_b.id()));
|
|
|
|
assert!(index.is_ancestor(commit_a.id(), commit_e.id()));
|
|
|
|
assert!(index.is_ancestor(commit_a.id(), commit_f.id()));
|
|
|
|
assert!(index.is_ancestor(commit_a.id(), commit_g.id()));
|
|
|
|
assert!(index.is_ancestor(commit_a.id(), commit_h.id()));
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2020-12-12 11:00:42 +03:00
|
|
|
fn test_index_commits_criss_cross(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
2021-05-19 23:39:03 +03:00
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
2020-12-12 11:00:42 +03:00
|
|
|
|
|
|
|
let num_generations = 50;
|
|
|
|
|
|
|
|
// Create a long chain of criss-crossed merges. If they were traversed without
|
|
|
|
// keeping track of visited nodes, it would be 2^50 visits, so if this test
|
|
|
|
// finishes in reasonable time, we know that we don't do a naive traversal.
|
|
|
|
let mut tx = repo.start_transaction("test");
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, tx.mut_repo());
|
|
|
|
let mut left_commits = vec![graph_builder.initial_commit()];
|
|
|
|
let mut right_commits = vec![graph_builder.initial_commit()];
|
2020-12-12 11:00:42 +03:00
|
|
|
for gen in 1..num_generations {
|
2021-05-01 07:41:27 +03:00
|
|
|
let new_left =
|
|
|
|
graph_builder.commit_with_parents(&[&left_commits[gen - 1], &right_commits[gen - 1]]);
|
|
|
|
let new_right =
|
|
|
|
graph_builder.commit_with_parents(&[&left_commits[gen - 1], &right_commits[gen - 1]]);
|
2020-12-12 11:00:42 +03:00
|
|
|
left_commits.push(new_left);
|
|
|
|
right_commits.push(new_right);
|
|
|
|
}
|
2021-05-19 23:39:03 +03:00
|
|
|
let repo = tx.commit();
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should the root commit and the working copy commit, plus 2 for each
|
|
|
|
// generation
|
|
|
|
assert_eq!(index.num_commits(), 2 + 2 * (num_generations as u32));
|
|
|
|
|
|
|
|
let stats = index.stats();
|
|
|
|
assert_eq!(stats.num_commits, 2 + 2 * (num_generations as u32));
|
|
|
|
// The first generations are not merges
|
|
|
|
assert_eq!(stats.num_merges, 2 * (num_generations as u32 - 1));
|
|
|
|
assert_eq!(stats.max_generation_number, num_generations as u32);
|
|
|
|
|
|
|
|
// Check generation numbers
|
|
|
|
for gen in 0..num_generations {
|
|
|
|
assert_eq!(
|
2021-04-13 08:47:21 +03:00
|
|
|
generation_number(index.as_ref(), left_commits[gen].id()),
|
2020-12-12 11:00:42 +03:00
|
|
|
(gen as u32) + 1
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-04-13 08:47:21 +03:00
|
|
|
generation_number(index.as_ref(), right_commits[gen].id()),
|
2020-12-12 11:00:42 +03:00
|
|
|
(gen as u32) + 1
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The left and right commits of the same generation should not be ancestors of
|
|
|
|
// each other
|
|
|
|
for gen in 0..num_generations {
|
|
|
|
assert!(!index.is_ancestor(left_commits[gen].id(), right_commits[gen].id()));
|
|
|
|
assert!(!index.is_ancestor(right_commits[gen].id(), left_commits[gen].id()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Both sides of earlier generations should be ancestors. Check a few different
|
|
|
|
// earlier generations.
|
|
|
|
for gen in 1..num_generations {
|
|
|
|
for ancestor_side in &[&left_commits, &right_commits] {
|
|
|
|
for descendant_side in &[&left_commits, &right_commits] {
|
|
|
|
assert!(index.is_ancestor(ancestor_side[0].id(), descendant_side[gen].id()));
|
|
|
|
assert!(index.is_ancestor(ancestor_side[gen - 1].id(), descendant_side[gen].id()));
|
|
|
|
assert!(index.is_ancestor(ancestor_side[gen / 2].id(), descendant_side[gen].id()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
index
|
|
|
|
.walk_revs(&[left_commits[num_generations - 1].id().clone()], &[])
|
|
|
|
.count(),
|
|
|
|
2 * num_generations
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index
|
|
|
|
.walk_revs(&[right_commits[num_generations - 1].id().clone()], &[])
|
|
|
|
.count(),
|
|
|
|
2 * num_generations
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index
|
|
|
|
.walk_revs(
|
|
|
|
&[left_commits[num_generations - 1].id().clone()],
|
|
|
|
&[left_commits[num_generations - 2].id().clone()]
|
|
|
|
)
|
|
|
|
.count(),
|
|
|
|
2
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index
|
|
|
|
.walk_revs(
|
|
|
|
&[right_commits[num_generations - 1].id().clone()],
|
|
|
|
&[right_commits[num_generations - 2].id().clone()]
|
|
|
|
)
|
|
|
|
.count(),
|
|
|
|
2
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2020-12-12 11:00:42 +03:00
|
|
|
fn test_index_commits_previous_operations(use_git: bool) {
|
|
|
|
// Test that commits visible only in previous operations are indexed.
|
|
|
|
let settings = testutils::user_settings();
|
2021-05-19 23:39:03 +03:00
|
|
|
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
2020-12-12 11:00:42 +03:00
|
|
|
|
|
|
|
// Remove commit B and C in one operation and make sure they're still
|
|
|
|
// visible in the index after that operation.
|
|
|
|
// o C
|
|
|
|
// o B
|
|
|
|
// o A
|
|
|
|
// | o working copy
|
|
|
|
// |/
|
|
|
|
// o root
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
2021-05-01 07:41:27 +03:00
|
|
|
let mut graph_builder = CommitGraphBuilder::new(&settings, tx.mut_repo());
|
|
|
|
let commit_a = graph_builder.initial_commit();
|
|
|
|
let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
|
|
|
|
let commit_c = graph_builder.commit_with_parents(&[&commit_b]);
|
2021-05-19 23:39:03 +03:00
|
|
|
let repo = tx.commit();
|
2020-12-12 11:00:42 +03:00
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
2021-09-25 19:25:42 +03:00
|
|
|
tx.mut_repo().remove_head(commit_c.id());
|
2021-05-19 23:39:03 +03:00
|
|
|
let repo = tx.commit();
|
2020-12-12 11:00:42 +03:00
|
|
|
|
|
|
|
// Delete index from disk
|
|
|
|
let index_operations_dir = repo
|
|
|
|
.working_copy_path()
|
|
|
|
.join(".jj")
|
|
|
|
.join("index")
|
|
|
|
.join("operations");
|
|
|
|
assert!(index_operations_dir.is_dir());
|
|
|
|
std::fs::remove_dir_all(&index_operations_dir).unwrap();
|
|
|
|
std::fs::create_dir(&index_operations_dir).unwrap();
|
|
|
|
|
2021-01-04 10:11:22 +03:00
|
|
|
let repo = ReadonlyRepo::load(&settings, repo.working_copy_path().clone()).unwrap();
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit, plus
|
|
|
|
// 3 more
|
|
|
|
assert_eq!(index.num_commits(), 2 + 3);
|
|
|
|
|
|
|
|
let stats = index.stats();
|
|
|
|
assert_eq!(stats.num_commits, 2 + 3);
|
|
|
|
assert_eq!(stats.num_merges, 0);
|
|
|
|
assert_eq!(stats.max_generation_number, 3);
|
|
|
|
|
2021-04-13 08:47:21 +03:00
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_a.id()), 1);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_b.id()), 2);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_c.id()), 3);
|
2020-12-12 11:00:42 +03:00
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2020-12-12 11:00:42 +03:00
|
|
|
fn test_index_commits_incremental(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
// Create A in one operation, then B and C in another. Check that the index is
|
|
|
|
// valid after.
|
|
|
|
// o C
|
|
|
|
// o B
|
|
|
|
// o A
|
|
|
|
// | o working copy
|
|
|
|
// |/
|
|
|
|
// o root
|
|
|
|
|
|
|
|
let root_commit = repo.store().root_commit();
|
2021-09-11 19:45:06 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let commit_a = child_commit(&settings, &repo, &root_commit).write_to_repo(tx.mut_repo());
|
|
|
|
repo = tx.commit();
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit, plus
|
|
|
|
// 1 more
|
|
|
|
assert_eq!(index.num_commits(), 2 + 1);
|
|
|
|
|
|
|
|
let mut tx = repo.start_transaction("test");
|
2021-03-17 08:27:12 +03:00
|
|
|
let commit_b = child_commit(&settings, &repo, &commit_a).write_to_repo(tx.mut_repo());
|
|
|
|
let commit_c = child_commit(&settings, &repo, &commit_b).write_to_repo(tx.mut_repo());
|
2020-12-12 11:00:42 +03:00
|
|
|
tx.commit();
|
|
|
|
|
2021-01-04 10:11:22 +03:00
|
|
|
let repo = ReadonlyRepo::load(&settings, repo.working_copy_path().clone()).unwrap();
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit, plus
|
|
|
|
// 3 more
|
|
|
|
assert_eq!(index.num_commits(), 2 + 3);
|
|
|
|
|
|
|
|
let stats = index.stats();
|
|
|
|
assert_eq!(stats.num_commits, 2 + 3);
|
|
|
|
assert_eq!(stats.num_merges, 0);
|
|
|
|
assert_eq!(stats.max_generation_number, 3);
|
2021-02-16 22:50:28 +03:00
|
|
|
assert_eq!(stats.levels.len(), 1);
|
|
|
|
assert_eq!(stats.levels[0].num_commits, 5);
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2021-04-13 08:47:21 +03:00
|
|
|
assert_eq!(generation_number(index.as_ref(), root_commit.id()), 0);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_a.id()), 1);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_b.id()), 2);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_c.id()), 3);
|
2020-12-12 11:00:42 +03:00
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2020-12-12 11:00:42 +03:00
|
|
|
fn test_index_commits_incremental_empty_transaction(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
// Create A in one operation, then just an empty transaction. Check that the
|
|
|
|
// index is valid after.
|
|
|
|
// o A
|
|
|
|
// | o working copy
|
|
|
|
// |/
|
|
|
|
// o root
|
|
|
|
|
|
|
|
let root_commit = repo.store().root_commit();
|
2021-09-11 19:45:06 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let commit_a = child_commit(&settings, &repo, &root_commit).write_to_repo(tx.mut_repo());
|
|
|
|
repo = tx.commit();
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit, plus
|
|
|
|
// 1 more
|
|
|
|
assert_eq!(index.num_commits(), 2 + 1);
|
|
|
|
|
|
|
|
repo.start_transaction("test").commit();
|
|
|
|
|
2021-01-04 10:11:22 +03:00
|
|
|
let repo = ReadonlyRepo::load(&settings, repo.working_copy_path().clone()).unwrap();
|
2020-12-18 09:59:39 +03:00
|
|
|
let index = repo.index();
|
2020-12-12 11:00:42 +03:00
|
|
|
// There should be the root commit and the working copy commit, plus
|
|
|
|
// 1 more
|
|
|
|
assert_eq!(index.num_commits(), 2 + 1);
|
|
|
|
|
|
|
|
let stats = index.stats();
|
|
|
|
assert_eq!(stats.num_commits, 2 + 1);
|
|
|
|
assert_eq!(stats.num_merges, 0);
|
|
|
|
assert_eq!(stats.max_generation_number, 1);
|
2021-09-12 07:59:42 +03:00
|
|
|
assert_eq!(stats.levels.len(), 1);
|
|
|
|
assert_eq!(stats.levels[0].num_commits, 3);
|
2020-12-12 11:00:42 +03:00
|
|
|
|
2021-04-13 08:47:21 +03:00
|
|
|
assert_eq!(generation_number(index.as_ref(), root_commit.id()), 0);
|
|
|
|
assert_eq!(generation_number(index.as_ref(), commit_a.id()), 1);
|
2020-12-12 11:00:42 +03:00
|
|
|
}
|
2021-02-15 05:53:52 +03:00
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-02-15 05:53:52 +03:00
|
|
|
fn test_index_commits_incremental_already_indexed(use_git: bool) {
|
|
|
|
// Tests that trying to add a commit that's already been added is a no-op.
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
|
|
|
|
// Create A in one operation, then try to add it again an new transaction.
|
|
|
|
// o A
|
|
|
|
// | o working copy
|
|
|
|
// |/
|
|
|
|
// o root
|
|
|
|
|
|
|
|
let root_commit = repo.store().root_commit();
|
2021-09-11 19:45:06 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
let commit_a = child_commit(&settings, &repo, &root_commit).write_to_repo(tx.mut_repo());
|
|
|
|
repo = tx.commit();
|
2021-02-15 05:53:52 +03:00
|
|
|
|
|
|
|
assert!(repo.index().has_id(commit_a.id()));
|
|
|
|
assert_eq!(repo.index().num_commits(), 2 + 1);
|
|
|
|
let mut tx = repo.start_transaction("test");
|
2021-03-17 02:21:31 +03:00
|
|
|
let mut_repo = tx.mut_repo();
|
|
|
|
mut_repo.add_head(&commit_a);
|
|
|
|
assert_eq!(mut_repo.index().num_commits(), 2 + 1);
|
2021-02-15 05:53:52 +03:00
|
|
|
tx.discard();
|
|
|
|
}
|
2021-02-16 22:50:28 +03:00
|
|
|
|
2021-04-11 19:23:16 +03:00
|
|
|
#[must_use]
|
|
|
|
fn create_n_commits(
|
|
|
|
settings: &UserSettings,
|
|
|
|
repo: &Arc<ReadonlyRepo>,
|
|
|
|
num_commits: i32,
|
|
|
|
) -> Arc<ReadonlyRepo> {
|
2021-02-16 22:50:28 +03:00
|
|
|
let mut tx = repo.start_transaction("test");
|
|
|
|
for _ in 0..num_commits {
|
2021-03-17 08:27:12 +03:00
|
|
|
create_random_commit(settings, repo).write_to_repo(tx.mut_repo());
|
2021-02-16 22:50:28 +03:00
|
|
|
}
|
2021-05-19 23:39:03 +03:00
|
|
|
tx.commit()
|
2021-02-16 22:50:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn commits_by_level(repo: &ReadonlyRepo) -> Vec<u32> {
|
|
|
|
repo.index()
|
|
|
|
.stats()
|
|
|
|
.levels
|
|
|
|
.iter()
|
|
|
|
.map(|level| level.num_commits)
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:52:38 +03:00
|
|
|
#[test_case(false ; "local backend")]
|
|
|
|
#[test_case(true ; "git backend")]
|
2021-02-16 22:50:28 +03:00
|
|
|
fn test_index_commits_incremental_squashed(use_git: bool) {
|
|
|
|
let settings = testutils::user_settings();
|
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 1);
|
2021-09-12 07:59:42 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![3]);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 1);
|
2021-09-12 07:59:42 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![3, 1]);
|
2021-02-16 22:50:28 +03:00
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 2);
|
2021-02-16 22:50:28 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![4]);
|
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 100);
|
2021-02-16 22:50:28 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![102]);
|
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 2);
|
|
|
|
repo = create_n_commits(&settings, &repo, 4);
|
|
|
|
repo = create_n_commits(&settings, &repo, 8);
|
|
|
|
repo = create_n_commits(&settings, &repo, 16);
|
|
|
|
repo = create_n_commits(&settings, &repo, 32);
|
2021-02-16 22:50:28 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![64]);
|
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 32);
|
|
|
|
repo = create_n_commits(&settings, &repo, 16);
|
|
|
|
repo = create_n_commits(&settings, &repo, 8);
|
|
|
|
repo = create_n_commits(&settings, &repo, 4);
|
|
|
|
repo = create_n_commits(&settings, &repo, 2);
|
2021-09-12 07:59:42 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![58, 6]);
|
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
|
|
|
repo = create_n_commits(&settings, &repo, 29);
|
|
|
|
repo = create_n_commits(&settings, &repo, 15);
|
|
|
|
repo = create_n_commits(&settings, &repo, 7);
|
|
|
|
repo = create_n_commits(&settings, &repo, 3);
|
|
|
|
repo = create_n_commits(&settings, &repo, 1);
|
|
|
|
assert_eq!(commits_by_level(&repo), vec![31, 15, 7, 3, 1]);
|
2021-02-16 22:50:28 +03:00
|
|
|
|
|
|
|
let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git);
|
2021-04-11 19:23:16 +03:00
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
|
|
|
repo = create_n_commits(&settings, &repo, 10);
|
2021-02-16 22:50:28 +03:00
|
|
|
assert_eq!(commits_by_level(&repo), vec![72, 20]);
|
|
|
|
}
|