Skip to content

Commit 84b62a4

Browse files
committed
Auto merge of #3192 - Turbo87:dep-model, r=pietroalbini
Clean up `dependency` model module This PR slightly cleans up the `dependency` model module, primarily by moving the `add_dependencies()` function into the corresponding controller. The function is using view-specific classes, which should be avoided in the `models` modules. r? `@pietroalbini`
2 parents 4be4281 + bb2bebe commit 84b62a4

File tree

3 files changed

+87
-91
lines changed

3 files changed

+87
-91
lines changed

src/controllers/krate/publish.rs

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,30 @@ use swirl::Job;
66

77
use crate::controllers::cargo_prelude::*;
88
use crate::git;
9-
use crate::models::dependency;
109
use crate::models::{
11-
insert_version_owner_action, Badge, Category, Keyword, NewCrate, NewVersion, Rights,
12-
VersionAction,
10+
insert_version_owner_action, Badge, Category, Crate, DependencyKind, Keyword, NewCrate,
11+
NewVersion, Rights, VersionAction,
1312
};
1413

1514
use crate::render;
15+
use crate::schema::*;
16+
use crate::util::errors::{cargo_err, AppResult};
1617
use crate::util::{read_fill, read_le_u32, Maximums};
17-
use crate::views::{EncodableCrate, EncodableCrateUpload, GoodCrate, PublishWarnings};
18+
use crate::views::{
19+
EncodableCrate, EncodableCrateDependency, EncodableCrateUpload, GoodCrate, PublishWarnings,
20+
};
1821

1922
pub const MISSING_RIGHTS_ERROR_MESSAGE: &str =
2023
"this crate exists but you don't seem to be an owner. \
2124
If you believe this is a mistake, perhaps you need \
2225
to accept an invitation to be an owner before \
2326
publishing.";
2427

28+
pub const WILDCARD_ERROR_MESSAGE: &str = "wildcard (`*`) dependency constraints are not allowed \
29+
on crates.io. See https://doc.rust-lang.org/cargo/faq.html#can-\
30+
libraries-use--as-a-version-for-their-dependencies for more \
31+
information";
32+
2533
/// Handles the `PUT /crates/new` route.
2634
/// Used by `cargo publish` to publish a new crate or to publish a new version of an
2735
/// existing crate.
@@ -163,7 +171,7 @@ pub fn publish(req: &mut dyn RequestExt) -> EndpointResult {
163171
)?;
164172

165173
// Link this new version to all dependencies
166-
let git_deps = dependency::add_dependencies(&conn, &new_crate.deps, version.id)?;
174+
let git_deps = add_dependencies(&conn, &new_crate.deps, version.id)?;
167175

168176
// Update all keywords for this crate
169177
Keyword::update_crate(&conn, &krate, &keywords)?;
@@ -277,6 +285,76 @@ pub fn missing_metadata_error_message(missing: &[&str]) -> String {
277285
)
278286
}
279287

