Use leon for template in binstalk & detect malformed pkg-url/pkg-fmt early (#933)

Fixed #851

* Add new dep leon to crate binstalk
* Add new variant `BinstallError::Template{Parse, Render}Error`
* Use `leon::Template` in mod `bins`
* Use `leon::Template` in mod `fetchers::gh_crate_meta`
* Refactor mod `bins`: Rm unused associated fn & fields from `Context`
* Simplify unit testing in mod `fetchers::gh_crate_meta`
* Rm soft-deprecated field `fetchers::gh_crate_meta::Context::format`
  and change the `match` to resolve `archive` => `self.archive_format`.
* Make macro_rules `leon::template!` far easier to use
* Construct `leon::Template<'_>` as constant in `gh_crate_meta::hosting`
* Simplify `leon::Values` trait
   Change its method `get_value` signature to
   
   ```rust
       fn get_value(&self, key: &str) -> Option<Cow<'_, str>>;
   ```
   
   Now, `ValuesFn` also accepts non-`'static` function, but now
   `leon::Values` is only implemented for `&ValuesFn<F>` now.
   
   This makes it a little bit more cumbersome to use but I think it's a
   reasonable drawback.
* Rm `Send` bound req from `ValuesFn`
* Impl new fn `leon::Template::cast`
   for casting `Template<'s>` to `Template<'t>` where `'s: 't`
* Rename `leon::Template::has_keys` => `has_any_of_keys`
* Make checking whether format related keys are present more robust
* Optimize `GhCrateMeta::launch_baseline_find_tasks`: Skip checking all fmt ext
   if none of the format related keys ("format", "archive-format",
   "archive-suffix") are present.
* Only ret `.exe` in `PkgFmt::extensions` on windows
   by adding a new param `is_windows: bool`
* Improve debug msg in `GhCrateMeta::fetch_and_extract`
* Add warnings to `GhCrateMeta::find`
* Rm dep tinytemplate
* `impl<'s, 'rhs: 's> ops::AddAssign<&Template<'rhs>> for Template<'s>`
* `impl<'s, 'rhs: 's> ops::AddAssign<Template<'rhs>> for Template<'s>`
* `impl<'s, 'item: 's> ops::AddAssign<Item<'item>> for Template<'s>`
* `impl<'s, 'item: 's> ops::AddAssign<&Item<'item>> for Template<'s>`
* `impl<'s, 'rhs: 's> ops::Add<Template<'rhs>> for Template<'s>` (improved existing `Add` impl)
* `impl<'s, 'rhs: 's> ops::Add<&Template<'rhs>> for Template<'s>`
* `impl<'s, 'item: 's> ops::Add<Item<'item>> for Template<'s>`
* `impl<'s, 'item: 's> ops::Add<&Item<'item>> for Template<'s>`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
Co-authored-by: Félix Saparelli <felix@passcod.name>
This commit is contained in:
Jiahao XU 2023-03-26 16:11:10 +11:00 committed by GitHub
parent 47d4aeaa96
commit a27d5aebf6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 512 additions and 312 deletions

View file

@ -1,4 +1,5 @@
use itertools::Itertools;
use leon::{template, Item, Template};
use url::Url;
use crate::errors::BinstallError;
@ -14,20 +15,63 @@ pub enum RepositoryHost {
/// Make sure to update possible_dirs in `bins::infer_bin_dir_template`
/// if you modified FULL_FILENAMES or NOVERSION_FILENAMES.
pub const FULL_FILENAMES: &[&str] = &[
"{ name }-{ target }-v{ version }{ archive-suffix }",
"{ name }-{ target }-{ version }{ archive-suffix }",
"{ name }-{ version }-{ target }{ archive-suffix }",
"{ name }-v{ version }-{ target }{ archive-suffix }",
"{ name }_{ target }_v{ version }{ archive-suffix }",
"{ name }_{ target }_{ version }{ archive-suffix }",
"{ name }_{ version }_{ target }{ archive-suffix }",
"{ name }_v{ version }_{ target }{ archive-suffix }",
pub const FULL_FILENAMES: &[Template<'_>] = &[
template!("/", { "name" }, "-", { "target" }, "-v", { "version" }, {
"archive-suffix"
}),
template!("/", { "name" }, "-", { "target" }, "-", { "version" }, {
"archive-suffix"
}),
template!("/", { "name" }, "-", { "version" }, "-", { "target" }, {
"archive-suffix"
}),
template!("/", { "name" }, "-v", { "version" }, "-", { "target" }, {
"archive-suffix"
}),
template!("/", { "name" }, "_", { "target" }, "_v", { "version" }, {
"archive-suffix"
}),
template!("/", { "name" }, "_", { "target" }, "_", { "version" }, {
"archive-suffix"
}),
template!("/", { "name" }, "_", { "version" }, "_", { "target" }, {
"archive-suffix"
}),
template!("/", { "name" }, "_v", { "version" }, "_", { "target" }, {
"archive-suffix"
}),
];
pub const NOVERSION_FILENAMES: &[&str] = &[
"{ name }-{ target }{ archive-suffix }",
"{ name }_{ target }{ archive-suffix }",
pub const NOVERSION_FILENAMES: &[Template<'_>] = &[
template!("/", { "name" }, "-", { "target" }, { "archive-suffix" }),
template!("/", { "name" }, "_", { "target" }, { "archive-suffix" }),
];
const GITHUB_RELEASE_PATHS: &[Template<'_>] = &[
template!({ "repo" }, "/releases/download/", { "version" }),
template!({ "repo" }, "/releases/download/v", { "version" }),
];
const GITLAB_RELEASE_PATHS: &[Template<'_>] = &[
template!(
{ "repo" },
"/-/releases/",
{ "version" },
"/downloads/binaries"
),
template!(
{ "repo" },
"/-/releases/v",
{ "version" },
"/downloads/binaries"
),
];
const BITBUCKET_RELEASE_PATHS: &[Template<'_>] = &[template!({ "repo" }, "/downloads")];
const SOURCEFORGE_RELEASE_PATHS: &[Template<'_>] = &[
template!({ "repo" }, "/files/binaries/", { "version" }),
template!({ "repo" }, "/files/binaries/v", { "version" }),
];
impl RepositoryHost {
@ -45,36 +89,27 @@ impl RepositoryHost {
pub fn get_default_pkg_url_template(
self,
) -> Option<impl Iterator<Item = String> + Clone + 'static> {
) -> Option<impl Iterator<Item = Template<'static>> + Clone + 'static> {
use RepositoryHost::*;
match self {
GitHub => Some(apply_filenames_to_paths(
&[
"{ repo }/releases/download/{ version }",
"{ repo }/releases/download/v{ version }",
],
GITHUB_RELEASE_PATHS,
&[FULL_FILENAMES, NOVERSION_FILENAMES],
"",
)),
GitLab => Some(apply_filenames_to_paths(
&[
"{ repo }/-/releases/{ version }/downloads/binaries",
"{ repo }/-/releases/v{ version }/downloads/binaries",
],
GITLAB_RELEASE_PATHS,
&[FULL_FILENAMES, NOVERSION_FILENAMES],
"",
)),
BitBucket => Some(apply_filenames_to_paths(
&["{ repo }/downloads"],
BITBUCKET_RELEASE_PATHS,
&[FULL_FILENAMES],
"",
)),
SourceForge => Some(apply_filenames_to_paths(
&[
"{ repo }/files/binaries/{ version }",
"{ repo }/files/binaries/v{ version }",
],
SOURCEFORGE_RELEASE_PATHS,
&[FULL_FILENAMES, NOVERSION_FILENAMES],
"/download",
)),
@ -84,13 +119,17 @@ impl RepositoryHost {
}
fn apply_filenames_to_paths(
paths: &'static [&'static str],
filenames: &'static [&'static [&'static str]],
paths: &'static [Template<'static>],
filenames: &'static [&'static [Template<'static>]],
suffix: &'static str,
) -> impl Iterator<Item = String> + Clone + 'static {
) -> impl Iterator<Item = Template<'static>> + Clone + 'static {
filenames
.iter()
.flat_map(|fs| fs.iter())
.cartesian_product(paths.iter())
.map(move |(filename, path)| format!("{path}/{filename}{suffix}"))
.map(move |(filename, path)| {
let mut template = path.clone() + filename;
template += Item::Text(suffix);
template
})
}