Skip to content

Commit b95465f

Browse files
feat!: remove --extra-configs, add --configs
1 parent 9b01520 commit b95465f

File tree

5 files changed

+49
-61
lines changed

5 files changed

+49
-61
lines changed

Cargo.lock

Lines changed: 5 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "create-rust-github-repo"
33
description = "`create-rust-github-repo` is a CLI program that creates a new repository on GitHub, clones it locally, initializes a Rust project, copies the configs from a pre-existing directory."
4-
version = "0.3.4"
4+
version = "0.4.0"
55
edition = "2021"
66
license = "Apache-2.0 OR MIT"
77
homepage = "https://github.com/DenisGorbachev/create-rust-github-repo"
@@ -19,5 +19,5 @@ announcement = ""
1919
[dependencies]
2020
anyhow = "1.0.86"
2121
clap = { version = "4.3.24", features = ["derive"] }
22-
fs-err = "2.11.0"
2322
derive_setters = "0.1.6"
23+
fs_extra = "1.3.0"

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
create-rust-github-repo --name my-new-project
1919

2020
# Copy configs from existing project
21-
create-rust-github-repo --name my-new-project --copy-configs-from ~/workspace/my-existing-project
21+
create-rust-github-repo --name my-new-project --copy-configs-from ~/workspace/my-existing-project --configs .github,rustfmt.toml,clippy.toml
2222

2323
# Clone to a specific directory
2424
create-rust-github-repo --name my-new-project --dir ~/workspace/my-new-project
@@ -60,9 +60,9 @@ Options:
6060
--shell-cmd <SHELL_CMD>
6161
Shell to use for executing commands [default: /bin/sh]
6262
-c, --copy-configs-from <COPY_CONFIGS_FROM>
63-
Source directory for configuration files
64-
--extra-configs <EXTRA_CONFIGS>
65-
Extra config file paths (relative to resolved `dir`), separated by comma
63+
Source directory for config paths
64+
--configs <CONFIGS>
65+
Config paths separated by comma (relative to `copy_configs_from`) (only applies if `copy_configs_from` is specified) (supports files and directories)
6666
--repo-exists-cmd <REPO_EXISTS_CMD>
6767
Shell command to check if repo exists (supports substitutions - see help below) [default: "gh repo view --json nameWithOwner {{name}} 2>/dev/null"]
6868
--repo-create-cmd <REPO_CREATE_CMD>
@@ -76,7 +76,7 @@ Options:
7676
--repo-add-args <REPO_ADD_ARGS>
7777
Shell command to add new files (supports substitutions - see help below) [default: "git add ."]
7878
--repo-commit-args <REPO_COMMIT_ARGS>
79-
Shell command to make a commit (supports substitutions - see help below) [default: "git commit -m \"Add configs\""]
79+
Shell command to make a commit (supports substitutions - see help below) [default: "git commit -m \"Setup project\""]
8080
--repo-push-args <REPO_PUSH_ARGS>
8181
Shell command to push the commit (supports substitutions - see help below) [default: "git push"]
8282
-h, --help

lefthook.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ pre-commit:
2121
run: cargo test --doc
2222
lint-commit:
2323
run: commitlint --last
24+
lint-deps:
25+
run: cargo machete --with-metadata

src/lib.rs

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//! create-rust-github-repo --name my-new-project
1010
//!
1111
//! # Copy configs from existing project
12-
//! create-rust-github-repo --name my-new-project --copy-configs-from ~/workspace/my-existing-project
12+
//! create-rust-github-repo --name my-new-project --copy-configs-from ~/workspace/my-existing-project --configs .github,rustfmt.toml,clippy.toml
1313
//!
1414
//! # Clone to a specific directory
1515
//! create-rust-github-repo --name my-new-project --dir ~/workspace/my-new-project
@@ -38,6 +38,8 @@ use std::process::{Command, ExitStatus};
3838
use anyhow::Context;
3939
use clap::{value_parser, Parser, ValueEnum};
4040
use derive_setters::Setters;
41+
use fs_extra::copy_items;
42+
use fs_extra::dir::CopyOptions;
4143

