Skip to content

Commit

Permalink
feat!: add option to clone repo on creation
Browse files Browse the repository at this point in the history
Add an option to clone a repository on creation:
`gritty create -c <name> <remote>` will clone the repository into
./<name>

BREAKING CHANGE: Configs now need a "clone_protocol" option for each
remote.
  • Loading branch information
benpueschel committed Jul 6, 2024
1 parent 6e0a4ce commit 50b2fb4
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 10 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,14 @@ secrets = "Keyring"
provider = "GitHub"
url = "https://github.com"
username = "your_username"
clone_protocol = "ssh" # or "https"

# This adds a second remote to the configuration file, using Gitea as the provider.
[remotes.gitea]
provider = "Gitea"
url = "https://gitea.example.com"
username = "your_username"
clone_protocol = "https" # or "ssh"
```

# Examples
Expand Down
6 changes: 5 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};

use crate::{
log,
remote::{Auth, Provider, RemoteConfig},
remote::{Auth, CloneProtocol, Provider, RemoteConfig},
};

pub type Result<T> = std::result::Result<T, ConfigError>;
Expand Down Expand Up @@ -80,6 +80,7 @@ pub struct Config {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GitRemoteConfig {
pub provider: Provider,
pub clone_protocol: CloneProtocol,
pub url: String,
pub username: String,
}
Expand Down Expand Up @@ -158,6 +159,7 @@ impl Config {
pub fn get_remote_config(&self, name: &str) -> Result<RemoteConfig> {
if let Some(remote) = self.remotes.get(name) {
return Ok(RemoteConfig {
clone_protocol: remote.clone_protocol.clone(),
username: remote.username.clone(),
url: remote.url.clone(),
auth: self.get_auth(&self.secrets, name)?,
Expand Down Expand Up @@ -297,6 +299,7 @@ impl Default for Config {
provider: Provider::Gitea,
url: "https://gitea.example.com".to_string(),
username: "awesome-user".to_string(),
clone_protocol: CloneProtocol::HTTPS,
},
),
(
Expand All @@ -305,6 +308,7 @@ impl Default for Config {
provider: Provider::GitHub,
url: "https://github.com".to_string(),
username: "awesome-user".to_string(),
clone_protocol: CloneProtocol::SSH,
},
),
]),
Expand Down
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub enum Args {
Create {
#[structopt(short, long, help = "Create a private repository")]
private: bool,
#[structopt(short, long, help = "Clone the repository after creation")]
clone: bool,
#[structopt(short, long, help = "Initialize the repository with a README.md")]
init: bool,
#[structopt(
Expand Down Expand Up @@ -129,6 +131,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
Args::Create {
private,
clone,
init: _,
license: _,
name,
Expand All @@ -139,14 +142,17 @@ async fn main() -> Result<(), Box<dyn Error>> {
log::println("'...");
let remote = load_remote(&remote).await?;
let info = RepoCreateInfo {
name,
name: name.clone(),
description: None,
private,
};
let url = remote.create_repo(info).await?;
log::print("Repository created at: ");
log::info(&url);
log::end_line();
if clone {
remote.clone_repo(&name, &name).await?;
}
}
Args::Delete {
name,
Expand Down
26 changes: 20 additions & 6 deletions src/remote/gitea.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,21 @@ impl Remote for GiteaRemote {
}

async fn list_repos(&self) -> Result<Vec<Repository>, Error> {
let owner = self.client.get_authenticated_user().await.map_err(map_error)?;
let owner = self
.client
.get_authenticated_user()
.await
.map_err(map_error)?;
let search_option = teatime::SearchRepositoriesOption {
uid: Some(owner.id),
limit: Some(100),
..Default::default()
};
let repos = self.client.search_repositories(&search_option).await.map_err(map_error)?;
let repos = self
.client
.search_repositories(&search_option)
.await
.map_err(map_error)?;
let mut result = Vec::new();
for repo in repos {
result.push(self.get_repo_info(repo).await?);
Expand All @@ -73,10 +81,16 @@ impl Remote for GiteaRemote {
}

async fn clone_repo(&self, name: &str, path: &str) -> Result<(), Error> {
let url = format!(
"git@{}/{}:{}.git",
self.config.url, self.config.username, name
);
let username = &self.config.username;
let clean_url = self
.config
.url
.replace("https://", "")
.replace("http://", "");
let url = match self.config.clone_protocol {
CloneProtocol::SSH => format!("git@{}/{}:{}.git", clean_url, username, name),
CloneProtocol::HTTPS => format!("{}/{}/{}.git", self.config.url, username, name),
};

let status = std::process::Command::new("git")
.arg("clone")
Expand Down
10 changes: 8 additions & 2 deletions src/remote/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use octocrab::{
};
use serde::{Deserialize, Serialize};

use super::{map_error, Commit, Remote, RemoteConfig, RepoCreateInfo, Repository};
use super::{map_error, CloneProtocol, Commit, Remote, RemoteConfig, RepoCreateInfo, Repository};

pub struct GitHubRemote {
config: RemoteConfig,
Expand Down Expand Up @@ -91,7 +91,13 @@ impl Remote for GitHubRemote {
}

async fn clone_repo(&self, name: &str, path: &str) -> Result<(), Error> {
let url = format!("git@github.com/{}:{}.git", self.config.username, name);
let username = &self.config.username;
let url = match self.config.clone_protocol {
CloneProtocol::SSH => format!("git@github.com/{}:{}.git", &username, name),
CloneProtocol::HTTPS => {
format!("https://github.com/{}/{}.git", &username, name)
}
};

let status = std::process::Command::new("git")
.arg("clone")
Expand Down
9 changes: 9 additions & 0 deletions src/remote/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,18 @@ pub enum Auth {
Token { token: String },
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CloneProtocol {
#[serde(rename = "ssh")]
SSH,
#[serde(rename = "https")]
HTTPS,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RemoteConfig {
pub username: String,
pub clone_protocol: CloneProtocol,
pub url: String,
pub auth: Auth,
}
Expand Down

0 comments on commit 50b2fb4

Please sign in to comment.