feat: can get commit chain
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
1b9f8b26e6
commit
a63c6ce3be
@ -163,8 +163,7 @@ impl Command {
|
|||||||
self.ui.write_str_ln(&format!("cuddle-config"));
|
self.ui.write_str_ln(&format!("cuddle-config"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(Commands::Gitea { command }) => match command {
|
Some(Commands::Gitea { command }) => {
|
||||||
GiteaCommand::Connect {} => {
|
|
||||||
let git_url = url::Url::parse(&self.global.api_url.unwrap())?;
|
let git_url = url::Url::parse(&self.global.api_url.unwrap())?;
|
||||||
|
|
||||||
let mut url = String::new();
|
let mut url = String::new();
|
||||||
@ -176,10 +175,33 @@ impl Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let client = GiteaClient::new(url, self.global.token);
|
let client = GiteaClient::new(url, self.global.token);
|
||||||
|
match command {
|
||||||
|
GiteaCommand::Connect {} => {
|
||||||
client.connect(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
client.connect(self.global.owner.unwrap(), self.global.repo.unwrap())?;
|
||||||
self.ui.write_str_ln("connected succesfully go gitea");
|
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 => {
|
None => {
|
||||||
tracing::debug!("running bare command");
|
tracing::debug!("running bare command");
|
||||||
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
// 2. Parse the cuddle.please.yaml let cuddle.please.yaml take precedence
|
||||||
@ -247,6 +269,14 @@ enum ConfigCommand {
|
|||||||
#[derive(Subcommand, Debug, Clone)]
|
#[derive(Subcommand, Debug, Clone)]
|
||||||
enum GiteaCommand {
|
enum GiteaCommand {
|
||||||
Connect {},
|
Connect {},
|
||||||
|
Tags {},
|
||||||
|
SinceCommit {
|
||||||
|
#[arg(long)]
|
||||||
|
sha: String,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
branch: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_path(
|
fn get_current_path(
|
||||||
|
@ -55,6 +55,7 @@ impl GiteaClient {
|
|||||||
|
|
||||||
if !resp.status().is_success() {
|
if !resp.status().is_success() {
|
||||||
resp.error_for_status()?;
|
resp.error_for_status()?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -63,20 +64,263 @@ impl GiteaClient {
|
|||||||
pub fn get_tags(
|
pub fn get_tags(
|
||||||
&self,
|
&self,
|
||||||
owner: impl Into<String>,
|
owner: impl Into<String>,
|
||||||
repository: impl Into<String>,
|
repo: impl Into<String>,
|
||||||
) -> anyhow::Result<Vec<Tag>> {
|
) -> 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(
|
pub fn get_commits_since(
|
||||||
&self,
|
&self,
|
||||||
owner: impl Into<String>,
|
owner: impl Into<String>,
|
||||||
repository: impl Into<String>,
|
repo: impl Into<String>,
|
||||||
since_sha: impl Into<String>,
|
since_sha: impl Into<String>,
|
||||||
) -> anyhow::Result<Vec<Tag>> {
|
branch: impl Into<String>,
|
||||||
todo!()
|
) -> 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)]
|
#[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