288+
pub fn add_dependencies(
289+
conn: &PgConnection,
290+
deps: &[EncodableCrateDependency],
291+
target_version_id: i32,
292+
) -> AppResult<Vec<git::Dependency>> {
293+
use self::dependencies::dsl::*;
294+
use diesel::insert_into;
295+
296+
let git_and_new_dependencies = deps
297+
.iter()
298+
.map(|dep| {
299+
if let Some(registry) = &dep.registry {
300+
if !registry.is_empty() {
301+
return Err(cargo_err(&format_args!("Dependency `{}` is hosted on another registry. Cross-registry dependencies are not permitted on crates.io.", &*dep.name)));
302+
}
303+
}
304+
305+
// Match only identical names to ensure the index always references the original crate name
306+
let krate:Crate = Crate::by_exact_name(&dep.name)
307+
.first(&*conn)
308+
.map_err(|_| cargo_err(&format_args!("no known crate named `{}`", &*dep.name)))?;
309+
if semver::VersionReq::parse(&dep.version_req.0) == semver::VersionReq::parse("*") {
310+
return Err(cargo_err(WILDCARD_ERROR_MESSAGE));
311+
}
312+
313+
// If this dependency has an explicit name in `Cargo.toml` that
314+
// means that the `name` we have listed is actually the package name
315+
// that we're depending on. The `name` listed in the index is the
316+
// Cargo.toml-written-name which is what cargo uses for
317+
// `--extern foo=...`
318+
let (name, package) = match &dep.explicit_name_in_toml {
319+
Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),
320+
None => (dep.name.to_string(), None),
321+
};
322+
323+
Ok((
324+
git::Dependency {
325+
name,
326+
req: dep.version_req.to_string(),
327+
features: dep.features.iter().map(|s| s.0.to_string()).collect(),
328+
optional: dep.optional,
329+
default_features: dep.default_features,
330+
target: dep.target.clone(),
331+
kind: dep.kind.or(Some(DependencyKind::Normal)),
332+
package,
333+
},
334+
(
335+
version_id.eq(target_version_id),
336+
crate_id.eq(krate.id),
337+
req.eq(dep.version_req.to_string()),
338+
dep.kind.map(|k| kind.eq(k as i32)),
339+
optional.eq(dep.optional),
340+
default_features.eq(dep.default_features),
341+
features.eq(&dep.features),
342+
target.eq(dep.target.as_deref()),
343+
),
344+
))
345+
})
346+
.collect::<Result<Vec<_>, _>>()?;
347+
348+
let (git_deps, new_dependencies): (Vec<_>, Vec<_>) =
349+
git_and_new_dependencies.into_iter().unzip();
350+
351+
insert_into(dependencies)
352+
.values(&new_dependencies)
353+
.execute(conn)?;
354+
355+
Ok(git_deps)
356+
}
357+
280358
#[cfg(test)]
281359
mod tests {
282360
use super::missing_metadata_error_message;

src/models/dependency.rs

Lines changed: 3 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
use diesel::prelude::*;
2-
3-
use crate::git;
4-
use crate::util::errors::{cargo_err, AppResult};
1+
use diesel::deserialize::{self, FromSql};
2+
use diesel::pg::Pg;
3+
use diesel::sql_types::Integer;
54

65
use crate::models::{Crate, Version};
76
use crate::schema::*;
8-
use crate::views::EncodableCrateDependency;
9-
10-
pub const WILDCARD_ERROR_MESSAGE: &str = "wildcard (`*`) dependency constraints are not allowed \
11-
on crates.io. See https://doc.rust-lang.org/cargo/faq.html#can-\
12-
libraries-use--as-a-version-for-their-dependencies for more \
13-
information";
147

158
#[derive(Identifiable, Associations, Debug, Queryable, QueryableByName)]
169
#[belongs_to(Version)]
@@ -49,80 +42,6 @@ pub enum DependencyKind {
4942
// if you add a kind here, be sure to update `from_row` below.
5043
}
5144

52-
pub fn add_dependencies(
53-
conn: &PgConnection,
54-
deps: &[EncodableCrateDependency],
55-
target_version_id: i32,
56-
) -> AppResult<Vec<git::Dependency>> {
57-
use self::dependencies::dsl::*;
58-
use diesel::insert_into;
59-
60-
let git_and_new_dependencies = deps
61-
.iter()
62-
.map(|dep| {
63-
if let Some(registry) = &dep.registry {
64-
if !registry.is_empty() {
65-
return Err(cargo_err(&format_args!("Dependency `{}` is hosted on another registry. Cross-registry dependencies are not permitted on crates.io.", &*dep.name)));
66-
}
67-
}
68-
69-
// Match only identical names to ensure the index always references the original crate name
70-
let krate:Crate = Crate::by_exact_name(&dep.name)
71-
.first(&*conn)
72-
.map_err(|_| cargo_err(&format_args!("no known crate named `{}`", &*dep.name)))?;
73-
if semver::VersionReq::parse(&dep.version_req.0) == semver::VersionReq::parse("*") {
74-
return Err(cargo_err(WILDCARD_ERROR_MESSAGE));
75-
}
76-
77-
// If this dependency has an explicit name in `Cargo.toml` that
78-
// means that the `name` we have listed is actually the package name
79-
// that we're depending on. The `name` listed in the index is the
80-
// Cargo.toml-written-name which is what cargo uses for
81-
// `--extern foo=...`
82-
let (name, package) = match &dep.explicit_name_in_toml {
83-
Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),
84-
None => (dep.name.to_string(), None),
85-
};
86-
87-
Ok((
88-
git::Dependency {
89-
name,
90-
req: dep.version_req.to_string(),
91-
features: dep.features.iter().map(|s| s.0.to_string()).collect(),
92-
optional: dep.optional,
93-
default_features: dep.default_features,
94-
target: dep.target.clone(),
95-
kind: dep.kind.or(Some(DependencyKind::Normal)),
96-
package,
97-
},
98-
(
99-
version_id.eq(target_version_id),
100-
crate_id.eq(krate.id),
101-
req.eq(dep.version_req.to_string()),
102-
dep.kind.map(|k| kind.eq(k as i32)),
103-
optional.eq(dep.optional),
104-
default_features.eq(dep.default_features),
105-
features.eq(&dep.features),
106-
target.eq(dep.target.as_deref()),
107-
),
108-
))
109-
})
110-
.collect::<Result<Vec<_>, _>>()?;
111-
112-
let (git_deps, new_dependencies): (Vec<_>, Vec<_>) =
113-
git_and_new_dependencies.into_iter().unzip();
114-
115-
insert_into(dependencies)
116-
.values(&new_dependencies)
117-
.execute(conn)?;
118-
119-
Ok(git_deps)
120-
}
121-
122-
use diesel::deserialize::{self, FromSql};
123-
use diesel::pg::Pg;
124-
use diesel::sql_types::Integer;
125-
12645
impl FromSql<Integer, Pg> for DependencyKind {
12746
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
12847
match <i32 as FromSql<Integer, Pg>>::from_sql(bytes)? {

src/tests/krate/publish.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use crate::builders::{CrateBuilder, DependencyBuilder, PublishBuilder};
22
use crate::new_category;
33
use crate::util::{RequestHelper, TestApp};
44
use cargo_registry::controllers::krate::publish::{
5-
missing_metadata_error_message, MISSING_RIGHTS_ERROR_MESSAGE,
5+
missing_metadata_error_message, MISSING_RIGHTS_ERROR_MESSAGE, WILDCARD_ERROR_MESSAGE,
66
};
7-
use cargo_registry::models::dependency::WILDCARD_ERROR_MESSAGE;
87
use cargo_registry::models::krate::MAX_NAME_LENGTH;
98
use cargo_registry::schema::{api_tokens, emails, versions_published_by};
109
use cargo_registry::views::GoodCrate;

0 commit comments

Comments
 (0)