4244
#[derive(ValueEnum, Default, Eq, PartialEq, Hash, Clone, Copy, Debug)]
4345
pub enum RepoVisibility {
@@ -73,11 +75,12 @@ pub struct CreateRustGithubRepo {
7375
#[arg(long, help = "Shell to use for executing commands", default_value = "/bin/sh")]
7476
shell_cmd: String,
7577

76-
#[arg(long, short, help = "Source directory for configuration files", value_parser = value_parser!(PathBuf))]
78+
#[arg(long, short, help = "Source directory for config paths", value_parser = value_parser!(PathBuf))]
7779
copy_configs_from: Option<PathBuf>,
7880

79-
#[arg(long, help = "Extra config file paths (relative to resolved `dir`), separated by comma", value_delimiter = ',')]
80-
extra_configs: Vec<String>,
81+
/// Config paths separated by comma (relative to `copy_configs_from`) (only applies if `copy_configs_from` is specified) (supports files and directories)
82+
#[arg(long, value_delimiter = ',')]
83+
configs: Vec<String>,
8184

8285
#[arg(long, help = "Shell command to check if repo exists (supports substitutions - see help below)", default_value = "gh repo view --json nameWithOwner {{name}} 2>/dev/null")]
8386
repo_exists_cmd: String,
@@ -97,7 +100,7 @@ pub struct CreateRustGithubRepo {
97100
#[arg(long, help = "Shell command to add new files (supports substitutions - see help below)", default_value = "git add .")]
98101
repo_add_args: String,
99102

100-
#[arg(long, help = "Shell command to make a commit (supports substitutions - see help below)", default_value = "git commit -m \"Add configs\"")]
103+
#[arg(long, help = "Shell command to make a commit (supports substitutions - see help below)", default_value = "git commit -m \"Setup project\"")]
101104
repo_commit_args: String,
102105

103106
#[arg(long, help = "Shell command to push the commit (supports substitutions - see help below)", default_value = "git push")]
@@ -142,11 +145,16 @@ impl CreateRustGithubRepo {
142145
}
143146

144147
if let Some(copy_configs_from) = self.copy_configs_from {
145-
let mut configs: Vec<String> = vec![];
146-
configs.extend(CONFIGS.iter().copied().map(ToOwned::to_owned));
147-
configs.extend(self.extra_configs);
148-
// Copy config files
149-
copy_configs_if_not_exists(&copy_configs_from, &dir, configs).context("Failed to copy configuration files")?;
148+
let paths: Vec<PathBuf> = self
149+
.configs
150+
.iter()
151+
.map(|config| copy_configs_from.join(config))
152+
.collect();
153+
let options = CopyOptions::new()
154+
.skip_exist(true)
155+
.copy_inside(true)
156+
.buffer_size(MEGABYTE);
157+
copy_items(&paths, &dir, &options).context("Failed to copy configuration files")?;
150158
}
151159

152160
// test
@@ -178,27 +186,28 @@ pub fn replace_all(mut input: String, substitutions: &HashMap<&str, &str>) -> St
178186
input
179187
}
180188

181-
pub fn exec(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>, extra_args: impl IntoIterator<Item = String>, current_dir: impl AsRef<Path>, substitutions: &HashMap<&str, &str>) -> io::Result<ExitStatus> {
189+
pub fn exec(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone, extra_args: impl IntoIterator<Item = String>, current_dir: impl AsRef<Path>, substitutions: &HashMap<&str, &str>) -> io::Result<ExitStatus> {
182190
let replacements = replace_args(extra_args, substitutions);
183191
let extra_args = replacements.iter().map(AsRef::<OsStr>::as_ref);
184192
exec_raw(cmd, args, extra_args, current_dir)
185193
}
186194

187-
pub fn success(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>, extra_args: impl IntoIterator<Item = String>, current_dir: impl AsRef<Path>, substitutions: &HashMap<&str, &str>) -> io::Result<bool> {
195+
pub fn success(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone, extra_args: impl IntoIterator<Item = String>, current_dir: impl AsRef<Path>, substitutions: &HashMap<&str, &str>) -> io::Result<bool> {
188196
let replacements = replace_args(extra_args, substitutions);
189197
let extra_args = replacements.iter().map(AsRef::<OsStr>::as_ref);
190198
success_raw(cmd, args, extra_args, current_dir)
191199
}
192200

193-
pub fn exec_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>, extra_args: impl IntoIterator<Item = impl AsRef<OsStr>>, current_dir: impl AsRef<Path>) -> io::Result<ExitStatus> {
201+
pub fn exec_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone, extra_args: impl IntoIterator<Item = impl AsRef<OsStr>>, current_dir: impl AsRef<Path>) -> io::Result<ExitStatus> {
194202
get_status_raw(cmd, args, extra_args, current_dir).and_then(check_status)
195203
}
196204

197-
pub fn success_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>, extra_args: impl IntoIterator<Item = impl AsRef<OsStr>>, current_dir: impl AsRef<Path>) -> io::Result<bool> {
205+
pub fn success_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone, extra_args: impl IntoIterator<Item = impl AsRef<OsStr>>, current_dir: impl AsRef<Path>) -> io::Result<bool> {
198206
get_status_raw(cmd, args, extra_args, current_dir).map(|status| status.success())
199207
}
200208

201-
pub fn get_status_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>, extra_args: impl IntoIterator<Item = impl AsRef<OsStr>>, current_dir: impl AsRef<Path>) -> io::Result<ExitStatus> {
209+
pub fn get_status_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone, extra_args: impl IntoIterator<Item = impl AsRef<OsStr>>, current_dir: impl AsRef<Path>) -> io::Result<ExitStatus> {
210+
eprintln!("$ {}", cmd_to_string(cmd.as_ref(), args.clone()));
202211
Command::new(cmd)
203212
.args(args)
204213
.args(extra_args)
@@ -207,6 +216,15 @@ pub fn get_status_raw(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = imp
207216
.wait()
208217
}
209218

219+
fn cmd_to_string(cmd: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> String {
220+
let mut cmd_str = cmd.as_ref().to_string_lossy().to_string();
221+
for arg in args {
222+
cmd_str.push(' ');
223+
cmd_str.push_str(arg.as_ref().to_string_lossy().as_ref());
224+
}
225+
cmd_str
226+
}
227+
210228
pub fn check_status(status: ExitStatus) -> io::Result<ExitStatus> {
211229
if status.success() {
212230
Ok(status)
@@ -215,33 +233,10 @@ pub fn check_status(status: ExitStatus) -> io::Result<ExitStatus> {
215233
}
216234
}
217235

218-
pub fn copy_configs_if_not_exists<P: Clone + AsRef<Path>>(source: &Path, target: &Path, configs: impl IntoIterator<Item = P>) -> io::Result<()> {
219-
for config in configs {
220-
let source_path = source.join(config.clone());
221-
let target_path = target.join(config);
222-
if source_path.exists() && !target_path.exists() {
223-
fs_err::copy(&source_path, &target_path)?;
224-
}
225-
}
226-
Ok(())
227-
}
228-
229-
pub const CONFIGS: &[&str] = &[
230-
"clippy.toml",
231-
"rustfmt.toml",
232-
"Justfile",
233-
"lefthook.yml",
234-
".lefthook.yml",
235-
"lefthook.yaml",
236-
".lefthook.yaml",
237-
"lefthook.toml",
238-
".lefthook.toml",
239-
"lefthook.json",
240-
".lefthook.json",
241-
];
242-
243236
#[test]
244237
fn verify_cli() {
245238
use clap::CommandFactory;
246239
CreateRustGithubRepo::command().debug_assert();
247240
}
241+
242+
const MEGABYTE: usize = 1048576;

0 commit comments

Comments
 (0)