Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions src/controllers/krate/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,13 @@ pub async fn publish(app: AppState, req: Parts, body: Body) -> AppResult<Json<Go
validate_dependency(dep)?;
}

// We don't want to allow [patch] sections in manifests at all.
if matches!(&tarball_info.manifest.patch, Some(patch) if !patch.is_empty()) {
return Err(bad_request(
"crates.io does not allow crates to be published with `[patch]` sections in their manifests.",
));
}

let api_token_id = auth.api_token_id();
let user = auth.user();

Expand Down
32 changes: 32 additions & 0 deletions src/tests/krate/publish/dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,38 @@ async fn new_krate_with_wildcard_dependency() {
assert_that!(app.stored_files().await, empty());
}

#[tokio::test(flavor = "multi_thread")]
async fn new_krate_with_patch() {
let (app, _, user, token) = TestApp::full().with_token().await;
let mut conn = app.db_conn().await;

// Insert a crate directly into the database so that new_wild can depend on it
CrateBuilder::new("foo_patch", user.as_model().id)
.expect_build(&mut conn)
.await;

let manifest = r#"
[package]
name = "new_patch"
version = "1.0.0"
description = "foo?!"
license = "MIT"

[dependencies]
foo_patch = "1.0.0"

[patch.crates-io]
foo_patch = { git = "https://github.com/foo/patch.git" }
"#;

let crate_to_publish = PublishBuilder::new("new_patch", "1.0.0").custom_manifest(manifest);

let response = token.publish_crate(crate_to_publish).await;
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
assert_snapshot!(response.text(), @r###"{"errors":[{"detail":"crates.io does not allow crates to be published with `[patch]` sections in their manifests."}]}"###);
assert_that!(app.stored_files().await, empty());
}

#[tokio::test(flavor = "multi_thread")]
async fn new_krate_dependency_missing() {
let (app, _, _, token) = TestApp::full().with_token().await;
Expand Down