Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Validate and install extensions (final) #3158

Merged
merged 44 commits into from
Mar 19, 2013

Conversation

njx
Copy link
Contributor

@njx njx commented Mar 18, 2013

This supersedes #3137, and should contain just the changes for the installer pull request separate from the node modules in #3156.

dangoor and others added 30 commits March 18, 2013 16:44
…ate, but if you can access the class show() should be public). Also, remove the installer param to _showDialog() since it's never used.
installed (installing into disabled in those cases)
legally, and the test that follows the deleted one catches validation
issues in general)
the installation and mocks the extension loading to verify
that the extension *would* load.

disabled the test because it can only run once and will
fail on the second run because there's no way to delete the
target directory
.done(function (localPath) {
state = STATE_INSTALLING;

// TOOD: need to clean up ZIP from temp location
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like this comment is stale now since we call unlink() after the installation succeeds or fails below.

Copy link
Member

Choose a reason for hiding this comment

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

Yep, sorry. Removed.

@njx
Copy link
Contributor Author

njx commented Mar 19, 2013

@dangoor @peterflynn -- re-review (for non-UI parts) complete. I'm not going to merge right now, but will be online later tonight--Peter, if you push some fixes up before I get back online, that's cool, otherwise I'll likely go ahead and merge then; there aren't really any major showstoppers that I see, though there are a few things we should definitely address before DoD.

@dangoor -- don't remember where I mentioned this before, but the main changes for the UI stuff (outside of InstallExtensionDialog) were:

  1. refactor out the CSS for busy spinner so we use common code everywhere
  2. slightly refactor the HTML/CSS for the Project Settings dialog so I can use the same structure in the Install Extension dialog
  3. fix the button positioning in a couple of dialogs that had Cancel on the left side of the dialog instead of the right (it should be on the right, but to the left of the OK button)
  4. add an autoDismiss flag to showModalDialogUsingTemplate() that allows the caller to manually handle button clicks when set to false (instead of the dialog automatically dismissing itself)

@pthiess
Copy link
Contributor

pthiess commented Mar 19, 2013

@njx @dangoor @peterflynn Thank you guys for your hard work on this exciting pull into Brackets. Very cool!

njx added a commit that referenced this pull request Mar 19, 2013
Validate and install extensions (final)
@njx njx merged commit 730c806 into install-extensions-modules Mar 19, 2013
@njx
Copy link
Contributor Author

njx commented Mar 19, 2013

Went ahead and merged this. @dangoor -- if you end up having any comments on the UI stuff, feel free to add the comments to this pull request and I can look at them here later.

.fail(function (err) {
// Ignore expected case: the Promise is failed when we programmatically cancel
// In all other cases, record the error and transition to error display UI
if (!(err === "CANCELED" && self._state === STATE_INSTALL_CANCELLED)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is an almost embarrassing nit to bring up... there are two different spellings of CANCELED on the same line. Both are legit but canceled (one L) is the more common American way. Someone could come along later and misspell STATE_INSTALL_CANCELLED as a result, but I should hope the error would be obvious and we have JS autocompletion to help anyhow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Funny, I always preferred "cancelled", but it does look like American English is standardizing on one-l, and we already have "CANCELED" elsewhere in the API (e.g. dialogs). I've fixed this locally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually Peter is fixing it :)

Copy link
Member

Choose a reason for hiding this comment

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

I've fixed this in the process of doing all the async-cancellation code.

@dangoor
Copy link
Contributor

dangoor commented Mar 19, 2013

I've finished reviewing the UI code.

*/
function _cmdDownloadFile(downloadId, url, localPath, callback) {
if (pendingDownloads[downloadId]) {
callback(Errors.DOWNLOAD_ID_IN_USE, null);
Copy link
Contributor

Choose a reason for hiding this comment

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

I had commented in email separately, but I thought I should put it here with the other comments as well... it appears that the convention in Node is to pass Error objects, so this (and the callback below) should really be something like

callback(new Error(Errors.DOWNLOAD_ID_IN_USE), null);

Copy link
Member

Choose a reason for hiding this comment

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

@dangoor it seems like this is more analogous to the validation failures than it is to throwing an exception in synchronous code... so perhaps I should pass a success object containing an error(s) property instead? Is the first arg of the callback basically used only in cases where the code has essentially 'crashed' or hit an internal error?

Copy link
Member

Choose a reason for hiding this comment

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

It also looks like our node_core code fail to JSONify Error objects properly... we'll need to fix that too.

Copy link
Member

Choose a reason for hiding this comment

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

And actually of course, the standard Error.message doesn't support passing back structured data like the arrays we use for formatted errors in this file. So it seems like we have three options:

  • Use the success argument with an 'error(s)' property for most problems -- anything other than unexpected, thrown exceptions. (Seems a little gross and not really how most Node treats anticipated error cases).
  • Use a custom Error subclass that accepts a (non-string) data parameter, and add special logic to ConnectionManager to serialize back that parameter. (Doesn't seem that common in Node either, but still a bit cleaner than above).
  • Pass something other than an Error as the first arg (some references say this is ok). (But definitely not the standard Node way).

Right now our code seems evenly split between the 1st & 3rd approaches, which is not that ideal...

Copy link
Member

Choose a reason for hiding this comment

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

Also, @dangoor I think the existing change from strings to Errors is causing #3174 since the client side isn't getting any sort of error code info back anymore

Copy link
Contributor

Choose a reason for hiding this comment

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

Where I started with this was that for validation I assumed that unless the validation routine was actually broken, the whole point was to return whether or not the extension was valid. I carried that over into installation because installation validates first.

I do think you're right that the Node convention is generally to pass (err, null) for anything that goes wrong.

I did see one page about errors that talked about doing this:

var err = new Error("message");
err.data = {more: "stuff"};

It would certainly be more pleasant to have a constructor that can take additional data. And I do think that ConnectionManager should know what to do if the callback is given an error, since that's so common. (As some point, we should have a domain (in Node terms) to capture the errors and carry them up to the UI.)

I don't know how much work there would be in ConnectionManager, but I do think it's a good idea to stick to the node convention where possible.

Do you think validation should return (err, null) if the extension is invalid and (null, metadata) if it's valid?

if (!options || !options.disabledDirectory) {
callback(new Error(Errors.NO_DISABLED_DIRECTORY), null);
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

@dangoor I'm wondering if we should just make disabledDirectory required... It seems like if one of the standard codepaths will always throw an error without it, it'd be nicer just to make it a required parameter and dispense with the two copies of this code that guards against it being missing.

It seems like apiVersion shouldn't be optional either... unless we're trying to generalize this code to run in some app other than Brackets, it seems safe to assume that install() can always get an API version for context. (Not true of validate() when it runs on the server, of course, but install() seems ok to assume it's running against an actual app).

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, I'm fine with making those required (and will do so)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants