Skip to content

Commit e7fb8fa

Browse files
committed
Auto merge of #3178 - Turbo87:encodable-version, r=pietroalbini
Version|Crate: Replace `encodable()` methods This PR is similar to #3168 and brings us one step closer to removing the `models -> views` dependency by inverting the relationship for the `Version` model and `EncodableVersion` view. r? `@pietroalbini`
2 parents 90bb83b + bef2600 commit e7fb8fa

File tree

9 files changed

+244
-226
lines changed

9 files changed

+244
-226
lines changed

src/controllers/krate/metadata.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ pub fn summary(req: &mut dyn RequestExt) -> EndpointResult {
4141
.zip(krates)
4242
.zip(recent_downloads)
4343
.map(|((top_versions, krate), recent_downloads)| {
44-
Ok(krate.minimal_encodable(&top_versions, None, false, recent_downloads))
44+
Ok(EncodableCrate::from_minimal(
45+
krate,
46+
&top_versions,
47+
None,
48+
false,
49+
recent_downloads,
50+
))
4551
})
4652
.collect()
4753
};
@@ -165,7 +171,8 @@ pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
165171
categories: Vec<EncodableCategory>,
166172
}
167173
Ok(req.json(&R {
168-
krate: krate.clone().encodable(
174+
krate: EncodableCrate::from(
175+
krate.clone(),
169176
&top_versions,
170177
Some(ids),
171178
Some(&kws),
@@ -176,7 +183,7 @@ pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
176183
),
177184
versions: versions_publishers_and_audit_actions
178185
.into_iter()
179-
.map(|(v, pb, aas)| v.encodable(&krate.name, pb, aas))
186+
.map(|(v, pb, aas)| EncodableVersion::from(v, &krate.name, pb, aas))
180187
.collect(),
181188
keywords: kws.into_iter().map(Keyword::into).collect(),
182189
categories: cats.into_iter().map(Category::into).collect(),
@@ -226,7 +233,7 @@ pub fn versions(req: &mut dyn RequestExt) -> EndpointResult {
226233
let versions = versions_and_publishers
227234
.into_iter()
228235
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
229-
.map(|((v, pb), aas)| v.encodable(crate_name, pb, aas))
236+
.map(|((v, pb), aas)| EncodableVersion::from(v, crate_name, pb, aas))
230237
.collect();
231238

232239
#[derive(Serialize)]
@@ -271,7 +278,7 @@ pub fn reverse_dependencies(req: &mut dyn RequestExt) -> EndpointResult {
271278
.into_iter()
272279
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
273280
.map(|((version, krate_name, published_by), actions)| {
274-
version.encodable(&krate_name, published_by, actions)
281+
EncodableVersion::from(version, &krate_name, published_by, actions)
275282
})
276283
.collect();
277284

src/controllers/krate/publish.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::models::{
1414

1515
use crate::render;
1616
use crate::util::{read_fill, read_le_u32, Maximums};
17-
use crate::views::{EncodableCrateUpload, GoodCrate, PublishWarnings};
17+
use crate::views::{EncodableCrate, EncodableCrateUpload, GoodCrate, PublishWarnings};
1818

1919
pub const MISSING_RIGHTS_ERROR_MESSAGE: &str =
2020
"this crate exists but you don't seem to be an owner. \
@@ -218,7 +218,7 @@ pub fn publish(req: &mut dyn RequestExt) -> EndpointResult {
218218
};
219219

220220
Ok(req.json(&GoodCrate {
221-
krate: krate.minimal_encodable(&top_versions, None, false, None),
221+
krate: EncodableCrate::from_minimal(krate, &top_versions, None, false, None),
222222
warnings,
223223
}))
224224
})

src/controllers/krate/search.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ pub fn search(req: &mut dyn RequestExt) -> EndpointResult {
226226
.zip(badges)
227227
.map(
228228
|((((max_version, krate), perfect_match), recent_downloads), badges)| {
229-
krate.minimal_encodable(
229+
EncodableCrate::from_minimal(
230+
krate,
230231
&max_version,
231232
Some(badges),
232233
perfect_match,

src/controllers/user/me.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub fn updates(req: &mut dyn RequestExt) -> EndpointResult {
8383
let versions = data
8484
.into_iter()
8585
.map(|(version, crate_name, published_by, actions)| {
86-
version.encodable(&crate_name, published_by, actions)
86+
EncodableVersion::from(version, &crate_name, published_by, actions)
8787
})
8888
.collect();
8989

src/controllers/version/deprecated.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub fn index(req: &mut dyn RequestExt) -> EndpointResult {
4141
.into_iter()
4242
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
4343
.map(|((version, crate_name, published_by), actions)| {
44-
version.encodable(&crate_name, published_by, actions)
44+
EncodableVersion::from(version, &crate_name, published_by, actions)
4545
})
4646
.collect();
4747

@@ -76,6 +76,6 @@ pub fn show_by_id(req: &mut dyn RequestExt) -> EndpointResult {
7676
version: EncodableVersion,
7777
}
7878
Ok(req.json(&R {
79-
version: version.encodable(&krate.name, published_by, audit_actions),
79+
version: EncodableVersion::from(version, &krate.name, published_by, audit_actions),
8080
}))
8181
}

src/controllers/version/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,6 @@ pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
8181
version: EncodableVersion,
8282
}
8383
Ok(req.json(&R {
84-
version: version.encodable(&krate.name, published_by, actions),
84+
version: EncodableVersion::from(version, &krate.name, published_by, actions),
8585
}))
8686
}

src/models/krate.rs

+2-161
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,15 @@ use crate::controllers::helpers::pagination::*;
1010
use crate::email;
1111
use crate::models::version::TopVersions;
1212
use crate::models::{
13-
Badge, Category, CrateOwner, CrateOwnerInvitation, Keyword, NewCrateOwnerInvitation, Owner,
14-
OwnerKind, ReverseDependency, User, Version,
13+
Badge, CrateOwner, CrateOwnerInvitation, NewCrateOwnerInvitation, Owner, OwnerKind,
14+
ReverseDependency, User, Version,
1515
};
1616
use crate::util::errors::{cargo_err, AppResult};
17-
use crate::views::{EncodableCrate, EncodableCrateLinks};
1817

1918
use crate::models::helpers::with_count::*;
2019
use crate::publish_rate_limit::PublishRateLimit;
2120
use crate::schema::*;
2221

23-
/// Hosts in this list are known to not be hosting documentation,
24-
/// and are possibly of malicious intent e.g. ad tracking networks, etc.
25-
const DOCUMENTATION_BLOCKLIST: [&str; 2] = ["rust-ci.org", "rustless.org"];
26-
2722
#[derive(Debug, Queryable, Identifiable, Associations, Clone, Copy)]
2823
#[belongs_to(Crate)]
2924
#[primary_key(crate_id)]
@@ -296,127 +291,6 @@ impl Crate {
296291
&& prefix_part.map_or(true, Crate::valid_feature_prefix)
297292
}
298293

299-
pub fn minimal_encodable(
300-
self,
301-
top_versions: &TopVersions,
302-
badges: Option<Vec<Badge>>,
303-
exact_match: bool,
304-
recent_downloads: Option<i64>,
305-
) -> EncodableCrate {
306-
self.encodable(
307-
top_versions,
308-
None,
309-
None,
310-
None,
311-
badges,
312-
exact_match,
313-
recent_downloads,
314-
)
315-
}
316-
317-
#[allow(clippy::too_many_arguments)]
318-
pub fn encodable(
319-
self,
320-
top_versions: &TopVersions,
321-
versions: Option<Vec<i32>>,
322-
keywords: Option<&[Keyword]>,
323-
categories: Option<&[Category]>,
324-
badges: Option<Vec<Badge>>,
325-
exact_match: bool,
326-
recent_downloads: Option<i64>,
327-
) -> EncodableCrate {
328-
let Crate {
329-
name,
330-
created_at,
331-
updated_at,
332-
downloads,
333-
description,
334-
homepage,
335-
documentation,
336-
repository,
337-
..
338-
} = self;
339-
let versions_link = match versions {
340-
Some(..) => None,
341-
None => Some(format!("/api/v1/crates/{}/versions", name)),
342-
};
343-
let keyword_ids = keywords.map(|kws| kws.iter().map(|kw| kw.keyword.clone()).collect());
344-
let category_ids = categories.map(|cats| cats.iter().map(|cat| cat.slug.clone()).collect());
345-
let badges = badges.map(|bs| bs.into_iter().map(Badge::into).collect());
346-
let documentation = Crate::remove_blocked_documentation_urls(documentation);
347-
348-
let max_version = top_versions
349-
.highest
350-
.as_ref()
351-
.map(|v| v.to_string())
352-
.unwrap_or_else(|| "0.0.0".to_string());
353-
354-
let newest_version = top_versions
355-
.newest
356-
.as_ref()
357-
.map(|v| v.to_string())
358-
.unwrap_or_else(|| "0.0.0".to_string());
359-
360-
let max_stable_version = top_versions.highest_stable.as_ref().map(|v| v.to_string());
361-
362-
EncodableCrate {
363-
id: name.clone(),
364-
name: name.clone(),
365-
updated_at,
366-
created_at,
367-
downloads,
368-
recent_downloads,
369-
versions,
370-
keywords: keyword_ids,
371-
categories: category_ids,
372-
badges,
373-
max_version,
374-
newest_version,
375-
max_stable_version,
376-
documentation,
377-
homepage,
378-
exact_match,
379-
description,
380-
repository,
381-
links: EncodableCrateLinks {
382-
version_downloads: format!("/api/v1/crates/{}/downloads", name),
383-
versions: versions_link,
384-
owners: Some(format!("/api/v1/crates/{}/owners", name)),
385-
owner_team: Some(format!("/api/v1/crates/{}/owner_team", name)),
386-
owner_user: Some(format!("/api/v1/crates/{}/owner_user", name)),
387-
reverse_dependencies: format!("/api/v1/crates/{}/reverse_dependencies", name),
388-
},
389-
}
390-
}
391-
392-
/// Return `None` if the documentation URL host matches a blocked host
393-
fn remove_blocked_documentation_urls(url: Option<String>) -> Option<String> {
394-
// Handles if documentation URL is None
395-
let url = match url {
396-
Some(url) => url,
397-
None => return None,
398-
};
399-
400-
// Handles unsuccessful parsing of documentation URL
401-
let parsed_url = match Url::parse(&url) {
402-
Ok(parsed_url) => parsed_url,
403-
Err(_) => return None,
404-
};
405-
406-
// Extract host string from documentation URL
407-
let url_host = match parsed_url.host_str() {
408-
Some(url_host) => url_host,
409-
None => return None,
410-
};
411-
412-
// Match documentation URL host against blocked host array elements
413-
if DOCUMENTATION_BLOCKLIST.contains(&url_host) {
414-
None
415-
} else {
416-
Some(url)
417-
}
418-
}
419-
420294
/// Return both the newest (most recently updated) and
421295
/// highest version (in semver order) for the current crate.
422296
pub fn top_versions(&self, conn: &PgConnection) -> QueryResult<TopVersions> {
@@ -576,39 +450,6 @@ mod tests {
576450
assert_err!(krate.validate());
577451
}
578452

579-
#[test]
580-
fn documentation_blocked_no_url_provided() {
581-
assert_eq!(Crate::remove_blocked_documentation_urls(None), None);
582-
}
583-
584-
#[test]
585-
fn documentation_blocked_invalid_url() {
586-
assert_eq!(
587-
Crate::remove_blocked_documentation_urls(Some(String::from("not a url"))),
588-
None
589-
);
590-
}
591-
592-
#[test]
593-
fn documentation_blocked_url_contains_partial_match() {
594-
assert_eq!(
595-
Crate::remove_blocked_documentation_urls(Some(String::from(
596-
"http://rust-ci.organists.com"
597-
)),),
598-
Some(String::from("http://rust-ci.organists.com"))
599-
);
600-
}
601-
602-
#[test]
603-
fn documentation_blocked_url() {
604-
assert_eq!(
605-
Crate::remove_blocked_documentation_urls(Some(String::from(
606-
"http://rust-ci.org/crate/crate-0.1/doc/crate-0.1",
607-
),),),
608-
None
609-
);
610-
}
611-
612453
#[test]
613454
fn valid_name() {
614455
assert!(Crate::valid_name("foo"));

src/models/version.rs

+1-51
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ use diesel::prelude::*;
55

66
use crate::util::errors::{cargo_err, AppResult};
77

8-
use crate::models::{Crate, Dependency, User, VersionOwnerAction};
8+
use crate::models::{Crate, Dependency, User};
99
use crate::schema::*;
10-
use crate::views::{EncodableAuditAction, EncodableVersion, EncodableVersionLinks};
1110

1211
// Queryable has a custom implementation below
1312
#[derive(Clone, Identifiable, Associations, Debug, Queryable, Deserialize, Serialize)]
@@ -80,55 +79,6 @@ impl TopVersions {
8079
}
8180

8281
impl Version {
83-
pub fn encodable(
84-
self,
85-
crate_name: &str,
86-
published_by: Option<User>,
87-
audit_actions: Vec<(VersionOwnerAction, User)>,
88-
) -> EncodableVersion {
89-
let Version {
90-
id,
91-
num,
92-
updated_at,
93-
created_at,
94-
downloads,
95-
features,
96-
yanked,
97-
license,
98-
crate_size,
99-
..
100-
} = self;
101-
let num = num.to_string();
102-
EncodableVersion {
103-
dl_path: format!("/api/v1/crates/{}/{}/download", crate_name, num),
104-
readme_path: format!("/api/v1/crates/{}/{}/readme", crate_name, num),
105-
num: num.clone(),
106-
id,
107-
krate: crate_name.to_string(),
108-
updated_at,
109-
created_at,
110-
downloads,
111-
features,
112-
yanked,
113-
license,
114-
links: EncodableVersionLinks {
115-
dependencies: format!("/api/v1/crates/{}/{}/dependencies", crate_name, num),
116-
version_downloads: format!("/api/v1/crates/{}/{}/downloads", crate_name, num),
117-
authors: format!("/api/v1/crates/{}/{}/authors", crate_name, num),
118-
},
119-
crate_size,
120-
published_by: published_by.map(User::into),
121-
audit_actions: audit_actions
122-
.into_iter()
123-
.map(|(audit_action, user)| EncodableAuditAction {
124-
action: audit_action.action.into(),
125-
user: user.into(),
126-
time: audit_action.time,
127-
})
128-
.collect(),
129-
}
130-
}
131-
13282
/// Returns (dependency, crate dependency name)
13383
pub fn dependencies(&self, conn: &PgConnection) -> QueryResult<Vec<(Dependency, String)>> {
13484
Dependency::belonging_to(self)

0 commit comments

Comments
 (0)