Skip to content

Commit

Permalink
publish: Read keywords metadata from embedded Cargo.toml file (#7214
Browse files Browse the repository at this point in the history
)

... instead of the metadata JSON blob
  • Loading branch information
Turbo87 authored Sep 30, 2023
1 parent 408545c commit b96ed5c
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 52 deletions.
25 changes: 20 additions & 5 deletions src/controllers/krate/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,25 @@ pub async fn publish(app: AppState, req: BytesRequest) -> AppResult<Json<GoodCra
validate_url(documentation.as_deref(), "documentation")?;
validate_url(repository.as_deref(), "repository")?;

let keywords = package
.keywords
.map(|it| it.as_local().unwrap())
.unwrap_or_default();

if keywords.len() > 5 {
return Err(cargo_err("expected at most 5 keywords per crate"));
}

for keyword in keywords.iter() {
if keyword.len() > 20 {
return Err(cargo_err(&format!(
"\"{keyword}\" is an invalid keyword (keywords must have less than 20 characters)"
)));
} else if !Keyword::valid_name(keyword) {
return Err(cargo_err(&format!("\"{keyword}\" is an invalid keyword")));
}
}

let categories = package
.categories
.map(|it| it.as_local().unwrap())
Expand All @@ -176,11 +195,7 @@ pub async fn publish(app: AppState, req: BytesRequest) -> AppResult<Json<GoodCra
.into_iter()
.map(|(k, v)| (k.0, v.into_iter().map(|v| v.0).collect()))
.collect();
let keywords = metadata
.keywords
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>();
let keywords = keywords.iter().map(|s| s.as_str()).collect::<Vec<_>>();
let categories = categories.iter().map(|s| s.as_str()).collect::<Vec<_>>();

// Persist the new crate, if it doesn't already exist
Expand Down
7 changes: 0 additions & 7 deletions src/tests/builders/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,6 @@ impl PublishBuilder {
deps: self.deps.clone(),
readme: self.readme,
readme_file: None,
keywords: u::EncodableKeywordList(
self.keywords
.clone()
.into_iter()
.map(u::EncodableKeyword)
.collect(),
),
};

let mut tarball_builder = TarballBuilder::new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ expression: response.into_json()
{
"errors": [
{
"detail": "invalid upload request: invalid value: string \"?@?%\", expected a valid keyword specifier at line 1 column 113"
"detail": "\"?@?%\" is an invalid keyword"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ expression: response.into_json()
{
"errors": [
{
"detail": "invalid upload request: invalid value: string \"áccênts\", expected a valid keyword specifier at line 1 column 118"
"detail": "\"áccênts\" is an invalid keyword"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ expression: response.into_json()
{
"errors": [
{
"detail": "invalid upload request: invalid length 29, expected a keyword with less than 20 characters at line 1 column 138"
"detail": "\"super-long-keyword-name-oh-no\" is an invalid keyword (keywords must have less than 20 characters)"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ expression: response.into_json()
{
"errors": [
{
"detail": "invalid upload request: invalid length 6, expected at most 5 keywords per crate at line 1 column 139"
"detail": "expected at most 5 keywords per crate"
}
]
}
36 changes: 0 additions & 36 deletions src/views/krate_publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::models::krate::MAX_NAME_LENGTH;

use crate::models::Crate;
use crate::models::DependencyKind;
use crate::models::Keyword as CrateKeyword;

#[derive(Deserialize, Serialize, Debug)]
pub struct PublishMetadata {
Expand All @@ -23,8 +22,6 @@ pub struct PublishMetadata {
pub features: BTreeMap<EncodableFeatureName, Vec<EncodableFeature>>,
pub readme: Option<String>,
pub readme_file: Option<String>,
#[serde(default)]
pub keywords: EncodableKeywordList,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
Expand Down Expand Up @@ -87,25 +84,6 @@ impl<'de> Deserialize<'de> for EncodableDependencyName {
}
}

#[derive(Serialize, Debug, Deref)]
pub struct EncodableKeyword(pub String);

impl<'de> Deserialize<'de> for EncodableKeyword {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<EncodableKeyword, D::Error> {
let s = String::deserialize(d)?;
if s.len() > 20 {
let expected = "a keyword with less than 20 characters";
Err(de::Error::invalid_length(s.len(), &expected))
} else if !CrateKeyword::valid_name(&s) {
let value = de::Unexpected::Str(&s);
let expected = "a valid keyword specifier";
Err(de::Error::invalid_value(value, &expected))
} else {
Ok(EncodableKeyword(s))
}
}
}

#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Clone, Debug, Deref)]
pub struct EncodableFeatureName(pub String);

Expand Down Expand Up @@ -179,20 +157,6 @@ impl<'de> Deserialize<'de> for EncodableCrateVersionReq {
}
}

#[derive(Serialize, Debug, Deref, Default)]
pub struct EncodableKeywordList(pub Vec<EncodableKeyword>);

impl<'de> Deserialize<'de> for EncodableKeywordList {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<EncodableKeywordList, D::Error> {
let inner = <Vec<EncodableKeyword> as Deserialize<'de>>::deserialize(d)?;
if inner.len() > 5 {
let expected = "at most 5 keywords per crate";
return Err(de::Error::invalid_length(inner.len(), &expected));
}
Ok(EncodableKeywordList(inner))
}
}

#[test]
fn feature_deserializes_for_valid_features() {
use serde_json as json;
Expand Down

0 comments on commit b96ed5c

Please sign in to comment.