Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "buffrs"
version = "0.13.2"
version = "0.14.0"
edition = "2024"
description = "Modern protobuf package management"
authors = [
Expand Down Expand Up @@ -55,6 +55,7 @@ glob = "0.3"
hex = "0.4.3"
home = "0.5.5"
human-panic = "2"
ignore = "0.4.25"
miette = { version = "7", features = ["fancy"] }
protobuf = { version = "3.7.2", optional = true }
protobuf-parse = { version = "3.7.2", optional = true }
Expand Down
8 changes: 7 additions & 1 deletion src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub async fn init(kind: Option<PackageType>, name: Option<PackageName>) -> miett
name,
version: INITIAL_VERSION,
description: None,
include: Default::default(),
exclude: Default::default(),
})
})
.transpose()?;
Expand Down Expand Up @@ -106,6 +108,8 @@ pub async fn new(kind: Option<PackageType>, name: PackageName) -> miette::Result
name,
version: INITIAL_VERSION,
description: None,
include: Default::default(),
exclude: Default::default(),
})
})
.transpose()?;
Expand Down Expand Up @@ -371,7 +375,9 @@ pub async fn list() -> miette::Result<()> {
store.populate(pkg).await?;
}

let protos = store.collect(&store.proto_vendor_path(), true).await;
let protos = store
.collect(&store.proto_vendor_path(), true, None, None)
.await?;

