Git Product home page Git Product logo

cargo-generate's Introduction

cargo-generate

Build status crates.io dependency status Chat on Matrix

cargo, make me a project

cargo-generate is a developer tool to help you get up and running quickly with a new Rust project by leveraging a pre-existing git repository as a template.

Here's an example of using cargo-generate with this template: demo.gif

Documentation

See the cargo-generate guide for complete documentation.

Templates

One place to find templates is to look for the cargo-generate topic on GitHub.

Quickstart

Installation

cargo install cargo-generate

or if you have no time, use cargo-binstall:

cargo binstall cargo-generate

Usage

# templates on github
cargo generate --git https://github.com/username-on-github/mytemplate.git

# or just
cargo generate username-on-github/mytemplate

# templates on other git platforms
cargo generate gl:username-on-gitlab/mytemplate # translates to https://gitlab.com/username-on-gitlab/mytemplate.git
cargo generate bb:username-on-bitbucket/mytemplate # translates to https://bitbucket.org/username-on-bitbucket/mytemplate.git
cargo generate sr:username-on-sourcehut/mytemplate # translates to https://git.sr.ht/~username-on-sourcehut/mytemplate (note the tilde)

# this scheme is also available for github
cargo generate gh:username-on-github/mytemplate # translates to https://github.com/username-on-github/mytemplate.git

# for a complete list of arguments and options
cargo help generate

License

Licensed under either of

at your option.

Contributions

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. If you want to contribute to cargo-generate, please read our CONTRIBUTING notes.

cargo-generate would not be what it is today without the wonderful contributions from the community. Thank you!

cargo-generate's People

Contributors

9999years avatar ashleygwilliams avatar cecton avatar csmoe avatar dave-tucker avatar dd5ht avatar dependabot-preview[bot] avatar dependabot[bot] avatar elijah-potter avatar epage avatar eupn avatar everlastingbugstopper avatar gabrieldertoni avatar jashandeep-sohi avatar joshrotenberg avatar k0pernicus avatar kianmeng avatar killercup avatar marcoieni avatar no9 avatar orhun avatar rotationmatrix avatar sassman avatar sergiogasquez avatar softprops avatar sreyas-sreelal avatar taurr avatar veetaha avatar xortive avatar yozhgoor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cargo-generate's Issues

Project examples as templates

In #47, one of the possibilities noted is

sub dir in a repo

I wanted to make a suggestion that's a little more extensive than this, and I think it's enough of an expansion to list as a separate issue.

A number of projects have examples/ directories with cargo support for running them directly, and there's also a proposal to let cargo support larger per-directory examples in a sub-structure under there. These are often good starting points for customising your own code; I know I've done this a number of times, especially with some embedded projects. That sounds a lot like a template!

I think is worth combining these proposals and having some specific conventions to make it easier, such that project example directories can always/automatically be templates. I'd like it to be sufficiently low-friction that neither general crate authors nor template consumers need to do anything much extra or unusual to use examples as templates, and offering templates becomes the norm.

This probably involves some changes on both sides, perhaps something like this:

  • example directories look like templates, with placeholders, and have an example.toml with placeholder values. Cargo knows how to use this when running in-place as an example.
  • this in turn suggests that making a new example (directory) should itself make a bare template (cargo new --example?) so that there's a cohesive story from start to, well, new start :)
  • when given a repo, cargo generate can look in the examples directories to find templates, and (in interactive mode) offer a list to pick from, so that repos can be discoverable as either single templates at the root, or more structured collections.

One of the strongest reasons for this is to keep examples and templates in sync with the libraries they represent; cargo should test each of the templates-as-examples just like today. If they're in a separate repo, there's always a risk they'll languish. If they're in the one repo, examples can also be updated to match library code changes on branches.

force flag

right now, we receive a project name from the user and then force it to kebab case. a user might not love this. let's give an option to force, which will skip the case check and conversion. crate_name should still be snake case, but project-name should be exactly whatever the user entered.

remove libgit2 in favor of shelling out to git

This would remove the dependency on Git, and we would just link in libgit2. It would require less things to be installed, especially when you start distributing this as a binary, since Rust statically links everything!

Custom variables.

For my python projects, I've found cookiecutter's custom variables really helpful. I'm assuming it would be the same for cargo-generate (including unexpected cases like #14).

Ideas from cookiecutter

I'm also assuming that environment-derived variables (author) would still be gathered but built-in policy like "name" would not be.

  • In place of this, there could be an option for variables to be set on the commandline (cargo generate --variable name some-crate).
  • For built-in magic like case changing, can be provided as liquid filters to the template author.
  • Unsure of a good way to handle ident verification.

Only works as `cargo-generate`, not `cargo generate`

Doesn't work as cargo generate:

$ cargo generate --help
error: Found argument 'generate' which wasn't expected, or isn't valid in this context

