Skip to content

Commit

Permalink
Allow git subfolder as a template.
Browse files Browse the repository at this point in the history
Using cargo generate --git <repo>#<sub-folder, this one
1) Allows to use a subfolder as the actual template (see #47)
2) Allows to e.g. generate a project from an example in a repo (see #78)
3) Avoids the conflicting requirements for cargo-generate#295 and cargo-generate#291, allowing for easier implementation of `--pick` for cargo-generate#291.
  • Loading branch information
taurr committed Jul 29, 2021
1 parent 4b42337 commit ac4beb6
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 90 deletions.
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ You can also pass the name of your project to the tool using the `--name` or `-n
cargo generate --git https://github.com/githubusername/mytemplate.git --name myproject
```

If the git repository contains multiple templates, the specific subfolder in the git repository may be specified like this:

```sh
cargo generate --git "https://github.com/githubusername/mytemplate.git <relative-template-path>"
```

> NOTE: The specified `relative-template-path` will be used as the actual template root, whether or not this is actually true!
> NOTE: When using the `subfolder` feature, `cargo-generate` will search for
## git over ssh

New in version [0.7.0] is the support for both public and private and ssh git remote urls.
Expand All @@ -82,7 +92,7 @@ cargo generate --git rustwasm/wasm-pack-template --name mywasm
## http(s) proxy

New in version [0.7.0] is automatic proxy usage. So, if http(s)_PROXY env variables are provided, they
New in version [0.7.0] is automatic proxy usage. So, if http(s)\_PROXY env variables are provided, they
will be used for cloning a http(s) template repository.

## Favorites
Expand All @@ -94,12 +104,13 @@ Each favorite template is specified in its own section, e.g.:

```toml
[favorites.demo]
description = "Demo template for cargo-generate"
description = "<optional description, visible with --list-favorites>"
git = "https://github.com/ashleygwilliams/wasm-pack-template"
branch = "master"
branch = "<optional-branch>"
subfolder = "<optional-subfolder>"
```

Both `branch` and `description` are optional, and the branch may be overridden by specifying `--branch <branch>` on the command line.
Values may be overridden using the CLI arguments of the same names (e.g. `--subfolder` for the `subfolder` value).

When favorites are available, they can be generated simply by invoking:

Expand All @@ -110,7 +121,7 @@ cargo gen <favorite>
or slightly more involved:

```cli
cargo generate demo --branch master --name expanded_demo
cargo generate demo --branch mybranch --name expanded_demo --subfolder myfolder
```

> NOTE: when `<favorite>` is not defined in the config file, it is interpreted as a git repo like as if `--git <favorite>`
Expand Down Expand Up @@ -295,6 +306,8 @@ include = ["Cargo.toml"]
exclude = ["*.c"]
```

The `cargo-generate.toml` file should be placed in the root of the template. If using the `subfolder` feature, the root is the `subfolder` inside the repository, though `cargo-generate` will look for the file in all parent folders until it reaches the repository root.

## Cargo gen - alias

`cargo gen` requires an [cargo alias](https://doc.rust-lang.org/cargo/reference/config.html)
Expand Down Expand Up @@ -323,4 +336,4 @@ conditions.
If you want to contribute to `cargo-generate`, please read our [CONTRIBUTING notes].

[CONTRIBUTING notes]: CONTRIBUTING.md
[0.7.0]: https://github.com/cargo-generate/cargo-generate/releases/tag/v0.7.0
[0.7.0]: https://github.com/cargo-generate/cargo-generate/releases/tag/v0.7.0
1 change: 1 addition & 0 deletions src/app_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) struct FavoriteConfig {
pub description: Option<String>,
pub git: Option<String>,
pub branch: Option<String>,
pub subfolder: Option<String>,
}

impl Default for AppConfig {
Expand Down
24 changes: 15 additions & 9 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,21 @@ impl TryFrom<String> for Config {
}

impl Config {
pub(crate) fn new<P: AsRef<Path>>(path: P) -> Result<Option<Self>> {
match fs::read_to_string(path) {
Ok(contents) => Config::try_from(contents)
.map(Option::from)
.map_err(|e| e.into()),
Err(e) => match e.kind() {
ErrorKind::NotFound => Ok(None),
_ => anyhow::bail!(e),
pub(crate) fn from_path<P>(path: &Option<P>) -> Result<Option<Self>>
where
P: AsRef<Path>,
{
match path {
Some(path) => match fs::read_to_string(path) {
Ok(contents) => Config::try_from(contents)
.map(Option::from)
.map_err(|e| e.into()),
Err(e) => match e.kind() {
ErrorKind::NotFound => Ok(None),
_ => anyhow::bail!(e),
},
},
None => Ok(None),
}
}
}
Expand Down Expand Up @@ -89,7 +95,7 @@ mod tests {
)
.unwrap();

let config = Config::new(&config_path).unwrap().unwrap();
let config = Config::from_path(&Some(config_path)).unwrap().unwrap();

assert_eq!(
config.template,
Expand Down
15 changes: 13 additions & 2 deletions src/favorites.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub(crate) fn list_favorites(args: &Args) -> Result<()> {

pub(crate) fn resolve_favorite_args(args: &mut Args) -> Result<()> {
if args.git.is_some() {
args.subfolder = args.favorite.take();
return Ok(());
}

Expand All @@ -48,7 +49,7 @@ pub(crate) fn resolve_favorite_args(args: &mut Args) -> Result<()> {
let app_config_path = app_config_path(&args.config)?;
let app_config = AppConfig::from_path(app_config_path.as_path())?;

let (git, branch) = app_config
let (git, branch, subfolder) = app_config
.favorites
.get(favorite_name.as_str())
.map_or_else(
Expand All @@ -57,17 +58,27 @@ pub(crate) fn resolve_favorite_args(args: &mut Args) -> Result<()> {
"Favorite {} not found in config, using it as a git repo url",
style(&favorite_name).bold()
);
(Some(favorite_name.clone()), args.branch.as_ref().cloned())
(
Some(favorite_name.clone()),
args.branch.as_ref().cloned(),
args.subfolder.clone(),
)
},
|f| {
(
f.git.clone(),
args.branch.as_ref().or_else(|| f.branch.as_ref()).cloned(),
args.subfolder
.as_ref()
.or_else(|| f.subfolder.as_ref())
.cloned(),
)
},
);

args.git = git;
args.branch = branch;
args.subfolder = subfolder;

Ok(())
}

0 comments on commit ac4beb6

Please sign in to comment.