let cwd = {
let cwd = std::env::current_dir()
Expand Down
170 changes: 170 additions & 0 deletions src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub enum Edition {
/// at any time. Users are responsible for consulting documentation and
/// help channels if errors occur.
Canary,
/// The canary edition used by buffrs 0.13.x
Canary13,
/// The canary edition used by buffrs 0.12.x
Canary12,
/// The canary edition used by buffrs 0.11.x
Expand Down Expand Up @@ -80,6 +82,7 @@ impl From<&str> for Edition {
fn from(value: &str) -> Self {
match value {
CANARY_EDITION => Self::Canary,
"0.13" => Self::Canary13,
"0.12" => Self::Canary12,
"0.11" => Self::Canary11,
"0.10" => Self::Canary10,
Expand All @@ -95,6 +98,7 @@ impl From<Edition> for &'static str {
fn from(value: Edition) -> Self {
match value {
Edition::Canary => CANARY_EDITION,
Edition::Canary13 => "0.13",
Edition::Canary12 => "0.12",
Edition::Canary11 => "0.11",
Edition::Canary10 => "0.10",
Expand Down Expand Up @@ -367,6 +371,7 @@ mod tests {

#[test]
fn edition_from_str_legacy_versions() {
assert_eq!(Edition::from("0.13"), Edition::Canary13);
assert_eq!(Edition::from("0.12"), Edition::Canary12);
assert_eq!(Edition::from("0.11"), Edition::Canary11);
assert_eq!(Edition::from("0.10"), Edition::Canary10);
Expand All @@ -385,6 +390,7 @@ mod tests {
#[test]
fn edition_to_str() {
assert_eq!(<&str>::from(Edition::Canary), CANARY_EDITION);
assert_eq!(<&str>::from(Edition::Canary13), "0.13");
assert_eq!(<&str>::from(Edition::Canary12), "0.12");
assert_eq!(<&str>::from(Edition::Canary11), "0.11");
assert_eq!(<&str>::from(Edition::Canary10), "0.10");
Expand Down Expand Up @@ -536,6 +542,8 @@ mod tests {
name: PackageName::from_str("test").unwrap(),
version: Version::new(1, 0, 0),
description: Some("Test description".to_string()),
include: Default::default(),
exclude: Default::default(),
})
.dependencies(vec![])
.build();
Expand All @@ -544,6 +552,166 @@ mod tests {
assert!(serialized.contains("Test description"));
}

#[test]
fn serialize_package_manifest_with_include() {
let manifest = PackagesManifest::builder()
.package(PackageManifest {
kind: PackageType::Api,
name: PackageName::from_str("test").unwrap(),
version: Version::new(1, 0, 0),
description: None,
include: Some(vec!["foo".to_string()]),
exclude: Default::default(),
})
.build();

let serialized: String = manifest.try_into().expect("should serialize");
assert!(serialized.contains("include"));
assert!(!serialized.contains("exclude"));
}

#[test]
fn serialize_package_manifest_with_exclude() {
let manifest = PackagesManifest::builder()
.package(PackageManifest {
kind: PackageType::Api,
name: PackageName::from_str("test").unwrap(),
version: Version::new(1, 0, 0),
description: None,
include: None,
exclude: Some(vec!["bar".to_string()]),
})
.build();

let serialized: String = manifest.try_into().expect("should serialize");
assert!(!serialized.contains("include"));
assert!(serialized.contains("exclude"));
}

#[test]
fn serialize_package_manifest_omits_empty_include_and_exclude() {
let manifest = PackagesManifest::builder()
.package(PackageManifest {
kind: PackageType::Api,
name: PackageName::from_str("test").unwrap(),
version: Version::new(1, 0, 0),
description: None,
include: None,
exclude: Default::default(),
})
.build();

let serialized: String = manifest.try_into().expect("should serialize");
assert!(!serialized.contains("include"));
assert!(!serialized.contains("exclude"));
}

#[test]
fn deserialize_manifest_with_include() {
let toml = r#"
edition = "0.14"

[package]
type = "lib"
name = "test"
version = "1.0.0"
include = ["src/**/*.proto", "api/*.proto"]

[dependencies]
"#;

let manifest = PackagesManifest::from_str(toml).expect("should parse");
let pkg = manifest.package.expect("package should be present");
assert_eq!(
pkg.include,
Some(vec![
"src/**/*.proto".to_string(),
"api/*.proto".to_string()
])
);
assert!(pkg.exclude.is_none());
}

#[test]
fn deserialize_manifest_with_exclude() {
let toml = r#"
edition = "0.14"

[package]
type = "lib"
name = "test"
version = "1.0.0"
exclude = ["internal.proto"]

[dependencies]
"#;

let manifest = PackagesManifest::from_str(toml).expect("should parse");
let pkg = manifest.package.expect("package should be present");
assert!(pkg.include.is_none());
assert_eq!(pkg.exclude, Some(vec!["internal.proto".to_string()]));
}

#[test]
fn deserialize_manifest_with_empty_exclude_preserves_distinction() {
let toml = r#"
edition = "0.14"

[package]
type = "lib"
name = "test"
version = "1.0.0"
exclude = []

[dependencies]
"#;

let manifest = PackagesManifest::from_str(toml).expect("should parse");
let pkg = manifest.package.expect("package should be present");
assert_eq!(pkg.exclude, Some(vec![]));
}

#[test]
fn deserialize_manifest_with_both_include_and_exclude_fails() {
let toml = r#"
edition = "0.14"

[package]
type = "lib"
name = "test"
version = "1.0.0"
include = ["src/**/*.proto"]
exclude = ["internal.proto"]

[dependencies]
"#;

let result = PackagesManifest::from_str(toml);
assert!(
result.is_err(),
"manifest with both include and exclude should fail"
);
}

#[test]
fn deserialize_manifest_with_empty_include_preserves_distinction() {
let toml = r#"
edition = "0.14"

[package]
type = "lib"
name = "test"
version = "1.0.0"
include = []

[dependencies]
"#;

let manifest = PackagesManifest::from_str(toml).expect("should parse");
let pkg = manifest.package.expect("package should be present");
assert_eq!(pkg.include, Some(vec![]));
}

#[test]
fn deserialize_manifest_with_local_dependency() {
let toml = r#"
Expand Down Expand Up @@ -647,6 +815,8 @@ mod tests {
name: PackageName::from_str("complex-package").unwrap(),
version: Version::new(2, 1, 0),
description: Some("A complex test package".to_string()),
include: Some(vec!["foo".to_string()]),
exclude: Default::default(),
};

let deps = vec![
Expand Down
Loading
Loading