feat: with gitea client

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2023-07-30 01:39:28 +02:00
parent 51115dc7fd
commit 5876ed847c
7 changed files with 762 additions and 8 deletions

View File

@@ -12,6 +12,8 @@ clap.workspace = true
dotenv.workspace = true
serde_yaml.workspace = true
serde.workspace = true
reqwest = {workspace = true, features = ["blocking", "json"]}
url.workspace = true
[dev-dependencies]
tracing-test = {workspace = true, features = ["no-env-filter"]}

View File

@@ -11,6 +11,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
git_client::VcsClient,
gitea_client::GiteaClient,
ui::{ConsoleUi, DynUi},
};
@@ -42,12 +43,20 @@ struct GlobalArgs {
)]
token: Option<String>,
/// Which repository to publish against. If not supplied remote url will be used.
#[arg(long, global = true, group = "global", help_heading = "Global")]
repo_url: Option<String>,
/// Which repository to publish against. If not supplied remote url will be inferred from environment or fail if not present.
#[arg(long, global = true, help_heading = "Global")]
api_url: Option<String>,
/// repo is the name of repository you want to release for
#[arg(long, global = true, help_heading = "Global")]
repo: Option<String>,
/// owner is the name of user from which the repository belongs <user>/<repo>
#[arg(long, global = true, help_heading = "Global")]
owner: Option<String>,
/// which source directory to use, if not set `std::env::current_dir` is used instead.
#[arg(long, global = true, group = "global", help_heading = "Global")]
#[arg(long, global = true, help_heading = "Global")]
source: Option<PathBuf>,
/// no version control system, forces please to allow no .git/ or friends
@@ -151,6 +160,23 @@ impl Command {
self.ui.write_str_ln(&format!("cuddle-config"));
}
},
Some(Commands::Gitea { command }) => match command {
GiteaCommand::Connect {} => {
let git_url = url::Url::parse(&self.global.api_url.unwrap())?;
let mut url = String::new();
url.push_str(git_url.scheme());
url.push_str("://");
url.push_str(&git_url.host().unwrap().to_string());
if let Some(port) = git_url.port() {
url.push_str(format!(":{port}").as_str());
}
let client = GiteaClient::new(url, self.global.token);
client.connect(self.global.owner.unwrap(), self.global.repo.unwrap())?;
self.ui.write_str_ln("connected succesfully go gitea");
}
},
None => {
tracing::debug!("running bare command");
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
@@ -195,13 +221,24 @@ enum Commands {
#[command(subcommand)]
command: ConfigCommand,
},
Gitea {
#[command(subcommand)]
command: GiteaCommand,
},
}
#[derive(Subcommand, Debug, Clone)]
enum ConfigCommand {
/// List will list the final configuration
List {},
}
#[derive(Subcommand, Debug, Clone)]
enum GiteaCommand {
Connect {},
}
fn get_current_path(
optional_current_dir: Option<&Path>,
optional_source_path: Option<PathBuf>,

View File

@@ -1 +1,82 @@
use reqwest::header::{HeaderMap, HeaderValue};
use serde::{Deserialize, Serialize};
#[allow(dead_code)]
pub struct GiteaClient {
url: String,
token: Option<String>,
pub allow_insecure: bool,
}
const APP_USER_AGENT: &'static str =
concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
impl GiteaClient {
pub fn new(url: impl Into<String>, token: Option<impl Into<String>>) -> Self {
Self {
url: url.into(),
token: token.map(|t| t.into()),
allow_insecure: false,
}
}
fn create_client(&self) -> anyhow::Result<reqwest::blocking::Client> {
let cb = reqwest::blocking::ClientBuilder::new();
let mut header_map = HeaderMap::new();
if let Some(token) = &self.token {
header_map.insert(
"Authorization",
HeaderValue::from_str(format!("token {}", token).as_str())?,
);
}
let client = cb
.user_agent(APP_USER_AGENT)
.default_headers(header_map)
.danger_accept_invalid_certs(self.allow_insecure)
.build()?;
Ok(client)
}
pub fn connect(&self, owner: impl Into<String>, repo: impl Into<String>) -> anyhow::Result<()> {
let client = self.create_client()?;
let request = client
.get(format!(
"{}/api/v1/repos/{}/{}",
&self.url.trim_end_matches("/"),
owner.into(),
repo.into()
))
.build()?;
let resp = client.execute(request)?;
if !resp.status().is_success() {
resp.error_for_status()?;
}
Ok(())
}
pub fn get_tags(
&self,
owner: impl Into<String>,
repository: impl Into<String>,
) -> anyhow::Result<Vec<Tag>> {
todo!()
}
pub fn get_commits_since(
&self,
owner: impl Into<String>,
repository: impl Into<String>,
since_sha: impl Into<String>,
) -> anyhow::Result<Vec<Tag>> {
todo!()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Tag {}

View File

@@ -5,8 +5,7 @@ pub mod ui;
use command::Command;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
tracing_subscriber::fmt::init();

View File

@@ -16,6 +16,7 @@ impl Default for DynUi {
pub(crate) struct ConsoleUi {}
#[allow(dead_code)]
impl ConsoleUi {
pub fn new() -> Self {
Self::default()