From 57164bcfd3170f523eeec0a1aef11c99dd0cc0f1 Mon Sep 17 00:00:00 2001 From: Guillaume Bouvignies Date: Thu, 4 Jul 2024 11:22:15 +0100 Subject: [PATCH 1/4] Add `buffrs new` command to init a package in a non-existing folder --- src/command.rs | 46 ++++++++++++++++++++++++++++++++++++++++++---- src/main.rs | 40 +++++++++++++++++++++++++++++++++------- src/manifest.rs | 10 ++++++---- 3 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/command.rs b/src/command.rs index 3c6398eb..888331d6 100644 --- a/src/command.rs +++ b/src/command.rs @@ -25,7 +25,11 @@ use crate::{ use async_recursion::async_recursion; use miette::{bail, ensure, miette, Context as _, IntoDiagnostic}; use semver::{Version, VersionReq}; -use std::{env, path::Path, str::FromStr}; +use std::{ + env, + path::{Path, PathBuf}, + str::FromStr, +}; use tokio::{ fs, io::{self, AsyncBufReadExt, BufReader}, @@ -68,7 +72,7 @@ pub async fn init(kind: Option, name: Option) -> miett let manifest = Manifest::new(package, vec![]); - manifest.write().await?; + manifest.write(None).await?; PackageStore::open(std::env::current_dir().unwrap_or_else(|_| ".".into())) .await @@ -77,6 +81,40 @@ pub async fn init(kind: Option, name: Option) -> miett Ok(()) } +/// Initializes a project with the given name in the current directory +pub async fn new(kind: Option, name: PackageName) -> miette::Result<()> { + let mut package_dir: PathBuf = ".".into(); + package_dir.push::(name.clone().into()); + // create_dir fails if the folder already exists + fs::create_dir(&package_dir) + .await + .into_diagnostic() + .wrap_err(miette!( + "failed to create {} directory", + package_dir.display() + ))?; + + let package = kind + .map(|kind| -> miette::Result { + Ok(PackageManifest { + kind, + name, + version: INITIAL_VERSION, + description: None, + }) + }) + .transpose()?; + + let manifest = Manifest::new(package, vec![]); + manifest.write(Some(package_dir.clone())).await?; + + PackageStore::open(&package_dir) + .await + .wrap_err(miette!("failed to create buffrs `proto` directories"))?; + + Ok(()) +} + struct DependencyLocator { repository: String, package: PackageName, @@ -139,7 +177,7 @@ pub async fn add(registry: RegistryUri, dependency: &str) -> miette::Result<()> .push(Dependency::new(registry, repository, package, version)); manifest - .write() + .write(None) .await .wrap_err(miette!("failed to write `{MANIFEST_FILE}`")) } @@ -159,7 +197,7 @@ pub async fn remove(package: PackageName) -> miette::Result<()> { store.uninstall(&dependency.package).await.ok(); - manifest.write().await + manifest.write(None).await } /// Packages the api and writes it to the filesystem diff --git a/src/main.rs b/src/main.rs index 2c792d5f..53644651 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,6 +46,21 @@ enum Command { package: Option, }, + /// Creates a new buffrs package in the current directory + New { + /// Sets up the package as lib + #[clap(long, conflicts_with = "api")] + #[arg(group = "pkg")] + lib: bool, + /// Sets up the package as api + #[clap(long, conflicts_with = "lib")] + #[arg(group = "pkg")] + api: bool, + /// The package name + #[clap(requires = "pkg")] + package: PackageName, + }, + /// Check rule violations for this package. Lint, @@ -177,13 +192,7 @@ async fn main() -> miette::Result<()> { match cli.command { Command::Init { lib, api, package } => { - let kind = if lib { - Some(PackageType::Lib) - } else if api { - Some(PackageType::Api) - } else { - None - }; + let kind = infer_package_type(lib, api); command::init(kind, package.to_owned()) .await @@ -192,6 +201,13 @@ async fn main() -> miette::Result<()> { package.map(|p| format!("`{p}`")).unwrap_or_default() )) } + Command::New { lib, api, package } => { + let kind = infer_package_type(lib, api); + + command::new(kind, package.to_owned()) + .await + .wrap_err(miette!("failed to initialize {}", format!("`{package}`"))) + } Command::Login { registry } => command::login(registry.to_owned()) .await .wrap_err(miette!("failed to login to `{registry}`")), @@ -255,3 +271,13 @@ async fn main() -> miette::Result<()> { }, } } + +fn infer_package_type(lib: bool, api: bool) -> Option { + if lib { + Some(PackageType::Lib) + } else if api { + Some(PackageType::Api) + } else { + None + } +} diff --git a/src/manifest.rs b/src/manifest.rs index 49128dda..95bf7228 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, fmt::{self, Display}, - path::Path, + path::{Path, PathBuf}, str::FromStr, }; use tokio::fs; @@ -313,16 +313,18 @@ impl Manifest { Ok(Some(raw.into())) } - /// Persists the manifest into the current directory - pub async fn write(&self) -> miette::Result<()> { + /// Persists the manifest into the provided directory, which must exist (or current directory if None) + pub async fn write(&self, dir_path: Option) -> miette::Result<()> { // hint: create a canary manifest from the current one let raw = RawManifest::from(Manifest::new( self.package.clone(), self.dependencies.clone(), )); + let mut manifest_file_path = dir_path.unwrap_or_else(|| ".".into()); + manifest_file_path.push(MANIFEST_FILE); fs::write( - MANIFEST_FILE, + manifest_file_path, toml::to_string(&raw) .into_diagnostic() .wrap_err(SerializationError(ManagedFile::Manifest))? From cbd4e525fe0f92e1694d9562cf3c74c8e8077f8a Mon Sep 17 00:00:00 2001 From: Guillaume Bouvignies Date: Thu, 4 Jul 2024 16:37:44 +0200 Subject: [PATCH 2/4] Add write_at method in addition to write --- src/command.rs | 11 +++++------ src/manifest.rs | 13 +++++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/command.rs b/src/command.rs index 888331d6..69e1db0a 100644 --- a/src/command.rs +++ b/src/command.rs @@ -72,7 +72,7 @@ pub async fn init(kind: Option, name: Option) -> miett let manifest = Manifest::new(package, vec![]); - manifest.write(None).await?; + manifest.write().await?; PackageStore::open(std::env::current_dir().unwrap_or_else(|_| ".".into())) .await @@ -83,8 +83,7 @@ pub async fn init(kind: Option, name: Option) -> miett /// Initializes a project with the given name in the current directory pub async fn new(kind: Option, name: PackageName) -> miette::Result<()> { - let mut package_dir: PathBuf = ".".into(); - package_dir.push::(name.clone().into()); + let package_dir = PathBuf::from(name.to_string()); // create_dir fails if the folder already exists fs::create_dir(&package_dir) .await @@ -106,7 +105,7 @@ pub async fn new(kind: Option, name: PackageName) -> miette::Result .transpose()?; let manifest = Manifest::new(package, vec![]); - manifest.write(Some(package_dir.clone())).await?; + manifest.write_at(&package_dir).await?; PackageStore::open(&package_dir) .await @@ -177,7 +176,7 @@ pub async fn add(registry: RegistryUri, dependency: &str) -> miette::Result<()> .push(Dependency::new(registry, repository, package, version)); manifest - .write(None) + .write() .await .wrap_err(miette!("failed to write `{MANIFEST_FILE}`")) } @@ -197,7 +196,7 @@ pub async fn remove(package: PackageName) -> miette::Result<()> { store.uninstall(&dependency.package).await.ok(); - manifest.write(None).await + manifest.write().await } /// Packages the api and writes it to the filesystem diff --git a/src/manifest.rs b/src/manifest.rs index 95bf7228..485bda8e 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -313,16 +313,21 @@ impl Manifest { Ok(Some(raw.into())) } - /// Persists the manifest into the provided directory, which must exist (or current directory if None) - pub async fn write(&self, dir_path: Option) -> miette::Result<()> { + /// Persists the manifest into the current directory + pub async fn write(&self) -> miette::Result<()> { + let current_dir = PathBuf::from("."); + return self.write_at(¤t_dir).await; + } + + /// Persists the manifest into the provided directory, which must exist + pub async fn write_at(&self, dir_path: &PathBuf) -> miette::Result<()> { // hint: create a canary manifest from the current one let raw = RawManifest::from(Manifest::new( self.package.clone(), self.dependencies.clone(), )); - let mut manifest_file_path = dir_path.unwrap_or_else(|| ".".into()); - manifest_file_path.push(MANIFEST_FILE); + let manifest_file_path = dir_path.join(MANIFEST_FILE); fs::write( manifest_file_path, toml::to_string(&raw) From c85c117dcff7cd796984e519d7666e0f26aed469 Mon Sep 17 00:00:00 2001 From: Guillaume Bouvignies Date: Thu, 4 Jul 2024 16:37:58 +0200 Subject: [PATCH 3/4] Update README and book --- README.md | 1 + docs/src/SUMMARY.md | 1 + docs/src/commands/buffrs-new.md | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 docs/src/commands/buffrs-new.md diff --git a/README.md b/README.md index e1dc2cd8..d5066855 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Usage: buffrs Commands: init Initializes a buffrs setup + new Creates a new buffrs package in the current directory lint Check rule violations for this package add Adds dependencies to a manifest file remove Removes dependencies from a manifest file diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 0bfca219..f6668084 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -76,6 +76,7 @@ * [buffrs update]() * [Package Commands](commands/package-commands.md) * [buffrs init](commands/buffrs-init.md) + * [buffrs new](commands/buffrs-new.md) * [buffrs lint](commands/buffrs-lint.md) * [buffrs package](commands/buffrs-package.md) * [buffrs install](commands/buffrs-install.md) diff --git a/docs/src/commands/buffrs-new.md b/docs/src/commands/buffrs-new.md new file mode 100644 index 00000000..db26bfff --- /dev/null +++ b/docs/src/commands/buffrs-new.md @@ -0,0 +1,21 @@ +## buffrs init + +Initializes a Buffrs project in a new folder created in the current directory. + +### Synopsis + +`buffrs new ` + +`buffrs new --lib ` + +`buffrs new --api ` + +### Description + +This command creates a new Buffrs project with the provided name by creating a +manifest file (`Proto.toml`) as well as `proto` and `proto/vendor` directories +in a new directory created at the current location. + +By default, if no package type is provided, `impl` (implementation) will be +used. The meaning of this is described in [Package +Types](../guide/package-types.md). From ec1ea6865c0e686da7cf28972728d9bd3416ecf1 Mon Sep 17 00:00:00 2001 From: Guillaume Bouvignies Date: Thu, 4 Jul 2024 16:44:41 +0200 Subject: [PATCH 4/4] Fix clippy --- src/manifest.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/manifest.rs b/src/manifest.rs index 485bda8e..e72ae2f0 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, fmt::{self, Display}, - path::{Path, PathBuf}, + path::Path, str::FromStr, }; use tokio::fs; @@ -315,12 +315,11 @@ impl Manifest { /// Persists the manifest into the current directory pub async fn write(&self) -> miette::Result<()> { - let current_dir = PathBuf::from("."); - return self.write_at(¤t_dir).await; + self.write_at(Path::new(".")).await } /// Persists the manifest into the provided directory, which must exist - pub async fn write_at(&self, dir_path: &PathBuf) -> miette::Result<()> { + pub async fn write_at(&self, dir_path: &Path) -> miette::Result<()> { // hint: create a canary manifest from the current one let raw = RawManifest::from(Manifest::new( self.package.clone(),