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

feat: Support additional patterns for cloning #81

Merged
merged 7 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 129 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ indicatif = "0.17.1"
lazy_static = "1.4"
regex = "1.6"
serde = { version = "1.0", features = ["derive"] }
serde_regex = "1.1"
serde_with = "2.2"
tokio = { version = "1.25", features = ["macros", "rt-multi-thread"] }
toml = "0.7.2"
tracing = "0.1.37"
Expand Down
54 changes: 54 additions & 0 deletions ghr.example.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# Example configuration for ghr.
#

[defaults]
# Sets the default owner of repositories.
# You can pass only repository name to 'ghr clone' when this is set.
owner = "siketyan"

[git]
# Chooses the strategy to use on Git clones.
# 'Cli' is the default. 'Git2' is also supported, but deprecated.
strategy.clone = "Cli"

[[patterns]]
# You can use additional patterns to specify where the repository is cloned from.
# For details of regular expression syntax, see https://docs.rs/regex/latest/regex/index.html .
regex = "^(?P<scheme>https)://(?P<host>git\\.kernel\\.org)/pub/scm/linux/kernel/git/(?P<owner>.+)/(?P<repo>.+)\\.git"

# You can override parameters if those are not in or different from the pattern.
vcs = "git"
scheme = "https"
user = ""
host = "git.kernel.org"
owner = "torvalds"

# Composes URL different from the input.
# This does not work when inferring is enabled.
url = "{{scheme}}://{{host}}/pub/scm/linux/kernel/git/{{owner}}/{{repo}}.{{vcs}}"

# Turn off inferring URL to use the raw input to clone.
infer = false

[profiles.work]
# Overrides Git profile using the profile.
# You need to add rule(s) to attach this profile onto a repository.
user.name = "My Working Name"
user.email = "[email protected]"

[applications.vscode]
# You can open a repository in VS Code using `ghr open <repo> vscode`.
cmd = "code"
args = ["%p"]

[[rules]]
# 'work' profile declared above is attached on this rule.
profile.name = "work"

# This rule is applied when the repository is owned by your company on GitHub.
host = "github.com"
owner = "my-company-org"

# Optionally you can apply the rule onto a specific repo.
#repo = "company-repo"
4 changes: 3 additions & 1 deletion src/cmd/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ impl Cmd {
}

fn clone(&self, root: &Root, config: &Config, repo: &str) -> Result<CloneResult> {
let url = Url::from_str(repo, config.defaults.owner.as_deref())?;
let url = Url::from_str(repo, &config.patterns, config.defaults.owner.as_deref())?;
let path = PathBuf::from(Path::resolve(root, &url));
let profile = config
.rules
.resolve(&url)
.and_then(|r| config.profiles.resolve(&r.profile));

info!("Cloning from '{}'", url.to_string());

config.git.strategy.clone.clone_repository(
url,
&path,
Expand Down
6 changes: 5 additions & 1 deletion src/cmd/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ impl Cmd {
return Ok(());
}

let url = Url::from_str(&self.repo, config.defaults.owner.as_deref())?;
let url = Url::from_str(
&self.repo,
&config.patterns,
config.defaults.owner.as_deref(),
)?;
let path = PathBuf::from(Path::resolve(&root, &url));

Spinner::new("Deleting the repository...")
Expand Down
6 changes: 5 additions & 1 deletion src/cmd/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ impl Cmd {
let root = Root::find()?;
let config = Config::load_from(&root)?;

let url = Url::from_str(&self.repo, config.defaults.owner.as_deref())?;
let url = Url::from_str(
&self.repo,
&config.patterns,
config.defaults.owner.as_deref(),
)?;
let path = Path::resolve(&root, &url);
let profile = config
.rules
Expand Down
6 changes: 5 additions & 1 deletion src/cmd/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ impl Cmd {
let root = Root::find()?;
let config = Config::load_from(&root)?;

let url = Url::from_str(&self.repo, config.defaults.owner.as_deref())?;
let url = Url::from_str(
&self.repo,
&config.patterns,
config.defaults.owner.as_deref(),
)?;
let path = PathBuf::from(Path::resolve(&root, &url));

config
Expand Down
1 change: 1 addition & 0 deletions src/cmd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl Cmd {
let path = if let Some(repo) = self.repo.as_deref() {
let url = Url::from_str(
repo,
&config.patterns,
self.owner.as_deref().or(config.defaults.owner.as_deref()),
)?;

Expand Down
24 changes: 23 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::git::Config as GitConfig;
use crate::profile::Profiles;
use crate::root::Root;
use crate::rule::Rules;
use crate::url::Patterns;

#[derive(Debug, Default, Deserialize)]
pub struct Defaults {
Expand All @@ -22,6 +23,8 @@ pub struct Config {
#[serde(default)]
pub git: GitConfig,
#[serde(default)]
pub patterns: Patterns,
#[serde(default)]
pub profiles: Profiles,
#[serde(default)]
pub applications: Applications,
Expand All @@ -43,8 +46,27 @@ impl Config {
P: AsRef<Path>,
{
Ok(match path.as_ref().exists() {
true => Some(toml::from_str(read_to_string(path)?.as_str())?),
true => Some(Self::load_from_str(read_to_string(path)?.as_str())?),
_ => None,
})
}

fn load_from_str(s: &str) -> Result<Self> {
Ok(toml::from_str::<Self>(s)?.with_defaults())
}

fn with_defaults(mut self) -> Self {
self.patterns = self.patterns.with_defaults();
self
}
}

#[cfg(test)]
mod tests {
use crate::config::Config;

#[test]
fn load_example_config() {
Config::load_from_str(include_str!("../ghr.example.toml")).unwrap();
}
}
Loading