Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upImplement `cargo init` #2081
Conversation
rust-highfive
assigned
wycats
Oct 26, 2015
This comment has been minimized.
This comment has been minimized.
rust-highfive
commented
Oct 26, 2015
|
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @wycats (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. 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. |
This comment has been minimized.
This comment has been minimized.
|
Assignee for my previous attempt was @alexcrichton, but I don't know how to specify assignee when doing pull request here. Update: found: |
vi
changed the title
Implement `cargo init` (#21)
Implement `cargo init`
Oct 26, 2015
This comment has been minimized.
This comment has been minimized.
|
Nice work @vi! I'll see if I can get around to reviewing this tomorrow |
alexcrichton
assigned
alexcrichton
and unassigned
wycats
Oct 28, 2015
alexcrichton
reviewed
Nov 2, 2015
| Create a new cargo package in current directory | ||
| Usage: | ||
| cargo init [options] |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
Perhaps this could take an optional argument of a directory to initialize as well?
This comment has been minimized.
This comment has been minimized.
vi
Nov 4, 2015
Author
Contributor
I'm not sure how do I make optional positional arguments here. Naive attempt failed.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
vi
Nov 7, 2015
Author
Contributor
Found out: the main thing that it's a special library (Docopt) is in use and the usage string matters.
alexcrichton
reviewed
Nov 2, 2015
| Some(name) => name, | ||
| fn get_name<'a>(path: &'a Path, opts: &'a NewOptions, config: &Config) -> CargoResult<&'a str> { | ||
| match opts.name { | ||
| Some(name) => Ok(name), |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
This may be a little more nicely formatted as:
if let Some(name) = opts.name {
return Ok(name)
}
// rest ...
alexcrichton
reviewed
Nov 2, 2015
| metadata(&path).map(|x| x.is_file()).unwrap_or(false) | ||
| } | ||
|
|
||
| pub fn directory_already_exists(path: &Path) -> bool { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
This may be best named is_dir to mirror what the standard library provides
This comment has been minimized.
This comment has been minimized.
vi
Nov 4, 2015
Author
Contributor
It may be confused with stdlib's is_dir then, suprising readers with unusually simple signature.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Nov 2, 2015
| }) | ||
| } | ||
|
|
||
| pub fn write_if_not_exists(path: &Path, contents: &[u8]) -> CargoResult<()> { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
This helper function seems a little dangerous as it doesn't allow distinguishing the case where a file existed or the file was successfully written, perhaps the relevant locations this is called could just have guards on paths::is_file?
alexcrichton
reviewed
Nov 2, 2015
| mk(config, &path, name, &opts).chain_error(|| { | ||
| human(format!("Failed to create project `{}` at `{}`", | ||
| name, path.display())) | ||
| }) | ||
| } | ||
|
|
||
| pub fn init(opts: NewOptions, config: &Config) -> CargoResult<()> { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
Currently other commands all take the struct of options via a reference, so perhaps that could happen here as well?
This comment has been minimized.
This comment has been minimized.
vi
Nov 4, 2015
Author
Contributor
I have just copied the signature of pub fn new, which accepts ownership of its options.
alexcrichton
reviewed
Nov 2, 2015
| @@ -17,11 +17,13 @@ use toml; | |||
| #[derive(Clone, Copy, Debug, PartialEq)] | |||
| pub enum VersionControl { Git, Hg, NoVcs } | |||
|
|
|||
| #[derive(Clone, Debug, PartialEq)] | |||
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
Ideally these extra derive modes wouldn't be necessary, how come they were added?
This comment has been minimized.
This comment has been minimized.
vi
Nov 2, 2015
Author
Contributor
I needed Clone to be able to pass changed options (auto-detected bin, for example) to mk, so duplicated VersionControl's derive line, then removed incompatible Copy, thinking that Debug and PartialEq won't be amiss in any case when they can be implemented.
Should we economize derivations?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
Yeah I suspect the changes below would remove the need for Clone, and otherwise I personally prefer to minimize the number of derivations needed to reduce codegen/compile time.
alexcrichton
reviewed
Nov 2, 2015
| // if none exists, maybe create git, like in `cargo new` | ||
|
|
||
| if num_detected_vsces > 1 { | ||
| return Err(human("Both .git and .hg exist. I don't know what to choose.")); |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
Hm this error seems kinda odd, perhaps cargo init could just not do anything VCS-related if no VCS was found? If at least one was found it could just skip that step.
This comment has been minimized.
This comment has been minimized.
vi
Nov 4, 2015
Author
Contributor
It is the case when multiple VCS-es found, which I expect to be rare and confusing. If none VCS-es found and user hasn't specified any option, it follows what caro new does (i.e. initialize Git, unless it's already inside some another VSC).
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 5, 2015
Member
If any existing VCS is detected though, couldn't cargo just act as if --vcs none was specified?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
vi
Nov 5, 2015
Author
Contributor
No, I expect git init && cargo init to also fill in .gitignore.
Actually git init && hg init && cargo init could have been adding both .gitignore and .hgignore, but that (like with multiple source files) complexifies things a bit.
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 6, 2015
Member
Ah ok that's a good point, I forgot about filling in the ignore files! In that case this error can be a little more targeted than "I don't know what to choose" and could instead mention that with multiple VCS solutions it's not clear which ignore file to fill out.
alexcrichton
reviewed
Nov 2, 2015
|
|
||
| fn detect_source_path_and_type<'a : 'b, 'b>(project_path : &Path, | ||
| project_name: &str, | ||
| opts2: &'b mut NewOptions) -> CargoResult<()> { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
This argument should probably be called opts rather than opts2, and similarly if the two other arguments are renamed down below they can probably just have those names for the arguments
alexcrichton
reviewed
Nov 2, 2015
| pub struct NewOptions<'a> { | ||
| pub version_control: Option<VersionControl>, | ||
| pub bin: bool, | ||
| pub path: &'a str, | ||
| pub name: Option<&'a str>, | ||
| pub sourcefile_relative_path : Option<String>, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
This seems a little odd as an option here as it's calculated instead of ever passed in, perhaps this could be stored elsewhere?
This comment has been minimized.
This comment has been minimized.
vi
Nov 2, 2015
Author
Contributor
In this case mk should accept not NewOptions, but something else. Shall I create special private struct like MkOptions and convert from NewOptions to MkOptions both in new and in init?
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
Yeah that seems plausible, it could also just be an extra parameter to mk or could be attached to a MkContext which has a method doit or something like that.
alexcrichton
reviewed
Nov 2, 2015
| } | ||
| fn autodetect_bin_file(p: &Path) -> CargoResult<bool> { | ||
| let mut content = String::new(); | ||
| try!(File::open(p).and_then(|mut x| x.read_to_string(&mut content))); |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
I think there's a paths::read utility function which should help doing this.
alexcrichton
reviewed
Nov 2, 2015
|
|
||
| } | ||
| opts2.sourcefile_relative_path = Some(format!("{}.rs", name)); | ||
| found_source_files += 1; |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 2, 2015
Member
This may not be quite the logic we want, this means that if you have src/main.rs as well as src/foo.rs that you'll get an error about multiple source files, right? The latter may just be the library used by the first though.
This comment has been minimized.
This comment has been minimized.
|
Shall I try to improve things according to line comments or there needs to be major redesign of the feature? |
This comment has been minimized.
This comment has been minimized.
|
Nah I think this is definitely along the right lines, so feel free to make changes in this PR! |
This comment has been minimized.
This comment has been minimized.
|
How should the {both Ideally Cargo should create a project file with both Is support of bin+lib project in |
This comment has been minimized.
This comment has been minimized.
|
To me it just seemed a little odd to explicitly deny as it's relatively common. It may require some tweaks of how the implementation goes, but in theory it shouldn't be too onerous I think. |
This comment has been minimized.
This comment has been minimized.
|
Implemented updated
|
alexcrichton
reviewed
Nov 5, 2015
| pub fn append(path: &Path, contents: &[u8]) -> CargoResult<()> { | ||
| (|| -> CargoResult<()> { | ||
| let mut f = try!( | ||
| OpenOptions::new() |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 5, 2015
Member
This indentation seems a bit off, the OpenOptions should come right after the ( of the try!(
alexcrichton
reviewed
Nov 5, 2015
| @@ -1,5 +1,5 @@ | |||
| use std::env; | |||
| use std::fs; | |||
| use std::fs::{self}; | |||
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 5, 2015
Member
This probably doesn't need to be changed if it's just importing self
alexcrichton
reviewed
Nov 5, 2015
| H::Bin => | ||
| SourceFileInformation { relative_path: pp, bin: true }, | ||
| H::Lib => | ||
| SourceFileInformation { relative_path: pp, bin: false }, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Nov 5, 2015
|
|
||
| for i in tests { | ||
| let pp = i.proposed_path; | ||
| if ! paths::file_already_exists(&path.join(pp.clone())) { |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 5, 2015
Member
You can avoid the .clone() here by just passing &pp, and there's an extra space after the !
alexcrichton
reviewed
Nov 5, 2015
| Ok(()) | ||
| } | ||
|
|
||
| fn detect_source_paths_and_types<'a : 'b, 'b>(project_path : &'a Path, |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Nov 5, 2015
Member
Are these lifetime annotations necessary? If they're not being returned they can probably be elided
alexcrichton
reviewed
Nov 5, 2015
| Ok(()) | ||
| } | ||
|
|
||
| fn plan_new_source_file(bin: bool) -> SourceFileInformation { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
vi
Nov 5, 2015
Author
Contributor
No, it something around "add creation of new source file to the queue" or "get default SourceFileInformation depending on binary-ness" or "schedule creation of a new source file".
This comment has been minimized.
This comment has been minimized.
|
(sorry it's being a bit slow...) |
This comment has been minimized.
This comment has been minimized.
|
Thanks for being patient @vi! I talked with @wycats today and we're both quite comfortable moving forward with this. The only lingering thing we thought of is could you tweak the error message for when |
alexcrichton
added
the
relnotes
label
Jan 23, 2016
This comment has been minimized.
This comment has been minimized.
|
Done + rebased yet again. |
vi
force-pushed the
vi:cargo_init
branch
from
ebd2186
to
5e62d85
Jan 23, 2016
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Jan 23, 2016
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
This test differs from I can reproduce the failure with
but not with
What shall be fixed? Testing tool or Update: I see tests do something with |
vi
force-pushed the
vi:cargo_init
branch
from
5e62d85
to
800172f
Jan 23, 2016
This comment has been minimized.
This comment has been minimized.
|
Fixed the test to have |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Jan 24, 2016
This comment has been minimized.
This comment has been minimized.
|
|
bors
merged commit 800172f
into
rust-lang:master
Jan 24, 2016
bors
referenced this pull request
Jan 24, 2016
Closed
Allow licenses to be specified during `cargo new` #2013
This comment has been minimized.
This comment has been minimized.
|
Any reason why |
This comment has been minimized.
This comment has been minimized.
ticki
commented
Feb 17, 2016
|
@WiSaGaN Because |
This comment has been minimized.
This comment has been minimized.
|
It should be in the ignore for libraries, but not for binaries. On Feb 17, 2016, 09:29 -0500, Tickinotifications@github.com, wrote:
|
This comment has been minimized.
This comment has been minimized.
|
Is there any reason to include Better extra entry in gitignore than missing entry. Project may be recrafted into a library after creation... |
This comment has been minimized.
This comment has been minimized.
|
Yes, for repeatable builds. There's a FAQ entry about this distinction. On Feb 17, 2016, 09:59 -0500, Vitaly Shukelanotifications@github.com, wrote:
|
This comment has been minimized.
This comment has been minimized.
|
Shall I implement again bin/lib distinction for ignore file generation? Shall the lock file be checked into Git automatically by cargo new/init (in addition to not being added to gitignore) for bin projects? |
This comment has been minimized.
This comment has been minimized.
|
@vi , yes, please. |
This comment has been minimized.
This comment has been minimized.
|
It's not that simple. Restored the function in a proper way: #2390 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I remember wondering about whether the condition around adding |
vi commentedOct 26, 2015
Implement
cargo initcommand and appropriate tests ( #21).Features:
cargo newif there are no files in current directory--bin[lib]or[[bin]]section toCargo.tomlin case of some non-standard source locationsConcerns: