Skip to content
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

repl: Fixed node repl history edge case. Fixes #4102. #4108

Closed
wants to merge 1 commit into from

Conversation

zeusdeux
Copy link
Contributor

@zeusdeux zeusdeux commented Dec 1, 2015

If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Also, in the test file, I moved the file paths above common
messages to make it easier to shift to template strings in the
future to build the messages.

@Fishrock123 Fishrock123 added the repl Issues and PRs related to the REPL subsystem. label Dec 1, 2015
@@ -121,22 +121,43 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) {
if (data) {
repl.history = data.split(/[\n\r]+/, repl.historySize);
} else if (oldHistoryPath) {
// Grab data from the older pre-v3.0 JSON NODE_REPL_HISTORY_FILE format.
repl._writeToOutput(
if (oldHistoryPath === historyPath) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this if/else be wrapped into the above if/else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could but that would give rise to else if branches with repeated checks. It would end up looking something like the following:

if (data) {
  repl.history = data.split(/[\n\r]+/, repl.historySize);
} else if (oldHistoryPath && oldHistoryPath === historyPath) {
  // If pre-v3.0, the user had set NODE_REPL_HISTORY_FILE to
  // ~/.node_repl_history. Warn the user about it and proceed.
  ...
} else if (oldHistoryPath && oldHistoryPath !== historyPath) {
  // Grab data from the older pre-v3.0 JSON NODE_REPL_HISTORY_FILE format.
  repl._writeToOutput(
    '\nConverting old JSON repl history to line-separated history.\n' +
    `The new repl history file can be found at ${historyPath}.\n`);
  repl._refreshLine();
  ...
}

I am not a fan tbh but if that is what works for the node project then I have no qualms @Fishrock123 :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong, but I think it could be shortened to:

if (data) {
} else if (oldHistoryPath === historyPath) {
} else if (oldHistoryPath) {
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yupp that would. historyPath can never be empty. Boop!

@zeusdeux
Copy link
Contributor Author

zeusdeux commented Dec 2, 2015

@Fishrock123 Do you prefer squashed commits + force pushes or a verbose commit history?
I force pushed my changes based on your feedback for this iteration but can change how we go about this based on what work for this project.

@Fishrock123
Copy link
Contributor

@zeusdeux Either or. Squashing at the end is fine, and often what I do unless it's more convenient to squash inbetween.

@@ -66,17 +77,24 @@ const homedirErr = '\nError: Could not get the home directory.\n' +
'REPL session history will not be persisted.\n';
const replFailedRead = '\nError: Could not open history file.\n' +
'REPL session history will not be persisted.\n';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zeusdeux I'd just put the new message here. :)

@zeusdeux zeusdeux force-pushed the issue-4102 branch 2 times, most recently from 5c7f3f5 to 0ff9fb3 Compare December 4, 2015 17:45
@zeusdeux
Copy link
Contributor Author

zeusdeux commented Dec 4, 2015

Made changes based on feedback, rebased against master and sorted it all into one commit, 0ff9fb3.

@@ -94,6 +100,17 @@ const tests = [{
expected: [prompt, replDisabled, prompt]
},
{
env: { NODE_REPL_HISTORY_FILE: emptyHistoryPath },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this one be defaultHistoryPath?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, this test would test the same path as the test on line 108 since oldHistoryPath === historyPath as both would be $HOME/.node_repl_history.
This test exists to test the the else if (oldHistoryPath) branch.

@Fishrock123
Copy link
Contributor

@zeusdeux could you make sure to run make -j$(getconf _NPROCESSORS_ONLN) test? That will run the tests and the linter. (Which you could also run with make jslint.


// If there is NO old history, set repl history to an empty array.
if (oldReplJSONHistory) repl.history = JSON.parse(oldReplJSONHistory);
else repl.history = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto, shouldn't need the else.

@zeusdeux
Copy link
Contributor Author

zeusdeux commented Dec 7, 2015

I run make -j4 test before every commit to make sure my changes aren't breaking stuff. :)

},
{
env: { NODE_REPL_HISTORY: emptyHistoryPath,
NODE_REPL_HISTORY_FILE: emptyHistoryPath },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zeusdeux The history is cleaned up and emptied by default in these tests, is it possible this one should be as follows?

env: { NODE_REPL_HISTORY_FILE: defaultHistoryPath },

If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.
@zeusdeux
Copy link
Contributor Author

Included your suggestions and moved stuff into the parallel directory @Fishrock123 :)

@Fishrock123 Fishrock123 self-assigned this Dec 16, 2015
@zeusdeux
Copy link
Contributor Author

Is there anything else you would want me to work on to get this PR ready @Fishrock123?

// to line separated history.
var oldReplJSONHistory = fs.readFileSync(oldHistoryPath, 'utf8');

// If there is NO old history, set repl history to an empty array.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be something like "Only use old history if there was any"

@Fishrock123
Copy link
Contributor

@zeusdeux lgtm, you're free to fix that nit, otherwise I will on merging sometime later today/tomorrow.

Fishrock123 pushed a commit that referenced this pull request Dec 22, 2015
If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Fixes: #4102
PR-URL: #4108
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
@Fishrock123
Copy link
Contributor

Thanks, landed in 29c4a2a with the following nits patched: (just comment-y stuff and position of a thing in a test)

diff --git a/lib/internal/repl.js b/lib/internal/repl.js
index fa357c1..4825d5d 100644
--- a/lib/internal/repl.js
+++ b/lib/internal/repl.js
@@ -122,7 +122,7 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) {
       repl.history = data.split(/[\n\r]+/, repl.historySize);
     } else if (oldHistoryPath === historyPath) {
       // If pre-v3.0, the user had set NODE_REPL_HISTORY_FILE to
-      // ~/.node_repl_history. Warn the user about it and proceed.
+      // ~/.node_repl_history, warn the user about it and proceed.
       repl._writeToOutput(
           '\nThe old repl history file has the same name and location as ' +
           `the new one i.e., ${historyPath} and is empty.\nUsing it as is.\n`);
@@ -136,11 +136,11 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) {
       repl._refreshLine();

       try {
-        // Pre-v3.0, repl history was stored as JSON. Try and convert it
-        // to line separated history.
-        var oldReplJSONHistory = fs.readFileSync(oldHistoryPath, 'utf8');
+        // Pre-v3.0, repl history was stored as JSON.
+        // Try and convert it to line separated history.
+        const oldReplJSONHistory = fs.readFileSync(oldHistoryPath, 'utf8');

-        // If there is NO old history, set repl history to an empty array.
+        // Only attempt to use the history if there was any.
         if (oldReplJSONHistory) repl.history = JSON.parse(oldReplJSONHistory);

         if (!Array.isArray(repl.history)) {
diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js
index 8e6433c..9b4b389 100644
--- a/test/parallel/test-repl-persistent-history.js
+++ b/test/parallel/test-repl-persistent-history.js
@@ -66,6 +66,10 @@ const homedirErr = '\nError: Could not get the home directory.\n' +
                    'REPL session history will not be persisted.\n';
 const replFailedRead = '\nError: Could not open history file.\n' +
                        'REPL session history will not be persisted.\n';
+const sameHistoryFilePaths = '\nThe old repl history file has the same name ' +
+                             'and location as the new one i.e., ' +
+                             path.join(common.tmpDir, '.node_repl_history') +
+                             ' and is empty.\nUsing it as is.\n';
 // File paths
 const fixtures = path.join(common.testDir, 'fixtures');
 const historyFixturePath = path.join(fixtures, '.node_repl_history');
@@ -76,11 +80,6 @@ const enoentHistoryPath = path.join(fixtures, 'enoent-repl-history-file.json');
 const emptyHistoryPath = path.join(fixtures, '.empty-repl-history-file');
 const defaultHistoryPath = path.join(common.tmpDir, '.node_repl_history');

-const sameHistoryFilePaths = '\nThe old repl history file has the same name ' +
-                             'and location as the new one i.e., ' +
-                             path.join(common.tmpDir, '.node_repl_history') +
-                             ' and is empty.\nUsing it as is.\n';
-
 const tests = [{
   env: { NODE_REPL_HISTORY: '' },
   test: [UP],

@Fishrock123
Copy link
Contributor

(I guess I should have left comments on more for those, but eh, I didn't feel like it was worth it.)

@MylesBorins
Copy link
Contributor

@Fishrock123 should this be on lts watch? are the changes that broke repl in v4.x-staging?

Fishrock123 pushed a commit to Fishrock123/node that referenced this pull request Dec 22, 2015
If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Fixes: nodejs#4102
PR-URL: nodejs#4108
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
@Fishrock123
Copy link
Contributor

@thealphanerd Oh good call. Yes we should probably backport it.

@zeusdeux
Copy link
Contributor Author

@Fishrock123 Thanks for the clean up and merge. Sorry I couldn't get on it. Was travelling.

PS: How do you get the "commit with" message btw? Always been curious how y'all do that. ^_^

Edit: I think I got it. It's like this, right?

Fishrock123 pushed a commit to Fishrock123/node that referenced this pull request Jan 6, 2016
If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Fixes: nodejs#4102
PR-URL: nodejs#4108
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
MylesBorins pushed a commit that referenced this pull request Jan 13, 2016
If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Fixes: #4102
PR-URL: #4108
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
MylesBorins pushed a commit that referenced this pull request Jan 19, 2016
If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Fixes: #4102
PR-URL: #4108
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
@MylesBorins MylesBorins mentioned this pull request Jan 19, 2016
scovetta pushed a commit to scovetta/node that referenced this pull request Apr 2, 2016
If the deprecated NODE_REPL_HISTORY_FILE is set to default
node history file path ($HOME/.node_repl_history) and the file
doesn't exist, then node creates the file and then crashes when
it tries to parse that file as JSON thinking that it's an older
JSON formatted history file. This fixes that bug.

This patch also prevents node repl from throwing if the old
history file is empty or if $HOME/.node_repl_history is empty.

Fixes: nodejs#4102
PR-URL: nodejs#4108
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
repl Issues and PRs related to the REPL subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants