Vscode: "Download Now" button should respect the used installation method on Linux

Created on 14 Feb 2018  路  25Comments  路  Source: microsoft/vscode

Issue Type

Bug

Description

__Edit:__ Originally this issue was specifically about the .deb installation method, but since this problem is not specific to it, I edited the issue to be more general.

How to reproduce

  1. Install (an outdated version of) VS Code using one of the installation methods.
  2. Open VSCode and wait for the (1) to appear on the settings icon.
  3. Click on the settings icon and then on Download Now.

Expected behavior

VSCode starts the download of the latest version's file (when the .tar.gz was used to install VS Code) or instructs the user to run an update through the relevant package manager.

Actual behavior

VS Code always starts the download of the latest version's .tar.gz file.

Possible solution

VS Code could check what type of download was used to install and behave differently based on that.
Checking whether a .deb was used could look something like this:

import { spawn } from 'child_process';

export function isDebInstallation(): Promise<boolean> {
  return new Promise(resolve => {
    spawn('dpkg', ['--list', 'code']).on('close', code => {
      resolve(code === 0);
    });
  });
}

Another option would be to include the information about what installation method was used in the release.

VS Code Info

VS Code version: Code 1.20.0 (c63189deaa8e620f650cc28792b8f5f3363f2c5b, 2018-02-07T17:10:15.949Z)
OS version: Linux x64 4.13.0-32-generic


System Info

|Item|Value|
|---|---|
|CPUs|Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz (4 x 3300)|
|Load (avg)|1, 1, 1|
|Memory (System)|15.61GB (10.31GB free)|
|Process Argv|/usr/share/code/code .|
|Screen Reader|no|
|VM|0%|


Reproduces without extensions

feature-request good first issue help wanted install-update linux

Most helpful comment

The think the ideal behavior for deb and rpm would actually be to either not show the download now button at all, or query the detected apt/yum/dnf for whether there is an update and then provide a notification (which defers to software updater?)

All 25 comments

Nice solution 馃憤. Opening up to PRs for now, most relevant files are likely updateService.linux.ts and .../parts/update/electron-browser/update.ts

Ive got the same issue, using deepin (based on debian) I just updated from 120.xxx,

An alternative solution might be to check for the presence of GDebi on the system (or another package installer that consumes .deb packages), this information is probably available in the mime file type system somewhere.
If no one else has picked this up it might be a suitable issue for me to pop my vscode-contributor-cherry on. I would like that but I havent worked on an electron based package before and I'm not at all familiar with the codebase, I might need a bit of guidance.

@flurbius well the solution needs to cover the following install types:

  • Install via deb
  • Install via rpm
  • Install via snap package
  • Extract tarball manually

Checking for gdebi probably wouldn't be enough, ideally we would check if vscode was installed through dpkg as mentioned in the OP's comment and potentially even validating the path is as expected (to avoid the wrong message if both the snap and deb is installed).

I mentioned the 2 files in my comment above that will likely need changing for this, let me know if you have more specific questions 馃槂

The think the ideal behavior for deb and rpm would actually be to either not show the download now button at all, or query the detected apt/yum/dnf for whether there is an update and then provide a notification (which defers to software updater?)

PackageKit could be relevant here

@ZanderBrown we probably wouldn't want to ship some extra dependency like this when we could just query the various package manages when available?

PackageKit is used by GNOME Software (inc Ubuntu Software) and KDE Discover and as such is present on many systems already.

It acts as an abstraction to the various underlying package managers and is actually used in a few extensions already e.g. Uncrustify

@shroudedcode @Tyriar Querying various package managers to check if a Code package was installed via one of them may let some Code instances be incorrectly attributed. It could be that more than one install of Code is on a machine, installed via different methods (e.g. via apt for day-to-day, via source for bleeding edge). Ideally, any check should be specific to a running instance.

