Explode out even more variants of default download URLs (#329)

This commit is contained in:
Félix Saparelli 2022-09-02 16:00:46 +12:00 committed by GitHub
parent b330a18d40
commit 0cb4c993b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 90 deletions

View file

@ -55,80 +55,61 @@ The default value for `pkg-url` will depend on the repository of the package.
It is setup to work with github releases, gitlab releases, bitbucket downloads
and source forge downloads.
#### Github
If your package already uses any of these URLs, you shouldn't need to set anything.
For github, the `pkg-url` is set to
The URLs are derived from a set of filenames and a set of paths, which are
"multiplied together": every filename appended to every path. The filenames
are:
```rust
[
"{ repo }/releases/download/v{ version }/{ name }-{ target }-v{ version }.{ archive-format }",
"{ repo }/releases/download/v{ version }/{ name }-v{ version }-{ target }.{ archive-format }",
"{ repo }/releases/download/v{ version }/{ name }-{ version }-{ target }.{ archive-format }",
"{ repo }/releases/download/v{ version }/{ name }-{ target }.{ archive-format }",
]
```
- `{ name }-{ target }-{ version }.{ archive-format }`
- `{ name }-{ target }-v{ version }.{ archive-format }`
- `{ name }-{ version }-{ target }.{ archive-format }`
- `{ name }-v{ version }-{ target }.{ archive-format }`
- `{ name }-{ version }-{ target }.{ archive-format }`
- `{ name }-v{ version }-{ target }.{ archive-format }`
- `{ name }-{ target }.{ archive-format }` ("versionless")
The first 3 versions does not overwrite different targets or versions when manually downloaded.
The paths are:
All `pkg-url` templates download binaries located at `{ repo }/releases/download/v{ version }/`, which
is compatible with github tags / releases.
#### for GitHub
If your package already uses this approach, you shouldn't need to set anything.
- `{ repo }/releases/download/{ version }/`
- `{ repo }/releases/download/v{ version }/`
#### GitLab
#### for GitLab
For gitlab, the `pkg-url` is set to
- `{ repo }/-/releases/{ version }/downloads/binaries/`
- `{ repo }/-/releases/v{ version }/downloads/binaries/`
```rust
[
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-{ target }-v{ version }.{ archive-format }",
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-v{ version }-{ target }.{ archive-format }",
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-{ version }-{ target }.{ archive-format }",
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-{ target }.{ archive-format }",
]
```
Note that this uses the [Permanent links to release assets][gitlab-permalinks]
feature of GitLab EE: it requires you to create an asset as a link with a
`filepath`, which, as of writing, can only be set using GitLab's API.
This will attempt to find the release assets with `filepath` set to
`binaries/{ name }-{ target }.{ archive-format }`
[gitlab-permalinks]: https://docs.gitlab.com/ee/user/project/releases/index.html#permanent-links-to-latest-release-assets
Note that this uses the [Permanent links to release assets](https://gitlab.kitware.com/help/user/project/releases/index#permanent-links-to-latest-release-assets) feature of gitlab, it requires you to
create an asset as a link with a `filepath`, which can be set only using gitlab api as of the writing.
#### for BitBucket
#### BitBucket
- `{ repo }/downloads/`
For bitbucket, the `pkg-url` is set to
Binaries must be uploaded into the project's "Downloads" page on BitBucket.
```rust
[
"{ repo }/downloads/{ name }-{ target }-v{ version }.{ archive-format }",
"{ repo }/downloads/{ name }-v{ version }-{ target }.{ archive-format }",
"{ repo }/downloads/{ name }-{ version }-{ target }.{ archive-format }",
]
```
Also note that as there are no per-release downloads, the "versionless"
filename is not considered here.
To setup the package for binstall, upload the binary into bitbucket downloads page of your project,
with its name set to be `{ name }-{ target }-v{ version }.{ archive-format }`.
#### for SourceForge
#### SourceForge
- `{ repo }/files/binaries/{ version }`
- `{ repo }/files/binaries/v{ version }`
For source forge, the `pkg-url` is set to
The URLs also have `/download` appended as per SourceForge's schema.
```rust
[
"{ repo }/files/binaries/v{ version }/{ name }-{ target }-v{ version }.{ archive-format }/download",
"{ repo }/files/binaries/v{ version }/{ name }-v{ version }-{ target }.{ archive-format }/download",
"{ repo }/files/binaries/v{ version }/{ name }-{ version }-{ target }.{ archive-format }/download",
"{ repo }/files/binaries/v{ version }/{ name }-{ target }.{ archive-format }/download",
]
```
To setup the package for binstall, upload the binary to the file page of your project,
under the directory `binaries/v{ version }` with the filename `{ name }-{ target }.{ archive-format }`.
Binary must be uploaded to the "File" page of your project, under the directory
`binaries/v{ version }`.
#### Others
For all other situations, `binstall` does not provide a default `pkg-url` and you need to manually
specify it.
For all other situations, `binstall` does not provide a default `pkg-url` and
you need to manually specify it.
### QuickInstall

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, path::Path, sync::Arc};
use std::{path::Path, sync::Arc};
use compact_str::{CompactString, ToCompactString};
use futures_util::stream::{FuturesUnordered, StreamExt};
@ -23,7 +23,7 @@ use crate::{
use super::Data;
mod hosting;
use hosting::GitHostingServices;
use hosting::RepositoryHost;
pub struct GhCrateMeta {
client: Client,
@ -86,13 +86,13 @@ impl super::Fetcher for GhCrateMeta {
None
};
let pkg_urls = if let Some(pkg_url) = self.data.meta.pkg_url.as_deref() {
Cow::Owned(vec![pkg_url])
let pkg_urls = if let Some(pkg_url) = self.data.meta.pkg_url.clone() {
vec![pkg_url]
} else if let Some(repo) = repo.as_ref() {
if let Some(pkg_urls) =
GitHostingServices::guess_git_hosting_services(repo)?.get_default_pkg_url_template()
RepositoryHost::guess_git_hosting_services(repo)?.get_default_pkg_url_template()
{
Cow::Borrowed(pkg_urls)
pkg_urls
} else {
warn!(
concat!(

View file

@ -3,16 +3,17 @@ use url::Url;
use crate::errors::BinstallError;
#[derive(Copy, Clone, Debug)]
pub enum GitHostingServices {
pub enum RepositoryHost {
GitHub,
GitLab,
BitBucket,
SourceForge,
Unknown,
}
impl GitHostingServices {
impl RepositoryHost {
pub fn guess_git_hosting_services(repo: &Url) -> Result<Self, BinstallError> {
use GitHostingServices::*;
use RepositoryHost::*;
match repo.domain() {
Some(domain) if domain.starts_with("github") => Ok(GitHub),
@ -23,34 +24,60 @@ impl GitHostingServices {
}
}
pub fn get_default_pkg_url_template(self) -> Option<&'static [&'static str]> {
use GitHostingServices::*;
pub fn get_default_pkg_url_template(self) -> Option<Vec<String>> {
use RepositoryHost::*;
let full_filenames = &[
"{ name }-{ target }-v{ version }.{ archive-format }",
"{ name }-{ target }-{ version }.{ archive-format }",
"{ name }-{ version }-{ target }.{ archive-format }",
"{ name }-v{ version }-{ target }.{ archive-format }",
"{ name }-{ version }-{ target }.{ archive-format }",
"{ name }-v{ version }-{ target }.{ archive-format }",
];
let noversion_filenames = &["{ name }-{ target }.{ archive-format }"];
match self {
GitHub => Some(&[
"{ repo }/releases/download/v{ version }/{ name }-{ target }-v{ version }.{ archive-format }",
"{ repo }/releases/download/v{ version }/{ name }-v{ version }-{ target }.{ archive-format }",
"{ repo }/releases/download/v{ version }/{ name }-{ version }-{ target }.{ archive-format }",
"{ repo }/releases/download/v{ version }/{ name }-{ target }.{ archive-format }",
]),
GitLab => Some(&[
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-{ target }-v{ version }.{ archive-format }",
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-v{ version }-{ target }.{ archive-format }",
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-{ version }-{ target }.{ archive-format }",
"{ repo }/-/releases/v{ version }/downloads/binaries/{ name }-{ target }.{ archive-format }",
]),
BitBucket => Some(&[
"{ repo }/downloads/{ name }-{ target }-v{ version }.{ archive-format }",
"{ repo }/downloads/{ name }-v{ version }-{ target }.{ archive-format }",
"{ repo }/downloads/{ name }-{ version }-{ target }.{ archive-format }",
]),
SourceForge => Some(&[
"{ repo }/files/binaries/v{ version }/{ name }-{ target }-v{ version }.{ archive-format }/download",
"{ repo }/files/binaries/v{ version }/{ name }-v{ version }-{ target }.{ archive-format }/download",
"{ repo }/files/binaries/v{ version }/{ name }-{ version }-{ target }.{ archive-format }/download",
"{ repo }/files/binaries/v{ version }/{ name }-{ target }.{ archive-format }/download",
]),
Unknown => None,
GitHub => Some(apply_filenames_to_paths(
&[
"{ repo }/releases/download/{ version }",
"{ repo }/releases/download/v{ version }",
],
&[full_filenames, noversion_filenames],
)),
GitLab => Some(apply_filenames_to_paths(
&[
"{ repo }/-/releases/{ version }/downloads/binaries",
"{ repo }/-/releases/v{ version }/downloads/binaries",
],
&[full_filenames, noversion_filenames],
)),
BitBucket => Some(apply_filenames_to_paths(
&["{ repo }/downloads"],
&[full_filenames],
)),
SourceForge => Some(
apply_filenames_to_paths(
&[
"{ repo }/files/binaries/{ version }",
"{ repo }/files/binaries/v{ version }",
],
&[full_filenames, noversion_filenames],
)
.into_iter()
.map(|url| format!("{url}/download"))
.collect(),
),
Unknown => None,
}
}
}
fn apply_filenames_to_paths(paths: &[&str], filenames: &[&[&str]]) -> Vec<String> {
filenames
.iter()
.flat_map(|fs| fs.iter())
.flat_map(|filename| paths.iter().map(move |path| format!("{path}/{filename}")))
.collect()
}

View file

@ -25,7 +25,7 @@ where
block_in_place(move || {
fs::create_dir_all(path.parent().unwrap())?;
let mut file = fs::File::create(&path)?;
let mut file = fs::File::create(path)?;
// remove it unless the operation isn't aborted and no write
// fails.