Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add version and update commands #13

Merged
merged 2 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 2 additions & 20 deletions src/git.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::utils::process_command;
use std::{
fs,
io::{Error, ErrorKind},
process::{Command, Stdio},
process::Command,
};

pub fn create_branch(branch: &str) -> Result<String, Error> {
Expand Down Expand Up @@ -66,22 +67,3 @@ pub fn get_default_branch() -> Result<String, Error> {
"Could not find the default branch.".to_string(),
))
}

fn process_command(command: &mut Command) -> Result<String, Error> {
let output = command
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()?;

if output.status.success() {
Ok(String::from_utf8(output.stdout).unwrap())
} else {
Err(Error::new(
ErrorKind::Other,
String::from_utf8(output.stderr).unwrap(),
))
}
}
33 changes: 25 additions & 8 deletions src/github.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::process;
use std::{error::Error, process};

use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, USER_AGENT};

Expand All @@ -16,7 +16,7 @@ impl<'a> Github<'a> {
Self { token, client }
}

pub async fn create_pr(&self, config: Config) -> Result<String, Box<dyn std::error::Error>> {
pub async fn create_pr(&self, config: Config) -> Result<String, Box<dyn Error>> {
let repo = git::get_current_repo()?;
let default_desc = Config::get_default_desc()?;
let base = git::get_default_branch()?;
Expand Down Expand Up @@ -53,11 +53,7 @@ impl<'a> Github<'a> {
Ok(json["html_url"].to_string())
}

pub async fn assign_to_pr(
&self,
username: &str,
number: &str,
) -> Result<(), Box<dyn std::error::Error>> {
pub async fn assign_to_pr(&self, username: &str, number: &str) -> Result<(), Box<dyn Error>> {
let repo = git::get_current_repo()?;

let body = HashMap::from([("assignees", vec![username])]);
Expand Down Expand Up @@ -85,7 +81,7 @@ impl<'a> Github<'a> {
Ok(())
}

pub async fn get_username(&self) -> Result<String, Box<dyn std::error::Error>> {
pub async fn get_username(&self) -> Result<String, Box<dyn Error>> {
let response = self
.client
.get("https://api.github.com/user")
Expand All @@ -112,3 +108,24 @@ impl<'a> Github<'a> {
headers
}
}

pub async fn get_package_latest_version() -> Result<String, Box<dyn Error>> {
let client = reqwest::Client::new();

let mut headers = HeaderMap::new();
headers.insert(USER_AGENT, HeaderValue::from_static(""));

let response = client
.get("https://api.github.com/repos/colinlienard/ghl/releases/latest")
.headers(headers)
.send()
.await?;

let text = response.text().await?;
let json: serde_json::Value = serde_json::from_str(&text)?;

let name = json["name"].as_str().unwrap().to_string();
let version = name.split('v').last().unwrap().to_string();

Ok(version)
}
145 changes: 88 additions & 57 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,37 @@
use colored::*;
use config::Config;
use github::Github;
use std::{env, process};
use home::home_dir;
use std::{env, error::Error, fs, process};
use utils::process_command;

mod config;
mod git;
mod github;
mod utils;

#[tokio::main]
async fn main() {
async fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
let arg = if args.len() > 1 { &args[1] } else { "" };

match arg {
"create" => {}
"config" => {
match Config::set_github_token() {
Ok(set) => match set {
true => println!("{}", "✔ Token set.".green()),
false => println!("{}", "Skipped.".dimmed()),
},
Err(e) => {
eprintln!("{}", e);
process::exit(1);
}
};
match Config::set_default_desc() {
Ok(set) => match set {
true => println!("{}", "✓ Default pull request description set.".green()),
false => println!("{}", "Skipped.".dimmed()),
},
Err(e) => {
eprintln!("{}", e);
process::exit(1);
}
};
return;
}
_ => {
println!("{}", "Usage".bold());
println!(" ghl [command]");
println!();
println!("{}", "Commands".bold());
println!(" help Display this message.");
println!(
" config Set the GitHub token and the default pull request description."
);
println!(" create Do the following:");
println!(" 1. Create a new branch.");
println!(" 2. Create a new commit.");
println!(" 3. Push to the remote repository.");
println!(" 4. Create a new pull request.");
println!(" 5. Assign you the pull request.");
return;
}
"pr" => pr_command().await?,
"config" => config_command()?,
"version" | "-v" => version_command().await?,
"update" | "-up" => update_command()?,
_ => help_command(),
}

Ok(())
}

async fn pr_command() -> Result<(), Box<dyn Error>> {
let github_token = Config::get_github_token().unwrap_or_else(|_| {
eprintln!("Please set the token with `ghl config`.");
process::exit(1);
});

let pr_url = create(&github_token).await.unwrap_or_else(|e| {
eprintln!("{}", e);
process::exit(1);
});

println!(
"🎉 Success! The pull request url is: {}",
pr_url.replace('"', "").bright_cyan()
);
}

async fn create(github_token: &str) -> Result<String, Box<dyn std::error::Error>> {
let config = Config::ask()?;

match Config::confirm(&config)? {
Expand All @@ -90,7 +50,7 @@ async fn create(github_token: &str) -> Result<String, Box<dyn std::error::Error>
git::push(&config.branch)?;
println!("{}", "✔ Successfully pushed.".green());

let gh = Github::new(github_token);
let gh = Github::new(&github_token);

let pr_url = gh.create_pr(config).await?;
println!("{}", "✔ Pull request created.".green());
Expand All @@ -101,5 +61,76 @@ async fn create(github_token: &str) -> Result<String, Box<dyn std::error::Error>
gh.assign_to_pr(&username, pr_number).await?;
println!("{}", "✔ Successfully assigned you.".green());

Ok(pr_url)
println!(
"🎉 Success! The pull request url is: {}",
pr_url.replace('"', "").bright_cyan()
);

Ok(())
}

fn config_command() -> Result<(), Box<dyn Error>> {
match Config::set_github_token()? {
true => println!("{}", "✔ Token set.".green()),
false => println!("{}", "Skipped.".dimmed()),
};

match Config::set_default_desc()? {
true => println!("{}", "✓ Default pull request description set.".green()),
false => println!("{}", "Skipped.".dimmed()),
};

Ok(())
}

async fn version_command() -> Result<(), Box<dyn Error>> {
let current_version = env!("CARGO_PKG_VERSION");
println!("Current version: {}", current_version);

let latest_version = github::get_package_latest_version().await?;
println!("Latest version: {}\n", latest_version);

if latest_version == current_version {
println!("{}", "You are using the latest version.".green());
} else {
println!("{}", "You can update with `ghl update`".yellow());
}

Ok(())
}

fn update_command() -> Result<(), Box<dyn Error>> {
process_command(process::Command::new("curl").args([
"-o",
"ghl",
"-L",
"https://github.com/colinlienard/ghl/releases/latest/download/ghl",
]))?;

process_command(process::Command::new("chmod").args(["+x", "ghl"]))?;

let home_dir = home_dir().unwrap();
let target_path = home_dir.join(".local/bin/ghl");
fs::rename("ghl", target_path)?;

println!("{}", "✔ Updated successfully.".green());

Ok(())
}

fn help_command() {
println!("{}", "Usage".bold());
println!(" ghl [command]");
println!();
println!("{}", "Commands".bold());
println!(" help Display this message.");
println!(" config Set the GitHub token and the default pull request description.");
println!(" create, -c Do the following:");
println!(" 1. Create a new branch.");
println!(" 2. Create a new commit.");
println!(" 3. Push to the remote repository.");
println!(" 4. Create a new pull request.");
println!(" 5. Assign you the pull request.");
println!(" version, -v Display the current and the latest version.");
println!(" update, -up Update the binary to the latest version.");
}
23 changes: 23 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::{
io::{Error, ErrorKind},
process::{Command, Stdio},
};

pub fn process_command(command: &mut Command) -> Result<String, Error> {
let output = command
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()?;

if output.status.success() {
Ok(String::from_utf8(output.stdout).unwrap())
} else {
Err(Error::new(
ErrorKind::Other,
String::from_utf8(output.stderr).unwrap(),
))
}
}