mirror of https://github.com/sgoudham/git-view.git
feat: Add MVP git-browser
Given no arguments, this version opens up the remote git repository on the main branchpull/6/head
parent
78d72cef00
commit
b46891e841
@ -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…
Reference in New Issue