You can check if a running instance was installed from a deb with dpkg -S <path-to-executable>, for example. Unfortunately, it gets trickier, or impossible, to do the same for all methods. There's apt-file search <path-to-executable> for apt, but apt-file is often not installed by default so that's not much use. There's probably similar tools for other package managers. I can't think of a full-proof way to determine if it was built from source locally.

Although not automatic, a new setting(s) in Code to disable update checks, notifications and the download menu item, would be a nice enough solution for many people I think.

@monkeyhybrid

IF NOT insiders AND path = "/usr/bin/code" AND packagekit_query_installed() THEN
    packagekit_update()
ELSE
    download_tar()
ENDIF

@ZanderBrown I missed your initial comment about PackageKit. If your method works as well as it looks like it should do, then that looks like the way to go! As far as I can tell, PackageKit is going to be standard on practically any Linux distro that's likely to be running Code.

@Tyriar looks like this issue needs attention. I'm starting out with VS Code contributions, and I'd like to take this up in case no one else is working on it.

@kanishk98 sure, the best place to start is updateService.linux.js:

https://github.com/Microsoft/vscode/blob/f34300b82ea2cabc4713096aa72d78c743fe3e57/src/vs/platform/update/electron-main/updateService.linux.ts#L76-L83

I think this will involve detecting whether it's installed in apt-get/apt or dnf/yum there, and if so route to a new download url. You will need to add some keys to product.json to get this to work (downloadUrlDeb, downloadUrlRpm), when we merge the PR I'll will add these keys to the official build's product.json.

Thanks for the help, @Tyriar. I have a couple of solutions in mind for the problem, and I'll implement them as you suggest:

  1. We could execute the shell command command-v-apt or command-v-dnf from within the updateService.linux.js file and make a decision based on the output received.
  2. We could search the etc/ directory for the os-release file (for systems running systemd) and resort to a fallback mechanism for systems that don't have that file yet. That'll involve comparing file names in the /etc directory with a list of possible file names for different Linux distros.

I'm not sure what approach the VS community would prefer, so I figured it's better to ask before writing any code.

@kanishk98 command-v-apt doesn't seem to be available on Ubuntu 18.10? Ideally we will do this checking without any additional dependencies. ideally we would query apt or dnf themselves (or packagekit?). Scanning etc/ is also not preferable as the registration may not be in the expected place.

@kanishk98 I'd still recommend packagekit

@Tyriar sorry, didn't know Ubuntu 18.10 would be a problem with command-v-apt.
@ZanderBrown as far as I understand, packagekit won't work for certain systems (say old Ubuntu systems that don't have GNOME installed). Does it offer some specific advantage over querying apt or dnf and so on?

@kanishk98 @Tyriar I'm guessing kanishk98 means command -v apt and command -v dnf, to test if Debian based / Fedora based package managers are in use? Along with the idea of looking for an os-release file, neither method tells us enough.

@kanishk98 Look at @ZanderBrown's comments regarding PackageKit, earlier in this thread. That seems like the best direction to head in.

@kanishk98 I'm just having a quick play with PackageKit command line tools to see how best to check if a package is installed or not. The command, pkcon resolve <package-name>, should show the install status for the given package.

If code package is installed:-

$ pkcon resolve code             
Resolving                     [=========================]         
Loading cache                 [=========================]         
Installed       code-1.26.0-1534177765.amd64 (installed:vscode_stable-stable-main)      Code editing. Redefined.

If code package not installed, but available in a repo:-

$ pkcon resolve code             
Resolving                     [=========================]         
Loading cache                 [=========================]         
Available       code-1.26.0-1534177765.amd64 (vscode_stable-stable-main)      Code editing. Redefined.

If code package not installed and not available in repos:-

$ pkcon resolve code             
Resolving                     [=========================]         
Loading cache                 [=========================]         

All three examples return exit code 0.

Checking for the Installed string at least tells you that VSCode has been installed from a repo. As suggested by @ZanderBrown, you may then want to check if the running instance is /usr/bin/code (the default install path for VSCode from repo, at least on Ubunutu).

The VSCode package for Ubuntu is called code. I don't know if this is the same for other distros.