USAGE:
    cargo-generate [OPTIONS] --git <git>

For more information try --help

$ cargo generate --version
error: Found argument 'generate' which wasn't expected, or isn't valid in this context

USAGE:
    cargo-generate [OPTIONS] --git <git>

For more information try --help

However it does work as cargo-generate:

$ cargo-generate --version
cargo-generate 0.1.0

$ cargo-generate --help
cargo-generate 0.1.0
Ashley Williams <[email protected]>, Pascal Hertleif <[email protected]>
Generate a new Cargo project from a given template

Right now, only git repositories can be used as templates. Just execute

$ cargo generate --git https://github.com/user/template.git --name foo

and a new Cargo project called foo will be generated.

TEMPLATES:

In templates, the following placeholders can be used:

- `project-name`: Name of the project, in dash-case

- `crate_name`: Name of the project, but in a case valid for a Rust identifier, i.e., snake_case

- `authors`: Author names, taken from usual environment variables (i.e. those which are also used by Cargo and git)

USAGE:
    cargo-generate [OPTIONS] --git <git>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --git <git>      
        --name <name>    

improve error message when passed a git repo that does not exist

I am getting an error while creating a cli-wg project ggrs.

dinesh@Personal /Users/dinesh $  
|  Mac => cargo generate --git https://github.com/rust-clique/cargo-template-cli
🤷  Project Name: grrs
🔧   Creating project called `grrs`...
error: authentication required but no callback set; class=Net (12)

RFC: Only replace variables in files with specific extension?

Context

Currently, cargo-generate tries to find and replace all {{ blocks }} in all files. This is the most trivial implementation, but not necessarily the best or most user friendly one.

As written in #14 (comment) and #40 (comment), an alternative might be to instead only consider files whose names match a specific pattern as templates.

