Skip to content

Commit

Permalink
feat!: forward full commands to shell
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisGorbachev committed Jul 20, 2024
1 parent db8fddd commit d81a9d2
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 75 deletions.
35 changes: 17 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,37 +56,36 @@ Options:
Target directory for cloning the repository (must include the repo name) (defaults to "{current_dir}/{repo_name}") (see also: --workspace)
-w, --workspace <WORKSPACE>
Parent of the target directory for cloning the repository (must NOT include the repo name). If this option is specified, then the repo is cloned to "{workspace}/{repo_name}". The --dir option overrides this option
--shell <SHELL>
--shell-cmd <SHELL_CMD>
Shell to use for executing commands [default: /bin/sh]
-v, --visibility <VISIBILITY>
Repository visibility [default: private] [possible values: public, private, internal]
-c, --copy-configs-from <COPY_CONFIGS_FROM>
Source directory for configuration files
--git-commit-message <GIT_COMMIT_MESSAGE>
Message for git commit [default: "Add configs"]
--extra-configs <EXTRA_CONFIGS>
Extra config file paths (relative to `source` directory)
--repo-exists-cmd <REPO_EXISTS_CMD>
Shell command to check if repo exists (supports substitutions - see help below) [default: "gh repo view --json nameWithOwner \"{{name}}\" | grep \"{{name}}\""]
--gh-repo-create-args <GH_REPO_CREATE_ARGS>
Forwarded arguments for `gh repo create`
--gh-repo-clone-args <GH_REPO_CLONE_ARGS>
Forwarded arguments for `gh repo clone`
--cargo-init-args <CARGO_INIT_ARGS>
Forwarded arguments for `cargo init`
--cargo-build-args <CARGO_BUILD_ARGS>
Forwarded arguments for `cargo build`
--git-commit-args <GIT_COMMIT_ARGS>
Forwarded arguments for `git commit`
--git-push-args <GIT_PUSH_ARGS>
Forwarded arguments for `git push`
Shell command to check if repo exists (supports substitutions - see help below) [default: "gh repo view --json nameWithOwner {{name}} | grep {{name}}"]
--repo-create-cmd <REPO_CREATE_CMD>
Shell command to create a repo (supports substitutions - see help below) [default: "gh repo create --private {{name}}"]
--repo-clone-cmd <REPO_CLONE_CMD>
Shell command to clone a repo (supports substitutions - see help below) [default: "gh repo clone {{name}} {{dir}}"]
--project-init-cmd <PROJECT_INIT_CMD>
Shell command to initialize a project (supports substitutions - see help below) [default: "cargo init"]
--project-test-cmd <PROJECT_TEST_CMD>
Shell command to test a project (supports substitutions - see help below) [default: "cargo test"]
--repo-add-args <REPO_ADD_ARGS>
Shell command to add new files (supports substitutions - see help below) [default: "git add ."]
--repo-commit-args <REPO_COMMIT_ARGS>
Shell command to make a commit (supports substitutions - see help below) [default: "git commit -m \"Add configs\""]
--repo-push-args <REPO_PUSH_ARGS>
Shell command to push the commit (supports substitutions - see help below) [default: "git push"]
-h, --help
Print help
-V, --version
Print version
All command arg options support the following substitutions:
* {{name}} - substituted with --name arg
* {{dir}} - substituted with resolved directory for repo (the resolved value of --dir)
```

## Additional binaries
Expand Down
7 changes: 4 additions & 3 deletions src/bin/create-rust-github-private-bin.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use clap::Parser;
use create_rust_github_repo::{CreateRustGithubRepo, RepoVisibility};

use create_rust_github_repo::CreateRustGithubRepo;

fn main() -> anyhow::Result<()> {
CreateRustGithubRepo::parse()
.visibility(RepoVisibility::Private)
.cargo_init_args(["--bin".to_string()])
.project_init_cmd("gh repo create --private {{name}}")
.project_init_cmd("cargo init --bin")
.run()
}
7 changes: 4 additions & 3 deletions src/bin/create-rust-github-private-lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use clap::Parser;
use create_rust_github_repo::{CreateRustGithubRepo, RepoVisibility};

use create_rust_github_repo::CreateRustGithubRepo;

fn main() -> anyhow::Result<()> {
CreateRustGithubRepo::parse()
.visibility(RepoVisibility::Private)
.cargo_init_args(["--lib".to_string()])
.project_init_cmd("gh repo create --private {{name}}")
.project_init_cmd("cargo init --lib")
.run()
}
7 changes: 4 additions & 3 deletions src/bin/create-rust-github-public-bin.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use clap::Parser;
use create_rust_github_repo::{CreateRustGithubRepo, RepoVisibility};

use create_rust_github_repo::CreateRustGithubRepo;

fn main() -> anyhow::Result<()> {
CreateRustGithubRepo::parse()
.visibility(RepoVisibility::Public)
.cargo_init_args(["--bin".to_string()])
.project_init_cmd("gh repo create --public {{name}}")
.project_init_cmd("cargo init --bin")
.run()
}
7 changes: 4 additions & 3 deletions src/bin/create-rust-github-public-lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use clap::Parser;
use create_rust_github_repo::{CreateRustGithubRepo, RepoVisibility};

use create_rust_github_repo::CreateRustGithubRepo;

fn main() -> anyhow::Result<()> {
CreateRustGithubRepo::parse()
.visibility(RepoVisibility::Public)
.cargo_init_args(["--lib".to_string()])
.project_init_cmd("gh repo create --public {{name}}")
.project_init_cmd("cargo init --lib")
.run()
}
80 changes: 35 additions & 45 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl RepoVisibility {
}

#[derive(Parser, Setters, Debug)]
#[command(version, about, author, after_help = "All command arg options support the following substitutions:\n* {{name}} - substituted with --name arg\n")]
#[command(version, about, author, after_help = "All command arg options support the following substitutions:\n* {{name}} - substituted with --name arg\n* {{dir}} - substituted with resolved directory for repo (the resolved value of --dir)\n")]
#[setters(into)]
pub struct CreateRustGithubRepo {
#[arg(long, short = 'n', help = "Repository name")]
Expand All @@ -41,40 +41,37 @@ pub struct CreateRustGithubRepo {
workspace: Option<PathBuf>,

#[arg(long, help = "Shell to use for executing commands", default_value = "/bin/sh")]
shell: String,

#[arg(long, short = 'v', help = "Repository visibility", value_enum, default_value_t)]
visibility: RepoVisibility,
shell_cmd: String,

#[arg(long, short, help = "Source directory for configuration files", value_parser = value_parser!(PathBuf))]
copy_configs_from: Option<PathBuf>,

#[arg(long, help = "Message for git commit", default_value = "Add configs")]
git_commit_message: String,

#[arg(long, help = "Extra config file paths (relative to `source` directory)", value_delimiter = ',')]
extra_configs: Vec<String>,

#[arg(long, help = "Shell command to check if repo exists (supports substitutions - see help below)", default_value = "gh repo view --json nameWithOwner \"{{name}}\" | grep \"{{name}}\"")]
#[arg(long, help = "Shell command to check if repo exists (supports substitutions - see help below)", default_value = "gh repo view --json nameWithOwner {{name}} | grep {{name}}")]
repo_exists_cmd: String,

#[arg(long, help = "Forwarded arguments for `gh repo create`", value_delimiter = ' ')]
gh_repo_create_args: Vec<String>,
#[arg(long, help = "Shell command to create a repo (supports substitutions - see help below)", default_value = "gh repo create --private {{name}}")]
repo_create_cmd: String,

#[arg(long, help = "Shell command to clone a repo (supports substitutions - see help below)", default_value = "gh repo clone {{name}} {{dir}}")]
repo_clone_cmd: String,

#[arg(long, help = "Forwarded arguments for `gh repo clone`", value_delimiter = ' ')]
gh_repo_clone_args: Vec<String>,
#[arg(long, help = "Shell command to initialize a project (supports substitutions - see help below)", default_value = "cargo init")]
project_init_cmd: String,

#[arg(long, help = "Forwarded arguments for `cargo init`", value_delimiter = ' ')]
cargo_init_args: Vec<String>,
#[arg(long, help = "Shell command to test a project (supports substitutions - see help below)", default_value = "cargo test")]
project_test_cmd: String,

#[arg(long, help = "Forwarded arguments for `cargo build`", value_delimiter = ' ')]
cargo_build_args: Vec<String>,
#[arg(long, help = "Shell command to add new files (supports substitutions - see help below)", default_value = "git add .")]
repo_add_args: String,

#[arg(long, help = "Forwarded arguments for `git commit`", value_delimiter = ' ')]
git_commit_args: Vec<String>,
#[arg(long, help = "Shell command to make a commit (supports substitutions - see help below)", default_value = "git commit -m \"Add configs\"")]
repo_commit_args: String,

#[arg(long, help = "Forwarded arguments for `git push`", value_delimiter = ' ')]
git_push_args: Vec<String>,
#[arg(long, help = "Shell command to push the commit (supports substitutions - see help below)", default_value = "git push")]
repo_push_args: String,
}

impl CreateRustGithubRepo {
Expand All @@ -84,31 +81,23 @@ impl CreateRustGithubRepo {
.dir
.or_else(|| self.workspace.map(|workspace| workspace.join(&self.name)))
.unwrap_or(current_dir.join(&self.name));
let dir_string = dir.display().to_string();

let substitutions = HashMap::<&'static str, &str>::from([("{{name}}", self.name.as_str())]);
let substitutions = HashMap::<&'static str, &str>::from([
("{{name}}", self.name.as_str()),
("{{dir}}", dir_string.as_str()),
]);

let repo_exists = success(&self.shell, ["-c"], [self.repo_exists_cmd], &current_dir, &substitutions)?;
let repo_exists = success(&self.shell_cmd, ["-c"], [self.repo_exists_cmd], &current_dir, &substitutions)?;

if !repo_exists {
// Create a GitHub repo
exec(
"gh",
[
"repo",
"create",
&self.name,
self.visibility.to_gh_create_repo_flag(),
],
self.gh_repo_create_args,
&current_dir,
&substitutions,
)
.context("Failed to create GitHub repository")?;
exec(&self.shell_cmd, ["-c"], [self.repo_create_cmd], &current_dir, &substitutions).context("Failed to create repository")?;
}

if !dir.exists() {
// Clone the repo
exec("gh", ["repo", "clone", &self.name, dir.to_str().unwrap()], self.gh_repo_clone_args.into_iter(), &current_dir, &substitutions).context("Failed to clone repository")?;
exec(&self.shell_cmd, ["-c"], [self.repo_clone_cmd], &current_dir, &substitutions).context("Failed to clone repository")?;
} else {
println!("Directory \"{}\" exists, skipping clone command", dir.display())
}
Expand All @@ -117,7 +106,7 @@ impl CreateRustGithubRepo {

if !cargo_toml.exists() {
// Run cargo init
exec("cargo", ["init"], self.cargo_init_args.into_iter(), &dir, &substitutions).context("Failed to initialize Cargo project")?;
exec(&self.shell_cmd, ["-c"], [self.project_init_cmd], &dir, &substitutions).context("Failed to initialize the project")?;
} else {
println!("Cargo.toml exists in \"{}\", skipping `cargo init` command", dir.display())
}
Expand All @@ -130,16 +119,17 @@ impl CreateRustGithubRepo {
copy_configs_if_not_exists(&copy_configs_from, &dir, configs).context("Failed to copy configuration files")?;
}

// Run cargo build
exec("cargo", ["build"], self.cargo_build_args.into_iter(), &dir, &substitutions).context("Failed to build Cargo project")?;
// test
exec(&self.shell_cmd, ["-c"], [self.project_test_cmd], &dir, &substitutions).context("Failed to test the project")?;

// Git commit
exec("git", ["add", "."], Vec::<String>::new().into_iter(), &dir, &substitutions).context("Failed to stage files for commit")?;
// add
exec(&self.shell_cmd, ["-c"], [self.repo_add_args], &dir, &substitutions).context("Failed to add files for commit")?;

exec("git", ["commit", "-m", &self.git_commit_message], self.git_commit_args.into_iter(), &dir, &substitutions).context("Failed to commit changes")?;
// commit
exec(&self.shell_cmd, ["-c"], [self.repo_commit_args], &dir, &substitutions).context("Failed to commit changes")?;

// Git push
exec("git", ["push"], self.git_push_args.into_iter(), &dir, &substitutions).context("Failed to push changes")?;
// push
exec(&self.shell_cmd, ["-c"], [self.repo_push_args], &dir, &substitutions).context("Failed to push changes")?;

Ok(())
}
Expand Down

0 comments on commit d81a9d2

Please sign in to comment.