-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Reduce complexity of src/cli/index.js #2887
Reduce complexity of src/cli/index.js #2887
Conversation
4d8ffe6
to
7272f83
Compare
I'll get back to this in a couple of days, thanks for waiting |
I added some comments in the code but i will wait your feedback before pushing anything else ;) |
I opened other two pull requests for what can be saved from #2810 ;) |
@bestander do you have any news on this? :p |
Sorry, Simon, it is definitely on my list.
I'll try to have a look ASAP.
…On 1 April 2017 at 18:15, Simon Vocella ***@***.***> wrote:
@bestander <https://github.com/bestander> do you have any news on this? :p
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2887 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACBdWCXSJ72Tom6hH1NIWQX5L5KX_R62ks5rroZJgaJpZM4MZbH8>
.
|
Hey @bestander , don't worry ;) and thanks for your work! |
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.
Great work, @voxsim!
Let's rebase and merge this.
yeah sure, I need some support from @arcanis for a5a5915. Could you please write me an use case for @bestander could you please answer about this queston? I hope to not mistype anything, but sorry I am writing from my phone :p |
ok maybe I get it, sorry @arcanis for bother you ;) |
Just a guess - so that commands could be referred a object properties when needed |
mmh if we do that right now It will not work because it has an uppercase letter. If we don't find any use case maybe we should delete that code and let's wait for complains :p |
@voxsim you may have already found it, but the code you quoted is related to this PR, and should be covered by these tests 😃 Let me know if you have specific questions about it (disregard the "test disabled for now" comment, I've just enabled it but forgot to remove the comment) |
Btw, I think there's two reasons the command name is camelCased:
|
@arcanis i tried both and they work as expected without camelCase. I always advocate "no code over code that i don't understand", but i don't want to be pushy, I'll let decide you, I understand that some time it's better to be conservative ;) Btw I finished I should push in a bunch of minutes |
b231c80
to
0dd467c
Compare
…; flags and arguments after --
…because the previous one was flaky
… set commandName as the first arg for npm_config_argv
0dd467c
to
1e35469
Compare
Ok i finished to rebase everything ;) let me know! For what i see the tests failed for reasons not related to my pull request |
I was wrong and after some digging we use the camelCase function only for 'generate-lock-entry' and 'upgrade-interactive'. Maybe we can achieve the same behaviour without camelCase every command. I will prepare another pull request on this part. |
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.
Nice work, thanks! :) The only thing I'm a bit concerned with (and that's not related to your PR in itself) is that we seem to be hardcoding a lot of logic that should imo be handled by a dedicated third-party library instead. For example, aliases, camelCasing, this cmd
hack, the --help
output, extracting the command name from the argv
, ...
Maybe in a future PR it could be interesting to look if we can use anything out there that would discard the need to maintain all of this logic. What do you think?
const commandName = camelCase(args.shift()); | ||
|
||
if (commandName) { | ||
const command = commands[commandName]; |
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.
We probably should validate every such access with Object.prototype.hasOwnProperty
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 validate here maybe we should validate in src/cli/index.js. What do you think?
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.
Yep! It will fix this:
❯ [mael-mbp?] yarn git:(0.23-stable) ❯ yarn constructor
yarn constructor v0.23.0
error An unexpected error occurred: "command.run is not a function".
info If you think this is a bug, please open a bug report with the information provided in "/Users/mael/yarn/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/constructor for documentation about this command.
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 is a pre-existent error, but i prefer to fix here right now. If I am correctly after this part, we will finish this review.
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.
👍
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.
@arcanis done!
continue; | ||
const commandName = camelCase(args.shift()); | ||
|
||
if (commandName) { |
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 don't have to check this, since it won't pass the following test (commands[commandName]
will be undefined)
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 have to check this because commandName can be null, sorry I lost this comment!
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.
Yeah ... it seems this camelCase
function should rather be called ifCamelCaseNullElseCamelCase
😄
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.
YES T_T XD
src/cli/index.js
Outdated
let command; | ||
const camelised = camelCase(commandName); | ||
if (camelised) { | ||
command = commands[camelised]; |
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.
Why not
commandName = camelCase(commandName);
if (!Object.prototype.hasOwnProperty.call(commands, commandName)) {
args.unshift(commandName);
commandName = `run`;
}
command = commands[commandName];
?
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 added a || commandName
because camelCase
function return null in some cases.
The final version:
commandName = camelCase(commandName) || commandName;
if (!Object.prototype.hasOwnProperty.call(commands, commandName)) {
args.unshift(commandName);
commandName = 'run';
}
command = commands[commandName];
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.
@arcanis I am sorry but I can't do that :( because if you type yarn custom-script
it does something horrible because it camel case custom-script
.
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.
Oooooh right :/ damn.
src/cli/index.js
Outdated
...startArgs, | ||
// we use this for https://github.com/tj/commander.js/issues/346, otherwise | ||
// it will strip some args that match with any options | ||
'cmd', |
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.
Use something more descriptive than cmd
, something like this-arg-will-get-stripped-later
. It will help the next person to read this hack to understand how it works, and doesn't risk to conflict with any future command.
src/cli/index.js
Outdated
} | ||
invariant(command, 'missing command'); | ||
// we strip cmd | ||
commander.args.shift(); |
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.
We probably want to make a console.assert
here to make sure that we're shifting the right argument, what do you think?
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.
Mmh could you please write an example to understand on how you want to use console.assert
here?
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.
console.assert(commander.args.length >= 1);
console.assert(commander.args[0] === 'cmd');
commander.args.shift();
So that if for some reason we would be shifting the wrong argument, the code early crashes instead of doing something else than what the user expected, which might be hard to debug otherwise.
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.
done!
@@ -382,7 +343,7 @@ config.init({ | |||
httpsProxy: commander.httpsProxy, | |||
networkConcurrency: commander.networkConcurrency, | |||
nonInteractive: commander.nonInteractive, | |||
commandName, | |||
commandName: commandName === 'run' ? commander.args[0] : commandName, |
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.
Not sure we can do this; yarn version
and yarn run version
would both end up with a version
commandName, which is semantically wrong because they have different behaviors. If we want to support user-defined commands here, then it should be in a separate field.
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.
Ok this was a pre-existent error, can we open another pull request on this?
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.
Yep, you're right. Let's keep the current behavior
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 evening I have to remember to open at least one issue, otherwise I will forget everything :)
continue; | ||
const commandName = camelCase(args.shift()); | ||
|
||
if (commandName) { |
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 need to check what happened when i type yarn unknown-command --help. It should ignore everything and display standard help. Maybe this behaviour is wrong
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.
OK I was right. In detail: yarn unknown --help
before:
Usage: yarn [command] [flags]
Options:
-h, --help output usage information
-V, --version output the version number
--verbose output verbose messages on internal operations
--offline trigger an error if any required dependencies are not available in local cache
--prefer-offline use network only if dependencies are not available in local cache
--strict-semver
--json
--ignore-scripts don't run lifecycle scripts
--har save HAR output of network traffic
--ignore-platform ignore platform checks
--ignore-engines ignore engines check
--ignore-optional ignore optional dependencies
--force ignore all caches
--no-bin-links don't generate bin links when setting up packages
--flat only allow one version of a package
--prod, --production [prod]
--no-lockfile don't read or generate a lockfile
--pure-lockfile don't generate a lockfile
--frozen-lockfile don't generate a lockfile and fail if an update is needed
--link-duplicates create hardlinks to the repeated modules in node_modules
--global-folder <path>
--modules-folder <path> rather than installing modules into the node_modules folder relative to the cwd, output them here
--cache-folder <path> specify a custom folder to store the yarn cache
--mutex <type>[:specifier] use a mutex to ensure only one yarn instance is executing
--no-emoji disable emoji in output
--proxy <host>
--https-proxy <host>
--no-progress disable progress bar
--network-concurrency <number> maximum number of concurrent network requests
after pr:
Usage: yarn [command] [flags]
Options:
-h, --help output usage information
-V, --version output the version number
--verbose output verbose messages on internal operations
--offline trigger an error if any required dependencies are not available in local cache
--prefer-offline use network only if dependencies are not available in local cache
--strict-semver
--json
--ignore-scripts don't run lifecycle scripts
--har save HAR output of network traffic
--ignore-platform ignore platform checks
--ignore-engines ignore engines check
--ignore-optional ignore optional dependencies
--force install and build packages even if they were built before, overwrite lockfile
--skip-integrity-check run install without checking if node_modules is installed
--no-bin-links don't generate bin links when setting up packages
--flat only allow one version of a package
--prod, --production [prod]
--no-lockfile don't read or generate a lockfile
--pure-lockfile don't generate a lockfile
--frozen-lockfile don't generate a lockfile and fail if an update is needed
--link-duplicates create hardlinks to the repeated modules in node_modules
--global-folder <path>
--modules-folder <path> rather than installing modules into the node_modules folder relative to the cwd, output them here
--cache-folder <path> specify a custom folder to store the yarn cache
--mutex <type>[:specifier] use a mutex to ensure only one yarn instance is executing
--no-emoji disable emoji in output
--proxy <host>
--https-proxy <host>
--no-progress disable progress bar
--network-concurrency <number> maximum number of concurrent network requests
--non-interactive do not show interactive prompts
Commands:
- access
- add
- bin
- cache
- check
- clean
- config
- generate-lock-entry
- global
- help
- import
- info
- init
- install
- licenses
- link
- list
- login
- logout
- outdated
- owner
- pack
- publish
- remove
- run
- tag
- team
- unlink
- upgrade
- upgrade-interactive
- version
- versions
- why
Run `yarn help COMMAND` for more information on specific commands.
Visit https://yarnpkg.com/en/docs/cli/ to learn more about Yarn.
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.
Good idea! I'd probably put them on a single line, comma-separate, restricted to 80 columns. Otherwise they take a lot of vertical space.
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.
Do you mean the commands
part? I can do that if you confirm
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.
Yep!
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 can't overwrite the commands part without doing other horrible things for what I understand because it is a feature of commander.js -.-. In detail the function help.
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.
Actually I think it's done userland, more precisely here. That being said, I've checked locally and it seems that this display (one command each line) was already printed this way in recent Yarn releases, so let's keep it this way. 👍
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 are right! As you wish :)
src/cli/index.js
Outdated
let command; | ||
const camelised = camelCase(commandName); | ||
if (camelised) { | ||
command = commands[camelised]; |
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 added a || commandName
because camelCase
function return null in some cases.
The final version:
commandName = camelCase(commandName) || commandName;
if (!Object.prototype.hasOwnProperty.call(commands, commandName)) {
args.unshift(commandName);
commandName = 'run';
}
command = commands[commandName];
@@ -382,7 +343,7 @@ config.init({ | |||
httpsProxy: commander.httpsProxy, | |||
networkConcurrency: commander.networkConcurrency, | |||
nonInteractive: commander.nonInteractive, | |||
commandName, | |||
commandName: commandName === 'run' ? commander.args[0] : commandName, |
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.
Ok this was a pre-existent error, can we open another pull request on this?
src/cli/index.js
Outdated
} | ||
invariant(command, 'missing command'); | ||
// we strip cmd | ||
commander.args.shift(); |
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.
Mmh could you please write an example to understand on how you want to use console.assert
here?
@arcanis I think you are totally right about that ;) If you see some something weird about reviews, I am sorry but I forgot to submit many days ago O.o |
1e35469
to
4d930e9
Compare
@@ -70,7 +70,7 @@ export function getRcArgs(command: string): Array<string> { | |||
|
|||
let result = rcArgsCache['*'] || []; | |||
|
|||
if (command !== '*') { | |||
if (command !== '*' && Object.prototype.hasOwnProperty.call(rcArgsCache, command)) { |
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.
Ah! You got me :)
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.
:D
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.
Great job 👍 I'll just wait to see what Travis has to say, but it's good for me
After working some time on #2810 I thought that maybe I was trying to reduce the complexity of src/cli/index.js from the wrong point of view.
In this pull request I:
Test plan, add test:
Everything else seems tested properly and this change is less invasive than what i do in #2810.
@bestander let me know if you like and sorry if I spam you a lot :P
Feedbacks from everyone are always welcome :)
Questions:
Simon
PS I left some other useful commits from #2810, maybe I will add to this pull request or open others after, in detail: