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

Portable mode: VSCODE_PORTABLE not available for uninstall script #54345

Closed
JimiC opened this issue Jul 15, 2018 · 24 comments
Closed

Portable mode: VSCODE_PORTABLE not available for uninstall script #54345

JimiC opened this issue Jul 15, 2018 · 24 comments
Assignees
Labels
info-needed Issue requires more information from poster

Comments

@JimiC
Copy link
Contributor

JimiC commented Jul 15, 2018

  • VSCode Version: 1.25.1
  • OS Version: Any

Steps to Reproduce:

  1. Uninstall any extension that provides a vscode:uninstall script
  2. Inspect process.env.
  3. process.env.VSCODE_PORTABLE is missing

Does this issue occur when all extensions are disabled?: Yes

When trying to support Portable Mode on vscode-icons, process.env.VSCODE_PORTABLE is very handy to determine if the vscode instance is started in portable mode (thus finding where the user-data directory is). Unfortunately the same can not be achieved for the uninstall script.

@Tyriar Tyriar added the portable-mode VS Code portable mode issues label Jul 16, 2018
@joaomoreno joaomoreno removed the portable-mode VS Code portable mode issues label Jul 16, 2018
@joaomoreno
Copy link
Member

@JimiC Isn't it better to actually get the user-data directory?

Why do you need that path, anyway?

@joaomoreno joaomoreno added the info-needed Issue requires more information from poster label Jul 16, 2018
@jens1o
Copy link
Contributor

jens1o commented Jul 16, 2018

@vscodebot vscodebot bot removed the new release label Jul 16, 2018
@JimiC
Copy link
Contributor Author

JimiC commented Jul 16, 2018

@joaomoreno You see having process.env.VSCODE_PORTABLE simplifies the whole determining logic.

Then the code would look like this:

let userDir: string;
if (process.env.VSCODE_PORTABLE) {
  userDir = path.join(process.env.VSCODE_PORTABLE, 'user-data', 'User');
} else {
  const appDir = /^win/.test(process.platform) 
    ? process.env,APPDATA 
    : process.platform === 'darwin'
        ?`${os.homeDir()}/Library/Application Support` 
        : process.platform === 'linux' 
           ? `${os.homedir()}/.config`
           : '/var/local';
  const baseUserDataDir = /dev/i.test(__dirname)
    ? 'code-oss-dev'
    : /oss/i.test(__dirname);
       ? 'Code - OSS'
       : /insiders/i.test(__dirname)
          ? 'Code - Insiders'
          : 'Code';
  userDir = path.join(appDir, baseUserDataDir, 'User');
}

Now, if we had an env variable for the "user data" directory and one for the "extensions" directory, for the non-portable instances, I would make you a statue.

@joaomoreno
Copy link
Member

Now, if we had an env variable for the "user data" directory and one for the "extensions" directory, for the non-portable instances, I would make you a statue.

Get the marble.

@joaomoreno
Copy link
Member

Actually, hold the marble.

After discussing with @sandy081, we think you might benefit more from two other options:

This is because our settings files might (and often do) contain comments, which your parseJSON function can't handle. We also should preserve settings file whitespace as much as possible when modifying it, which your saveSettings function won't do.

Closing this for now.

@JimiC
Copy link
Contributor Author

JimiC commented Jul 17, 2018

Having access to vscode API is a plus, and would help in cleaning up the settings.json properly. But what about the scenario that we want to delete a file that was put in the User directory by the extension? And that proposal surely doesn't justify a statue. 😄

@joaomoreno
Copy link
Member

joaomoreno commented Jul 17, 2018

But what about the scenario that we want to delete a file that was put in the User directory by the extension?

Well, I sure do hope the hypothetical extension would be using the official ExtensionContext.storagePath API, instead of putting files where it shouldn't. 😉

@JimiC
Copy link
Contributor Author

JimiC commented Jul 17, 2018

Ooops. I'll have to explore that ExtensionContext, which I admit, was not aware of.
I thought that this was only to register the commands. RTFM to the rescue.

