Skip to content

cargo new --template needs a documented way to pass files through literally #3860

@ssokolow

Description

@ssokolow

When I went to test the behaviour of a tweak to my CLI utility boilerplate and ran just build-release, I got an error about "" being incorrectly indented.

After a little investigation, I realized that cargo new --template's default behaviour is incompatible with just because they use the same syntax for substitution.

Here's how --template mangled the project that, up until now, I've been generating new projects from using cp -r rust-cli-boilerplate "$1"; rm "$1"/.git; {some omitted stuff to sed into Cargo.toml}; git init.

diff -u -ur ../rust-cli-boilerplate/justfile ./justfile
--- ../rust-cli-boilerplate/justfile    2017-03-18 10:21:52.823085192 -0400
+++ ./justfile  2017-03-23 10:16:33.320413082 -0400
@@ -47,21 +47,21 @@
 build-release: miniclean build
        @# Depend on miniclean since stripping UPXd executables is fatal
        @printf "\n--== Stripping, SStripping, and Compressing With UPX ==--\n"
-       {{strip_bin}} {{strip_flags}} "{{zz_target_path}}"
+         ""
        @# Allow sstrip to fail because it can't be installed via "just install-deps"
-       sstrip "{{zz_target_path}}" || true
-       upx {{upx_flags}} "{{zz_target_path}}"
+       sstrip "" || true
+       upx  ""
        @printf "\n--== Final Result ==--\n"
-       @ls -sh "{{zz_target_path}}"
+       @ls -sh ""
        @printf "\n"
 
-# Alias for `cargo check {{args}}` with the default toolchain
+# Alias for `cargo check ` with the default toolchain
 check +args="":
-       cargo check {{args}}
+       cargo check 
 
-# Alias for `cargo fmt -- {{args}}`
+# Alias for `cargo fmt -- `
 fmt +args="":
-       cargo fmt -- {{args}}
+       cargo fmt -- 
 
 # Use `apt-get` to install dependencies `cargo` can't (except `kcov` and `sstrip`)
 install-apt-deps:
@@ -80,8 +80,8 @@
        @# Prevent this from gleefully doing an unwanted "rustup update"
        rustup toolchain list | grep -q stable || rustup toolchain install stable
        rustup toolchain list | grep -q nightly || rustup toolchain install nightly
-       rustup toolchain list | grep -q '{{channel}}' || rustup toolchain install '{{channel}}'
-       rustup target list | grep -q '{{target}} (' || rustup target add '{{target}}'
+       rustup toolchain list | grep -q '' || rustup toolchain install ''
+       rustup target list | grep -q ' (' || rustup target add ''
 
 # Run `install-apt-deps` and `install-cargo-deps`, list what remains.
 @install-deps: install-apt-deps install-cargo-deps
@@ -95,10 +95,10 @@
 # Run a debug build under callgrind, then open the profile in KCachegrind.
 kcachegrind +args="":
        cargo build
-       rm -rf '{{ callgrind_out_file }}'
-       valgrind --tool=callgrind --callgrind-out-file='{{ callgrind_out_file }}' {{ callgrind_args }} 'target/debug/{{ zz_pkgname }}' '{{ args }}' || true
-       test -e '{{ callgrind_out_file }}'
-       kcachegrind '{{ callgrind_out_file }}'
+       rm -rf ''
+       valgrind --tool=callgrind --callgrind-out-file=''  'target/debug/' '' || true
+       test -e ''
+       kcachegrind ''
 
 # Generate a statement coverage report in `target/cov/`
 kcov:
@@ -139,11 +139,11 @@
 
 # Remove the release binary. (Used to avoid `strip`-ing UPX'd files.)
 @miniclean:
-       rm -f "{{zz_target_path}}"
+       rm -f ""
 
-# Alias for `cargo run -- {{args}}` with the *default* toolchain
+# Alias for `cargo run -- ` with the *default* toolchain
 run +args="":
-       cargo run -- {{args}}
+       cargo run -- 
 
 # Run all installed static analysis, plus `cargo +stable test`.
 test:
diff -u -ur ../rust-cli-boilerplate/README.md ./README.md
--- ../rust-cli-boilerplate/README.md   2017-03-18 10:20:27.496284234 -0400
+++ ./README.md 2017-03-23 10:16:33.360412488 -0400
@@ -134,12 +134,12 @@
 <tr>
   <td><code>check</code></td>
   <td>args (optional)</td>
-  <td>Alias for <code>cargo check {{args}}</code> with the default toolchain.</code></td>
+  <td>Alias for <code>cargo check </code> with the default toolchain.</code></td>
 </tr>
 <tr>
   <td><code>fmt</code></td>
   <td>args (optional)</td>
-  <td>Alias for <code>cargo fmt -- {{args}}</code></td>
+  <td>Alias for <code>cargo fmt -- </code></td>
 </tr>
 <tr>
   <td><code>install-apt-deps</code></td>
@@ -186,7 +186,7 @@
 <tr>
   <td><code>run</code></td>
   <td>args (optional)</td>
-  <td>Alias for <code>cargo run -- {{args}}</code> with the <em>default</em>
+  <td>Alias for <code>cargo run -- </code> with the <em>default</em>
 toolchain.</td>
 </tr>
 <tr>

Just isn't exactly the most obscure thing and I think you can see how this would be a problem, so I hope you'll agree that there needs to be some kind of solution to pass things like justfile (which use {{ and }} in their own syntax) through literally.

(Imagine if I want to include a base.html.incl with the Twitter Bootstrap boilerplate in a web project which uses a templating engine with this sort of Django/Jinja/Twig-style syntax. cargo new --template would mangle that too.)

Heck, in hindsight, it'd make a lot more sense to make it opt-in. Perhaps a backwards-compatible middle ground could be achieved using some kind of "template config file" which, if present, overrides the current behaviour. That'd allow...

  • Specifying a whitelist for things to template.
  • Specifying a blacklist for things like README.md which need to exist in the template repo, but not get copied over.
  • Specifying a "rename list" for situations like LICENSE and .travis.yml where the template and the project it generates need different content for the same files. (My template is MIT/Apache, but it generates GPL3 boilerplate. Also, the template needs a special .travis.yml to run cargo new --template before testing.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions