From 90a66ec2621fc16dd04766845e49b2b9ba1b9da1 Mon Sep 17 00:00:00 2001 From: Daniel Ploch Date: Fri, 16 Dec 2022 11:19:04 -0500 Subject: [PATCH] op_heads_store: move op_heads into a subdir, to make room for the 'type' marker --- lib/src/simple_op_heads_store.rs | 91 +++++++++++++++++++++++++++++--- lib/tests/test_operations.rs | 6 +-- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/lib/src/simple_op_heads_store.rs b/lib/src/simple_op_heads_store.rs index 97ed00810..5ec9babcc 100644 --- a/lib/src/simple_op_heads_store.rs +++ b/lib/src/simple_op_heads_store.rs @@ -14,6 +14,7 @@ use std::collections::HashSet; use std::fmt::{Debug, Formatter}; +use std::fs; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -76,9 +77,9 @@ impl InnerSimpleOpHeadsStore { let init_operation_id = op_store.write_operation(&init_operation).unwrap(); let init_operation = Operation::new(op_store.clone(), init_operation_id, init_operation); - let op_heads_store = InnerSimpleOpHeadsStore { - dir: dir.to_path_buf(), - }; + let op_heads_dir = dir.join("simple_op_heads"); + fs::create_dir(&op_heads_dir).unwrap(); + let op_heads_store = InnerSimpleOpHeadsStore { dir: op_heads_dir }; op_heads_store.add_op_head(init_operation.id()); (op_heads_store, init_operation) } @@ -143,10 +144,27 @@ impl SimpleOpHeadsStore { } pub fn load(dir: &Path) -> Self { - SimpleOpHeadsStore { - store: Arc::new(InnerSimpleOpHeadsStore { + let op_heads_dir = dir.join("simple_op_heads"); + + // TODO: Delete this migration code at 0.8+ or so + if !op_heads_dir.exists() { + let old_store = InnerSimpleOpHeadsStore { dir: dir.to_path_buf(), - }), + }; + fs::create_dir(&op_heads_dir).unwrap(); + let new_store = InnerSimpleOpHeadsStore { dir: op_heads_dir }; + + for id in old_store.get_op_heads() { + old_store.remove_op_head(&id); + new_store.add_op_head(&id); + } + return SimpleOpHeadsStore { + store: Arc::new(new_store), + }; + } + + SimpleOpHeadsStore { + store: Arc::new(InnerSimpleOpHeadsStore { dir: op_heads_dir }), } } } @@ -236,3 +254,64 @@ impl OpHeadsStore for SimpleOpHeadsStore { }) } } + +#[cfg(test)] +mod tests { + use std::collections::HashSet; + use std::fs; + use std::path::Path; + + use itertools::Itertools; + + use super::InnerSimpleOpHeadsStore; + use crate::op_heads_store::OpHeadsStore; + use crate::op_store::OperationId; + use crate::simple_op_heads_store::SimpleOpHeadsStore; + + fn read_dir(dir: &Path) -> Vec { + fs::read_dir(dir) + .unwrap() + .map(|entry| entry.unwrap().file_name().to_str().unwrap().to_string()) + .sorted() + .collect() + } + + #[test] + fn test_simple_op_heads_store_migration() { + let test_dir = testutils::new_temp_dir(); + let store_path = test_dir.path().join("op_heads"); + fs::create_dir(&store_path).unwrap(); + + let op1 = OperationId::from_hex("012345"); + let op2 = OperationId::from_hex("abcdef"); + let mut ops = HashSet::new(); + ops.insert(op1.clone()); + ops.insert(op2.clone()); + + let old_store = InnerSimpleOpHeadsStore { + dir: store_path.clone(), + }; + old_store.add_op_head(&op1); + old_store.add_op_head(&op2); + + assert_eq!(vec!["012345", "abcdef"], read_dir(&store_path)); + drop(old_store); + + let new_store = SimpleOpHeadsStore::load(&store_path); + assert_eq!(&ops, &new_store.get_op_heads().into_iter().collect()); + assert_eq!(vec!["simple_op_heads"], read_dir(&store_path)); + assert_eq!( + vec!["012345", "abcdef"], + read_dir(&store_path.join("simple_op_heads")) + ); + + // Migration is idempotent + let new_store = SimpleOpHeadsStore::load(&store_path); + assert_eq!(&ops, &new_store.get_op_heads().into_iter().collect()); + assert_eq!(vec!["simple_op_heads"], read_dir(&store_path)); + assert_eq!( + vec!["012345", "abcdef"], + read_dir(&store_path.join("simple_op_heads")) + ); + } +} diff --git a/lib/tests/test_operations.rs b/lib/tests/test_operations.rs index c115282c5..6d5a42803 100644 --- a/lib/tests/test_operations.rs +++ b/lib/tests/test_operations.rs @@ -35,7 +35,7 @@ fn test_unpublished_operation(use_git: bool) { let test_repo = TestRepo::init(use_git); let repo = &test_repo.repo; - let op_heads_dir = repo.repo_path().join("op_heads"); + let op_heads_dir = repo.repo_path().join("op_heads").join("simple_op_heads"); let op_id0 = repo.op_id().clone(); assert_eq!(list_dir(&op_heads_dir), vec![repo.op_id().hex()]); @@ -58,7 +58,7 @@ fn test_consecutive_operations(use_git: bool) { let test_repo = TestRepo::init(use_git); let repo = &test_repo.repo; - let op_heads_dir = repo.repo_path().join("op_heads"); + let op_heads_dir = repo.repo_path().join("op_heads").join("simple_op_heads"); let op_id0 = repo.op_id().clone(); assert_eq!(list_dir(&op_heads_dir), vec![repo.op_id().hex()]); @@ -91,7 +91,7 @@ fn test_concurrent_operations(use_git: bool) { let test_repo = TestRepo::init(use_git); let repo = &test_repo.repo; - let op_heads_dir = repo.repo_path().join("op_heads"); + let op_heads_dir = repo.repo_path().join("op_heads").join("simple_op_heads"); let op_id0 = repo.op_id().clone(); assert_eq!(list_dir(&op_heads_dir), vec![repo.op_id().hex()]);