-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resubmission of templating PR (#1747) #3004
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Nice! I would really love to have this. Copying the same README.md, LICENSE, travis, gitignore, editorconfig, etc. files into every repo can't be the way it's supposed to go. |
Thanks for re-submitting this. I never got the time to come back to it unfortunately, but I think its very useful and would love to see it finished off and merged. Thanks for taking it on @ehiggs! |
The biggest thing not addressed by this from the earlier PR was the use of Handlebars instead of Mustache. At the time the existing Handlebars implementations were a little unstable, but I imagine it's better now so should be easier to work in. |
@gchp agreed. So the work is as follows:
Future work: |
Cargo.lock
Outdated
"openssl-sys-extras 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", | ||
] | ||
|
||
[[package]] | ||
name = "openssl-sys" | ||
version = "0.7.14" | ||
version = "0.7.17" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this may have run cargo update
, but could this commit just add the dependencies it needs to?
Thanks for the revival @ehiggs! Excited to see progress on this |
src/cargo/ops/cargo_new.rs
Outdated
}; | ||
let template_dir = templates_dir.join(repo_name); | ||
|
||
match Repository::clone(template, &*template_dir) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cargo typically issues a status message for operations that may take a long time, so perhaps this could indicate that a repository is being cloned?
I think this may also wish to use the helpers in git/utils.rs
to ensure this handles pieces such as authentication, retries, etc.
I've done some work on this and rebased. I changed the way remote repos work by cloning them into a tempdir and using them as a template. The tempdir is then deleted when it goes out of scope. I do something similar with the default bin/lib templates. These are dumped to a tempdir and then used as a template. I tried to use In trying to get the I also made a skeleton repository to test this with. It used docopt and has a LICENSE file and everything to get started writing command line programs that use subcommands. It's basically @BurntSushi's xsv stripped down to... a skeleton 💀 (I keep calling it a skeleton since that's what it's called in |
I've added some commits that address docs and fix the tests. |
Travis failed due to a network issue. Appveyor failed on "override_cargo_home" but I don't have access to a Windows box to try and reproduce it. |
Thanks for the update @ehiggs! Some thoughts of mine:
Also cc @rust-lang/tools, would be good to start hearing thoughts about this as well! |
There seems to be some confusion here. @gchp's original work cloned the remote repository into So I guess the resulting work should be:
For the default template, I would keep |
I like the feature and from reading the docs this seems pretty reasonable. I've always envisioned project templates being part of the platform, so I would expect us to eventually distribute a bunch of them by default, and for IDEs to have options to instantiate them. This implementation doesn't provide for that yet since it only reads from As a step toward including templates in the Rust distribution by default I might expect and encourage somebody to maintain a project collecting templates - a single repo that contains nothing but templates. Thus people would naturally want to instantiate templates out of a subdirectory of a git repo, not from the top-level of the repo. This implementation seems to support one template per repo. |
In writing the example repository I thought that it might be a pain the backside to maintain several repositories for each skeleton. I think the options would be:
|
After discussion with @brson on irc, we think this will work: New lib: New local template:
New template based on git repo:
New template based on git repo where the repo is a collection of templates:
Probably new errors:
|
☔ The latest upstream changes (presumably #3057) made this pull request unmergeable. Please resolve the merge conflicts. |
@ehiggs oh thanks for the previous clarifications! The strategy you and @brson came up with sounds reasonable to me, but I wonder if we could perhaps forgo the If you want to rebase I can take another look as well. |
I rebased and removed use of the config. So now there is The following is supported: New default library: New default binary: New templated project based on remote repo: New templated project selecting a single template from a bunch in the repository: Local repo (untested Local directory: Error (template with no associated repo): |
src/cargo/ops/cargo_new.rs
Outdated
|
||
let template_dir = match (opts.template_repo, opts.template) { | ||
// given template is a remote git repository & needs to be cloned | ||
// This will be cloned to .cargo/templates/<repo_name> where <repo_name> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be true anymore, I think that's a left over from previous iterations.
☔ The latest upstream changes (presumably #3185) made this pull request unmergeable. Please resolve the merge conflicts. |
I think travis had some network trouble: Linux beta toolchain:
OS X stable toolchain:
|
src/cargo/ops/cargo_new.rs
Outdated
println!("Checking out repo to dir: {}", template_dir.path().display()); | ||
|
||
try!(config.shell().status("Cloning", repo_url)); | ||
match Repository::clone(repo_url, &*template_dir.path()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this use the support in the sources::git
module? That way it'd handle cloning concerns like proxies and such.
src/cargo/ops/cargo_new.rs
Outdated
match Repository::clone(repo_url, &*template_dir.path()) { | ||
Ok(_) => {}, | ||
Err(e) => { | ||
return Err(human(format!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this use chain_error
and try!
?
src/cargo/ops/cargo_new.rs
Outdated
// given template is a remote git repository & needs to be cloned | ||
TemplateType::GitRepo(repo_url) => { | ||
let template_dir = try!(TempDir::new(name)); | ||
println!("Checking out repo to dir: {}", template_dir.path().display()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print?
src/cargo/ops/cargo_new.rs
Outdated
@@ -366,6 +461,10 @@ fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool { | |||
GitRepo::discover(path, cwd).is_ok() || HgRepo::discover(path, cwd).is_ok() | |||
} | |||
|
|||
fn file(p: &Path, contents: &[u8]) -> io::Result<()> { | |||
try!(File::create(p)).write_all(contents) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra indent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think there may be a helper for this in cargo::util::paths
? If not, could you add one there?
src/cargo/ops/cargo_new.rs
Outdated
} | ||
// make sure that the template exists | ||
if fs::metadata(&template_path).is_err() { | ||
return Err(human(format!("Template `{}` not found", template_path.display()))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the bail!
macro here for a bit more ergonomic bailing out, and also stylistically Cargo error messages start with a lowercase letter.
src/cargo/ops/cargo_new.rs
Outdated
} | ||
|
||
// create the new file & render the template to it | ||
let mut dest_file = OpenOptions::new().write(true).create(true).open(&dest_path).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unwrap
should be an error (I think there may also be a utility function for this)
src/cargo/ops/cargo_new.rs
Outdated
fn walk_template_dir(dir: &Path, cb: &mut FnMut(DirEntry)) -> CargoResult<()> { | ||
let attr = try!(fs::metadata(&dir)); | ||
|
||
let ignore_files = vec!(".gitignore"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically we use vec![]
instead of vec!()
src/cargo/ops/cargo_new.rs
Outdated
let attr = try!(fs::metadata(&dir)); | ||
|
||
let ignore_files = vec!(".gitignore"); | ||
let ignore_types = vec!("png", "jpg", "gif"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a bit of an odd ignore list, shouldn't we try to walk over everything?
src/cargo/ops/cargo_new.rs
Outdated
try!(walk_template_dir(&entry.path(), cb)); | ||
} | ||
} else { | ||
if let &Some(extension) = &entry.path().extension() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could these &
sigils get removed?
src/cargo/ops/cargo_new.rs
Outdated
} else { | ||
try!(create_lib_template(&temp_templates_path)); | ||
} | ||
TemplateDirectory::Temp(temp_templates_dir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are using a builtin template, could we avoid writing out to the filesystem? That shouldn't be strictly required, right?
Perhaps the template could get loaded into memory here in all cases?
I've fixed it so |
☔ The latest upstream changes (presumably #3618) made this pull request unmergeable. Please resolve the merge conflicts. |
PR #3004 This is a resubmission of the PR #1747 (from scratch) which adds support for templating in Cargo. The templates are implemented using the handlebars crate (where the original PR used mustache). Examples: cargo new --template https://url/to/template somedir foo cargo new --template https://url/to/templates --template-subdir somedir foo cargo new --template ../path/to/template somedir foo
Beta was branched let's merge! @bors: r+ |
📌 Commit 265452d has been approved by |
⌛ Testing commit 265452d with merge 5ef54e0... |
Travis has had problems with the OS X queue. Hence the ❌ |
💔 Test failed - status-travis |
@bors: retry |
Resubmission of templating PR (#1747) This is a manual rebase of the older #1747 PR which was basically unrebasable due to the time it's been dormant.. This implements templating for Cargo and is basically the work of Greg Chapple (@gchp). I'd love for this feature to move forward since it's really tedious to create all the directories (e.g. `src/bin`) and copy paste docopt examples which I then edit. Then implement the `main` program to delegate to the subcommands in `src/bin`, etc.
☀️ Test successful - status-appveyor, status-travis |
🎉 Thanks so much again @ehiggs for your patience! |
Thank you for the patience. Now time to go bash out some templates. 😀 |
@ehiggs I think it's safe to say you far out-did my original work 😄 great job! |
…alexcrichton Restore the generated tests module created by `cargo new` Appears to have been removed unintentionally in #3004. Was just working on the book, ran `cargo new adder` with cargo-0.18.0-nightly (6f1b860 2017-02-11), and got this in `src/lib.rs`: ```rust #[test] fn it_works() { } ``` when I expected to get this: ```rust #[cfg(test)] mod tests { #[test] fn it_works() { } } ``` It looks like this was changed as part of #3004 ([removed](875a8ab#diff-149dd4362a3b0dc13b113762713119dfL477), [added](875a8ab#diff-149dd4362a3b0dc13b113762713119dfR678)), I'm assuming unintentionally? The regression has not yet hit the beta channel; `cargo-0.17.0-nightly (0bb8047 2017-02-06)` generates the src/lib.rs I expect.
A note that this pull-request has been reverted in #3878 in waiting for a RFC. |
Indeed, ongoing discussion is here. It seems there is no consensus yet. |
This is a manual rebase of the older #1747 PR which was basically unrebasable due to the time it's been dormant.. This implements templating for Cargo and is basically the work of Greg Chapple (@gchp).
I'd love for this feature to move forward since it's really tedious to create all the directories (e.g.
src/bin
) and copy paste docopt examples which I then edit. Then implement themain
program to delegate to the subcommands insrc/bin
, etc.