diff --git a/rust/noosphere-cli/src/native/commands/sphere/mod.rs b/rust/noosphere-cli/src/native/commands/sphere/mod.rs index 423e11515..1280a407f 100644 --- a/rust/noosphere-cli/src/native/commands/sphere/mod.rs +++ b/rust/noosphere-cli/src/native/commands/sphere/mod.rs @@ -42,7 +42,7 @@ use url::Url; pub async fn sphere_create(owner_key: &str, workspace: &mut Workspace) -> Result<(Did, Mnemonic)> { workspace.ensure_sphere_uninitialized()?; - let sphere_paths = SpherePaths::initialize(workspace.working_directory()).await?; + let sphere_paths = SpherePaths::new(workspace.working_directory()); let sphere_context_artifacts = SphereContextBuilder::default() .create_sphere() @@ -74,7 +74,7 @@ You will be asked to enter them if you ever need to transfer ownership of the sp mnemonic ); - workspace.initialize(sphere_paths)?; + workspace.initialize(sphere_paths).await?; Ok((sphere_identity.clone(), mnemonic.into())) } @@ -124,7 +124,7 @@ Type or paste the code here and press enter:"# let cid = Cid::from_str(cid_string.trim()) .map_err(|_| anyhow!("Could not parse the authorization identity as a CID"))?; - let sphere_paths = SpherePaths::initialize(workspace.working_directory()).await?; + let sphere_paths = SpherePaths::new(workspace.working_directory()); { let mut sphere_context = Arc::new(Mutex::new( @@ -150,7 +150,7 @@ Type or paste the code here and press enter:"# sphere_context.sync().await?; } - workspace.initialize(sphere_paths)?; + workspace.initialize(sphere_paths).await?; workspace.render(render_depth, true).await?; // TODO(#103): Recovery path if the auth needs to change for some reason diff --git a/rust/noosphere-cli/src/native/paths.rs b/rust/noosphere-cli/src/native/paths.rs index 234306fa7..5fa470f27 100644 --- a/rust/noosphere-cli/src/native/paths.rs +++ b/rust/noosphere-cli/src/native/paths.rs @@ -73,8 +73,9 @@ impl SpherePaths { path.is_absolute() && path.join(SPHERE_DIRECTORY).is_dir() } - // Root is the path that contains the .sphere folder - fn new(root: &Path) -> Self { + /// Construct a new [SpherePaths] given a `root` path, a directory + /// that will contain a `.sphere` directory. + pub fn new(root: &Path) -> Self { let sphere = root.join(SPHERE_DIRECTORY); Self { @@ -90,25 +91,23 @@ impl SpherePaths { } } - /// Initialize [SpherePaths] for a given root path. This has the effect of + /// Initialize [SpherePaths] given its root path. This has the effect of /// creating the "private" directory hierarchy (starting from /// [SPHERE_DIRECTORY] inside the root). - pub async fn initialize(root: &Path) -> Result { - if !root.is_absolute() { + pub async fn initialize(&self) -> Result<()> { + if !self.root.is_absolute() { return Err(anyhow!( "Must use an absolute path to initialize sphere directories; got {:?}", - root + self.root )); } - let paths = Self::new(root); + std::fs::create_dir_all(&self.storage)?; + std::fs::create_dir_all(&self.content)?; + std::fs::create_dir_all(&self.peers)?; + std::fs::create_dir_all(&self.slugs)?; - std::fs::create_dir_all(&paths.storage)?; - std::fs::create_dir_all(&paths.content)?; - std::fs::create_dir_all(&paths.peers)?; - std::fs::create_dir_all(&paths.slugs)?; - - Ok(paths) + Ok(()) } /// Attempt to discover an existing workspace root by traversing ancestor diff --git a/rust/noosphere-cli/src/native/workspace.rs b/rust/noosphere-cli/src/native/workspace.rs index 52626a229..64fc0f2da 100644 --- a/rust/noosphere-cli/src/native/workspace.rs +++ b/rust/noosphere-cli/src/native/workspace.rs @@ -138,7 +138,7 @@ impl Workspace { } } - /// Asserts that a local sphere has been intiialized + /// Asserts that a local sphere has been initialized pub fn ensure_sphere_initialized(&self) -> Result<()> { let sphere_paths = self.require_sphere_paths()?; if !sphere_paths.sphere().exists() { @@ -150,7 +150,7 @@ impl Workspace { Ok(()) } - /// Asserts that a local sphere has _not_ been intiialized + /// Asserts that a local sphere has _not_ been initialized pub fn ensure_sphere_uninitialized(&self) -> Result<()> { if let Some(sphere_paths) = self.sphere_paths() { match sphere_paths.sphere().exists() { @@ -291,11 +291,11 @@ impl Workspace { } /// Initialize a [Workspace] in place with a given set of [SpherePaths]. - pub fn initialize(&mut self, sphere_paths: SpherePaths) -> Result<()> { + pub async fn initialize(&mut self, sphere_paths: SpherePaths) -> Result<()> { self.ensure_sphere_uninitialized()?; + sphere_paths.initialize().await?; self.sphere_paths = Some(Arc::new(sphere_paths)); - Ok(()) } diff --git a/rust/noosphere/tests/cli.rs b/rust/noosphere/tests/cli.rs index 4acba1574..992d3846d 100644 --- a/rust/noosphere/tests/cli.rs +++ b/rust/noosphere/tests/cli.rs @@ -37,6 +37,28 @@ async fn orb_sphere_create_initializes_a_sphere() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread")] +async fn orb_sphere_create_failure_cleans_directory() -> Result<()> { + initialize_tracing(None); + let client = CliSimulator::new()?; + + client.orb(&["key", "create", "foobar"]).await?; + if client + .orb(&["sphere", "create", "--owner-key", "not-foo"]) + .await + .is_ok() + { + panic!("Unexpected success."); + } + + assert!(client + .orb(&["sphere", "create", "--owner-key", "foobar"]) + .await + .is_ok()); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread")] async fn orb_can_enable_multiple_replicas_to_synchronize() -> Result<()> { initialize_tracing(None);