I had a quick search for distro support of PackageKit. I didn't turn up first versions / dates for when support started, but it seems very widespread nowadays and goes back to 2008 in the case of Fedora. I'll look into that more when I get a chance later.

@Tyriar

I think this will involve detecting whether it's installed in apt-get/apt or dnf/yum there, and if so route to a new download url.

Wouldn't it be better to just do nothing, in that case? No routing to a download URL, no VSCode notifications; just leave it to the OS package manager from there on.

@monkeyhybrid I thought we'd ruled out the possibility of using command-v-apt and command-v-dnf. I looked into PackageKit, and it seems that Ubuntu systems don't have great support for it. On an AWS instance running Ubuntu 16.04, I checked for PackageKit and it wasn't installed by default. I'll grab a 16.04 image and try the same thing on my own machine to make sure that AWS isn't the problem.

Considering Code's website offers three options for Linux installation - .deb, .rpm, and a tarball, shouldn't it be simpler and more reliable to just run apt list code/dnf list code/yum list code and if none of the stdout results contain "installed", default to the tarball?

Let me know if I'm missing something here.

@kanishk98 I just tested with a Ubuntu 16.04 virtual machine and you're right, no default support for PackageKit. It's an LTS release too, so could be around for a few years to come. Hmmm, that's a shame. :(

So I guess that leaves the options as:-

  • Use apt, dpkg, dnf, yum, etc, to test if code package was installed.
  • Require PackageKit as a package dependency (seems a bit overkill - maybe has other consequences?)
  • Make tailored builds for package releases that disable update checks.
  • Add an option to settings.json to allow users to disable update checks (which could be handy for other corner cases).

I just had a peek at the Gulp build file for Linux and there are references to Snap and Flatpak packages in addition to deb and RPM. On top of that, there are multiple AUR packages made by the Arch community, and I'm sure the same applies to other distros. Checking all of this could be a real mess.

So... how about this:

  • A new default config setting ("update.enableChecks": true) is added to VSCode.
  • The Linux build script changes the default setting from true to false when building for any form of package management system.
  • At runtime, VSCode checks this setting before running update checks.
  • Optionally, allow users to override "update.enableChecks" in settings.json as they see fit.

Bonus is that people building third-party packages can also easily disable update checks as part of their build process, with no need for distro specific tests and no risk of false positives. The same applies for macOS builds in Brew / MacPorts, or anything else for that matter.

I haven't checked, but I would guess this is similar to how Firefox packages are built, for example.

Everyone's a winner?

Wouldn't it be better to just do nothing, in that case? No routing to a download URL, no VSCode notifications; just leave it to the OS package manager from there on.

If we could differentiate Available and repo not installed that would be best.

I just had a peek at the Gulp build file for Linux and there are references to Snap and Flatpak packages in addition to deb and RPM. On top of that, there are multiple AUR packages made by the Arch community, and I'm sure the same applies to other distros. Checking all of this could be a real mess.

References to flatpak will be removed, AUR is managed by the community and we should route to the regular download url in this case. Snap is in progress and will be handled when that gets handled. For now we only need to worry about deb and rpm and fallback to the regular download url.

A new default config setting ("update.enableChecks": true) is added to VSCode.

We already have this: "update.channel": "none"

If we could differentiate Available and repo not installed that would be best.

That should be simple enough if we check stdout.

When there is no package:

~$ apt list go
Listing... Done

When the package is available but not installed:

~$ apt list zsh
Listing... Done
zsh/bionic 5.4.2-3ubuntu3 amd64

When the package is installed:

~$ apt list bash
Listing... Done
bash/bionic,now 4.4.18-2ubuntu1 amd64 [installed]


:slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our documentation.

Happy Coding!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ryan-wong picture ryan-wong  路  3Comments

lukehoban picture lukehoban  路  3Comments

chrisdias picture chrisdias  路  3Comments

borekb picture borekb  路  3Comments

vsccarl picture vsccarl  路  3Comments