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

Feature/push and open pr #2

Merged
merged 10 commits into from
Nov 4, 2021
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Add fmt and clippy
run: rustup component add rustfmt clippy
- uses: dtolnay/rust-toolchain@1.51.0
with:
components: clippy, rustfmt
- name: Print rust version
run: rustup show
- name: Print clippy version
run: cargo clippy --version
- name: Lint
run: make lint
- name: Run tests
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[package]
name = "gitopen"
version = "0.1.0"
version = "1.1.0"
authors = ["oren0e <none>"]
edition = "2018"

[dependencies]
webbrowser = "0.5.5"
anyhow = "1.0.44"
regex = "1.5.4"
clap = "2.33.3"
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@ Note: You have to have rust installed with cargo to be able to install this util

# Usage

When in git repository in terminal, run `gitopen`.
There are 2 basic usages:

- When in git repository in terminal, run `gitopen`.
- After you've opened a branch and you are ready to push and open a PR, run `gitopen -p`. This will push the changes to the current branch and open the PR in the browser.

For help, use `gitopen --help`
74 changes: 74 additions & 0 deletions src/actions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::match_logic::parse_url_from_git;
use anyhow::anyhow;
use anyhow::Result as AnyhowResult;
use regex::Regex;
use std::process::{Command, Stdio};

pub fn open_repo() -> AnyhowResult<()> {
let git_repo = Command::new("git")
.args(&["config", "--get", "remote.origin.url"])
.stdout(Stdio::piped())
.output()?;

let stdout = String::from_utf8(git_repo.stdout)?;
let parsed_url = parse_url_from_git(stdout)?;
webbrowser::open(&parsed_url)?;
Ok(())
}

pub fn push_and_open_pr() -> AnyhowResult<()> {
let current_branch = Command::new("git")
.args(&["branch", "--show-current"])
.stdout(Stdio::piped())
.output()?;
let current_branch_text = &String::from_utf8(current_branch.stdout)?;
let current_branch_text_stripped = current_branch_text.trim();
let output_from_push = Command::new("git")
.args(&["push", "origin", &current_branch_text_stripped])
.stderr(Stdio::piped())
.output()?;
let pr_re = Regex::new(&format!(
r"remote:.*(https.*{}).*\n",
current_branch_text_stripped
))?;
let output_from_push_text = String::from_utf8(output_from_push.stderr)?;
println!("{:?}", &output_from_push_text);
let captured = pr_re
.captures(&output_from_push_text)
.ok_or_else(|| anyhow!("Error capturing PR url"))?;
println!("{:?}", &captured[1]);
webbrowser::open(&captured[1])?;
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_correct_pr_parsing_from_output() {
let output = r#"Counting objects: 4, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 3.01 KiB | 3.01 MiB/s, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote:
remote: Create a pull request for 'feat/add-more-pokemons' on GitHub by visiting:
remote: /~https://github.com/tobiasbueschel/awesome-pokemon/pull/new/feat/add-more-pokemons
remote:
To github.com:tobiasbueschel/awesome-pokemon.git
* [new branch] feat/add-more-pokemons -> feat/add-more-pokemons"#;
let current_branch = "feat/add-more-pokemons\n";
let current_branch_text_stripped = current_branch.trim();
let re = Regex::new(&format!(
r"remote:.*(https.*{}).*\n",
current_branch_text_stripped
))
.unwrap();
let captured = re.captures(&output).unwrap();
println!("{:?}", &captured[1]);
assert!(&captured[1].starts_with("https"));
assert!(&captured[1].ends_with("add-more-pokemons"));
}
}
34 changes: 23 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
use crate::match_logic::parse_url_from_git;
extern crate clap;
use clap::{crate_version, App, Arg};

use crate::actions::{open_repo, push_and_open_pr};
use anyhow::Result as AnyhowResult;
use std::process::{Command, Stdio};

mod actions;
mod match_logic;

fn main() -> AnyhowResult<()> {
let git_repo = Command::new("git")
.args(&["config", "--get", "remote.origin.url"])
.stdout(Stdio::piped())
.output()?;

let stdout = String::from_utf8(git_repo.stdout)?;
let parsed_url = parse_url_from_git(stdout)?;
webbrowser::open(&parsed_url)?;
Ok(())
let matches = App::new("Gitopen")
.version(crate_version!())
.author("Oren Epshtain")
.about("Utility to open repo from terminal and pull requests after push")
.arg(
Arg::with_name("push_and_pr")
.short("p")
.long("push-open-pr")
.help("Pushes to current branch and opens corresponding PR"),
)
.get_matches();
if matches.is_present("push_and_pr") {
push_and_open_pr()?;
Ok(())
} else {
open_repo()?;
Ok(())
}
}