Questions

  • Should we filter by file extensions?
  • If yes, which ones?
  • If yes, where to define this extension? (Also cf. #48)

Possibles solutions

  • Yes, with .template

    (Because it's pretty obvious and also not bound to any implementation. It has the added advantage that projects that already have .hbs or .liquid files are unlikely to conflict.)

  • Yes, defined in config file (cf. #48), defaulting to .tplt

  • No

Notes

The implementation should be pretty straightforward. I assume it's a matter of expanding this condition and adding a test or two.

Pre/Post Hooks

This is something else that has been handy from cookiecutter but is more questionable due to security.

Use cases from my python cookiecutter translated to Rust.

  • Custom SCM support
  • Verifying ident (see #17)
  • cargo update && git add Cargo.lock for bins

The main question is how would we handle this in Rust?

  • shell scripts aren't portable
  • cargo-script?

To alleviate security concerns, we could have flags for

  • Showing what will be done to the system (prints the scripts)
  • Runs the template but not the hooks (requiring manual intervention)

{{crate_name}} isn't being turned to snake_case

$ cargo new --lib my-template
     Created library `my-template` project

$ cd my-template/

$ cat Cargo.toml # <-- edited to have name be {{project-name}}
[package]
name = "{{project-name}}"
version = "0.1.0"
authors = ["Nick Fitzgerald <[email protected]>"]

[dependencies]

$ mkdir tests

$ echo 'extern crate {{crate_name}};' > tests/tests.rs

$ git add .

$ git commit -m "initial"
[master (root-commit) 5db8b7e] initial
 4 files changed, 17 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Cargo.toml
 create mode 100644 src/lib.rs
 create mode 100644 tests/tests.rs

$ cd ..

$ cargo-generate --git my-template --name my-project-with-hyphens
⠁
 Done! New project created /tmp/my-project-with-hyphens

$ cd my-project-with-hyphens/

$ cargo test
   Compiling my-project-with-hyphens v0.1.0 (file:///tmp/my-project-with-hyphens)
error: expected one of `;` or `as`, found `-`
 --> tests/tests.rs:1:16
  |
1 | extern crate my-project-with-hyphens;
  |                ^ expected one of `;` or `as` here

error: aborting due to previous error

error: Could not compile `my-project-with-hyphens`.
warning: build failed, waiting for other jobs to finish...
error: build failed

check template pkg metadata for cargo gen version, warn on mismatch

to help make it easier for us to proceed without breaking things, i'd like to propose that template authors be required to include a cargo-generate version in their cargo toml, e.g.

[package]
name = "{{project-name}}"
version = "0.1.0"
cargo-generate = "0.1.0"

if the version doesn't exist in the cargo toml, we should WARN
if the version of cargo-generate on disk is different than the listed version, we should WARN

this should be fully semver feature full, so folks should be able to write something like:
cargo-generate = "~0.2.0"

add `-n` short alias for `--name`

There is already a short version of generate, why don't we add -n for name and -g for git?
Example:
cargo gen -g https://github.com/user/template.git -n foo

handle projects that contain other templating languages

Hello!
I am trying to make a template for creating mdbooks. cargo-generate currently analyses the Cargo.toml file and then tries to replace the placeholders. It would be great to have mdbook templates, however, the book.toml file should be parsed instead. Having a --book flag could direct cargo-generate to parse book.toml. Any suggestions?

doesn't seem to be replacing project-name and authors

Ashleys-MacBook-Pro-2:cargo-generate ag_dubs$ cargo run -- --git https://github.com/ashleygwilliams/wasm-pack-template.git
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/cargo-generate --git 'https://github.com/ashleygwilliams/wasm-pack-template.git'`
The project's name is: wasm-fart
Nice, I'll call your project `wasm-fart`
Done!
Ashleys-MacBook-Pro-2:cargo-generate ag_dubs$ ls
CODE_OF_CONDUCT.md	Cargo.lock		LICENSE-APACHE		README.md		target
CONTRIBUTING.md		Cargo.toml		LICENSE-MIT		src			wasm-fart
Ashleys-MacBook-Pro-2:cargo-generate ag_dubs$ cd wasm-fart/
Ashleys-MacBook-Pro-2:wasm-fart ag_dubs$ ls
Cargo.toml	LICENSE_APACHE	LICENSE_MIT	README.md	src
Ashleys-MacBook-Pro-2:wasm-fart ag_dubs$ cat Cargo.toml
[package]
name = {{project-name}}
version = "0.1.0"
authors = {{authors}}

[dependencies]
wasm-bindgen = "0.2"

Reconsider subcommand name

This might be trivial bike-shedding territory, but I'm not in love with the naming.
generate is very generic and doesn't communicate the intent all that clearly.

Some options I would like more:

  • bootstrap
  • kickstart

Actually, having this integrated into "cargo new" might also be a cool option, although one that would probably take some time to get right.
Eg:
cargo new --template=diesel-rs/diesel

A new clone fails `cargo test` on second test on Windows 10

Example output:

> cargo test
<snip>
   Compiling cargo-generate v0.0.0 (file:///C:/Users/steve/tmp/cargo-generate)
    Finished dev [unoptimized + debuginfo] target(s) in 6m 40s
     Running target\debug\deps\cargo_generate-4873338d5974a9ff.exe

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target\debug\deps\integration-1d803e56ff299d5d.exe

running 1 test
test basics::simple_cargo_thing ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
> cargo test
    Finished dev [unoptimized + debuginfo] target(s) in 0.73s
     Running target\debug\deps\cargo_generate-4873338d5974a9ff.exe

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target\debug\deps\integration-1d803e56ff299d5d.exe

running 1 test
test basics::simple_cargo_thing ... FAILED

failures:

---- basics::simple_cargo_thing stdout ----
thread 'basics::simple_cargo_thing' panicked at 'Unexpected failure.
code-1
stderr=``````
command=`"git" "commit" "--message" "initial commit"`
code=1
stdout=```On branch master
nothing to commit, working tree clean

stderr=

', C:\Users\steve\.cargo\registry\src\github.com-1ecc6299db9ec823\assert_cmd-0.4.0\src\assert.rs:140:13
note: Run with `RUST_BACKTRACE=1` for a backtrace.


failures:
    basics::simple_cargo_thing

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test integration'

RFC: Have a config file for cargo-generate?

Context

When cargo-generate tries to generate a project, it may require meta-information, e.g. which placeholders to look for, or how to find files to apply substitutions to. While currently, this is defined by hard-coded rules in the tool itself, in the future this might be configurable.

Questions

Should templates be able to contain (optional) config files to pass parameters and meta information to cargo-generate?

Possibles solutions

  • Yes, and it'll be in TOML format with a schema like

    [template]
    name = "foo"
    repository = "https://github.com/rust-lang-nursery/cargo-template-foo"
    placeholders = ["project-name", "author"]
  • Yes, and it can also be a subsection of a Cargo.toml file

  • Yes, and it can also be a subsection of a book.toml file

  • No

refactor/modularize

in prep for publishing this and opening to contributors, let's break the src and tests up into modules

Document build dependencies

I wanted to install cargo-generate in my WSL Ubuntu and ran into a few problems. One was with the openssl-sys crate that needs at least two additional packages that weren't installed on my system. The other was libssh2-sys that needs cmake. So in order to install cargo-generate I had to

sudo apt-get install pkg-config libssl-dev cmake

first. The openssl-sys crate has a guide on how to install the build dependencies on various systems. I don't know if cmake is needed on all systems.

warn user if we change given name's case

right now, we receive a name from the user, force it to kebab case, and make the project. we should check the user's entered name and warn them if we are changing the case of the name they passed.

Support conditional tags in templates

Example from #51

Cargo.toml

{% if use_serde %}
serde = "1.*"
serde_derive = "1.*"
{% endif %}

lib.rs

{% if db_type = "postgres" % } 
type Connection = diesel::pg::PgConnection;
{% elseif db_type = "mysql" % } 
...
{% endif %}

Relevant tags

RFC: Where do the values of substitution variables come from?

Context

cargo-generate's main job is to copy file and replace some of their contents. It does so by looking for placeholders and replacing them with known values for known placeholder names.

Questions

Where do the values for these placeholders come from?

If they come from multiple sources, in which order are these accessed (with either first/last one wins)?

Possibles solutions

Suggestion:

  1. (optional) global config files
  2. env vars
  3. CLI arguments (exact naming and syntax t.b.d.)
  4. prompting the user

Last one wins.

wrong argument handling when invoked as cargo subcommand

This seems to be a common trap for subcommands...

$ cargo-generate
error: The following required arguments were not provided:
    --git <git>
$ cargo generate
error: Found argument 'generate' which wasn't expected, or isn't valid in this context

suggestion: cargo new --template <crate>:<template>

Rationale:

  1. Generating project code from templates is a basic and common task, and I think it should be provided by default rather than be shipped as external tool
  2. It could be even easier for newcomers to get started with specific templates, since there will be less steps to do and less specific things to remember
  3. It could be easier to provide project templates, since that assumes well defined place for them inside of crate (e.g. templates folder), and that will not require additional git setup ceremony
  4. This will be more convenient, since cargo new already acts like code generator and features like --name and --vcs might be effectively combined and reused here
  5. Examples are already handled by cargo, as well as tests, docs, benchmarks and other things that belongs to project, so it's expected to handle templates in the same way

RFC: What can be a template?

Context

When executing cargo-generate a user needs to pass an identifier for the template they want to generate a project from.

Questions

What can be such template identifiers?

How can we extract a cargo-generate compatible template from them?

Possibles solutions

One or more of

  • git repo
  • directory
  • crate
  • sub dir in a repo

usage documentation

let's add some basic usage documentation to the readme

@killercup if you wanna do this go for it- otherwise i'll find sometime, perhaps today

Use proper template engine

As mentioned on Reddit,
I think this crate is not very useful without more advanced customization based on variables.
This would require a template engine though.

Example:

Cargo.toml

{% if use_serde %}
serde = "1.*"
serde_derive = "1.*"
{% endif %}

lib.rs

{% if db_type = "postgres" % } 
type Connection = diesel::pg::PgConnection;
{% elseif db_type = "mysql" % } 
...
{% endif %}

Two options for a template engine that come to mind:

RFC: How to have CI for templates?

The https://github.com/rustwasm/rust_wasm_template template has travis ci pre-configured. We use travis to make sure that the template doesn't break. But it also works out so that if you clone the template, all you have to do is flip the switch in your travis ci dashboard to also get ci set up and configured.

In the process of moving that template over to cargo-generate, the template's CI is broken because of all the {{variables}}. I could fix this by making the CI script run cargo-generate and test the generated template, but now I have two different CI scripts: one for the template and another for the projects generated from the template.

How can we maintain a single CI script for both?


The Output of Broken Builds Before cargo-generate Fills in Variables
$ cargo +nightly build --release --target wasm32-unknown-unknown
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling unicode-xid v0.1.0
   Compiling serde v1.0.59
   Compiling wasm-bindgen-shared v0.2.12
   Compiling dtoa v0.4.2
   Compiling cfg-if v0.1.3
   Compiling itoa v0.4.1
   Compiling log v0.4.3
   Compiling proc-macro2 v0.4.8
   Compiling quote v0.6.2
   Compiling syn v0.14.0
   Compiling serde_json v1.0.17
   Compiling serde_derive v1.0.59
   Compiling wasm-bindgen-backend v0.2.12
   Compiling wasm-bindgen-macro v0.2.12
   Compiling wasm-bindgen v0.2.12
   Compiling {{project-name}} v0.1.0 (file:///home/fitzgen/rust_wasm_template)
error: invalid character `{` in crate name: `{{project_name}}`

error: invalid character `}` in crate name: `{{project_name}}`

error: aborting due to 2 previous errors

error: Could not compile `{{project-name}}`.

To learn more, run the command again with --verbose.

Support repository banches

I set my templates up in one repository and was branching for differences in my templates (see cli-templates for my rough drafts); however, as of now cargo-generate only supports main branch templating.

To me it makes sense to have all my custom templates in one repostory but have the ability to call them by branch, vice several different repositories. Also it might make sense for offical templates to have branches with different specializations or layouts.

Related to RFC #47

0.2.0

make a changelog, etc

update liquid dep, document date functionality

While setting up my environment and templates I noticed a few areas that would be helpful to have a {{date}} placeholder. Might also be nice to have sub-date strings like {{year}} as well (e.g. for license, info).

Related to #46

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.