From eb74fee6be6876b86c97cdea0205ec970152358e Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 1 Aug 2020 01:38:07 +0200 Subject: Add a function to get an owner-repo pair from the Git repo remote This will allow us to accept suggestion IDs alone, without a full URL, like the following: $ git sugapply 459691747 # or $ git sugapply --remote upstream 459691747 # or $ git config github-suggestion.remote upstream $ git sugapply 459691747 We do this by extracting the pair from the remote URL. --- Cargo.lock | 10 +++++ Cargo.toml | 8 ++++ github-suggestion-config/Cargo.toml | 9 +++++ github-suggestion-config/src/lib.rs | 75 +++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 github-suggestion-config/Cargo.toml create mode 100644 github-suggestion-config/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index aa308c9..f4c3d6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,6 +264,7 @@ version = "0.0.1" dependencies = [ "git2", "github-rs", + "github-suggestion-config", "regex", "serde", "serde_json", @@ -272,6 +273,15 @@ dependencies = [ "url", ] +[[package]] +name = "github-suggestion-config" +version = "0.0.1" +dependencies = [ + "git2", + "thiserror", + "url", +] + [[package]] name = "h2" version = "0.1.26" diff --git a/Cargo.toml b/Cargo.toml index b494e8e..d5d3dd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,11 @@ serde_json = "1.0.56" tempfile = "3.1.0" thiserror = "1.0.20" url = "2.1.1" + +github-suggestion-config = { path = "github-suggestion-config" } + + +[workspace] +members = [ + "github-suggestion-config", +] diff --git a/github-suggestion-config/Cargo.toml b/github-suggestion-config/Cargo.toml new file mode 100644 index 0000000..788d00d --- /dev/null +++ b/github-suggestion-config/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "github-suggestion-config" +version = "0.0.1" +edition = "2018" + +[dependencies] +git2 = "0.13.8" +thiserror = "1.0.20" +url = "2.1.1" diff --git a/github-suggestion-config/src/lib.rs b/github-suggestion-config/src/lib.rs new file mode 100644 index 0000000..c0d97a2 --- /dev/null +++ b/github-suggestion-config/src/lib.rs @@ -0,0 +1,75 @@ +use std::str::FromStr; + +use git2::Repository; +use thiserror::Error; +use url; +use url::Url; + + +#[derive(Debug, Error)] +pub enum Error { + #[error(transparent)] + Git(#[from] git2::Error), + + #[error(transparent)] + OwnerRepo(#[from] OwnerRepoError), + + #[error("Unable to find remote '{0}'")] + NoRemote(String), +} + +#[derive(Debug, Error)] +pub enum OwnerRepoError { + #[error("Unable to parse URL")] + Url(#[from] url::ParseError), + + #[error("URL has no path")] + NoPath, + + #[error("Unable to parse owner or repo")] + NoOwnerRepo, +} + + +#[derive(Debug)] +pub struct OwnerRepo { + pub owner: String, + pub repo: String, +} + +impl FromStr for OwnerRepo { + type Err = OwnerRepoError; + + fn from_str(s: &str) -> Result { + let url = Url::parse(s)?; + let path = url.path_segments() + .ok_or(OwnerRepoError::NoPath)? + .collect::>(); + + if path.len() < 2 { + return Err(OwnerRepoError::NoOwnerRepo); + } + + Ok(OwnerRepo { + owner: path[0].to_owned(), + repo: path[1].to_owned(), + }) + } +} + +pub fn identifier_for_remote( + remote_name: Option<&str>, +) -> Result { + let repo = Repository::open(".")?; + + let remote_name = match remote_name { + Some(r) => r, + None => "origin", + }; + + let remote = repo.find_remote(remote_name)?; + let url = remote.url() + .ok_or_else(|| Error::NoRemote(remote_name.to_owned()))?; + + Ok(url.parse()?) +} -- cgit v1.2.3