feat(package): implement gitlab package provider

This commit is contained in:
Federico Terzi 2021-09-06 22:37:14 +02:00
parent db77e9617a
commit d86c6f7c46
5 changed files with 138 additions and 10 deletions

View File

@ -51,8 +51,15 @@ pub fn get_provider(package: &PackageSpecifier, runtime_dir: &Path, options: &Pr
true true
} else if let Some(gitlab_parts) = util::gitlab::extract_gitlab_url_parts(git_repo_url) { } else if let Some(gitlab_parts) = util::gitlab::extract_gitlab_url_parts(git_repo_url) {
panic!("GitLab is not supported yet!"); if let Some(repo_scheme) =
todo!(); util::gitlab::resolve_repo_scheme(gitlab_parts, package.git_branch.as_deref())?
{
return Ok(Box::new(provider::gitlab::GitLabPackageProvider::new(
repo_scheme.author,
repo_scheme.name,
repo_scheme.branch,
)));
}
true true
} else { } else {
@ -64,7 +71,7 @@ pub fn get_provider(package: &PackageSpecifier, runtime_dir: &Path, options: &Pr
// available to non-authenticated requests), so we check if a "git ls-remote" command // available to non-authenticated requests), so we check if a "git ls-remote" command
// is able to access it. // is able to access it.
if matches_known_hosts && !util::git::is_private_repo(git_repo_url) { if matches_known_hosts && !util::git::is_private_repo(git_repo_url) {
bail!("could not access repository: {}, make sure it exists and that you have the necessary access rights."); bail!("could not access repository: {}, make sure it exists and that you have the necessary access rights.", git_repo_url);
} }
} }

View File

@ -0,0 +1,68 @@
/*
* This file is part of espanso.
*
* Copyright (C) 2019-2021 Federico Terzi
*
* espanso is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* espanso is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::{
package::DefaultPackage, resolver::resolve_package, Package, PackageSpecifier,
};
use anyhow::{Result};
use super::PackageProvider;
pub struct GitLabPackageProvider {
repo_author: String,
repo_name: String,
repo_branch: String,
}
impl GitLabPackageProvider {
pub fn new(repo_author: String, repo_name: String, repo_branch: String) -> Self {
Self {
repo_author,
repo_name,
repo_branch,
}
}
}
impl PackageProvider for GitLabPackageProvider {
fn name(&self) -> String {
"gitlab".to_string()
}
fn download(&self, package: &PackageSpecifier) -> Result<Box<dyn Package>> {
let download_url = format!(
"https://gitlab.com/{}/{}/-/archive/{}/{}-{}.zip",
&self.repo_author, &self.repo_name, &self.repo_branch, &self.repo_name, &self.repo_branch
);
let temp_dir = tempdir::TempDir::new("espanso-package-download")?;
crate::util::download::download_and_extract_zip(&download_url, temp_dir.path())?;
let resolved_package =
resolve_package(temp_dir.path(), &package.name, package.version.as_deref())?;
let package = DefaultPackage::new(
resolved_package.manifest,
temp_dir,
resolved_package.base_dir,
);
Ok(Box::new(package))
}
}

View File

@ -24,6 +24,7 @@ use crate::Package;
pub(crate) mod hub; pub(crate) mod hub;
pub(crate) mod git; pub(crate) mod git;
pub(crate) mod github; pub(crate) mod github;
pub(crate) mod gitlab;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct PackageSpecifier { pub struct PackageSpecifier {

View File

@ -59,6 +59,14 @@ pub fn resolve_repo_scheme(parts: GitHubParts, force_branch: Option<&str>) -> Re
})) }))
} }
} else { } else {
if check_repo_with_branch(&parts, "main")? {
return Ok(Some(ResolvedRepoScheme {
author: parts.author,
name: parts.name,
branch: "main".to_string(),
}));
}
if check_repo_with_branch(&parts, "master")? { if check_repo_with_branch(&parts, "master")? {
return Ok(Some(ResolvedRepoScheme { return Ok(Some(ResolvedRepoScheme {
author: parts.author, author: parts.author,
@ -67,13 +75,6 @@ pub fn resolve_repo_scheme(parts: GitHubParts, force_branch: Option<&str>) -> Re
})); }));
} }
if check_repo_with_branch(&parts, "main")? {
return Ok(Some(ResolvedRepoScheme {
author: parts.author,
name: parts.name,
branch: "main".to_string(),
}));
}
} }
Ok(None) Ok(None)

View File

@ -19,6 +19,8 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
use anyhow::Result;
use reqwest::StatusCode;
lazy_static! { lazy_static! {
static ref GITLAB_REGEX: Regex = Regex::new(r"(https://gitlab.com/|git@gitlab.com:)(?P<author>.*?)/(?P<name>.*?)(/|\.|$)").unwrap(); static ref GITLAB_REGEX: Regex = Regex::new(r"(https://gitlab.com/|git@gitlab.com:)(?P<author>.*?)/(?P<name>.*?)(/|\.|$)").unwrap();
@ -41,6 +43,55 @@ pub fn extract_gitlab_url_parts(url: &str) -> Option<GitLabParts> {
}) })
} }
pub struct ResolvedRepoScheme {
pub author: String,
pub name: String,
pub branch: String,
}
pub fn resolve_repo_scheme(parts: GitLabParts, force_branch: Option<&str>) -> Result<Option<ResolvedRepoScheme>> {
if let Some(force_branch) = force_branch {
if check_repo_with_branch(&parts, force_branch)? {
return Ok(Some(ResolvedRepoScheme {
author: parts.author,
name: parts.name,
branch: force_branch.to_string(),
}))
}
} else {
if check_repo_with_branch(&parts, "main")? {
return Ok(Some(ResolvedRepoScheme {
author: parts.author,
name: parts.name,
branch: "main".to_string(),
}));
}
if check_repo_with_branch(&parts, "master")? {
return Ok(Some(ResolvedRepoScheme {
author: parts.author,
name: parts.name,
branch: "master".to_string(),
}));
}
}
Ok(None)
}
pub fn check_repo_with_branch(parts: &GitLabParts, branch: &str) -> Result<bool> {
let client = reqwest::blocking::Client::new();
let url = generate_gitlab_download_url(parts, branch);
let response = client.head(url).send()?;
Ok(response.status() == StatusCode::OK)
}
fn generate_gitlab_download_url(parts: &GitLabParts, branch: &str) -> String {
format!("https://gitlab.com/{}/{}/-/archive/{}/{}-{}.zip", parts.author, parts.name, branch, parts.name, branch)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;