@JimiC
Copy link
Contributor Author

JimiC commented Jul 17, 2018

I see it now. Guilty as charged. Just for the record, I've seen other extensions storing files where they shouldn't too. We are going to adjust our code to use the API instead. And let's hope we will get the API for the uninstall script real soon.

@joaomoreno
Copy link
Member

@JimiC Sweet!

@JimiC
Copy link
Contributor Author

JimiC commented Aug 4, 2018

@joaomoreno After trying to implement settings storage using ExtensionContext.storagePath I came upon the following cases:

  • storagePath is undefined when a workspace is not loaded
  • storagePath is different for every workspace loaded

Therefore using ExtensionContext.storagePath to store extension settings is not a viable solution, as a constant path is required.

The offer for the statue still stands.

@joaomoreno
Copy link
Member

cc @sandy081 for insights

@sandy081
Copy link
Member

@JimiC You are right, storagePath is workspace scoped. Why not using ExtensionContext.extensionPath for global storage of files? These gets cleaned up when extension is removed from the disk

@JimiC
Copy link
Contributor Author

JimiC commented Aug 13, 2018

Because we want this file to be persistent during a new extension version release. If we are to use ExtensionContext.extensionPath then we will have to implement a previous extension version folder detection (note that not everyone updates as soon as a new version gets released), which can cause other issues for us, and transfer that file to the new extension version folder, modified appropriately.

@JimiC
Copy link
Contributor Author

JimiC commented Aug 13, 2018

This #2741 would be the proper solution.

@JimiC
Copy link
Contributor Author

JimiC commented Aug 13, 2018

@sandy081 One other thing is that we support icons customization and we need a persistent location where the user can put their custom icons. These icons should not be removed with every new extension version release. User directory seems the logical place to put those.

@sandy081
Copy link
Member

I see, not sure if we expose user data directory as an API.

@jrieken What location do we recommend authors if they want to store files as global cache?

If user data directory is the common usage why not expose it in the extension context?

@jrieken
Copy link
Member

jrieken commented Aug 13, 2018

There is ExtensionContext#storagePath which can be used to persist things

@JimiC
Copy link
Contributor Author

JimiC commented Aug 13, 2018

@jrieken We have already ruled out that this path does not suffice (#54345 (comment)).
We need a location to persist things across new extension version releases.

@JimiC
Copy link
Contributor Author

JimiC commented Aug 13, 2018

@jrieken Can we get an ExtensionContext#userDataPath ?

@jrieken
Copy link
Member

jrieken commented Aug 13, 2018

That sounds wrong... The ExtensionContext is private and scoped to each extension and userDataPath sounds pretty global/shared to my ears. Do you want something like ExtensionContext#globalStoragePath that's shared between all windows (empty, single file, folder, workspace) but scoped to an extension?

@JimiC
Copy link
Contributor Author

JimiC commented Aug 13, 2018

Do you want something like ExtensionContext#globalStoragePath that's shared between all windows (empty, single file, folder, workspace) but scoped to an extension?

If this will be persistent across extension updates, yes, please. And we will need this path to be available on uninstall script also. Is there a way to have access to ExtensionContext in that too?

@JimiC
Copy link
Contributor Author

JimiC commented Aug 15, 2018

@jrieken I have solved half my problem by using ExtensionContext#globalState to store the extensions state (the place was obvious but who cares to read the entire f@cking manual). This though requires that ExtensionContext#globalState is accessible in the uninstall script also so that we can clean up the state, although I'm not sure that this task is crucial.

Now I'm up to solve the other half of my problem, which is where to store user files by default (in our case custom icons) and have access to that via the API. Any recommendations?

@joaomoreno
Copy link
Member

Do you want something like ExtensionContext#globalStoragePath that's shared between all windows (empty, single file, folder, workspace) but scoped to an extension?

@jrieken 👍

@vscodebot vscodebot bot locked and limited conversation to collaborators Aug 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
info-needed Issue requires more information from poster
Projects
None yet
Development

No branches or pull requests

6 participants