From 4d51cd96a1c59b1d179b67f8f8e42c0db765036c Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Sun, 16 May 2021 10:33:52 -0700 Subject: [PATCH] repo: scan for .jj/ directory up the tree It's kind of silly that I haven't fixed this earlier. I just don't need it often myself. --- lib/src/repo.rs | 23 +++++++++++++++++------ lib/tests/test_load_repo.rs | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/lib/src/repo.rs b/lib/src/repo.rs index 850870330..559f3ba1d 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -17,7 +17,7 @@ use std::fmt::{Debug, Formatter}; use std::fs; use std::fs::File; use std::io::Write; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, MutexGuard}; use thiserror::Error; @@ -384,16 +384,27 @@ pub struct RepoLoader { index_store: Arc, } +fn find_repo_dir(mut wc_dir: &Path) -> Option { + loop { + let repo_path = wc_dir.join(".jj"); + if repo_path.is_dir() { + return Some(repo_path); + } + if let Some(wc_dir_parent) = wc_dir.parent() { + wc_dir = wc_dir_parent; + } else { + return None; + } + } +} + impl RepoLoader { pub fn init( user_settings: &UserSettings, wc_path: PathBuf, ) -> Result { - let repo_path = wc_path.join(".jj"); - // TODO: Check if ancestor directory has a .jj/ - if !repo_path.is_dir() { - return Err(RepoLoadError::NoRepoHere(wc_path)); - } + let repo_path = find_repo_dir(&wc_path).ok_or(RepoLoadError::NoRepoHere(wc_path))?; + let wc_path = repo_path.parent().unwrap().to_owned(); let store = StoreWrapper::load_store(&repo_path); let repo_settings = user_settings.with_repo(&repo_path).unwrap(); let op_store: Arc = Arc::new(SimpleOpStore::load(repo_path.join("op_store"))); diff --git a/lib/tests/test_load_repo.rs b/lib/tests/test_load_repo.rs index acdce5674..832b5837f 100644 --- a/lib/tests/test_load_repo.rs +++ b/lib/tests/test_load_repo.rs @@ -26,6 +26,21 @@ fn test_load_bad_path() { assert_eq!(result.err(), Some(RepoLoadError::NoRepoHere(wc_path))); } +#[test_case(false ; "local store")] +#[test_case(true ; "git store")] +fn test_load_from_subdir(use_git: bool) { + let settings = testutils::user_settings(); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); + + let subdir = repo.working_copy_path().join("dir").join("subdir"); + std::fs::create_dir_all(subdir.clone()).unwrap(); + let same_repo = ReadonlyRepo::load(&settings, subdir); + assert!(same_repo.is_ok()); + let same_repo = same_repo.unwrap(); + assert_eq!(same_repo.repo_path(), repo.repo_path()); + assert_eq!(same_repo.working_copy_path(), repo.working_copy_path()); +} + #[test_case(false ; "local store")] #[test_case(true ; "git store")] fn test_load_at_operation(use_git: bool) {