feat: can get commit chain
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
1b9f8b26e6
commit
a63c6ce3be
@ -163,23 +163,45 @@ 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())?;
|
||||
Some(Commands::Gitea { command }) => {
|
||||
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");
|
||||
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);
|
||||
match command {
|
||||
GiteaCommand::Connect {} => {
|
||||
client.connect(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
||||
self.ui.write_str_ln("connected succesfully go gitea");
|
||||
}
|
||||
GiteaCommand::Tags {} => {
|
||||
let tags = client
|
||||
.get_tags(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
||||
self.ui.write_str_ln("got tags from gitea");
|
||||
for tag in tags {
|
||||
self.ui.write_str_ln(&format!("- {}", tag.name))
|
||||
}
|
||||
}
|
||||
GiteaCommand::SinceCommit { sha, branch } => {
|
||||
let commits = client.get_commits_since(
|
||||
self.global.owner.unwrap(),
|
||||
self.global.repo.unwrap(),
|
||||
sha,
|
||||
branch,
|
||||
)?;
|
||||
self.ui.write_str_ln("got commits from gitea");
|
||||
for commit in commits {
|
||||
self.ui.write_str_ln(&format!("- {}", commit.get_title()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
tracing::debug!("running bare command");
|
||||
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
||||
@ -247,6 +269,14 @@ enum ConfigCommand {
|
||||
#[derive(Subcommand, Debug, Clone)]
|
||||
enum GiteaCommand {
|
||||
Connect {},
|
||||
Tags {},
|
||||
SinceCommit {
|
||||
#[arg(long)]
|
||||
sha: String,
|
||||
|
||||
#[arg(long)]
|
||||
branch: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn get_current_path(
|
||||
|
@ -55,6 +55,7 @@ impl GiteaClient {
|
||||
|
||||
if !resp.status().is_success() {
|
||||
resp.error_for_status()?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -63,20 +64,263 @@ impl GiteaClient {
|
||||
pub fn get_tags(
|
||||
&self,
|
||||
owner: impl Into<String>,
|
||||
repository: impl Into<String>,
|
||||
repo: impl Into<String>,
|
||||
) -> anyhow::Result<Vec<Tag>> {
|
||||
todo!()
|
||||
let client = self.create_client()?;
|
||||
|
||||
let request = client
|
||||
.get(format!(
|
||||
"{}/api/v1/repos/{}/{}/tags",
|
||||
&self.url.trim_end_matches("/"),
|
||||
owner.into(),
|
||||
repo.into()
|
||||
))
|
||||
.build()?;
|
||||
|
||||
let resp = client.execute(request)?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(anyhow::anyhow!(resp.error_for_status().unwrap_err()));
|
||||
}
|
||||
let tags: Vec<Tag> = resp.json()?;
|
||||
|
||||
Ok(tags)
|
||||
}
|
||||
|
||||
pub fn get_commits_since(
|
||||
&self,
|
||||
owner: impl Into<String>,
|
||||
repository: impl Into<String>,
|
||||
repo: impl Into<String>,
|
||||
since_sha: impl Into<String>,
|
||||
) -> anyhow::Result<Vec<Tag>> {
|
||||
todo!()
|
||||
branch: impl Into<String>,
|
||||
) -> anyhow::Result<Vec<Commit>> {
|
||||
let get_commits_since_page = |owner: &str,
|
||||
repo: &str,
|
||||
branch: &str,
|
||||
page: usize|
|
||||
-> anyhow::Result<(Vec<Commit>, bool)> {
|
||||
let client = self.create_client()?;
|
||||
tracing::trace!(
|
||||
owner = owner,
|
||||
repo = repo,
|
||||
branch = branch,
|
||||
page = page,
|
||||
"fetching tags"
|
||||
);
|
||||
let request = client
|
||||
.get(format!(
|
||||
"{}/api/v1/repos/{}/{}/commits?page={}&limit={}&sha={}&stat=false&verification=false&files=false",
|
||||
&self.url.trim_end_matches("/"),
|
||||
owner,
|
||||
repo,
|
||||
page,
|
||||
50,
|
||||
branch,
|
||||
))
|
||||
.build()?;
|
||||
let resp = client.execute(request)?;
|
||||
|
||||
let mut has_more = false;
|
||||
|
||||
if let Some(gitea_has_more) = resp.headers().get("X-HasMore") {
|
||||
let gitea_has_more = gitea_has_more.to_str()?;
|
||||
if gitea_has_more == "true" || gitea_has_more == "True" {
|
||||
has_more = true;
|
||||
}
|
||||
}
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(anyhow::anyhow!(resp.error_for_status().unwrap_err()));
|
||||
}
|
||||
let commits: Vec<Commit> = resp.json()?;
|
||||
|
||||
Ok((commits, has_more))
|
||||
};
|
||||
|
||||
let commits =
|
||||
self.get_commits_since_inner(owner, repo, since_sha, branch, get_commits_since_page)?;
|
||||
|
||||
Ok(commits)
|
||||
}
|
||||
|
||||
fn get_commits_since_inner<F>(
|
||||
&self,
|
||||
owner: impl Into<String>,
|
||||
repo: impl Into<String>,
|
||||
since_sha: impl Into<String>,
|
||||
branch: impl Into<String>,
|
||||
get_commits: F,
|
||||
) -> anyhow::Result<Vec<Commit>>
|
||||
where
|
||||
F: Fn(&str, &str, &str, usize) -> anyhow::Result<(Vec<Commit>, bool)>,
|
||||
{
|
||||
let mut commits = Vec::new();
|
||||
let mut page = 1;
|
||||
|
||||
let owner: String = owner.into();
|
||||
let repo: String = repo.into();
|
||||
let since_sha: String = since_sha.into();
|
||||
let branch: String = branch.into();
|
||||
let mut found_commit = false;
|
||||
loop {
|
||||
let (mut new_commits, has_more) = get_commits(&owner, &repo, &branch, page)?;
|
||||
|
||||
for commit in new_commits {
|
||||
if commit.sha.contains(&since_sha) {
|
||||
found_commit = true;
|
||||
} else {
|
||||
if !found_commit {
|
||||
commits.push(commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !has_more {
|
||||
break;
|
||||
}
|
||||
page += 1;
|
||||
}
|
||||
|
||||
if found_commit == false {
|
||||
return Err(anyhow::anyhow!(
|
||||
"sha was not found in commit chain: {} on branch: {}",
|
||||
since_sha,
|
||||
branch
|
||||
));
|
||||
}
|
||||
|
||||
Ok(commits)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct Commit {
|
||||
sha: String,
|
||||
pub created: String,
|
||||
pub commit: CommitDetails,
|
||||
}
|
||||
|
||||
impl Commit {
|
||||
pub fn get_title(&self) -> String {
|
||||
self.commit
|
||||
.message
|
||||
.split("\n")
|
||||
.take(1)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct CommitDetails {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Tag {}
|
||||
pub struct Tag {
|
||||
pub id: String,
|
||||
pub message: String,
|
||||
pub name: String,
|
||||
pub commit: TagCommit,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct TagCommit {
|
||||
created: String,
|
||||
pub sha: String,
|
||||
url: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use tracing_test::traced_test;
|
||||
|
||||
use crate::gitea_client::{Commit, CommitDetails};
|
||||
|
||||
use super::GiteaClient;
|
||||
|
||||
fn get_api_res() -> Vec<Vec<Commit>> {
|
||||
let api_results = vec![
|
||||
vec![Commit {
|
||||
sha: "first-sha".into(),
|
||||
created: "".into(),
|
||||
commit: CommitDetails {
|
||||
message: "first-message".into(),
|
||||
},
|
||||
}],
|
||||
vec![Commit {
|
||||
sha: "second-sha".into(),
|
||||
created: "".into(),
|
||||
commit: CommitDetails {
|
||||
message: "second-message".into(),
|
||||
},
|
||||
}],
|
||||
vec![Commit {
|
||||
sha: "third-sha".into(),
|
||||
created: "".into(),
|
||||
commit: CommitDetails {
|
||||
message: "third-message".into(),
|
||||
},
|
||||
}],
|
||||
];
|
||||
|
||||
api_results
|
||||
}
|
||||
|
||||
fn get_commits(sha: String) -> anyhow::Result<(Vec<Vec<Commit>>, Vec<Commit>)> {
|
||||
let api_res = get_api_res();
|
||||
let client = GiteaClient::new("", Some(""));
|
||||
|
||||
let commits = client.get_commits_since_inner(
|
||||
"owner",
|
||||
"repo",
|
||||
sha,
|
||||
"some-branch",
|
||||
|_, _, _, page| -> anyhow::Result<(Vec<Commit>, bool)> {
|
||||
let commit_page = api_res.get(page - 1).unwrap();
|
||||
|
||||
Ok((commit_page.clone(), page != 3))
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok((api_res, commits))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[traced_test]
|
||||
fn finds_tag_in_list() {
|
||||
let (expected, actual) = get_commits("second-sha".into()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
expected.get(0).unwrap().clone().as_slice(),
|
||||
actual.as_slice()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[traced_test]
|
||||
fn finds_tag_in_list_already_newest_commit() {
|
||||
let (_, actual) = get_commits("first-sha".into()).unwrap();
|
||||
|
||||
assert_eq!(0, actual.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[traced_test]
|
||||
fn finds_tag_in_list_is_base() {
|
||||
let (expected, actual) = get_commits("third-sha".into()).unwrap();
|
||||
|
||||
assert_eq!(expected[0..=1].concat().as_slice(), actual.as_slice());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[traced_test]
|
||||
fn finds_didnt_find_tag_in_list() {
|
||||
let error = get_commits("not-found-sha".into()).unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
"sha was not found in commit chain: not-found-sha on branch: some-branch",
|
||||
error.to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user