feat: Add MVP git-browser

Given no arguments, this version opens up the remote git repository on
the main branch
pull/6/head
sgoudham 3 years ago
parent 78d72cef00
commit b46891e841
Signed by: hammy
GPG Key ID: 44E818FD5457EEA4

@ -0,0 +1,53 @@
use std::panic::set_hook;
use clap::{command, crate_authors, crate_description, crate_version, Arg, Command, ErrorKind};
use git_browser::GitUpstream;
macro_rules! clap_panic {
($e:expr) => {
command!().error(ErrorKind::DisplayHelp, $e).exit()
};
}
fn main() {
set_hook(Box::new(|info| clap_panic!(info)));
let matches = Command::new("git-upstream")
.version(crate_version!())
.author(crate_authors!())
.about(crate_description!())
.long_about(None)
.arg(Arg::new("branch").help("The branch to open Github repo on"))
.arg(
Arg::new("remote")
.help("The remote to open Github repo on")
.short('r')
.long("remote")
.default_value("origin"),
)
.arg(
Arg::new("commit")
.help("Open Github on the current commit")
.short('c')
.long("commit")
.conflicts_with_all(&["remote", "branch"]),
)
.arg(
Arg::new("print")
.help("Only display the URL, does not open Github")
.short('p')
.long("print"),
);
let matches = matches.get_matches();
let mut git_upstream = GitUpstream::new(
matches.value_of("branch").map(str::to_string),
matches.value_of("remote").unwrap().to_string(),
matches.is_present("commit"),
matches.is_present("print"),
);
if let Err(err) = git_upstream.open_upstream_repository() {
clap_panic!(err);
}
}

@ -1,3 +0,0 @@
fn main() {
todo!()
}

@ -1,8 +1,84 @@
struct GitRemote;
use std::process::Command;
impl GitRemote {
fn is_inside_git_repository() -> bool {
todo!()
pub struct GitUpstream {
remote: String,
branch: Option<String>,
is_commit: bool,
is_print: bool,
}
impl GitUpstream {
pub fn new(branch: Option<String>, remote: String, is_commit: bool, is_print: bool) -> Self {
Self {
remote,
branch,
is_commit,
is_print,
}
}
pub fn open_upstream_repository(&mut self) -> Result<(), String> {
// Exit out if we're not inside a git repository
self.is_inside_git_repository()?;
// Retrieve the current branch
self.populate_branch()?;
let git_url = Command::new("git")
.args(["ls-remote", "--get-url", &self.remote])
.output()
.expect("`git ls-remote --get-url <remote>`");
if git_url.status.success() {
webbrowser::open(unsafe {
trim_string(std::str::from_utf8_unchecked(&git_url.stdout))
})
.expect("Couldn't find the browser!");
} else {
return Err(unsafe { String::from_utf8_unchecked(git_url.stderr) });
}
Ok(())
}
fn populate_branch(&mut self) -> Result<(), String> {
if self.branch.is_none() {
let branch = Command::new("git")
.arg("symbolic-ref")
.arg("-q")
.arg("--short")
.arg("HEAD")
.output()
.expect("`git symbolic-ref -q --short HEAD`");
if branch.status.success() {
let branch_str = unsafe { std::str::from_utf8_unchecked(&branch.stdout) };
self.branch = Some(String::from(trim_string(branch_str)));
} else {
return Err(unsafe { String::from_utf8_unchecked(branch.stderr) });
}
}
Ok(())
}
fn is_inside_git_repository(&self) -> Result<(), String> {
let output = Command::new("git")
.arg("rev-parse")
.arg("--is-inside-work-tree")
.output()
.expect("`git rev-parse --is-inside-work-tree`");
if output.status.success() {
Ok(())
} else {
Err(String::from("Looks like you're not in a valid git repository!"))
}
}
}
fn trim_string(str: &str) -> &str {
str.trim()
.strip_suffix("\r\n")
.or_else(|| str.strip_suffix('\n'))
.unwrap_or(str)
}

Loading…
Cancel
Save