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 {
|
pub struct GitUpstream {
|
||||||
fn is_inside_git_repository() -> bool {
|
remote: String,
|
||||||
todo!()
|
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