ok/jj
1
0
Fork 0
forked from mirrors/jj

index: on reinit(), don't remove "operations" directory itself

This should be slightly safer as the store may be accessed concurrently from
another process.
This commit is contained in:
Yuya Nishihara 2024-02-09 21:24:40 +09:00
parent 81837897dc
commit 4b541e6c93
2 changed files with 22 additions and 6 deletions

View file

@ -30,7 +30,7 @@ use super::readonly::{DefaultReadonlyIndex, ReadonlyIndexLoadError, ReadonlyInde
use crate::backend::{BackendError, BackendInitError, CommitId};
use crate::commit::CommitByCommitterTimestamp;
use crate::dag_walk;
use crate::file_util::{persist_content_addressed_temp_file, IoResultExt as _, PathError};
use crate::file_util::{self, persist_content_addressed_temp_file, IoResultExt as _, PathError};
use crate::index::{
Index, IndexReadError, IndexStore, IndexWriteError, MutableIndex, ReadonlyIndex,
};
@ -92,8 +92,7 @@ impl DefaultIndexStore {
let store = DefaultIndexStore {
dir: dir.to_owned(),
};
let op_dir = store.operations_dir();
std::fs::create_dir(&op_dir).context(&op_dir)?;
store.ensure_base_dirs()?;
Ok(store)
}
@ -104,10 +103,10 @@ impl DefaultIndexStore {
}
pub fn reinit(&self) -> Result<(), DefaultIndexStoreInitError> {
// Create base directories in case the store was initialized by old jj.
self.ensure_base_dirs()?;
// Remove all operation links to trigger rebuilding.
let op_dir = self.operations_dir();
std::fs::remove_dir_all(&op_dir).context(&op_dir)?;
std::fs::create_dir(&op_dir).context(&op_dir)?;
file_util::remove_dir_contents(&self.operations_dir())?;
// Remove index segments to save disk space. If raced, new segment file
// will be created by the other process.
for entry in self.dir.read_dir().context(&self.dir)? {
@ -122,6 +121,11 @@ impl DefaultIndexStore {
Ok(())
}
fn ensure_base_dirs(&self) -> Result<(), PathError> {
let op_dir = self.operations_dir();
file_util::create_or_reuse_dir(&op_dir).context(&op_dir)
}
fn operations_dir(&self) -> PathBuf {
self.dir.join("operations")
}

View file

@ -55,6 +55,18 @@ pub fn create_or_reuse_dir(dirname: &Path) -> io::Result<()> {
}
}
/// Removes all files in the directory, but not the directory itself.
///
/// The directory must exist, and there should be no sub directories.
pub fn remove_dir_contents(dirname: &Path) -> Result<(), PathError> {
for entry in dirname.read_dir().context(dirname)? {
let entry = entry.context(dirname)?;
let path = entry.path();
fs::remove_file(&path).context(&path)?;
}
Ok(())
}
/// Turns the given `to` path into relative path starting from the `from` path.
///
/// Both `from` and `to` paths are supposed to be absolute and normalized in the