Skip to content

Commit

Permalink
Add buffrs new command to init a package in a non-existing folder
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume Bouvignies committed Jul 4, 2024
1 parent 8b49387 commit 0b71b8c
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 19 deletions.
39 changes: 35 additions & 4 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ 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},
Expand Down Expand Up @@ -68,7 +68,7 @@ pub async fn init(kind: Option<PackageType>, name: Option<PackageName>) -> 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
Expand All @@ -77,6 +77,37 @@ pub async fn init(kind: Option<PackageType>, name: Option<PackageName>) -> miett
Ok(())
}

/// Initializes a project with the given name in the current directory
pub async fn new(kind: Option<PackageType>, name: PackageName) -> miette::Result<()> {
let mut package_dir: PathBuf = ".".into();
package_dir.push::<String>(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<PackageManifest> {
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,
Expand Down Expand Up @@ -139,7 +170,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}`"))
}
Expand All @@ -159,7 +190,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
Expand Down
43 changes: 36 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ enum Command {
package: Option<PackageName>,
},

/// 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,

Expand Down Expand Up @@ -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
Expand All @@ -192,6 +201,16 @@ 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}`")),
Expand Down Expand Up @@ -255,3 +274,13 @@ async fn main() -> miette::Result<()> {
},
}
}

fn infer_package_type(lib: bool, api: bool) -> Option<PackageType> {
if lib {
Some(PackageType::Lib)
} else if api {
Some(PackageType::Api)
} else {
None
}
}
15 changes: 7 additions & 8 deletions src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@ use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fmt::{self, Display},
path::Path,
path::{Path, PathBuf},
str::FromStr,
};
use tokio::fs;

use crate::{
errors::{DeserializationError, FileExistsError, SerializationError, WriteError},
package::{PackageName, PackageType},
registry::RegistryUri,
ManagedFile,
errors::{DeserializationError, FileExistsError, SerializationError, WriteError}, package::{PackageName, PackageType}, registry::RegistryUri, ManagedFile
};

/// The name of the manifest file
Expand Down Expand Up @@ -313,16 +310,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<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);
fs::write(
MANIFEST_FILE,
manifest_file_path,
toml::to_string(&raw)
.into_diagnostic()
.wrap_err(SerializationError(ManagedFile::Manifest))?
Expand Down

0 comments on commit 0b71b8c

Please sign in to comment.