Skip to content

Commit 59184f2

Browse files
committed
use cargo-util-schemas to parse package id schema
as sugested by epage rust-lang/cargo#15048 (comment)
1 parent 70ef827 commit 59184f2

File tree

3 files changed

+142
-145
lines changed

3 files changed

+142
-145
lines changed

Cargo.lock

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ aws-sdk-s3 = "1.7"
6363
aws-config = { version = "1", features = ["behavior-version-latest"] }
6464
thiserror = "1.0.38"
6565
nix = { version = "0.27.1", features = ["mman", "resource"] }
66+
cargo-util-schemas = "0.7.1"
6667

6768
[dev-dependencies]
6869
assert_cmd = "2.0.4"

src/crates/mod.rs

Lines changed: 78 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -120,159 +120,88 @@ impl TryFrom<&'_ PackageId> for Crate {
120120
pkgid.repr
121121
),
122122
}
123-
} else if pkgid.repr.contains("://") {
124-
// Cargo Package Id Spec URL format
125-
// <https://doc.rust-lang.org/cargo/reference/pkgid-spec.html>
126-
127-
let pkg_url = url::Url::parse(&pkgid.repr)?;
128-
129-
let (kind, proto) = if let Some((kind, proto)) = pkg_url.scheme().split_once('+') {
130-
(Some(kind), proto)
131-
} else {
132-
(None, pkg_url.scheme())
133-
};
134-
135-
let anchor = pkg_url.fragment();
136-
let query = pkg_url.query();
137-
138-
match (kind, proto) {
139-
(Some("path") | None, "file") => Ok(Crate::Path(pkg_url.path().to_string())),
140-
(Some("registry"), _) => {
141-
if let Some(anchor) = anchor {
142-
if let Some((package_name, version)) = anchor.split_once(['@', ':']) {
143-
Ok(Crate::Registry(RegistryCrate {
144-
name: package_name.to_string(),
145-
version: version.to_string(),
146-
}))
147-
} else if !anchor
148-
.contains(|c: char| !c.is_ascii_alphanumeric() && c != '_' && c != '-')
149-
{
150-
// anchor appears to be a valid package name
151-
Ok(Crate::Registry(RegistryCrate {
152-
name: anchor.to_string(),
153-
version: "unknown".to_string(),
123+
} else {
124+
use cargo_util_schemas::core::*;
125+
126+
let package_id = PackageIdSpec::parse(&pkgid.repr)?;
127+
128+
match package_id.kind() {
129+
Some(SourceKind::LocalRegistry) => Ok(Crate::Local(package_id.name().to_string())),
130+
Some(SourceKind::Git(rev)) => {
131+
if let Some(url) = package_id.url() {
132+
if url.domain() == Some("github.com") {
133+
Ok(Crate::GitHub(GitHubRepo {
134+
org: url
135+
.path_segments()
136+
.and_then(|mut path| path.next())
137+
.unwrap_or_default()
138+
.to_string(),
139+
name: package_id.name().to_string(),
140+
sha: rev.pretty_ref(false).map(|rev| rev.to_string()),
154141
}))
155142
} else {
156-
// as the anchor is not a valid package name check whether it can be a version
157-
let Some(minor_major_path) = anchor.split(['-', '+']).next() else {
158-
bail!("split always returns at least one element")
159-
};
160-
161-
if minor_major_path.split('.').count() > 3
162-
|| minor_major_path
163-
.split('.')
164-
.any(|part| part.contains(|c: char| !c.is_ascii_digit()))
165-
{
166-
bail!(
167-
"malformed pkgid format: {}\n maybe the representation has changed?",
168-
pkgid.repr
169-
)
170-
}
171-
172-
let Some(package_name) =
173-
pkg_url.path_segments().and_then(|segments| segments.last())
174-
else {
175-
bail!(
176-
"malformed pkgid format: {}\n maybe the representation has changed?",
177-
pkgid.repr
178-
)
179-
};
180-
181-
Ok(Crate::Registry(RegistryCrate {
182-
name: package_name.to_string(),
183-
version: anchor.to_string(),
143+
Ok(Crate::Git(GitRepo {
144+
url: url.to_string(),
145+
sha: rev.pretty_ref(false).map(|rev| rev.to_string()),
184146
}))
185147
}
186148
} else {
187-
bail!(
188-
"malformed pkgid format: {}\n maybe the representation has changed?",
189-
pkgid.repr
190-
)
149+
bail!("Package Id with SourceKind Git should have a URL")
191150
}
192151
}
193-
(Some("git"), _) | (None, "ssh" | "git" | "http" | "https") => {
194-
let sha = if let Some(query) = query {
195-
let Some((query_kind, rev)) = query.split_once('=') else {
196-
bail!(
197-
"malformed pkgid format: {}\n maybe the representation has changed?",
198-
pkgid.repr
199-
)
200-
};
201-
match query_kind {
202-
"branch" | "tag" | "rev" => Some(rev.to_string()),
203-
_ => {
204-
bail!(
205-
"malformed pkgid format: {}\n maybe the representation has changed?",
206-
pkgid.repr
207-
)
208-
}
209-
}
210-
} else {
211-
None
212-
};
213-
214-
if pkg_url.domain() == Some("github.com") {
215-
let Some(org) = pkg_url
216-
.path_segments()
217-
.and_then(|mut segments| segments.next())
218-
else {
219-
bail!(
220-
"malformed pkgid format: {}\n maybe the representation has changed?",
221-
pkgid.repr
222-
)
223-
};
224-
225-
let name = if let Some((package_name, _version)) =
226-
anchor.and_then(|anchor| anchor.split_once(['@', ':']))
227-
{
228-
package_name
229-
} else if let Some(name) = pkg_url
230-
.path_segments()
231-
.and_then(|mut segments| segments.nth(1))
232-
{
233-
name
234-
} else {
235-
bail!(
236-
"malformed pkgid format: {}\n maybe the representation has changed?",
237-
pkgid.repr
238-
)
239-
};
240-
241-
Ok(Crate::GitHub(GitHubRepo {
242-
org: org.to_string(),
243-
name: name.to_string(),
244-
sha,
245-
}))
152+
Some(SourceKind::Path) => {
153+
if let Some(url) = package_id.url() {
154+
Ok(Crate::Path(url.path().to_string()))
246155
} else {
247-
let mut repo_url = pkg_url.clone();
248-
repo_url.set_fragment(None);
249-
repo_url.set_query(None);
250-
251-
Ok(Crate::Git(GitRepo {
252-
url: repo_url.to_string(),
253-
sha,
254-
}))
156+
bail!("Package Id with SourceKind Path should have a URL")
255157
}
256158
}
257-
_ => bail!(
258-
"malformed pkgid format: {}\n maybe the representation has changed?",
259-
pkgid.repr
260-
),
159+
Some(SourceKind::Registry | SourceKind::SparseRegistry) => {
160+
Ok(Crate::Registry(RegistryCrate {
161+
name: package_id.name().to_string(),
162+
version: package_id
163+
.version()
164+
.map(|version| version.to_string())
165+
.unwrap_or_else(|| String::from("unknown")),
166+
}))
167+
}
168+
Some(SourceKind::Directory) => {
169+
bail!("Unsupported SourceKind Directory")
170+
}
171+
None => match package_id.url() {
172+
None => Ok(Crate::Registry(RegistryCrate {
173+
name: package_id.name().to_string(),
174+
version: package_id
175+
.version()
176+
.map(|version| version.to_string())
177+
.unwrap_or_else(|| String::from("unknown")),
178+
})),
179+
Some(url) => match url.scheme() {
180+
"http" | "https" | "git" | "ssh" => {
181+
if url.domain() == Some("github.com") {
182+
Ok(Crate::GitHub(GitHubRepo {
183+
org: url
184+
.path_segments()
185+
.and_then(|mut path| path.next())
186+
.unwrap_or_default()
187+
.to_string(),
188+
name: package_id.name().to_string(),
189+
sha: None,
190+
}))
191+
} else {
192+
Ok(Crate::Git(GitRepo {
193+
url: url.to_string(),
194+
sha: None,
195+
}))
196+
}
197+
}
198+
"file" => Ok(Crate::Path(url.path().to_string())),
199+
other => {
200+
bail!(format!("Unsuported Protocol: {other}"))
201+
}
202+
},
203+
},
261204
}
262-
} else if let Some((package_name, version)) = pkgid.repr.split_once(['@', ':']) {
263-
// Cargo Package Id Spec
264-
// name ("@"|":") semver
265-
Ok(Crate::Registry(RegistryCrate {
266-
name: package_name.to_string(),
267-
version: version.to_string(),
268-
}))
269-
} else {
270-
// Cargo Package Id Spec
271-
// name only
272-
Ok(Crate::Registry(RegistryCrate {
273-
name: pkgid.repr.clone(),
274-
version: "unknown".to_string(),
275-
}))
276205
}
277206
}
278207
}
@@ -414,6 +343,10 @@ mod tests {
414343
name: "cookie".to_string(),
415344
version: "0.15.0".to_string(),
416345
}),
346+
"sparse+https://github.com/rust-lang/crates.io-index#[email protected]" => Crate::Registry(RegistryCrate {
347+
name: "cookie".to_string(),
348+
version: "0.15.0".to_string(),
349+
}),
417350
"[email protected]" => Crate::Registry(RegistryCrate {
418351
name: "regex".to_string(),
419352
version: "1.4.3".to_string(),
@@ -442,13 +375,13 @@ mod tests {
442375
"git+ssh://[email protected]/rust-lang/regex.git?branch=dev#[email protected]" => Crate::GitHub(GitHubRepo {
443376
org: "rust-lang".to_string(),
444377
name: "regex".to_string(),
445-
sha: Some("dev".to_string())
378+
sha: Some("branch=dev".to_string())
446379
}),
447380

448381
"git+https://gitlab.com/dummy_org/dummy?rev=9823f01cf4948a41279f6a3febcf793130cab4f6" => Crate::Git(GitRepo {
449-
url: "git+https://gitlab.com/dummy_org/dummy"
382+
url: "https://gitlab.com/dummy_org/dummy"
450383
.to_string(),
451-
sha: Some("9823f01cf4948a41279f6a3febcf793130cab4f6".to_string())
384+
sha: Some("rev=9823f01cf4948a41279f6a3febcf793130cab4f6".to_string())
452385
}),
453386

454387
"file:///path/to/my/project/foo" => Crate::Path("/path/to/my/project/foo".to_string()),

0 commit comments

Comments
 (0)