Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

Commit

Permalink
feat(cli): Find the nearest ancestor sphere
Browse files Browse the repository at this point in the history
The CLI now looks for the nearest ancestor sphere directory when
determining what "root" should be used for the purposes of the current
action.
  • Loading branch information
cdata committed Oct 31, 2022
1 parent 1ca3fcd commit 6b3c337
Showing 1 changed file with 69 additions and 20 deletions.
89 changes: 69 additions & 20 deletions rust/noosphere-cli/src/native/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use path_absolutize::Absolutize;
use pathdiff::diff_paths;
use std::{
collections::{BTreeMap, BTreeSet},
path::PathBuf,
path::{Path, PathBuf},
str::FromStr,
};
use subtext::util::to_slug;
Expand Down Expand Up @@ -549,6 +549,11 @@ The available keys are:
Err(anyhow!("No keys found; have you created any yet?"))
}

/// Returns true if the given path has a .sphere folder in it
fn has_sphere_directory(path: &Path) -> bool {
path.is_absolute() && path.join(SPHERE_DIRECTORY).is_dir()
}

/// Asserts that all related directories for the suggested working file
/// tree root are present
pub fn expect_local_directories(&self) -> Result<()> {
Expand All @@ -559,7 +564,7 @@ The available keys are:
));
}

if !self.sphere.is_dir() {
if !Workspace::has_sphere_directory(&self.root) {
return Err(anyhow!(
"The {:?} folder within {:?} is missing or corrupted",
SPHERE_DIRECTORY,
Expand Down Expand Up @@ -587,20 +592,12 @@ The available keys are:
pub async fn initialize_local_directories(&self) -> Result<()> {
let mut root = self.root.clone();

// Crawl up the directories to the root of the filesystem and make sure
// we aren't initializing a sphere within a sphere
while let Some(parent) = root.clone().parent() {
root = parent.to_path_buf();
let working_paths = Workspace::new(&root, None)?;
if let Ok(_) = working_paths.expect_local_directories() {
return Err(anyhow!(
r#"Tried to initialize sphere directories in {:?}
...but a sphere is already initialized in {:?}
Unexpected things will happen if you try to nest spheres this way!"#,
self.root,
parent
))?;
}
if let Ok(_) = self.expect_local_directories() {
return Err(anyhow!(
r#"Cannot initialize the sphere; a sphere is already initialized in {:?}
Unexpected (bad) things will happen if you try to nest spheres this way!"#,
self.root,
))?;
}

fs::create_dir_all(&self.sphere).await?;
Expand All @@ -617,12 +614,38 @@ Unexpected things will happen if you try to nest spheres this way!"#,
Ok(())
}

pub fn new(root: &PathBuf, noosphere_global_root: Option<&PathBuf>) -> Result<Self> {
if !root.is_absolute() {
return Err(anyhow!("Ambiguous path to sphere root: {:?}", root));
pub fn new(
current_working_directory: &PathBuf,
noosphere_global_root: Option<&PathBuf>,
) -> Result<Self> {
if !current_working_directory.is_absolute() {
return Err(anyhow!(
"Ambiguous working directory: {:?} (must be an absolute path)",
current_working_directory
));
}

let mut root = current_working_directory.clone();

// Crawl up the directories to the root of the filesystem and use an
// existing `.sphere` directory to determine the root. If none are
// found, instead use the current working directory.
loop {
match root.parent() {
Some(parent) => {
root = parent.to_path_buf();

if Workspace::has_sphere_directory(&root) {
break;
}
}
None => {
root = current_working_directory.clone();
break;
}
}
}

let root = root.absolutize()?.to_path_buf();
let sphere = root.join(SPHERE_DIRECTORY);
let blocks = sphere.join(BLOCKS_DIRECTORY);
let authorization = sphere.join(AUTHORIZATION_FILE);
Expand Down Expand Up @@ -668,3 +691,29 @@ Unexpected things will happen if you try to nest spheres this way!"#,
)
}
}

#[cfg(test)]
mod tests {
use crate::native::commands::{key, sphere};
use tokio::fs;

use super::Workspace;

#[tokio::test]
async fn it_chooses_an_ancestor_sphere_directory_as_root_if_one_exists() {
let workspace = Workspace::temporary().unwrap();

key::key_create("FOO", &workspace).await.unwrap();

sphere::sphere_create("FOO", &workspace).await.unwrap();

let subdirectory = workspace.root_path().join("foo/bar");

fs::create_dir_all(&subdirectory).await.unwrap();

let new_workspace =
Workspace::new(&subdirectory, Some(workspace.noosphere_path())).unwrap();

assert_eq!(workspace.root_path(), new_workspace.root_path());
}
}

0 comments on commit 6b3c337

Please sign in to comment.